rk29: vpu_mem: add pool interface to limit vpu_mem usage
author陈恒明 <chm@rock-chips.com>
Wed, 14 Mar 2012 09:14:28 +0000 (17:14 +0800)
committer陈恒明 <chm@rock-chips.com>
Wed, 14 Mar 2012 09:15:19 +0000 (17:15 +0800)
arch/arm/mach-rk29/include/mach/vpu_mem.h
arch/arm/mach-rk29/vpu_mem.c

index 7d4c5279ef7be091f943fe8356ba1de19eaaabb9..40faef3c368d958eb1d2efcfa7560d31f1835d5f 100644 (file)
@@ -28,7 +28,9 @@
 #define VPU_MEM_LINK            _IOW(VPU_MEM_IOCTL_MAGIC, 7, unsigned int)
 #define VPU_MEM_CACHE_CLEAN     _IOW(VPU_MEM_IOCTL_MAGIC, 8, unsigned int)
 #define VPU_MEM_CACHE_INVALID   _IOW(VPU_MEM_IOCTL_MAGIC, 9, unsigned int)
-
+#define VPU_MEM_POOL_SET        _IOW(VPU_MEM_IOCTL_MAGIC, 10, unsigned int)
+#define VPU_MEM_POOL_UNSET      _IOW(VPU_MEM_IOCTL_MAGIC, 11, unsigned int)
+#define VPU_MEM_POOL_CHECK      _IOW(VPU_MEM_IOCTL_MAGIC, 12, unsigned int)
 
 struct vpu_mem_platform_data
 {
index bc05e6842ea4600295909caf20e46a626d9f46a6..d5ce57e43ac732710d8280f6ca69fb25224afa8d 100644 (file)
  * @author ChenHengming (2011-4-11)\r
  */\r
 typedef struct vpu_mem_session {\r
-    /* a list of memory region used posted by current process */\r
-    struct list_head list_used;\r
-    struct list_head list_post;\r
-    /* a linked list of data so we can access them for debugging */\r
-    struct list_head list_session;\r
+       /* a list of memory region used posted by current process */\r
+       struct list_head list_used;\r
+       struct list_head list_post;\r
+       /* a linked list of data so we can access them for debugging */\r
+       struct list_head list_session;\r
+       /* a linked list of memory pool on current session */\r
+       struct list_head list_pool;\r
        /* process id of teh mapping process */\r
        pid_t pid;\r
 } vdm_session;\r
 \r
+/**\r
+ * session memory pool info\r
+ */\r
+typedef struct vpu_mem_pool_info {\r
+       struct list_head session_link;      /* link to session use for search */\r
+       struct list_head list_used;         /* a linked list for used memory in the pool */\r
+       vdm_session *session;\r
+       int count_current;\r
+       int count_target;\r
+       int count_used;\r
+       int pfn;\r
+} vdm_pool;\r
+\r
+/**\r
+ * session memory pool config input\r
+ */\r
+typedef struct vpu_mem_pool_config {\r
+       int size;\r
+       unsigned int count;\r
+} vdm_pool_config;\r
+\r
 /**\r
  * global region info\r
  */\r
 typedef struct vpu_mem_region_info {\r
-    struct list_head index_list;        /* link to index list use for search */\r
-    int used;\r
-    int post;\r
-    int index;\r
-    int pfn;\r
+       struct list_head index_list;        /* link to index list use for search */\r
+       int used;\r
+       int post;\r
+       int index;\r
+       int pfn;\r
 } vdm_region;\r
 \r
 /**\r
@@ -76,13 +99,19 @@ typedef struct vpu_mem_region_info {
  * this struct should be modified with bitmap lock\r
  */\r
 typedef struct vpu_mem_link_info {\r
-    struct list_head session_link;      /* link to vpu_mem_session list */\r
-    struct list_head status_link;       /* link to vdm_info.status list use for search */\r
-    vdm_region *region;\r
-    int link_post;\r
-    int link_used;\r
-    int index;\r
-    int pfn;\r
+       struct list_head session_link;      /* link to vpu_mem_session list */\r
+       struct list_head status_link;       /* link to vdm_info.status list use for search */\r
+       struct list_head pool_link;         /* link to vpu_mem_session pool list for search */\r
+       vdm_region *region;\r
+       vdm_pool *pool;\r
+       union {\r
+               int post;\r
+               int used;\r
+               int count;\r
+       } ref;\r
+       int *ref_ptr;\r
+       int index;\r
+       int pfn;\r
 } vdm_link;\r
 \r
 /**\r
@@ -106,11 +135,11 @@ typedef struct vpu_mem_info {
        /*\r
         * vdm_session init only store the free region but use a vdm_session for convenience\r
         */\r
-    vdm_session status;\r
+       vdm_session status;\r
        struct list_head list_index;        /* sort by index */\r
-    struct list_head list_free;         /* free region list */\r
-    struct list_head list_session;      /* session list */\r
-    struct rw_semaphore rw_sem;\r
+       struct list_head list_free;         /* free region list */\r
+       struct list_head list_session;      /* session list */\r
+       struct rw_semaphore rw_sem;\r
 } vdm_info;\r
 \r
 static vdm_info vpu_mem;\r
