mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-13 08:07:32 -04:00
Merge "haven: hh_msgq: Let clients manage the buffers for hh_msgq_send"
This commit is contained in:
commit
f3d61754e3
3 changed files with 77 additions and 27 deletions
|
|
@ -662,10 +662,16 @@ static void mem_buf_alloc_req_work(struct work_struct *work)
|
|||
|
||||
resp_msg->ret = ret;
|
||||
ret = hh_msgq_send(mem_buf_hh_msgq_hdl, resp_msg, sizeof(*resp_msg), 0);
|
||||
|
||||
/*
|
||||
* Free the buffer regardless of the return value as the hypervisor
|
||||
* would have consumed the data in the case of a success.
|
||||
*/
|
||||
kfree(resp_msg);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("%s: failed to send memory allocation response rc: %d\n",
|
||||
__func__, ret);
|
||||
kfree(resp_msg);
|
||||
mutex_lock(&mem_buf_xfer_mem_list_lock);
|
||||
list_del(&xfer_mem->entry);
|
||||
mutex_unlock(&mem_buf_xfer_mem_list_lock);
|
||||
|
|
@ -868,10 +874,15 @@ static int mem_buf_request_mem(struct mem_buf_desc *membuf)
|
|||
}
|
||||
|
||||
ret = mem_buf_msg_send(alloc_req_msg, msg_size);
|
||||
if (ret < 0) {
|
||||
kfree(alloc_req_msg);
|
||||
|
||||
/*
|
||||
* Free the buffer regardless of the return value as the hypervisor
|
||||
* would have consumed the data in the case of a success.
|
||||
*/
|
||||
kfree(alloc_req_msg);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = mem_buf_txn_wait(&txn);
|
||||
if (ret < 0)
|
||||
|
|
@ -897,11 +908,16 @@ static void mem_buf_relinquish_mem(struct mem_buf_desc *membuf)
|
|||
msg->hdl = membuf->memparcel_hdl;
|
||||
|
||||
ret = hh_msgq_send(mem_buf_hh_msgq_hdl, msg, sizeof(*msg), 0);
|
||||
if (ret < 0) {
|
||||
|
||||
/*
|
||||
* Free the buffer regardless of the return value as the hypervisor
|
||||
* would have consumed the data in the case of a success.
|
||||
*/
|
||||
kfree(msg);
|
||||
|
||||
if (ret < 0)
|
||||
pr_err("%s failed to send memory relinquish message rc: %d\n",
|
||||
__func__, ret);
|
||||
kfree(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static int mem_buf_map_mem_s2(struct mem_buf_desc *membuf)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include <linux/haven/hcall.h>
|
||||
#include <linux/haven/hh_msgq.h>
|
||||
|
|
@ -40,6 +41,7 @@ struct hh_msgq_cap_table {
|
|||
wait_queue_head_t rx_wq;
|
||||
};
|
||||
|
||||
static bool hh_msgq_initialized;
|
||||
static struct hh_msgq_cap_table hh_msgq_cap_table[HH_MSGQ_LABEL_MAX];
|
||||
|
||||
static irqreturn_t hh_msgq_rx_isr(int irq, void *dev)
|
||||
|
|
@ -118,6 +120,9 @@ static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry,
|
|||
* if the message queue is not yet ready to communicate, and -EPERM if the
|
||||
* caller doesn't have permissions to receive the data. 0 is the data is
|
||||
* successfully received.
|
||||
*
|
||||
* Note: this function may sleep and should not be called from interrupt
|
||||
* context
|
||||
*/
|
||||
int hh_msgq_recv(void *msgq_client_desc,
|
||||
void **buff, size_t *size, unsigned long flags)
|
||||
|
|
@ -139,15 +144,25 @@ int hh_msgq_recv(void *msgq_client_desc,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (cap_table_entry->rx_cap_id == HH_CAPID_INVAL) {
|
||||
pr_err("%s: Recv info for label %d not yet initialized\n",
|
||||
if ((cap_table_entry->rx_cap_id == HH_CAPID_INVAL) &&
|
||||
(flags & HH_MSGQ_NONBLOCK)) {
|
||||
pr_err_ratelimited(
|
||||
"%s: Recv info for label %d not yet initialized\n",
|
||||
__func__, client_desc->label);
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_unlock(&cap_table_entry->cap_entry_lock);
|
||||
|
||||
if (wait_event_interruptible(cap_table_entry->rx_wq,
|
||||
cap_table_entry->rx_cap_id != HH_CAPID_INVAL))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
spin_lock(&cap_table_entry->cap_entry_lock);
|
||||
|
||||
if (!cap_table_entry->rx_irq) {
|
||||
pr_err("%s: Rx IRQ for label %d not yet setup\n",
|
||||
pr_err_ratelimited("%s: Rx IRQ for label %d not yet setup\n",
|
||||
__func__, client_desc->label);
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
|
|
@ -224,15 +239,12 @@ static int __hh_msgq_send(struct hh_msgq_cap_table *cap_table_entry,
|
|||
/**
|
||||
* hh_msgq_send: Send a message to the client on a different VM
|
||||
* @client_desc: The client descriptor that was obtained via hh_msgq_register()
|
||||
* @buff: Pointer to the buffer that needs to be sent. The buffer should be
|
||||
* dynamically allocated via kmalloc/kzalloc.
|
||||
* @buff: Pointer to the buffer that needs to be sent
|
||||
* @size: The size of the buffer
|
||||
* @flags: Optional flags to pass to send the data. For the list of flags,
|
||||
* see linux/haven/hh_msgq.h
|
||||
*
|
||||
* The function would free the buffer upon success, and returns 0. The caller
|
||||
* should not be referencing the buffer anymore.
|
||||
* On the other hand, it returns -EINVAL if the caller passes invalid arguments,
|
||||
* The function returns -EINVAL if the caller passes invalid arguments,
|
||||
* -EAGAIN if the message queue is not yet ready to communicate, and -EPERM if
|
||||
* the caller doesn't have permissions to send the data.
|
||||
*
|
||||
|
|
@ -260,15 +272,25 @@ int hh_msgq_send(void *msgq_client_desc,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (cap_table_entry->tx_cap_id == HH_CAPID_INVAL) {
|
||||
pr_err("%s: Send info for label %d not yet initialized\n",
|
||||
if ((cap_table_entry->tx_cap_id == HH_CAPID_INVAL) &&
|
||||
(flags & HH_MSGQ_NONBLOCK)) {
|
||||
pr_err_ratelimited(
|
||||
"%s: Send info for label %d not yet initialized\n",
|
||||
__func__, client_desc->label);
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_unlock(&cap_table_entry->cap_entry_lock);
|
||||
|
||||
if (wait_event_interruptible(cap_table_entry->tx_wq,
|
||||
cap_table_entry->tx_cap_id != HH_CAPID_INVAL))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
spin_lock(&cap_table_entry->cap_entry_lock);
|
||||
|
||||
if (!cap_table_entry->tx_irq) {
|
||||
pr_err("%s: Tx IRQ for label %d not yet setup\n",
|
||||
pr_err_ratelimited("%s: Tx IRQ for label %d not yet setup\n",
|
||||
__func__, client_desc->label);
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
|
|
@ -287,12 +309,6 @@ int hh_msgq_send(void *msgq_client_desc,
|
|||
ret = __hh_msgq_send(cap_table_entry, buff, size, flags);
|
||||
} while (ret == -EAGAIN);
|
||||
|
||||
/* If the send is success, hypervisor should not be holding any
|
||||
* references to 'buff', and hence, can be released.
|
||||
*/
|
||||
if (!ret)
|
||||
kfree(buff);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
spin_unlock(&cap_table_entry->cap_entry_lock);
|
||||
|
|
@ -316,6 +332,9 @@ void *hh_msgq_register(enum hh_msgq_label label)
|
|||
struct hh_msgq_cap_table *cap_table_entry;
|
||||
struct hh_msgq_desc *client_desc;
|
||||
|
||||
if (!hh_msgq_initialized)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
if (label < 0 || label >= HH_MSGQ_LABEL_MAX)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
|
@ -393,6 +412,9 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id,
|
|||
struct hh_msgq_cap_table *cap_table_entry;
|
||||
int ret;
|
||||
|
||||
if (!hh_msgq_initialized)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (label < 0 || label >= HH_MSGQ_LABEL_MAX) {
|
||||
pr_err("%s: Invalid label passed\n", __func__);
|
||||
return -EINVAL;
|
||||
|
|
@ -415,6 +437,8 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id,
|
|||
|
||||
cap_table_entry->tx_irq = irq;
|
||||
cap_table_entry->tx_cap_id = cap_id;
|
||||
|
||||
wake_up_interruptible(&cap_table_entry->tx_wq);
|
||||
} else if (direction == HH_MSGQ_DIRECTION_RX) {
|
||||
ret = request_irq(irq, hh_msgq_rx_isr, 0,
|
||||
cap_table_entry->rx_irq_name, cap_table_entry);
|
||||
|
|
@ -423,6 +447,8 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id,
|
|||
|
||||
cap_table_entry->rx_cap_id = cap_id;
|
||||
cap_table_entry->rx_irq = irq;
|
||||
|
||||
wake_up_interruptible(&cap_table_entry->rx_wq);
|
||||
} else {
|
||||
pr_err("%s: Invalid direction passed\n", __func__);
|
||||
ret = -EINVAL;
|
||||
|
|
@ -493,6 +519,7 @@ static int __init hh_msgq_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
hh_msgq_initialized = true;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -518,10 +518,17 @@ static int hh_rm_send_request(u32 message_id,
|
|||
|
||||
ret = hh_msgq_send(hh_rm_msgq_desc, send_buff,
|
||||
sizeof(*hdr) + payload_size, tx_flags);
|
||||
if (ret) {
|
||||
kfree(send_buff);
|
||||
|
||||
/*
|
||||
* In the case of a success, the hypervisor would have consumed
|
||||
* the buffer. While in the case of a failure, we are going to
|
||||
* quit anyways. Hence, free the buffer regardless of the
|
||||
* return value.
|
||||
*/
|
||||
kfree(send_buff);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue