codec_mm: alloc fail issue [1/2]
authorrongrong zhou <rongrong.zhou@amlogic.com>
Thu, 28 Jun 2018 05:49:54 +0000 (13:49 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Wed, 4 Jul 2018 13:33:38 +0000 (06:33 -0700)
PD#167377

1. try_alloc_cma_size 4M -> 16M
2. dump free meminfo

Change-Id: Ideaf9f70067861d3b08b48336074b32213986cb6
Signed-off-by: rongrong zhou <rongrong.zhou@amlogic.com>
drivers/amlogic/media/common/codec_mm/codec_mm.c
drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c

index 814e545e299206bcc80a1a8e36f5adb38a9b28e0..e6665d306ad2f9102a2bd775c89cdf9d6d9a7bfe 100644 (file)
 #include <linux/genalloc.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
+#include <linux/delay.h>
 
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/codec_mm/codec_mm_scatter.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
+#include <linux/amlogic/media/video_sink/video_keeper.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
 
 #include "codec_mm_priv.h"
 #include "codec_mm_scatter_priv.h"
@@ -50,6 +53,7 @@
 
 
 #define MM_ALIGN_DOWN(addr, size)  ((addr) & (~((size) - 1)))
+#define MM_ALIGN_UP2N(addr, alg2n) ((addr+(1<<alg2n)-1)&(~((1<<alg2n)-1)))
 
 #define RES_IS_MAPED
 #define DEFAULT_TVP_SIZE_FOR_4K (256 * SZ_1M)
@@ -70,6 +74,7 @@
 
 #define RES_MEM_FLAGS_HAVE_MAPED 0x4
 static int dump_mem_infos(void *buf, int size);
+static int dump_free_mem_infos(void *buf, int size);
 
 /*
  *debug_mode:
@@ -577,6 +582,7 @@ struct codec_mm_s *codec_mm_alloc(const char *owner, int size,
                !(memflags & CODEC_MM_FLAGS_FOR_SCATTER)) {
                /*if not scatter, free scatter caches. */
                pr_err(" No mem ret=%d, clear scatter cache!!\n", ret);
+               dump_free_mem_infos(NULL, 0);
                codec_mm_scatter_free_all_ignorecache(1);
                ret = codec_mm_alloc_in(mgt, mem);
        }
@@ -1236,6 +1242,64 @@ static int dump_mem_infos(void *buf, int size)
        return tsize;
 }
 
+
+static int dump_free_mem_infos(void *buf, int size)
+{
+       struct codec_mm_mgt_s *mgt = get_mem_mgt();
+       struct codec_mm_s *mem;
+       unsigned long flags;
+       int i = 0, j, k;
+       unsigned long minphy;
+       u32 cma_base_phy, cma_end_phy;
+       struct dump_buf_s {
+               unsigned long phy_addr;
+               int buffer_size;
+               int align2n;
+       } *usedb, *freeb;
+       int total_free_size = 0;
+
+       usedb = kzalloc(sizeof(struct dump_buf_s) * 256, GFP_KERNEL);
+       if (usedb == NULL)
+               return 0;
+       freeb = usedb + 128;
+
+       spin_lock_irqsave(&mgt->lock, flags);
+       list_for_each_entry(mem, &mgt->mem_list, list) {
+               usedb[i].phy_addr = mem->phy_addr;
+               usedb[i].buffer_size = mem->buffer_size;
+               usedb[i].align2n = mem->align2n;
+               if (++i >= 128) {
+                       pr_info("too many memlist in codec_mm, break;\n");
+                       break;
+               }
+       };
+       cma_base_phy = cma_get_base(dev_get_cma_area(mgt->dev));
+       cma_end_phy = cma_base_phy + dma_get_cma_size_int_byte(mgt->dev);
+       spin_unlock_irqrestore(&mgt->lock, flags);
+       pr_info("free cma idea[%x-%x] from codec_mm items %d\n", cma_base_phy,
+                               cma_end_phy, i);
+       for (j = 0; j < i; j++) { /* free */
+               freeb[j].phy_addr = usedb[j].phy_addr +
+                       MM_ALIGN_UP2N(usedb[j].buffer_size, usedb[j].align2n);
+               minphy = cma_end_phy;
+               for (k = 0; k < i; k++) { /* used */
+                       if (usedb[k].phy_addr >= freeb[j].phy_addr &&
+                                               usedb[k].phy_addr < minphy)
+                               minphy = usedb[k].phy_addr;
+               }
+               freeb[j].buffer_size = minphy - freeb[j].phy_addr;
+               total_free_size += freeb[j].buffer_size;
+               if (freeb[j].buffer_size > 0)
+                       pr_info("\t[%d] free buf phyaddr=%p, used [%p,%x], size=%x\n",
+                               j, (void *)freeb[j].phy_addr,
+                               (void *)usedb[j].phy_addr,
+                               usedb[j].buffer_size, freeb[j].buffer_size);
+       }
+       pr_info("total_free_size %x\n", total_free_size);
+       kfree(usedb);
+       return 0;
+}
+
 int codec_mm_video_tvp_enabled(void)
 {
        struct codec_mm_mgt_s *mgt = get_mem_mgt();
@@ -1306,6 +1370,7 @@ int codec_mm_enough_for_size(int size, int with_wait)
                        return 1;
                if (debug_mode & 0x20)
                        dump_mem_infos(NULL, 0);
+               msleep(50);
                return 0;
        }
        return 1;