@@ -133,47 +162,52 @@ static int vpu_mem_over = 0;
  */\r
 static void dump_status(void)\r
 {\r
-    vdm_link    *link, *tmp_link;\r
-    vdm_region  *region, *tmp_region;\r
-    vdm_session *session, *tmp_session;\r
-\r
-    printk("vpu mem status dump :\n\n");\r
-\r
-    // °´ index ´òÓ¡È«²¿ region\r
-    printk("region:\n");\r
-    list_for_each_entry_safe(region, tmp_region, &vdm_index, index_list) {\r
-        printk("        idx %6d pfn %6d used %3d post %3d\n",\r
-            region->index, region->pfn, region->used, region->post);\r
-    }\r
-    printk("free  :\n");\r
-    list_for_each_entry_safe(link, tmp_link, &vdm_free, status_link) {\r
-        printk("        idx %6d pfn %6d used %3d post %3d\n",\r
-            link->index, link->pfn, link->link_used, link->link_post);\r
-    }\r
-    printk("used  :\n");\r
-    list_for_each_entry_safe(link, tmp_link, &vdm_used, status_link) {\r
-        printk("        idx %6d pfn %6d used %3d post %3d\n",\r
-            link->index, link->pfn, link->link_used, link->link_post);\r
-    }\r
-    printk("post  :\n");\r
-    list_for_each_entry_safe(link, tmp_link, &vdm_post, status_link) {\r
-        printk("        idx %6d pfn %6d used %3d post %3d\n",\r
-            link->index, link->pfn, link->link_used, link->link_post);\r
-    }\r
+       vdm_link    *link, *tmp_link;\r
+       vdm_pool    *pool, *tmp_pool;\r
+       vdm_region  *region, *tmp_region;\r
+       vdm_session *session, *tmp_session;\r
+\r
+       printk("vpu mem status dump :\n\n");\r
+\r
+       // °´ index ´òÓ¡È«²¿ region\r
+       printk("region:\n");\r
+       list_for_each_entry_safe(region, tmp_region, &vdm_index, index_list) {\r
+               printk("        idx %6d pfn %6d used %3d post %3d\n",\r
+                       region->index, region->pfn, region->used, region->post);\r
+       }\r
+       printk("free  :\n");\r
+       list_for_each_entry_safe(link, tmp_link, &vdm_free, status_link) {\r
+               printk("        idx %6d pfn %6d ref %3d\n",\r
+                       link->index, link->pfn, link->ref.used);\r
+       }\r
+       printk("used  :\n");\r
+       list_for_each_entry_safe(link, tmp_link, &vdm_used, status_link) {\r
+               printk("        idx %6d pfn %6d used %3d\n",\r
+                       link->index, link->pfn, link->ref.used);\r
+       }\r
+       printk("post  :\n");\r
+       list_for_each_entry_safe(link, tmp_link, &vdm_post, status_link) {\r
+               printk("        idx %6d pfn %6d post %3d\n",\r
+                       link->index, link->pfn, link->ref.post);\r
+       }\r
 \r
-    // ´òÓ¡ vpu_mem_info ÖеÄÈ«²¿ session µÄ region Õ¼ÓÃÇé¿ö\r
-    list_for_each_entry_safe(session, tmp_session, &vdm_proc, list_session) {\r
-        printk("pid: %d\n", session->pid);\r
+       // ´òÓ¡ vpu_mem_info ÖеÄÈ«²¿ session µÄ region Õ¼ÓÃÇé¿ö\r
+       list_for_each_entry_safe(session, tmp_session, &vdm_proc, list_session) {\r
+               printk("pid: %d\n", session->pid);\r
 \r
-        list_for_each_entry_safe(link, tmp_link, &session->list_used, session_link) {\r
-            printk("used: idx %6d pfn %6d used %3d\n",\r
-                link->index, link->pfn, link->link_used);\r
-        }\r
-        list_for_each_entry_safe(link, tmp_link, &session->list_post, session_link) {\r
-            printk("post: idx %6d pfn %6d post %3d\n",\r
-                link->index, link->pfn, link->link_post);\r
-        }\r
-    }\r
+               list_for_each_entry_safe(pool, tmp_pool, &session->list_pool, session_link) {\r
+                       printk("pool: pfn %6d target %3d current %2d\n",\r
+                               pool->pfn, pool->count_current, pool->count_target);\r
+               }\r
+               list_for_each_entry_safe(link, tmp_link, &session->list_used, session_link) {\r
+                       printk("used: idx %6d pfn %6d used %3d\n",\r
+                               link->index, link->pfn, link->ref.used);\r
+               }\r
+               list_for_each_entry_safe(link, tmp_link, &session->list_post, session_link) {\r
+                       printk("post: idx %6d pfn %6d post %3d\n",\r
+                               link->index, link->pfn, link->ref.post);\r
+               }\r
+       }\r
 }\r
 \r
 /**\r
@@ -192,7 +226,7 @@ static vdm_link *find_used_link(vdm_session *session, int index)
 \r
     list_for_each_entry_safe(pos, n, &session->list_used, session_link) {\r
         if (index == pos->index) {\r
-            DLOG("found index %d ptr %x\n", index, pos);\r
+            DLOG("found index %d ptr %p\n", index, pos);\r
             return pos;\r
         }\r
     }\r
@@ -243,6 +277,36 @@ static vdm_link *find_free_link(int index)
 \r
     return NULL;\r
 }\r
+\r
+static vdm_pool *find_pool_by_pfn(vdm_session *session, unsigned int pfn)\r
+{\r
+    vdm_pool *pos, *n;\r
+\r
+    list_for_each_entry_safe(pos, n, &session->list_pool, session_link) {\r
+        if (pfn == pos->pfn) {\r
+            return pos;\r
+        }\r
+    }\r
+\r
+    return NULL;\r
+}\r
+\r
+static void link_ref_inc(vdm_link *link)\r
+{\r
+       link->ref.count++;\r
+       if (link->ref_ptr) {\r
+               *link->ref_ptr += 1;\r
+       }\r
+}\r
+\r
+static void link_ref_dec(vdm_link *link)\r
+{\r
+       link->ref.count--;\r
+       if (link->ref_ptr) {\r
+               *link->ref_ptr -= 1;\r
+       }\r
+}\r
+\r
 /**\r
  * insert a region into the index list for search\r
  *\r
@@ -267,7 +331,7 @@ static int _insert_region_index(vdm_region *region)
 \r
     list_for_each_entry_safe(tmp, n, &vdm_index, index_list) {\r
         next = tmp->index;\r
-        DLOG("insert index %d pfn %d last %d next %d ptr %x\n", index, region->pfn, last, next, tmp);\r
+        DLOG("insert index %d pfn %d last %d next %d ptr %p\n", index, region->pfn, last, next, tmp);\r
         if ((last < index) && (index < next))  {\r
             DLOG("Done\n");\r
             list_add_tail(&region->index_list, &tmp->index_list);\r
@@ -304,14 +368,14 @@ static void _insert_link_status_free(vdm_link *link)
     list_for_each_entry_safe(tmp, n, &vdm_free, status_link) {\r
         next = tmp->index;\r
         if ((last < index) && (index < next))  {\r
-            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %x\n", index, link->pfn, last, next, tmp);\r
+            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %p\n", index, link->pfn, last, next, tmp);\r
             list_add_tail(&link->status_link, &tmp->status_link);\r
             return ;\r
         }\r
         last = next;\r
     }\r
     list_add_tail(&link->status_link, &tmp->status_link);\r
-    DLOG("list_add index %d pfn %d last %d ptr %x\n", index, link->pfn, last, tmp);\r
+    DLOG("list_add index %d pfn %d last %d ptr %p\n", index, link->pfn, last, tmp);\r
     return ;\r
 }\r
 \r
@@ -331,7 +395,7 @@ static void _insert_link_status_post(vdm_link *link)
     list_for_each_entry_safe(tmp, n, &vdm_post, status_link) {\r
         next = tmp->index;\r
         if ((last < index) && (index < next))  {\r
-            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %x\n", index, link->pfn, last, next, tmp);\r
+            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %p\n", index, link->pfn, last, next, tmp);\r
             list_add_tail(&link->status_link, &tmp->status_link);\r
             return ;\r
         }\r
@@ -339,7 +403,7 @@ static void _insert_link_status_post(vdm_link *link)
     }\r
 \r
     list_add_tail(&link->status_link, &tmp->status_link);\r
-    DLOG("list_add index %d pfn %d last %d ptr %x\n", index, link->pfn, last, tmp);\r
+    DLOG("list_add index %d pfn %d last %d ptr %p\n", index, link->pfn, last, tmp);\r
     return ;\r
 }\r
 \r
@@ -359,7 +423,7 @@ static void _insert_link_status_used(vdm_link *link)
     list_for_each_entry_safe(tmp, n, &vdm_used, status_link) {\r
         next = tmp->index;\r
         if ((last < index) && (index < next))  {\r
-            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %x\n", index, link->pfn, last, next, tmp);\r
+            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %p\n", index, link->pfn, last, next, tmp);\r
             list_add_tail(&link->status_link, &tmp->status_link);\r
             return ;\r
         }\r
@@ -367,7 +431,7 @@ static void _insert_link_status_used(vdm_link *link)
     }\r
 \r
     list_add_tail(&link->status_link, &tmp->status_link);\r
-    DLOG("list_add index %d pfn %d last %d ptr %x\n", index, link->pfn, last, tmp);\r
+    DLOG("list_add index %d pfn %d last %d ptr %p\n", index, link->pfn, last, tmp);\r
     return ;\r
 }\r
 \r
@@ -388,14 +452,14 @@ static void _insert_link_session_used(vdm_link *link, vdm_session *session)
         next = tmp->index;\r
         if ((last < index) && (index < next))  {\r
             list_add_tail(&link->session_link, &tmp->session_link);\r
-            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %x\n", index, link->pfn, last, next, tmp);\r
+            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %p\n", index, link->pfn, last, next, tmp);\r
             return ;\r
         }\r
         last = next;\r
     }\r
 \r
     list_add_tail(&link->session_link, &tmp->session_link);\r
-    DLOG("list_add index %d pfn %d last %d ptr %x\n", index, link->pfn, last, tmp);\r
+    DLOG("list_add index %d pfn %d last %d ptr %p\n", index, link->pfn, last, tmp);\r
     return ;\r
 }\r
 \r
@@ -416,14 +480,14 @@ static void _insert_link_session_post(vdm_link *link, vdm_session *session)
         next = tmp->index;\r
         if ((last < index) && (index < next))  {\r
             list_add_tail(&link->session_link, &tmp->session_link);\r
-            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %x\n", index, link->pfn, last, next, tmp);\r
+            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %p\n", index, link->pfn, last, next, tmp);\r
             return ;\r
         }\r
         last = next;\r
     }\r
 \r
     list_add_tail(&link->session_link, &tmp->session_link);\r
-    DLOG("list_add index %d pfn %d last %d ptr %x\n", index, link->pfn, last, tmp);\r
+    DLOG("list_add index %d pfn %d last %d ptr %p\n", index, link->pfn, last, tmp);\r
     return ;\r
 }\r
 \r
@@ -478,25 +542,50 @@ static void merge_free_region_and_link(vdm_region *region)
 \r
 static void put_free_link(vdm_link *link)\r
 {\r
-    list_del_init(&link->session_link);\r
-    list_del_init(&link->status_link);\r
-    _insert_link_status_free(link);\r
+       if (link->pool) {\r
+               vdm_pool *pool = link->pool;\r
+               link->pool = NULL;\r
+               list_del_init(&link->pool_link);\r
+               pool->count_current--;\r
+               pool->count_used--;\r
+       }\r
+       list_del_init(&link->session_link);\r
+       list_del_init(&link->status_link);\r
+       _insert_link_status_free(link);\r
 }\r
 \r
 static void put_used_link(vdm_link *link, vdm_session *session)\r
 {\r
-    list_del_init(&link->session_link);\r
-    list_del_init(&link->status_link);\r
-    _insert_link_status_used(link);\r
-    _insert_link_session_used(link, session);\r
+       list_del_init(&link->session_link);\r
+       list_del_init(&link->status_link);\r
+       _insert_link_status_used(link);\r
+       _insert_link_session_used(link, session);\r
+       if (NULL == link->pool) {\r
+               vdm_pool *pool = find_pool_by_pfn(session, link->pfn);\r
+               if (pool) {\r
+                       link->pool = pool;\r
+                       list_add_tail(&link->pool_link, &pool->list_used);\r
+                       pool->count_used++;\r
+                       pool->count_current++;\r
+               }\r
+       }\r
 }\r
 \r
 static void put_post_link(vdm_link *link, vdm_session *session)\r
 {\r
-    list_del_init(&link->session_link);\r
-    list_del_init(&link->status_link);\r
-    _insert_link_status_post(link);\r
-    _insert_link_session_post(link, session);\r
+       list_del_init(&link->session_link);\r
+       list_del_init(&link->status_link);\r
+       _insert_link_status_post(link);\r
+       _insert_link_session_post(link, session);\r
+       if (NULL == link->pool) {\r
+               vdm_pool *pool = find_pool_by_pfn(session, link->pfn);\r
+               if (pool) {\r
+                       link->pool = pool;\r
+                       list_add_tail(&link->pool_link, &pool->list_used);\r
+                       pool->count_used++;\r
+                       pool->count_current++;\r
+               }\r
+       }\r
 }\r
 \r
 /**\r
@@ -533,13 +622,15 @@ static vdm_link *new_link_by_index(int index, int pfn)
 \r
     INIT_LIST_HEAD(&region->index_list);\r
 \r
-    link->link_post = 0;\r
-    link->link_used = 0;\r
+    link->ref.count = 0;\r
+    link->ref_ptr   = NULL;\r
     link->region    = region;\r
     link->index     = region->index;\r
     link->pfn       = region->pfn;\r
     INIT_LIST_HEAD(&link->session_link);\r
     INIT_LIST_HEAD(&link->status_link);\r
+    INIT_LIST_HEAD(&link->pool_link);\r
+    link->pool      = NULL;\r
 \r
     return link;\r
 }\r
@@ -562,13 +653,15 @@ static vdm_link *new_link_by_region(vdm_region *region)
         return NULL;\r
     }\r
 \r
-    link->link_post = 0;\r
-    link->link_used = 0;\r
+    link->ref.count = 0;\r
+    link->ref_ptr   = NULL;\r
     link->region    = region;\r
     link->index     = region->index;\r
     link->pfn       = region->pfn;\r
     INIT_LIST_HEAD(&link->session_link);\r
     INIT_LIST_HEAD(&link->status_link);\r
+    INIT_LIST_HEAD(&link->pool_link);\r
+    link->pool      = NULL;\r
 \r
     return link;\r
 }\r
@@ -582,9 +675,21 @@ static vdm_link *new_link_by_region(vdm_region *region)
  */\r
 static void link_del(vdm_link *link)\r
 {\r
-    list_del_init(&link->session_link);\r
-    list_del_init(&link->status_link);\r
-    kfree(link);\r
+       if (link->pool) {\r
+               vdm_pool *pool = link->pool;\r
+               link->pool = NULL;\r
+               list_del_init(&link->pool_link);\r
+               pool->count_current--;\r
+               pool->count_used--;\r
+       }\r
+       list_del_init(&link->session_link);\r
+       list_del_init(&link->status_link);\r
+       if (is_free_region(link->region) && NULL == find_free_link(link->index)) {\r
+               put_free_link(link);\r
+               merge_free_region_and_link(link->region);\r
+       } else {\r
+               kfree(link);\r
+       }\r
 }\r
 \r
 /**\r
@@ -606,8 +711,9 @@ static vdm_link *get_used_link_from_free_link(vdm_link *link, vdm_session *sessi
     }\r
     if (pfn == link->pfn) {\r
         DLOG("pfn == link->pfn %d\n", pfn);\r
-        link->link_used     = 1;\r
+        link->ref.used      = 1;\r
         link->region->used  = 1;\r
+       link->ref_ptr       = &link->region->used;\r
         put_used_link(link, session);\r
         return link;\r
     } else {\r
@@ -619,10 +725,11 @@ static vdm_link *get_used_link_from_free_link(vdm_link *link, vdm_session *sessi
         link->pfn           -= pfn;\r
         link->region->index += pfn;\r
         link->region->pfn   -= pfn;\r
-        used->link_used      = 1;\r
-        used->region->used   = 1;\r
+        used->ref.used      = 1;\r
+        used->region->used  = 1;\r
+       used->ref_ptr       = &used->region->used;\r
 \r
-        DLOG("used: index %d pfn %d ptr %x\n", used->index, used->pfn, used->region);\r
+        DLOG("used: index %d pfn %d ptr %p\n", used->index, used->pfn, used->region);\r
         if (_insert_region_index(used->region)) {\r
             printk(KERN_ALERT "fail to insert allocated region index %d pfn %d\n", used->index, used->pfn);\r
             link_del(used);\r
@@ -639,18 +746,6 @@ static vdm_link *get_used_link_from_free_link(vdm_link *link, vdm_session *sessi
     }\r
 }\r
 \r
-static int vpu_mem_release(struct inode *, struct file *);\r
-static int vpu_mem_mmap(struct file *, struct vm_area_struct *);\r
-static int vpu_mem_open(struct inode *, struct file *);\r
-static long vpu_mem_ioctl(struct file *, unsigned int, unsigned long);\r
-\r
-struct file_operations vpu_mem_fops = {\r
-       .open = vpu_mem_open,\r
-    .mmap = vpu_mem_mmap,\r
-    .unlocked_ioctl = vpu_mem_ioctl,\r
-       .release = vpu_mem_release,\r
-};\r
-\r
 int is_vpu_mem_file(struct file *file)\r
 {\r
        if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode))\r
@@ -663,42 +758,42 @@ int is_vpu_mem_file(struct file *file)
 \r
 static long vpu_mem_allocate(struct file *file, unsigned int len)\r
 {\r
-    vdm_link *free, *n;\r
+       vdm_link *free, *n;\r
        unsigned int pfn = (len + VPU_MEM_MIN_ALLOC - 1)/VPU_MEM_MIN_ALLOC;\r
-    vdm_session *session = (vdm_session *)file->private_data;\r
+       vdm_session *session = (vdm_session *)file->private_data;\r
 \r
-    if (!is_vpu_mem_file(file)) {\r
-        printk(KERN_INFO "allocate vpu_mem session from invalid file\n");\r
-        return -ENODEV;\r
-    }\r
+       if (!is_vpu_mem_file(file)) {\r
+               printk(KERN_INFO "allocate vpu_mem session from invalid file\n");\r
+               return -ENODEV;\r
+       }\r
 \r
-    list_for_each_entry_safe(free, n, &vdm_free, status_link) {\r
-        /* find match free buffer use it first */\r
-        vdm_link *used = get_used_link_from_free_link(free, session, pfn);\r
-        DLOG("search free buffer at index %d pfn %d for len %d\n", free->index, free->pfn, pfn);\r
-        if (NULL == used) {\r
-            continue;\r
-        } else {\r
-            DLOG("found buffer at index %d pfn %d for ptr %x\n", used->index, used->pfn, used);\r
-            return used->index;\r
-        }\r
-    }\r
+       list_for_each_entry_safe(free, n, &vdm_free, status_link) {\r
+               /* find match free buffer use it first */\r
+               vdm_link *used = get_used_link_from_free_link(free, session, pfn);\r
+               DLOG("search free buffer at index %d pfn %d for len %d\n", free->index, free->pfn, pfn);\r
+               if (NULL == used) {\r
+                       continue;\r
+               } else {\r
+                       DLOG("found buffer at index %d pfn %d for ptr %p\n", used->index, used->pfn, used);\r
+                       return used->index;\r
+               }\r
+       }\r
 \r
        if (!vpu_mem_over) {\r
-        printk(KERN_INFO "vpu_mem: no space left to allocate!\n");\r
-        dump_status();\r
-        vpu_mem_over = 1;\r
-    }\r
-    return -1;\r
+               printk(KERN_INFO "vpu_mem: no space left to allocate!\n");\r
+               dump_status();\r
+               vpu_mem_over = 1;\r
+       }\r
+       return -1;\r
 }\r
 \r
 static int vpu_mem_free(struct file *file, int index)\r
 {\r
-    vdm_session *session = (vdm_session *)file->private_data;\r
+       vdm_session *session = (vdm_session *)file->private_data;\r
 \r
-    if (!is_vpu_mem_file(file)) {\r
-        printk(KERN_INFO "free vpu_mem session from invalid file.\n");\r
-        return -ENODEV;\r
+       if (!is_vpu_mem_file(file)) {\r
+               printk(KERN_INFO "free vpu_mem session from invalid file.\n");\r
+               return -ENODEV;\r
     }\r
 \r
        DLOG("searching for index %d\n", index);\r
@@ -708,100 +803,175 @@ static int vpu_mem_free(struct file *file, int index)
             DLOG("no link of index %d searched\n", index);\r
             return -1;\r
         }\r
-        link->link_used--;\r
-        link->region->used--;\r
-        if (0 == link->link_used) {\r
-            if (is_free_region(link->region)) {\r
-                put_free_link(link);\r
-                merge_free_region_and_link(link->region);\r
-            } else {\r
-                link_del(link);\r
-            }\r
+       link_ref_dec(link);\r
+        if (0 == link->ref.used) {\r
+               link_del(link);\r
         }\r
        }\r
-    return 0;\r
+       return 0;\r
 }\r
 \r
 static int vpu_mem_duplicate(struct file *file, int index)\r
 {\r
-    vdm_session *session = (vdm_session *)file->private_data;\r
+       vdm_session *session = (vdm_session *)file->private_data;\r
        /* caller should hold the write lock on vpu_mem_sem! */\r
-    if (!is_vpu_mem_file(file)) {\r
-        printk(KERN_INFO "duplicate vpu_mem session from invalid file.\n");\r
-        return -ENODEV;\r
-    }\r
+       if (!is_vpu_mem_file(file)) {\r
+               printk(KERN_INFO "duplicate vpu_mem session from invalid file.\n");\r
+               return -ENODEV;\r
+       }\r
 \r
        DLOG("duplicate index %d\n", index);\r
-    {\r
-        vdm_link *post = find_post_link(index);\r
-        if (NULL == post) {\r
-            vdm_link *used = find_used_link(session, index);\r
-            if (NULL == used) {\r
-                printk(KERN_ERR "try to duplicate unknown index %d\n", index);\r
-                dump_status();\r
-                return -1;\r
-            }\r
-            post = new_link_by_region(used->region);\r
-            post->link_post = 1;\r
-            post->region->post++;\r
-            put_post_link(post, session);\r
-        } else {\r
-            DLOG("duplicate posted index %d\n", index);\r
-            post->link_post++;\r
-            post->region->post++;\r
-        }\r
-    }\r
+       {\r
+               vdm_link *post = find_post_link(index);\r
+               if (NULL == post) {\r
+                       vdm_link *used = find_used_link(session, index);\r
+                       if (NULL == used) {\r
+                               printk(KERN_ERR "try to duplicate unknown index %d\n", index);\r
+                               dump_status();\r
+                               return -1;\r
+                       }\r
+                       post = new_link_by_region(used->region);\r
+                       post->ref_ptr  = &post->region->post;\r
+                       link_ref_inc(post);\r
+                       put_post_link(post, session);\r
+               } else {\r
+                       DLOG("duplicate posted index %d\n", index);\r
+                       link_ref_inc(post);\r
+               }\r
+       }\r
 \r
        return 0;\r
 }\r
 \r
 static int vpu_mem_link(struct file *file, int index)\r
 {\r
-    vdm_session *session = (vdm_session *)file->private_data;\r
+       vdm_session *session = (vdm_session *)file->private_data;\r
 \r
        if (!is_vpu_mem_file(file)) {\r
-        printk(KERN_INFO "link vpu_mem session from invalid file.\n");\r
-        return -ENODEV;\r
+               printk(KERN_INFO "link vpu_mem session from invalid file.\n");\r
+               return -ENODEV;\r
        }\r
 \r
-    DLOG("link index %d\n", index);\r
-    {\r
-        vdm_link *post = find_post_link(index);\r
-        if (NULL == post) {\r
-            printk(KERN_ERR "try to link unknown index %d\n", index);\r
-            dump_status();\r
-            return -1;\r
-        } else {\r
-            vdm_link *used = find_used_link(session, index);\r
-            post->link_post--;\r
-            post->region->post--;\r
-            if (0 == post->link_post) {\r
-                if (NULL == used) {\r
-                    post->link_used++;\r
-                    post->region->used++;\r
-                    put_used_link(post, session);\r
-                } else {\r
-                    used->link_used++;\r
-                    used->region->used++;\r
-                    link_del(post);\r
-                }\r
-            } else {\r
-                if (NULL == used) {\r
-                    used = new_link_by_region(post->region);\r
-                    used->link_used++;\r
-                    used->region->used++;\r
-                    put_used_link(used, session);\r
-                } else {\r
-                    used->link_used++;\r
-                    used->region->used++;\r
-                }\r
-            }\r
-        }\r
-    }\r
+       DLOG("link index %d\n", index);\r
+       {\r
+               vdm_link *post = find_post_link(index);\r
+               if (NULL == post) {\r
+                       printk(KERN_ERR "try to link unknown index %d\n", index);\r
+                       dump_status();\r
+                       return -1;\r
+               } else {\r
+                       vdm_link *used = find_used_link(session, index);\r
+                       link_ref_dec(post);\r
+\r
+                       if (used) {\r
+                               if (0 == post->ref.post) {\r
+                                       link_del(post);\r
+                                       post = NULL;\r
+                               }\r
+                       } else {\r
+                               if (post->ref.post) {\r
+                                       used = new_link_by_region(post->region);\r
+                               } else {\r
+                                       used = post;\r
+                                       post = NULL;\r
+                               }\r
+                               used->ref_ptr = &used->region->used;\r
+                               put_used_link(used, session);\r
+                       }\r
+                       link_ref_inc(used);\r
+               }\r
+       }\r
 \r
        return 0;\r
 }\r
 \r
