memshare: Add support to listen to SUBSYS_RAMDUMP_NOTIFICATION
Currently, on modem subsystem restart the area allocated from HLOS to modem at runtime is not captured as part of the ramdump collection.This patch creates separate elf files for all the clients which are using memshare feature for memory allocation which are later used to load as dumps. CRs-Fixed: 1058744 Change-Id: I66436b7c2d9e02658cfc4c195ca78852b09c01f7 Signed-off-by: Manoj Prabhu B <bmanoj@codeaurora.org>
This commit is contained in:
parent
de93e6c399
commit
69fb05e7e5
2 changed files with 160 additions and 2 deletions
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -114,9 +116,51 @@ 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 = NULL;
|
||||
|
||||
switch (num_clients) {
|
||||
case 0:
|
||||
clnt = "GPS";
|
||||
break;
|
||||
case 1:
|
||||
clnt = "FTM";
|
||||
break;
|
||||
case 2:
|
||||
clnt = "DIAG";
|
||||
break;
|
||||
default:
|
||||
pr_info("memshare: no memshare clients registered\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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++) {
|
||||
|
@ -127,7 +171,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) {
|
||||
|
@ -136,6 +180,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;
|
||||
}
|
||||
}
|
||||
|
@ -190,10 +244,75 @@ 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 = NULL;
|
||||
|
||||
for (i = 0; i < num_clients; i++) {
|
||||
|
||||
struct ramdump_segment *ramdump_segments_tmp = NULL;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
client_name = "GPS";
|
||||
break;
|
||||
case 1:
|
||||
client_name = "FTM";
|
||||
break;
|
||||
case 2:
|
||||
client_name = "DIAG";
|
||||
break;
|
||||
default:
|
||||
pr_info("memshare: no memshare clients registered\n");
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -202,8 +321,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:
|
||||
|
@ -260,6 +381,22 @@ 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_info("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;
|
||||
|
@ -800,6 +937,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,
|
||||
|
@ -812,6 +952,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;
|
||||
|
|
|
@ -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…
Add table
Reference in a new issue