From faf7c82fabcf97d4abb4eddda18001dda2de93ae Mon Sep 17 00:00:00 2001 From: Srinivasarao Pathipati Date: Mon, 10 Oct 2022 14:30:57 +0530 Subject: [PATCH] virt: haven: rm_core: Always allocate a connection for notifications Currently, there is an optimized path to directly use the message queue buffer when a received notification fits within a single message and there aren't any fragments. This greatly complicates buffer management and might not provide any measurable benefit. Suppose Linux receives a notification with one fragment then a notification with 3 fragments. In current flow, there is 1 alloc for the first notification and 4 allocations for the 2nd notification (1 for each message + 1 for overall combined buffer). In the new flow, we could optimize this to 0 allocations for each message because we can re-use the same message buffer for each fragment and then a single alloc for the entire payload. There is, however, a slightly increased cost for single-message notifications in the form of an extra memcpy from the message buffer to notification buffer. Under the code optimizations and simplifications that come with this cost, it is a worthy cost. Change-Id: Ib52bd332f59b108d7dab9121c0beefed0aa66994 Signed-off-by: Elliot Berman Signed-off-by: Srinivasarao Pathipati --- drivers/virt/haven/hh_rm_core.c | 75 +++++++++------------------------ 1 file changed, 19 insertions(+), 56 deletions(-) diff --git a/drivers/virt/haven/hh_rm_core.c b/drivers/virt/haven/hh_rm_core.c index 157513a1b1ff..c4246b6ca3f6 100644 --- a/drivers/virt/haven/hh_rm_core.c +++ b/drivers/virt/haven/hh_rm_core.c @@ -132,73 +132,36 @@ int hh_rm_unregister_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(hh_rm_unregister_notifier); -static struct hh_rm_connection * -hh_rm_wait_for_notif_fragments(void *recv_buff, size_t recv_buff_size) +static int hh_rm_process_notif(void *msg, size_t msg_size) { - struct hh_rm_rpc_hdr *hdr = recv_buff; + struct hh_rm_rpc_hdr *hdr = msg; struct hh_rm_connection *connection; + u32 notification; size_t payload_size; + void *payload; int ret = 0; - connection = hh_rm_alloc_connection(hdr->msg_id); - if (IS_ERR_OR_NULL(connection)) - return connection; - - payload_size = recv_buff_size - sizeof(*hdr); - curr_connection = connection; - - ret = hh_rm_init_connection_buff(connection, recv_buff, - sizeof(*hdr), payload_size); - if (ret < 0) - goto out; - - if (wait_for_completion_interruptible(&connection->seq_done)) { - ret = -ERESTARTSYS; - goto out; - } - - return connection; - -out: - kfree(connection); - return ERR_PTR(ret); -} - -static int hh_rm_process_notif(void *recv_buff, size_t recv_buff_size) -{ - struct hh_rm_connection *connection = NULL; - struct hh_rm_rpc_hdr *hdr = recv_buff; - u32 notification = hdr->msg_id; - void *payload = NULL; - size_t payload_size; - int ret = 0; - - pr_debug("Notification received from RM-VM: %x\n", notification); - if (curr_connection) { pr_err("Received new notification from RM-VM before completing last connection\n"); return -EINVAL; } - if (recv_buff_size > sizeof(*hdr)) - payload = recv_buff + sizeof(*hdr); + connection = hh_rm_alloc_connection(hdr->msg_id); + if (!connection) + return -EINVAL; - /* If the notification payload is split-up into - * fragments, wait until all them arrive. - */ - if (hdr->fragments) { - connection = hh_rm_wait_for_notif_fragments(recv_buff, - recv_buff_size); - if (IS_ERR_OR_NULL(connection)) - return PTR_ERR(connection); - - /* In the case of fragments, the complete payload - * is contained under connection->recv_buff - */ - payload = connection->recv_buff; - recv_buff_size = connection->recv_buff_size; + if (hh_rm_init_connection_buff(connection, msg, sizeof(*hdr), msg_size - sizeof(*hdr))) { + kfree(connection); + return -EINVAL; } - payload_size = recv_buff_size - sizeof(*hdr); + + if (hdr->fragments) + return PTR_ERR(connection); + + payload = connection->recv_buff; + payload_size = connection->recv_buff_size; + notification = connection->msg_id; + pr_debug("Notification received from RM-VM: %x\n", notification); switch (notification) { case HH_RM_NOTIF_VM_STATUS: @@ -297,7 +260,7 @@ static int hh_rm_process_notif(void *recv_buff, size_t recv_buff_size) err: if (connection) { - kfree(connection->recv_buff); + kfree(payload); kfree(connection); }