+static int vpu_mem_pool_add(vdm_session *session, unsigned int pfn, unsigned int count)\r
+{\r
+       vdm_link *link, *n;\r
+       vdm_pool *pool = kmalloc(sizeof(vdm_pool), GFP_KERNEL);\r
+       DLOG("vpu_mem_pool_add %p pfn %d count %d\n", pool, pfn, count);\r
+       if (NULL == pool) {\r
+               printk(KERN_ALERT "vpu_mem: unable to allocate memory for vpu_mem pool.");\r
+               return -1;\r
+       }\r
+       INIT_LIST_HEAD(&pool->session_link);\r
+       INIT_LIST_HEAD(&pool->list_used);\r
+       pool->session = session;\r
+       pool->pfn = pfn;\r
+       pool->count_target = count;\r
+       pool->count_current = 0;\r
+       pool->count_used = 0;\r
+\r
+       list_for_each_entry_safe(link, n, &session->list_used, session_link) {\r
+               if (pfn == link->pfn && NULL == link->pool) {\r
+                       link->pool = pool;\r
+                       list_add_tail(&link->pool_link, &pool->list_used);\r
+                       pool->count_used++;\r
+                       pool->count_current++;\r
+               }\r
+       }\r
+\r
+       list_add_tail(&pool->session_link, &session->list_pool);\r
+\r
+       return 0;\r
+}\r
+\r
+static void vpu_mem_pool_del(vdm_pool *pool)\r
+{\r
+       vdm_link *link, *n;\r
+       DLOG("vpu_mem_pool_del %p\n", pool);\r
+       list_for_each_entry_safe(link, n, &pool->list_used, pool_link) {\r
+               link->pool = NULL;\r
+               list_del_init(&link->pool_link);\r
+               pool->count_current--;\r
+               pool->count_used--;\r
+       }\r
+       return ;\r
+}\r
+\r
+static int vpu_mem_pool_set(struct file *file, unsigned int pfn, unsigned int count)\r
+{\r
+       int ret = 0;\r
+       vdm_session *session = (vdm_session *)file->private_data;\r
+       vdm_pool *pool = find_pool_by_pfn(session, pfn);\r
+       if (NULL == pool) {\r
+               // no pool build pool first\r
+               ret = vpu_mem_pool_add(session, pfn, count);\r
+       } else {\r
+               pool->count_target += count;\r
+       }\r
+       return ret;\r
+}\r
+\r
+static int vpu_mem_pool_unset(struct file *file, unsigned int pfn, unsigned int count)\r
+{\r
+       int ret = 0;\r
+       vdm_session *session = (vdm_session *)file->private_data;\r
+       vdm_pool *pool = find_pool_by_pfn(session, pfn);\r
+       if (pool) {\r
+               pool->count_target -= count;\r
+               if (pool->count_target <= 0) {\r
+                       vpu_mem_pool_del(pool);\r
+                       pool->count_target = 0;\r
+               }\r
+       }\r
+       return ret;\r
+}\r
+\r
+static int vpu_mem_pool_check(struct file *file, unsigned int pfn)\r
+{\r
+       int ret = 0;\r
+       vdm_session *session = (vdm_session *)file->private_data;\r
+       vdm_pool *pool = find_pool_by_pfn(session, pfn);\r
+       if (pool) {\r
+               if (pool->count_current > pool->count_target) {\r
+                       ret = 1;\r
+               }\r
+               DLOG("vpu_mem_pool_check pfn %u current %d target %d ret %d\n", pfn, pool->count_current, pool->count_target, ret);\r
+       }\r
+       return ret;\r
+}\r
+\r
 void vpu_mem_cache_opt(struct file *file, long index, unsigned int cmd)\r
 {\r
        vdm_session *session = (vdm_session *)file->private_data;\r
@@ -815,32 +985,32 @@ void vpu_mem_cache_opt(struct file *file, long index, unsigned int cmd)
                return;\r
 \r
        down_read(&vdm_rwsem);\r
-    do {\r
-        vdm_link *link = find_used_link(session, index);\r
-        if (NULL == link) {\r
-            pr_err("vpu_mem_cache_opt on non-exsist index %ld\n", index);\r
-            break;\r
-        }\r
-        start = vpu_mem.vbase + index * VPU_MEM_MIN_ALLOC;\r
-        end   = start + link->pfn * VPU_MEM_MIN_ALLOC;;\r
-        switch (cmd) {\r
-        case VPU_MEM_CACHE_FLUSH : {\r
-            dmac_flush_range(start, end);\r
-            break;\r
-        }\r
-        case VPU_MEM_CACHE_CLEAN : {\r
-            dmac_clean_range(start, end);\r
-            break;\r
-        }\r
-        case VPU_MEM_CACHE_INVALID : {\r
-            dmac_inv_range(start, end);\r
-            break;\r
-        }\r
-        default :\r
-            break;\r
-        }\r
-    } while (0);\r
-    up_read(&vdm_rwsem);\r
+       do {\r
+               vdm_link *link = find_used_link(session, index);\r
+               if (NULL == link) {\r
+                       pr_err("vpu_mem_cache_opt on non-exsist index %ld\n", index);\r
+                       break;\r
+               }\r
+               start = vpu_mem.vbase + index * VPU_MEM_MIN_ALLOC;\r
+               end   = start + link->pfn * VPU_MEM_MIN_ALLOC;;\r
+               switch (cmd) {\r
+               case VPU_MEM_CACHE_FLUSH : {\r
+                       dmac_flush_range(start, end);\r
+                       break;\r
+               }\r
+               case VPU_MEM_CACHE_CLEAN : {\r
+                       dmac_clean_range(start, end);\r
+                       break;\r
+               }\r
+               case VPU_MEM_CACHE_INVALID : {\r
+                       dmac_inv_range(start, end);\r
+                       break;\r
+               }\r
+               default :\r
+               break;\r
+               }\r
+       } while (0);\r
+       up_read(&vdm_rwsem);\r
 }\r
 \r
 static pgprot_t vpu_mem_phys_mem_access_prot(struct file *file, pgprot_t vma_prot)\r
