summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatish Paran <kparan@codeaurora.org>2015-10-28 18:43:35 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:08:14 -0700
commit4f3f0f26a76487be8f9bcf212153a56c5364d7ae (patch)
tree40c2c979a942c8f628a19c2ec8b1b8062283f16e
parent3565c0340c40306ea973a264e9eaa27036ec9b49 (diff)
memshare: Release the memory only if no allocation is done
Currently, memshare relies on the system monitor only for releasing memory for the allocated clients. It may happen that XPU is still intact on the modem side while driver tries to release the memory. This patch ensures that memory release only happens if XPU is released. Change-Id: I45716c0abe6bc08559854782ff73a332e148a7cb Signed-off-by: Katish Paran <kparan@codeaurora.org>
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.c68
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.h10
2 files changed, 48 insertions, 30 deletions
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index 50f3aeb0b4f0..a0f768401415 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -34,6 +34,7 @@ static struct qmi_handle *mem_share_svc_handle;
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;
/* Memshare Driver Structure */
struct memshare_driver {
@@ -156,25 +157,6 @@ void free_client(int id)
}
-void free_mem_clients(int proc)
-{
- int i;
-
- pr_debug("memshare: freeing clients\n");
-
- for (i = 0; i < MAX_CLIENTS; i++) {
- if (memblock[i].peripheral == proc &&
- !memblock[i].guarantee && memblock[i].alloted) {
- pr_debug("Freeing memory for client id: %d\n",
- memblock[i].client_id);
- dma_free_attrs(memsh_drv->dev, memblock[i].size,
- memblock[i].virtual_addr, memblock[i].phy_addr,
- &attrs);
- free_client(i);
- }
- }
-}
-
void fill_alloc_response(struct mem_alloc_generic_resp_msg_v01 *resp,
int id, int *flag)
{
@@ -208,6 +190,7 @@ void initialize_client(void)
memblock[i].peripheral = -1;
memblock[i].sequence_id = -1;
memblock[i].memory_type = MEMORY_CMA;
+ memblock[i].free_memory = 0;
}
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
}
@@ -215,13 +198,42 @@ void initialize_client(void)
static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
void *_cmd)
{
- pr_debug("memshare: Modem notification\n");
+ int i;
switch (code) {
+ case SUBSYS_BEFORE_SHUTDOWN:
+ bootup_request++;
+ break;
+
case SUBSYS_AFTER_POWERUP:
- pr_err("memshare: Modem Restart has happened\n");
- free_mem_clients(DHMS_MEM_PROC_MPSS_V01);
+ pr_debug("memshare: Modem has booted up\n");
+ for (i = 0; i < MAX_CLIENTS; i++) {
+ if (memblock[i].free_memory > 0 &&
+ bootup_request >= 2) {
+ memblock[i].free_memory -= 1;
+ pr_debug("memshare: free_memory count: %d for clinet id: %d\n",
+ memblock[i].free_memory,
+ memblock[i].client_id);
+ }
+
+ if (memblock[i].free_memory == 0) {
+ if (memblock[i].peripheral ==
+ DHMS_MEM_PROC_MPSS_V01 &&
+ !memblock[i].guarantee &&
+ memblock[i].alloted) {
+ pr_err("memshare: Freeing memory for client id: %d\n",
+ memblock[i].client_id);
+ dma_free_attrs(memsh_drv->dev,
+ memblock[i].size,
+ memblock[i].virtual_addr,
+ memblock[i].phy_addr,
+ &attrs);
+ free_client(i);
+ }
+ }
+ }
+ bootup_request++;
break;
default:
@@ -287,7 +299,7 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
int client_id;
alloc_req = (struct mem_alloc_generic_req_msg_v01 *)req;
- pr_debug("alloc request client id: %d proc _id: %d\n",
+ pr_debug("memshare: alloc request client id: %d proc _id: %d\n",
alloc_req->client_id, alloc_req->proc_id);
mutex_lock(&memsh_drv->mem_share);
alloc_resp = kzalloc(sizeof(struct mem_alloc_generic_resp_msg_v01),
@@ -308,6 +320,10 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
return -EINVAL;
}
+ memblock[client_id].free_memory += 1;
+ pr_debug("memshare: In %s, free memory count for client id: %d = %d",
+ __func__, memblock[client_id].client_id,
+ memblock[client_id].free_memory);
if (!memblock[client_id].alloted) {
rc = memshare_alloc(memsh_drv->dev, alloc_req->num_bytes,
&memblock[client_id]);
@@ -384,7 +400,7 @@ static int handle_free_generic_req(void *req_h, void *req, void *conn_h)
uint32_t client_id;
free_req = (struct mem_free_generic_req_msg_v01 *)req;
- pr_debug("%s: Received Free Request\n", __func__);
+ pr_debug("memshare: %s: Received Free Request\n", __func__);
mutex_lock(&memsh_drv->mem_free);
memset(&free_resp, 0, sizeof(struct mem_free_generic_resp_msg_v01));
free_resp.resp.error = QMI_ERR_INTERNAL_V01;
@@ -448,7 +464,7 @@ static int handle_query_size_req(void *req_h, void *req, void *conn_h)
mutex_unlock(&memsh_drv->mem_share);
return -ENOMEM;
}
- pr_debug("query request client id: %d proc _id: %d\n",
+ pr_debug("memshare: query request client id: %d proc _id: %d\n",
query_req->client_id, query_req->proc_id);
client_id = check_client(query_req->client_id, query_req->proc_id,
CHECK);
@@ -471,7 +487,7 @@ static int handle_query_size_req(void *req_h, void *req, void *conn_h)
query_resp->resp.error = QMI_ERR_NONE_V01;
mutex_unlock(&memsh_drv->mem_share);
- pr_debug("query_resp.size :%d, alloc_resp.mem_req_result :%lx\n",
+ pr_debug("memshare: query_resp.size :%d, alloc_resp.mem_req_result :%lx\n",
query_resp->size,
(unsigned long int)query_resp->resp.result);
rc = qmi_send_resp_from_cb(mem_share_svc_handle, conn_h, req_h,
diff --git a/drivers/soc/qcom/memshare/msm_memshare.h b/drivers/soc/qcom/memshare/msm_memshare.h
index 6ea44ac8d296..3d2651121079 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.h
+++ b/drivers/soc/qcom/memshare/msm_memshare.h
@@ -40,13 +40,15 @@ struct mem_blocks {
uint32_t alloted;
/* Size required for client */
uint32_t size;
- /* start address of the memory block reserved by server memory
+ /*
+ * start address of the memory block reserved by server memory
* subsystem to client
- */
+ */
phys_addr_t phy_addr;
- /* Virtual address for the physical address allocated
- */
+ /* Virtual address for the physical address allocated */
void *virtual_addr;
+ /* Release memory only when XPU is released*/
+ uint8_t free_memory;
};
int memshare_alloc(struct device *dev,