Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a3afc52 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "memshare: Add support to listen to SUBSYS_RAMDUMP_NOTIFICATION"

parents 01ab9399 099a932b
Loading
Loading
Loading
Loading
+132 −2
Original line number Diff line number Diff line
@@ -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,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++) {
@@ -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) {
@@ -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;
			}
		}
@@ -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)
{
@@ -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:
@@ -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;
@@ -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,
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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,