@@ -888,6 +1058,7 @@ static int vpu_mem_open(struct inode *inode, struct file *file)
     session->pid = current->pid;\r
     INIT_LIST_HEAD(&session->list_post);\r
     INIT_LIST_HEAD(&session->list_used);\r
+    INIT_LIST_HEAD(&session->list_pool);\r
 \r
     file->private_data = session;\r
 \r
@@ -899,7 +1070,7 @@ static int vpu_mem_open(struct inode *inode, struct file *file)
 \r
 static int vpu_mem_mmap(struct file *file, struct vm_area_struct *vma)\r
 {\r
-    vdm_session *session;\r
+       vdm_session *session;\r
        unsigned long vma_size =  vma->vm_end - vma->vm_start;\r
        int ret = 0;\r
 \r
@@ -911,7 +1082,7 @@ static int vpu_mem_mmap(struct file *file, struct vm_area_struct *vma)
 \r
        session = (vdm_session *)file->private_data;\r
 \r
-    /* assert: vma_size must be the total size of the vpu_mem */\r
+       /* assert: vma_size must be the total size of the vpu_mem */\r
        if (vpu_mem.size != vma_size) {\r
                printk(KERN_WARNING "vpu_mem: mmap size [%lu] does not match"\r
                       "size of backing region [%lu].\n", vma_size, vpu_mem.size);\r
@@ -948,31 +1119,15 @@ static int vpu_mem_release(struct inode *inode, struct file *file)
 \r
         list_for_each_entry_safe(link, tmp_link, &session->list_post, session_link) {\r
             do {\r
-                link->link_post--;\r
-                link->region->post--;\r
-            } while (link->link_post);\r
-            if (find_free_link(link->index)) {\r
-                link_del(link);\r
-            } else {\r
-                put_free_link(link);\r
-            }\r
-            if (is_free_region(link->region)) {\r
-                merge_free_region_and_link(link->region);\r
-            }\r
+               link_ref_dec(link);\r
+            } while (link->ref.post);\r
+           link_del(link);\r
         }\r
         list_for_each_entry_safe(link, tmp_link, &session->list_used, session_link) {\r
             do {\r
-                link->link_used--;\r
-                link->region->used--;\r
-            } while (link->link_used);\r
-            if (find_free_link(link->index)) {\r
-                link_del(link);\r
-            } else {\r
-                put_free_link(link);\r
-            }\r
-            if (is_free_region(link->region)) {\r
-                merge_free_region_and_link(link->region);\r
-            }\r
+               link_ref_dec(link);\r
+            } while (link->ref.used);\r
+           link_del(link);\r
         }\r
     }\r
     up_write(&vdm_rwsem);\r
