[RAMEN9610-10167][COMMON] ASoC: abox: Save abox DRAM memory
authorHyunwoong Kim <khw0178.kim@samsung.com>
Wed, 7 Mar 2018 08:34:34 +0000 (17:34 +0900)
committerhskang <hs1218.kang@samsung.com>
Mon, 31 Dec 2018 06:13:46 +0000 (15:13 +0900)
ABOX reserved memory for saving DRAM was removed.
But dumped DRAM data is important for working out a problem.
This patch allocates actual memory region for saving abox DRAM memory.

Change-Id: Id33aa8c4ce77916e63589b29e8fd7384d07d9432
Signed-off-by: Hyunwoong Kim <khw0178.kim@samsung.com>
sound/soc/samsung/abox/abox_dbg.c

index 0f3a09d6f727c9b2f9fb60824bb4300642fe541d..5a292acf10ea02660b1050d6edc9b85b68c8a3a2 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/of_reserved_mem.h>
 #include <linux/pm_runtime.h>
 #include <linux/sched/clock.h>
+#include <linux/mm_types.h>
+#include <asm/cacheflush.h>
 #include "abox_dbg.h"
 #include "abox_gic.h"
 
@@ -86,6 +88,8 @@ struct abox_dbg_dump {
 struct abox_dbg_dump_min {
        char sram[SZ_512K];
        char iva[IVA_FIRMWARE_SIZE];
+       void *dram;
+       struct page **pages;
        u32 sfr[SZ_64K / sizeof(u32)];
        u32 sfr_gic_gicd[SZ_4K / sizeof(u32)];
        unsigned int gpr[17];
@@ -112,6 +116,39 @@ static int __init abox_rmem_setup(struct reserved_mem *rmem)
 
 RESERVEDMEM_OF_DECLARE(abox_rmem, "exynos,abox_rmem", abox_rmem_setup);
 
+static void *abox_dbg_alloc_mem_atomic(struct device *dev, struct abox_dbg_dump_min *p_dump)
+{
+       int i, j;
+       int npages = DRAM_FIRMWARE_SIZE / PAGE_SIZE;
+       struct page **tmp;
+       gfp_t alloc_gfp_flag = GFP_KERNEL | GFP_ATOMIC;
+
+       p_dump->pages = kzalloc(sizeof(struct page *) * npages, alloc_gfp_flag);
+       if (!p_dump->pages) {
+               dev_info(dev, "Failed to allocate array of struct pages\n");
+               return NULL;
+       }
+
+       tmp = p_dump->pages;
+       for (i = 0; i < npages; i++, tmp++) {
+               *tmp = alloc_page(alloc_gfp_flag);
+               if (*tmp == NULL) {
+                       pr_err("Failed to allocate pages for abox debug\n");
+                       goto free_pg;
+               }
+       }
+
+       return vm_map_ram(p_dump->pages, npages, -1, PAGE_KERNEL);
+
+free_pg:
+       tmp = p_dump->pages;
+       for (j = 0; j < i; j++, tmp++)
+               __free_pages(*tmp, 0);
+       kfree(p_dump->pages);
+       p_dump->pages = NULL;
+       return NULL;
+}
+
 void abox_dbg_dump_gpr_from_addr(struct device *dev, unsigned int *addr,
                enum abox_dbg_dump_src src, const char *reason)
 {
@@ -206,7 +243,6 @@ void abox_dbg_dump_mem(struct device *dev, struct abox_data *data,
                                sizeof(p_dump->sfr_gic_gicd));
        } else if (p_abox_dbg_dump_min) {
                struct abox_dbg_dump_min *p_dump = &(*p_abox_dbg_dump_min)[src];
-
                p_dump->time = sched_clock();
                strncpy(p_dump->reason, reason, sizeof(p_dump->reason) - 1);
                memcpy_fromio(p_dump->sram, data->sram_base, data->sram_size);
@@ -219,6 +255,18 @@ void abox_dbg_dump_mem(struct device *dev, struct abox_data *data,
                memcpy_fromio(p_dump->sfr, data->sfr_base, sizeof(p_dump->sfr));
                memcpy_fromio(p_dump->sfr_gic_gicd, gic_data->gicd_base,
                                sizeof(p_dump->sfr_gic_gicd));
+               if (!p_dump->dram) {
+                       if (src == ABOX_DBG_DUMP_KERNEL)
+                               p_dump->dram = vzalloc(DRAM_FIRMWARE_SIZE);
+                       else if (src == ABOX_DBG_DUMP_FIRMWARE)
+                               p_dump->dram = abox_dbg_alloc_mem_atomic(dev, p_dump);
+               }
+               if (!IS_ERR_OR_NULL(p_dump->dram)) {
+                       memcpy(p_dump->dram, data->dram_base, DRAM_FIRMWARE_SIZE);
+                       flush_cache_all();
+               } else {
+                       dev_info(dev, "Failed to save ABOX dram\n");
+               }
        }
 }
 
@@ -395,6 +443,7 @@ static int samsung_abox_debug_probe(struct platform_device *pdev)
                        abox_rmem->size, 0);
        data->dump_base = phys_to_virt(abox_rmem->base);
        data->dump_base_phys = abox_rmem->base;
+       memset(data->dump_base, 0x0, abox_rmem->size);
        ret = device_create_file(dev, &dev_attr_gpr);
        bin_attr_calliope_sram.size = data->sram_size;
        bin_attr_calliope_sram.private = data->sram_base;
@@ -414,8 +463,26 @@ static int samsung_abox_debug_probe(struct platform_device *pdev)
 static int samsung_abox_debug_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       int i;
 
        dev_dbg(dev, "%s\n", __func__);
+       for (i = 0; i < ABOX_DBG_DUMP_COUNT; i++) {
+               if (i == ABOX_DBG_DUMP_KERNEL) {
+                       vfree(p_abox_dbg_dump_min[i]->dram);
+               } else if (i == ABOX_DBG_DUMP_FIRMWARE) {
+                       struct page **tmp = p_abox_dbg_dump_min[i]->pages;
+                       if (p_abox_dbg_dump_min[i]->dram)
+                               vm_unmap_ram(p_abox_dbg_dump_min[i]->dram,
+                                   DRAM_FIRMWARE_SIZE);
+                       if (tmp) {
+                               int j;
+                               for (j = 0; j < DRAM_FIRMWARE_SIZE / PAGE_SIZE; j++, tmp++)
+                                       __free_pages(*tmp, 0);
+                               kfree(p_abox_dbg_dump_min[i]->pages);
+                               p_abox_dbg_dump_min[i]->pages = NULL;
+                       }
+               }
+       }
 
        return 0;
 }