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

Commit 01acbed6 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_send



Currently, the clients of the hh_msgq driver would allocate buffers,
fill with data and call hh_msgq_send(). Upon success, hh_msgq_send()
would be freeing the buffer, while in the case of failure, the clients
are responsible for it. However, this approach of buffer management is
not symmetric and could be confusing for the clients. Hence, let the
clients take full ownership of the buffers- allocating and freeing.

Also make changes to the affected client drivers.

Change-Id: I73101d823f9d3de16414e444fde494222f584e53
Signed-off-by: default avatarRaghavendra Rao Ananta <rananta@codeaurora.org>
parent 3aa6a088
Loading
Loading
Loading
Loading
+23 −7
Original line number Diff line number Diff line
@@ -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) {

	/*
	 * 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)
+2 −11
Original line number Diff line number Diff line
@@ -239,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.
 *
@@ -312,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);
+10 −3
Original line number Diff line number Diff line
@@ -518,11 +518,18 @@ 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) {

		/*
		 * 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;
}