@@ -983,83 +1138,116 @@ static int vpu_mem_release(struct inode *inode, struct file *file)
 \r
 static long vpu_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
 {\r
-    long index, ret = 0;\r
+       long index, ret = 0;\r
 \r
        switch (cmd) {\r
-       case VPU_MEM_GET_PHYS:\r
+       case VPU_MEM_GET_PHYS: {\r
                DLOG("get_phys\n");\r
                printk(KERN_INFO "vpu_mem: request for physical address of vpu_mem region "\r
                                "from process %d.\n", current->pid);\r
                if (copy_to_user((void __user *)arg, &vpu_mem.base, sizeof(vpu_mem.base)))\r
-                       return -EFAULT;\r
-               break;\r
-       case VPU_MEM_GET_TOTAL_SIZE:\r
+               return -EFAULT;\r
+       } break;\r
+       case VPU_MEM_GET_TOTAL_SIZE: {\r
                DLOG("get total size\n");\r
                if (copy_to_user((void __user *)arg, &vpu_mem.size, sizeof(vpu_mem.size)))\r
                        return -EFAULT;\r
-               break;\r
-    case VPU_MEM_ALLOCATE:\r
+       } break;\r
+       case VPU_MEM_ALLOCATE: {\r
+               unsigned int size;\r
                DLOG("allocate\n");\r
-        {\r
-            unsigned int size;\r
-            if (copy_from_user(&size, (void __user *)arg, sizeof(size)))\r
-                return -EFAULT;\r
-            down_write(&vdm_rwsem);\r
-            ret = vpu_mem_allocate(file, size);\r
-            up_write(&vdm_rwsem);\r
-            DLOG("allocate at index %ld\n", ret);\r
-            break;\r
-        }\r
-    case VPU_MEM_FREE:\r
-        DLOG("mem free\n");\r
-        {\r
-            if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
-                return -EFAULT;\r
-            if (index >= vpu_mem.size)\r
-                return -EACCES;\r
-            down_write(&vdm_rwsem);\r
-            ret = vpu_mem_free(file, index);\r
-            up_write(&vdm_rwsem);\r
-            break;\r
-        }\r
+               if (copy_from_user(&size, (void __user *)arg, sizeof(size)))\r
+               return -EFAULT;\r
+               down_write(&vdm_rwsem);\r
+               ret = vpu_mem_allocate(file, size);\r
+               up_write(&vdm_rwsem);\r
+               DLOG("allocate at index %ld\n", ret);\r
+       } break;\r
+       case VPU_MEM_FREE: {\r
+               DLOG("mem free\n");\r
+               if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
+                       return -EFAULT;\r
+               if (index >= vpu_mem.size)\r
+                       return -EACCES;\r
+               down_write(&vdm_rwsem);\r
+               ret = vpu_mem_free(file, index);\r
+               up_write(&vdm_rwsem);\r
+       } break;\r
+\r
        case VPU_MEM_CACHE_FLUSH:\r
-    case VPU_MEM_CACHE_CLEAN:\r
-    case VPU_MEM_CACHE_INVALID:\r
-        DLOG("flush\n");\r
-               {\r
-                       if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
-                               return -EFAULT;\r
-            if (index < 0)\r
-                return -EINVAL;\r
-                       vpu_mem_cache_opt(file, index, cmd);\r
-                       break;\r
-               }\r
-       case VPU_MEM_DUPLICATE:\r
-        DLOG("duplicate\n");\r
-               {\r
-                       if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
-                               return -EFAULT;\r
-            down_write(&vdm_rwsem);\r
-                       ret = vpu_mem_duplicate(file, index);\r
-            up_write(&vdm_rwsem);\r
-                       break;\r
-               }\r
-       case VPU_MEM_LINK:\r
-        DLOG("link\n");\r
-               {\r
-                       if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
-                               return -EFAULT;\r
-            down_write(&vdm_rwsem);\r
-                       ret = vpu_mem_link(file, index);\r
-            up_write(&vdm_rwsem);\r
-                       break;\r
-               }\r
+       case VPU_MEM_CACHE_CLEAN:\r
+       case VPU_MEM_CACHE_INVALID: {\r
+               DLOG("flush\n");\r
+               if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
+                       return -EFAULT;\r
+               if (index < 0)\r
+                       return -EINVAL;\r
+               vpu_mem_cache_opt(file, index, cmd);\r
+       } break;\r
+       case VPU_MEM_DUPLICATE: {\r
+               DLOG("duplicate\n");\r
+               if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
+                       return -EFAULT;\r
+               down_write(&vdm_rwsem);\r
+               ret = vpu_mem_duplicate(file, index);\r
+               up_write(&vdm_rwsem);\r
+       } break;\r
+\r
+       case VPU_MEM_LINK: {\r
+               DLOG("link\n");\r
+               if (copy_from_user(&index, (void __user *)arg, sizeof(index)))\r
+                       return -EFAULT;\r
+               down_write(&vdm_rwsem);\r
+               ret = vpu_mem_link(file, index);\r
+               up_write(&vdm_rwsem);\r
+       } break;\r
+\r
+       case VPU_MEM_POOL_SET: {\r
+               struct vpu_mem_pool_config config;\r
+               DLOG("pool set\n");\r
+               if (copy_from_user(&config, (void __user *)arg, sizeof(config)))\r
+                       return -EFAULT;\r
+               config.size = (config.size + VPU_MEM_MIN_ALLOC - 1)/VPU_MEM_MIN_ALLOC;\r
+               down_write(&vdm_rwsem);\r
+               ret = vpu_mem_pool_set(file, config.size, config.count);\r
+               up_write(&vdm_rwsem);\r
+       } break;\r
+\r
+       case VPU_MEM_POOL_UNSET: {\r
+               struct vpu_mem_pool_config config;\r
+               DLOG("pool unset\n");\r
+               if (copy_from_user(&config, (void __user *)arg, sizeof(config)))\r
+                       return -EFAULT;\r
+               config.size = (config.size + VPU_MEM_MIN_ALLOC - 1)/VPU_MEM_MIN_ALLOC;\r
+               down_write(&vdm_rwsem);\r
+               ret = vpu_mem_pool_unset(file, config.size, config.count);\r
+               up_write(&vdm_rwsem);\r
+       } break;\r
+\r
+       case VPU_MEM_POOL_CHECK: {\r
+               int pfn;\r
+               if (copy_from_user(&pfn, (void __user *)arg, sizeof(int)))\r
+                       return -EFAULT;\r
+               pfn = (pfn + VPU_MEM_MIN_ALLOC - 1)/VPU_MEM_MIN_ALLOC;\r
+               DLOG("pool check\n");\r
+               down_write(&vdm_rwsem);\r
+               ret = vpu_mem_pool_check(file, pfn);\r
+               up_write(&vdm_rwsem);\r
+       } break;\r
+\r
        default:\r
                return -EINVAL;\r
        }\r
        return ret;\r
 }\r
 \r
