mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
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 <quic_eberman@quicinc.com> Signed-off-by: Srinivasarao Pathipati <quic_c_spathi@quicinc.com>
This commit is contained in:
parent
840766fa59
commit
faf7c82fab
1 changed files with 19 additions and 56 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue