Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bdb50ad authored by Raghavendra Rao Ananta's avatar Raghavendra Rao Ananta Committed by Elliot Berman
Browse files

haven: hh_msgq: Let clients manage the buffers for hh_msgq_recv



Currently, the hh_msgq driver allocates the receive-buffer on behalf
of the clients and it's the clients' responsibility to free it.
However, this creates asymmetry in the buffer management and may lead
to confusion. Hence, let the clients take full control of the buffers-
allocation and freeing.

Also make changes to the client driver to adapt to the new hh_msgq_recv
interface.

Change-Id: I95b72621ede5e62411e78e45c36d8a7ff3686bd4
Signed-off-by: default avatarRaghavendra Rao Ananta <rananta@codeaurora.org>
Signed-off-by: default avatarMurali Nalajala <mnalajal@codeaurora.org>
parent b38b5109
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -786,13 +786,20 @@ static int mem_buf_msgq_recv_fn(void *unused)
	int ret;

	while (!kthread_should_stop()) {
		ret = hh_msgq_recv(mem_buf_hh_msgq_hdl, &buf, &size, 0);
		if (ret < 0)
		buf = kzalloc(HH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
		if (!buf)
			continue;

		ret = hh_msgq_recv(mem_buf_hh_msgq_hdl, buf,
					HH_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
		} else {
			mem_buf_process_msg(buf, size);
		}
	}

	return 0;
}
+24 −30
Original line number Diff line number Diff line
@@ -71,7 +71,8 @@ static irqreturn_t hh_msgq_tx_isr(int irq, void *dev)
}

static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry,
				void *buff, size_t *size, u64 rx_flags)
				void *buff, size_t buff_size,
				size_t *recv_size, u64 rx_flags)
{
	struct hh_hcall_msgq_recv_resp resp = {};
	unsigned long flags;
@@ -83,11 +84,11 @@ static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry,

	spin_lock_irqsave(&cap_table_entry->rx_lock, flags);
	hh_ret = hh_hcall_msgq_recv(cap_table_entry->rx_cap_id, buff,
					HH_MSGQ_MAX_MSG_SIZE_BYTES, &resp);
					buff_size, &resp);

	switch (hh_ret) {
	case HH_ERROR_OK:
		*size = resp.recv_size;
		*recv_size = resp.recv_size;
		ret = 0;
		break;
	case HH_ERROR_MSGQUEUE_EMPTY:
@@ -110,30 +111,36 @@ static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry,
/**
 * hh_msgq_recv: Receive a message from the client running on a different VM
 * @client_desc: The client descriptor that was obtained via hh_msgq_register()
 * @buff: Pointer to the buffer where the received data must be placed. Note
 *        that the caller is responsible to free the data contained in buff
 * @size: The size of the buffer received
 * @buff: Pointer to the buffer where the received data must be placed
 * @buff_size: The size of the buffer space available
 * @recv_size: The actual amount of data that is copied into buff
 * @flags: Optional flags to pass to receive the data. For the list of flags,
 *         see linux/haven/hh_msgq.h
 *
 * The function returns -EINVAL if the caller passes invalid arguments, -EAGAIN
 * The function returns 0 if the data is successfully received and recv_size
 * would contain the actual amount of data copied into buff.
 * It 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 receive the data. 0 is the data is
 * successfully received.
 * caller doesn't have permissions to receive the data. In all these failure
 * cases, recv_size is unmodified.
 *
 * 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)
			void *buff, size_t buff_size,
			size_t *recv_size, unsigned long flags)
{
	struct hh_msgq_desc *client_desc = msgq_client_desc;
	struct hh_msgq_cap_table *cap_table_entry;
	int ret;

	if (!client_desc || !(*buff) || !size)
	if (!client_desc || !buff || !buff_size || !recv_size)
		return -EINVAL;

	if (buff_size > HH_MSGQ_MAX_MSG_SIZE_BYTES)
		return -E2BIG;

	cap_table_entry = &hh_msgq_cap_table[client_desc->label];

	spin_lock(&cap_table_entry->cap_entry_lock);
@@ -170,31 +177,18 @@ int hh_msgq_recv(void *msgq_client_desc,

	spin_unlock(&cap_table_entry->cap_entry_lock);

	*buff = kzalloc(HH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
	if (!(*buff))
		return -ENOMEM;

	do {
		if (cap_table_entry->rx_empty && (flags & HH_MSGQ_NONBLOCK)) {
			ret = -EAGAIN;
			goto buff_free;
		}
		if (cap_table_entry->rx_empty && (flags & HH_MSGQ_NONBLOCK))
			return -EAGAIN;

		if (wait_event_interruptible(cap_table_entry->rx_wq,
					!cap_table_entry->rx_empty)) {
			ret = -ERESTARTSYS;
			goto buff_free;
		}
					!cap_table_entry->rx_empty))
			return -ERESTARTSYS;

		ret = __hh_msgq_recv(cap_table_entry, *buff, size, flags);
		ret = __hh_msgq_recv(cap_table_entry, buff, buff_size,
					recv_size, flags);
	} while (ret == -EAGAIN);

buff_free:
	if (ret < 0) {
		kfree(*buff);
		*buff = NULL;
	}

	return ret;

err:
+8 −1
Original line number Diff line number Diff line
@@ -417,6 +417,7 @@ static void hh_rm_process_recv_work(struct work_struct *work)
	 * to release the original packet that arrived.
	 */
	kfree(recv_buff);
	kfree(msgq_data);
}

static int hh_rm_recv_task_fn(void *data)
@@ -427,12 +428,18 @@ static int hh_rm_recv_task_fn(void *data)
	int ret;

	while (!kthread_should_stop()) {
		recv_buff = kzalloc(HH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
		if (!recv_buff)
			continue;

		/* Block until a new message is received */
		ret = hh_msgq_recv(hh_rm_msgq_desc, &recv_buff,
		ret = hh_msgq_recv(hh_rm_msgq_desc, recv_buff,
					HH_MSGQ_MAX_MSG_SIZE_BYTES,
					&recv_buff_size, 0);
		if (ret < 0) {
			pr_err("%s: Failed to receive the message: %d\n",
				__func__, ret);
			kfree(recv_buff);
			continue;
		} else if (recv_buff_size <= sizeof(struct hh_rm_rpc_hdr)) {
			pr_err("%s: Invalid message size received\n", __func__);
+2 −1
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ int hh_msgq_unregister(void *msgq_client_desc);
int hh_msgq_send(void *msgq_client_desc,
			void *buff, size_t size, unsigned long flags);
int hh_msgq_recv(void *msgq_client_desc,
			void **buff, size_t *size, unsigned long flags);
			void *buff, size_t buff_size,
			size_t *recv_size, unsigned long flags);

int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id,
				int direction, int irq);