+struct file_operations vpu_mem_fops = {\r
+       .open = vpu_mem_open,\r
+       .mmap = vpu_mem_mmap,\r
+       .unlocked_ioctl = vpu_mem_ioctl,\r
+       .release = vpu_mem_release,\r
+};\r
+\r
 #if VPU_MEM_DEBUG\r
 static ssize_t debug_open(struct inode *inode, struct file *file)\r
 {\r
@@ -1230,6 +1418,7 @@ static int proc_vpu_mem_show(struct seq_file *s, void *v)
     down_read(&vdm_rwsem);\r
     {\r
         vdm_link    *link, *tmp_link;\r
+        vdm_pool    *pool, *tmp_pool;\r
         vdm_region  *region, *tmp_region;\r
         vdm_session *session, *tmp_session;\r
         // °´ index ´òÓ¡È«²¿ region\r
@@ -1244,7 +1433,7 @@ static int proc_vpu_mem_show(struct seq_file *s, void *v)
             seq_printf(s, "free :\n");\r
             list_for_each_entry_safe(link, tmp_link, &vdm_free, status_link) {\r
                 seq_printf(s, "       idx %6d pfn %6d used %3d post %3d\n",\r
-                    link->index, link->pfn, link->link_used, link->link_post);\r
+                    link->index, link->pfn, link->ref.used, link->ref.post);\r
             }\r
         }\r
         if (list_empty(&vdm_used)) {\r
@@ -1253,7 +1442,7 @@ static int proc_vpu_mem_show(struct seq_file *s, void *v)
             seq_printf(s, "used :\n");\r
             list_for_each_entry_safe(link, tmp_link, &vdm_used, status_link) {\r
                 seq_printf(s, "       idx %6d pfn %6d used %3d post %3d\n",\r
-                    link->index, link->pfn, link->link_used, link->link_post);\r
+                    link->index, link->pfn, link->ref.used, link->ref.post);\r
             }\r
         }\r
         if (list_empty(&vdm_post)) {\r
@@ -1262,20 +1451,29 @@ static int proc_vpu_mem_show(struct seq_file *s, void *v)
             seq_printf(s, "post :\n");\r
             list_for_each_entry_safe(link, tmp_link, &vdm_post, status_link) {\r
                 seq_printf(s, "       idx %6d pfn %6d used %3d post %3d\n",\r
-                    link->index, link->pfn, link->link_used, link->link_post);\r
+                    link->index, link->pfn, link->ref.used, link->ref.post);\r
             }\r
         }\r
 \r
         // ´òÓ¡ vpu_mem_info ÖеÄÈ«²¿ session µÄ region Õ¼ÓÃÇé¿ö\r
         list_for_each_entry_safe(session, tmp_session, &vdm_proc, list_session) {\r
             seq_printf(s, "\npid: %d\n", session->pid);\r
+            if (list_empty(&session->list_pool)) {\r
+                seq_printf(s, "pool : empty\n");\r
+            } else {\r
+                seq_printf(s, "pool :\n");\r
+                list_for_each_entry_safe(pool, tmp_pool, &session->list_pool, session_link) {\r
+                    seq_printf(s, "       pfn %6d target %4d current %2d\n",\r
+                        pool->pfn, pool->count_target, pool->count_current);\r
+                }\r
+            }\r
             if (list_empty(&session->list_used)) {\r
                 seq_printf(s, "used : empty\n");\r
             } else {\r
                 seq_printf(s, "used :\n");\r
                 list_for_each_entry_safe(link, tmp_link, &session->list_used, session_link) {\r
                     seq_printf(s, "       idx %6d pfn %6d used %3d\n",\r
-                        link->index, link->pfn, link->link_used);\r
+                        link->index, link->pfn, link->ref.used);\r
                 }\r
             }\r
             if (list_empty(&session->list_post)) {\r
@@ -1284,7 +1482,7 @@ static int proc_vpu_mem_show(struct seq_file *s, void *v)
                 seq_printf(s, "post :\n");\r
                 list_for_each_entry_safe(link, tmp_link, &session->list_post, session_link) {\r
                     seq_printf(s, "       idx %6d pfn %6d post %3d\n",\r
-                        link->index, link->pfn, link->link_post);\r
+                        link->index, link->pfn, link->ref.post);\r
                 }\r
             }\r
         }\r