@@ -1711,6 +1776,9 @@ static ssize_t codec_mm_debug_store(struct class *class,
        case 11:
                dump_mem_infos(NULL, 0);
                break;
+       case 12:
+               dump_free_mem_infos(NULL, 0);
+               break;
        case 20: {
                int cmd, len;
                unsigned int addr;
index b17e3d101b0a13a9cb4c07133622fc04f5dbc8cd..1f3e023d26ceb9bf43a9deb4ec083b01aa617933 100644 (file)
@@ -385,6 +385,44 @@ void codec_mm_clear_alloc_infos(void)
        codec_mm_clear_alloc_infos_in(codec_mm_get_scatter_mgt(1));
 }
 
+#if 0
+static int codec_mm_slot_get_info(struct codec_mm_scatter_mgt *smgt,
+                       int *free_pages, int *slot_num, int *max_sg_pages)
+{
+       struct codec_mm_slot *slot;
+       int total_pages = 0;
+       int alloced_pages = 0;
+       int slot_used_num = 0;
+       int max_free_pages_sg = 0;
+
+       codec_mm_list_lock(smgt);
+       if (!list_empty(&smgt->free_list)) {
+               struct list_head *header, *list;
+
+               header = &smgt->free_list;
+               list = header->prev;
+               while (list != header) {
+                       slot = list_entry(list, struct codec_mm_slot,
+                               free_list);
+                       total_pages += slot->page_num;
+                       alloced_pages += slot->alloced_page_num;
+                       slot_used_num++;
+                       if (slot->page_num - slot->alloced_page_num >
+                                       max_free_pages_sg)
+                               max_free_pages_sg = slot->page_num -
+                                       slot->alloced_page_num;
+                       list = list->prev;
+               };
+       }
+       codec_mm_list_unlock(smgt);
+       if (total_pages < alloced_pages)
+               return 0;
+       *free_pages = total_pages - alloced_pages;
+       *slot_num = slot_used_num;
+       *max_sg_pages = max_free_pages_sg;
+       return 0;
+}
+#endif
 
 static int codec_mm_set_slot_in_hash(
        struct codec_mm_scatter_mgt *smgt,
@@ -882,10 +920,19 @@ static int codec_mm_page_alloc_from_slot(
                        /*codec_mm_scatter_info_dump(NULL, 0);*/
                        slot = codec_mm_slot_alloc(smgt, 0, 0);
                        if (!slot) {
+                               u32 alloc_pages =
+                                        smgt->try_alloc_in_cma_page_cnt/4;
                                /*
                                   *ERR_LOG("can't alloc slot from system\n");
                                 */
-                               break;
+                               pr_info("alloc default cma size fail, try %d pages\n",
+                                               alloc_pages);
+                               slot = codec_mm_slot_alloc(smgt,
+                                        alloc_pages * PAGE_SIZE, 0);
+                               if (!slot) {
+                                       pr_info("slot alloc 4M fail!\n");
+                                       break;
+                               }
                        }
                }
                codec_mm_list_lock(smgt);
@@ -2432,6 +2479,8 @@ static int codec_mm_scatter_free_all_ignorecache_in(
                smgt->cached_pages = 0;
                codec_mm_list_unlock(smgt);
                if (mms) {
+                       pr_info("cache_sc page_max %d, page_used %d\n",
+                                       mms->page_max_cnt, mms->page_used);
                        codec_mm_scatter_dec_owner_user(mms, 0);
                        codec_mm_scatter_free_on_nouser(smgt, mms);
                }
@@ -2502,7 +2551,7 @@ static int codec_mm_scatter_mgt_alloc_in(struct codec_mm_scatter_mgt **psmgt)
        spin_lock_init(&smgt->list_lock);
        smgt->tag = SMGT_IDENTIFY_TAG;
        smgt->alloced_page_num = 0;
-       smgt->try_alloc_in_cma_page_cnt = (4 * 1024 * 1024) / PAGE_SIZE;
+       smgt->try_alloc_in_cma_page_cnt = (16 * 1024 * 1024) / PAGE_SIZE;
        smgt->try_alloc_in_sys_page_cnt_max = MAX_SYS_BLOCK_PAGE;
        smgt->try_alloc_in_sys_page_cnt = MAX_SYS_BLOCK_PAGE;
        smgt->try_alloc_in_sys_page_cnt_min = MIN_SYS_BLOCK_PAGE;