Loading drivers/soc/qcom/memshare/msm_memshare.c +132 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "heap_mem_ext_v01.h" #include <soc/qcom/secure_buffer.h> #include <soc/qcom/ramdump.h> /* Macros */ #define MEMSHARE_DEV_NAME "memshare" Loading @@ -37,6 +38,7 @@ static void mem_share_svc_recv_msg(struct work_struct *work); static DECLARE_DELAYED_WORK(work_recv_msg, mem_share_svc_recv_msg); static struct workqueue_struct *mem_share_svc_workqueue; static uint64_t bootup_request; static void *memshare_ramdump_dev[MAX_CLIENTS]; /* Memshare Driver Structure */ struct memshare_driver { Loading Loading @@ -114,9 +116,37 @@ static struct msg_desc mem_share_svc_size_query_resp_desc = { .ei_array = mem_query_size_resp_msg_data_v01_ei, }; /* * This API creates ramdump dev handlers * for each of the memshare clients. * These dev handlers will be used for * extracting the ramdump for loaned memory * segments. */ static int mem_share_configure_ramdump(void) { char client_name[18] = "memshare_"; char *clnt; clnt = ((!num_clients) ? "GPS" : ((num_clients == 1) ? "FTM" : "DIAG")); snprintf(client_name, 18, "memshare_%s", clnt); memshare_ramdump_dev[num_clients] = create_ramdump_device(client_name, NULL); if (IS_ERR_OR_NULL(memshare_ramdump_dev[num_clients])) { pr_err("memshare: %s: Unable to create memshare ramdump device.\n", __func__); memshare_ramdump_dev[num_clients] = NULL; return -ENOMEM; } return 0; } static int check_client(int client_id, int proc, int request) { int i = 0; int i = 0, rc; int found = DHMS_MEM_CLIENT_INVALID; for (i = 0; i < MAX_CLIENTS; i++) { Loading @@ -127,7 +157,7 @@ static int check_client(int client_id, int proc, int request) } } if ((found == DHMS_MEM_CLIENT_INVALID) && !request) { pr_debug("No registered client, adding a new client\n"); pr_debug("memshare: No registered client, adding a new client\n"); /* Add a new client */ for (i = 0; i < MAX_CLIENTS; i++) { if (memblock[i].client_id == DHMS_MEM_CLIENT_INVALID) { Loading @@ -136,6 +166,16 @@ static int check_client(int client_id, int proc, int request) memblock[i].guarantee = 0; memblock[i].peripheral = proc; found = i; if (!memblock[i].file_created) { rc = mem_share_configure_ramdump(); if (rc) pr_err("In %s, Cannot create ramdump for client: %d\n", __func__, client_id); else memblock[i].file_created = 1; } break; } } Loading Loading @@ -190,10 +230,63 @@ void initialize_client(void) memblock[i].memory_type = MEMORY_CMA; memblock[i].free_memory = 0; memblock[i].hyp_mapping = 0; memblock[i].file_created = 0; } dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); } /* * This API initializes the ramdump segments * with the physical address and size of * the memshared clients. Extraction of ramdump * is skipped if memshare client is not alloted * This calls the ramdump api in extracting the * ramdump in elf format. */ static int mem_share_do_ramdump(void) { int i = 0, ret; char *client_name; for (i = 0; i < num_clients; i++) { struct ramdump_segment *ramdump_segments_tmp = NULL; client_name = (i == 0) ? "GPS" : ((i == 1) ? "FTM" : ((i == 2) ? "DIAG" : "NULL")); if (!memblock[i].alloted) { pr_err("memshare:%s memblock is not alloted\n", client_name); continue; } ramdump_segments_tmp = kcalloc(1, sizeof(struct ramdump_segment), GFP_KERNEL); if (!ramdump_segments_tmp) return -ENOMEM; ramdump_segments_tmp[0].size = memblock[i].size; ramdump_segments_tmp[0].address = memblock[i].phy_addr; pr_debug("memshare: %s:%s client:phy_address = %llx, size = %d\n", __func__, client_name, (unsigned long long) memblock[i].phy_addr, memblock[i].size); ret = do_elf_ramdump(memshare_ramdump_dev[i], ramdump_segments_tmp, 1); if (ret < 0) { pr_err("memshare: Unable to dump: %d\n", ret); kfree(ramdump_segments_tmp); return ret; } kfree(ramdump_segments_tmp); } return 0; } static int modem_notifier_cb(struct notifier_block *this, unsigned long code, void *_cmd) { Loading @@ -202,8 +295,10 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, u32 source_vmlist[2] = {VMID_HLOS, VMID_MSS_MSA}; int dest_vmids[1] = {VMID_HLOS}; int dest_perms[1] = {PERM_READ|PERM_WRITE}; struct notif_data *notifdata = NULL; mutex_lock(&memsh_drv->mem_share); switch (code) { case SUBSYS_BEFORE_SHUTDOWN: Loading Loading @@ -260,6 +355,23 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, bootup_request++; break; case SUBSYS_RAMDUMP_NOTIFICATION: if (_cmd) notifdata = (struct notif_data *) _cmd; else break; if (!(notifdata->enable_ramdump)) { pr_err("In %s, Ramdump collection is disabled\n", __func__); } else { ret = mem_share_do_ramdump(); if (ret) pr_err("Ramdump collection failed\n"); } break; default: pr_debug("Memshare: code: %lu\n", code); break; Loading Loading @@ -800,6 +912,9 @@ static int memshare_child_probe(struct platform_device *pdev) memblock[num_clients].size = size; memblock[num_clients].client_id = client_id; /* * Memshare allocation for guaranteed clients */ if (memblock[num_clients].guarantee) { rc = memshare_alloc(memsh_child->dev, memblock[num_clients].size, Loading @@ -812,6 +927,21 @@ static int memshare_child_probe(struct platform_device *pdev) memblock[num_clients].alloted = 1; } /* * call for creating ramdump dev handlers for * memshare clients */ if (!memblock[num_clients].file_created) { rc = mem_share_configure_ramdump(); if (rc) pr_err("In %s, cannot collect dumps for client id: %d\n", __func__, memblock[num_clients].client_id); else memblock[num_clients].file_created = 1; } num_clients++; return 0; Loading drivers/soc/qcom/memshare/msm_memshare.h +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,9 @@ struct mem_blocks { uint8_t free_memory; /* Need Hypervisor mapping*/ uint8_t hyp_mapping; /* Status flag which checks if ramdump file is created*/ int file_created; }; int memshare_alloc(struct device *dev, Loading Loading
drivers/soc/qcom/memshare/msm_memshare.c +132 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "heap_mem_ext_v01.h" #include <soc/qcom/secure_buffer.h> #include <soc/qcom/ramdump.h> /* Macros */ #define MEMSHARE_DEV_NAME "memshare" Loading @@ -37,6 +38,7 @@ static void mem_share_svc_recv_msg(struct work_struct *work); static DECLARE_DELAYED_WORK(work_recv_msg, mem_share_svc_recv_msg); static struct workqueue_struct *mem_share_svc_workqueue; static uint64_t bootup_request; static void *memshare_ramdump_dev[MAX_CLIENTS]; /* Memshare Driver Structure */ struct memshare_driver { Loading Loading @@ -114,9 +116,37 @@ static struct msg_desc mem_share_svc_size_query_resp_desc = { .ei_array = mem_query_size_resp_msg_data_v01_ei, }; /* * This API creates ramdump dev handlers * for each of the memshare clients. * These dev handlers will be used for * extracting the ramdump for loaned memory * segments. */ static int mem_share_configure_ramdump(void) { char client_name[18] = "memshare_"; char *clnt; clnt = ((!num_clients) ? "GPS" : ((num_clients == 1) ? "FTM" : "DIAG")); snprintf(client_name, 18, "memshare_%s", clnt); memshare_ramdump_dev[num_clients] = create_ramdump_device(client_name, NULL); if (IS_ERR_OR_NULL(memshare_ramdump_dev[num_clients])) { pr_err("memshare: %s: Unable to create memshare ramdump device.\n", __func__); memshare_ramdump_dev[num_clients] = NULL; return -ENOMEM; } return 0; } static int check_client(int client_id, int proc, int request) { int i = 0; int i = 0, rc; int found = DHMS_MEM_CLIENT_INVALID; for (i = 0; i < MAX_CLIENTS; i++) { Loading @@ -127,7 +157,7 @@ static int check_client(int client_id, int proc, int request) } } if ((found == DHMS_MEM_CLIENT_INVALID) && !request) { pr_debug("No registered client, adding a new client\n"); pr_debug("memshare: No registered client, adding a new client\n"); /* Add a new client */ for (i = 0; i < MAX_CLIENTS; i++) { if (memblock[i].client_id == DHMS_MEM_CLIENT_INVALID) { Loading @@ -136,6 +166,16 @@ static int check_client(int client_id, int proc, int request) memblock[i].guarantee = 0; memblock[i].peripheral = proc; found = i; if (!memblock[i].file_created) { rc = mem_share_configure_ramdump(); if (rc) pr_err("In %s, Cannot create ramdump for client: %d\n", __func__, client_id); else memblock[i].file_created = 1; } break; } } Loading Loading @@ -190,10 +230,63 @@ void initialize_client(void) memblock[i].memory_type = MEMORY_CMA; memblock[i].free_memory = 0; memblock[i].hyp_mapping = 0; memblock[i].file_created = 0; } dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); } /* * This API initializes the ramdump segments * with the physical address and size of * the memshared clients. Extraction of ramdump * is skipped if memshare client is not alloted * This calls the ramdump api in extracting the * ramdump in elf format. */ static int mem_share_do_ramdump(void) { int i = 0, ret; char *client_name; for (i = 0; i < num_clients; i++) { struct ramdump_segment *ramdump_segments_tmp = NULL; client_name = (i == 0) ? "GPS" : ((i == 1) ? "FTM" : ((i == 2) ? "DIAG" : "NULL")); if (!memblock[i].alloted) { pr_err("memshare:%s memblock is not alloted\n", client_name); continue; } ramdump_segments_tmp = kcalloc(1, sizeof(struct ramdump_segment), GFP_KERNEL); if (!ramdump_segments_tmp) return -ENOMEM; ramdump_segments_tmp[0].size = memblock[i].size; ramdump_segments_tmp[0].address = memblock[i].phy_addr; pr_debug("memshare: %s:%s client:phy_address = %llx, size = %d\n", __func__, client_name, (unsigned long long) memblock[i].phy_addr, memblock[i].size); ret = do_elf_ramdump(memshare_ramdump_dev[i], ramdump_segments_tmp, 1); if (ret < 0) { pr_err("memshare: Unable to dump: %d\n", ret); kfree(ramdump_segments_tmp); return ret; } kfree(ramdump_segments_tmp); } return 0; } static int modem_notifier_cb(struct notifier_block *this, unsigned long code, void *_cmd) { Loading @@ -202,8 +295,10 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, u32 source_vmlist[2] = {VMID_HLOS, VMID_MSS_MSA}; int dest_vmids[1] = {VMID_HLOS}; int dest_perms[1] = {PERM_READ|PERM_WRITE}; struct notif_data *notifdata = NULL; mutex_lock(&memsh_drv->mem_share); switch (code) { case SUBSYS_BEFORE_SHUTDOWN: Loading Loading @@ -260,6 +355,23 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, bootup_request++; break; case SUBSYS_RAMDUMP_NOTIFICATION: if (_cmd) notifdata = (struct notif_data *) _cmd; else break; if (!(notifdata->enable_ramdump)) { pr_err("In %s, Ramdump collection is disabled\n", __func__); } else { ret = mem_share_do_ramdump(); if (ret) pr_err("Ramdump collection failed\n"); } break; default: pr_debug("Memshare: code: %lu\n", code); break; Loading Loading @@ -800,6 +912,9 @@ static int memshare_child_probe(struct platform_device *pdev) memblock[num_clients].size = size; memblock[num_clients].client_id = client_id; /* * Memshare allocation for guaranteed clients */ if (memblock[num_clients].guarantee) { rc = memshare_alloc(memsh_child->dev, memblock[num_clients].size, Loading @@ -812,6 +927,21 @@ static int memshare_child_probe(struct platform_device *pdev) memblock[num_clients].alloted = 1; } /* * call for creating ramdump dev handlers for * memshare clients */ if (!memblock[num_clients].file_created) { rc = mem_share_configure_ramdump(); if (rc) pr_err("In %s, cannot collect dumps for client id: %d\n", __func__, memblock[num_clients].client_id); else memblock[num_clients].file_created = 1; } num_clients++; return 0; Loading
drivers/soc/qcom/memshare/msm_memshare.h +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,9 @@ struct mem_blocks { uint8_t free_memory; /* Need Hypervisor mapping*/ uint8_t hyp_mapping; /* Status flag which checks if ramdump file is created*/ int file_created; }; int memshare_alloc(struct device *dev, Loading