From 63bddcd463fafd4c9567da1ac17ab363f6a8ea16 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Fri, 27 May 2022 12:33:38 -0700 Subject: [PATCH] mem-buf-msgq: Reduce buffer free complexity Reuse the same buffer for each message in mem_buf_msgq_recv_fn() instead of allocating a new one for each message, and freeing it in a dozen different locations depending on what type of message it is. If a consumer of the message needs to defer its work to a workqueue, it must allocate a new copy of the message. Change-Id: Ia5583bc7dc9937211f25624f7a679d34fe8fb521 Signed-off-by: Patrick Daly --- drivers/soc/qcom/mem_buf/mem-buf-gh.c | 27 ++++++++++++++++--------- drivers/soc/qcom/mem_buf/mem-buf-msgq.c | 13 +++++------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/soc/qcom/mem_buf/mem-buf-gh.c b/drivers/soc/qcom/mem_buf/mem-buf-gh.c index 09ed104768d6..85296e0be184 100644 --- a/drivers/soc/qcom/mem_buf/mem-buf-gh.c +++ b/drivers/soc/qcom/mem_buf/mem-buf-gh.c @@ -445,6 +445,7 @@ static void mem_buf_alloc_req_work(struct work_struct *work) } resp_msg = mem_buf_construct_alloc_resp(req_msg, ret, hdl); + kfree(rmt_msg->msg); kfree(rmt_msg); if (IS_ERR(resp_msg)) @@ -510,7 +511,6 @@ static int mem_buf_alloc_resp_hdlr(void *hdlr_data, void *msg_buf, size_t size, trace_receive_alloc_resp_msg(alloc_resp); if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER)) { - kfree(msg_buf); return -EPERM; } @@ -521,23 +521,26 @@ static int mem_buf_alloc_resp_hdlr(void *hdlr_data, void *msg_buf, size_t size, membuf->memparcel_hdl = get_alloc_resp_hdl(alloc_resp); } - kfree(msg_buf); return ret; } /* Functions invoked when treating allocation requests to other VMs. */ -static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *buf, size_t size) +static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *_buf, size_t size) { struct mem_buf_rmt_msg *rmt_msg; + void *buf; if (!(mem_buf_capability & MEM_BUF_CAP_SUPPLIER)) { - kfree(buf); return; } rmt_msg = kmalloc(sizeof(*rmt_msg), GFP_KERNEL); - if (!rmt_msg) { - kfree(buf); + if (!rmt_msg) + return; + + buf = kmemdup(_buf, size, GFP_KERNEL); + if (!buf) { + kfree(rmt_msg); return; } @@ -547,18 +550,22 @@ static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *buf, size_t size) queue_work(mem_buf_wq, &rmt_msg->work); } -static void mem_buf_relinquish_hdlr(void *hdlr_data, void *buf, size_t size) +static void mem_buf_relinquish_hdlr(void *hdlr_data, void *_buf, size_t size) { struct mem_buf_rmt_msg *rmt_msg; + void *buf; if (!(mem_buf_capability & MEM_BUF_CAP_SUPPLIER)) { - kfree(buf); return; } rmt_msg = kmalloc(sizeof(*rmt_msg), GFP_KERNEL); - if (!rmt_msg) { - kfree(buf); + if (!rmt_msg) + return; + + buf = kmemdup(_buf, size, GFP_KERNEL); + if (!buf) { + kfree(rmt_msg); return; } diff --git a/drivers/soc/qcom/mem_buf/mem-buf-msgq.c b/drivers/soc/qcom/mem_buf/mem-buf-msgq.c index 95465d60f313..8130ca1592b1 100644 --- a/drivers/soc/qcom/mem_buf/mem-buf-msgq.c +++ b/drivers/soc/qcom/mem_buf/mem-buf-msgq.c @@ -310,7 +310,6 @@ static void mem_buf_process_alloc_resp(struct mem_buf_msgq_desc *desc, void *buf if (!alloc_resp->ret) { desc->msgq_ops->relinquish_memparcel_hdl(desc->hdlr_data, hdr->txn_id, alloc_resp->hdl); - kfree(buf); } } else { txn->txn_ret = desc->msgq_ops->alloc_resp_hdlr(desc->hdlr_data, buf, size, @@ -328,7 +327,6 @@ static void mem_buf_process_msg(struct mem_buf_msgq_desc *desc, void *buf, size_ if (size < sizeof(*hdr) || hdr->msg_size != size) { pr_err("%s: message received is not of a proper size: 0x%lx\n", __func__, size); - kfree(buf); return; } @@ -345,7 +343,6 @@ static void mem_buf_process_msg(struct mem_buf_msgq_desc *desc, void *buf, size_ default: pr_err("%s: received message of unknown type: %d\n", __func__, hdr->msg_type); - kfree(buf); } } @@ -367,20 +364,20 @@ static int mem_buf_msgq_recv_fn(void *data) size_t size; int ret; - while (!kthread_should_stop()) { - buf = kzalloc(GH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL); - if (!buf) - continue; + buf = kzalloc(GH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL); + if (!buf) + return -ENOMEM; + while (!kthread_should_stop()) { ret = gh_msgq_recv(desc->msgq_hdl, buf, GH_MSGQ_MAX_MSG_SIZE_BYTES, &size, 0); if (ret < 0) { - kfree(buf); pr_err_ratelimited("%s failed to receive message rc: %d\n", __func__, ret); } else { mem_buf_process_msg(desc, buf, size); } } + kfree(buf); return 0; }