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

Commit c750f235 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mhi_dev: Handle wrap-around case for event ring updates"

parents 6f5aa8ec c12bc4a2
Loading
Loading
Loading
Loading
+52 −19
Original line number Diff line number Diff line
@@ -278,11 +278,12 @@ EXPORT_SYMBOL(mhi_dev_process_ring);

int mhi_dev_add_element(struct mhi_dev_ring *ring,
				union mhi_dev_ring_element_type *element,
				struct event_req *ereq, int evt_offset)
				struct event_req *ereq, int size)
{
	uint32_t old_offset = 0;
	struct mhi_addr host_addr;
	uint32_t num_elem = 0;
	uint32_t num_elem = 1;
	uint32_t num_free_elem;

	if (!ring || !element) {
		pr_err("%s: Invalid context\n", __func__);
@@ -291,16 +292,24 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring,

	mhi_dev_update_wr_offset(ring);

	if ((ring->rd_offset + 1) % ring->ring_size == ring->wr_offset) {
		mhi_log(MHI_MSG_VERBOSE, "ring full to insert element\n");
	if (ereq)
		num_elem = size / (sizeof(union mhi_dev_ring_element_type));

	if (ring->rd_offset < ring->wr_offset)
		num_free_elem = ring->wr_offset - ring->rd_offset - 1;
	else
		num_free_elem = ring->ring_size - ring->rd_offset +
				ring->wr_offset - 1;

	if (num_free_elem < num_elem) {
		mhi_log(MHI_MSG_ERROR, "No space to add %d elem in ring (%d)\n",
			num_elem, ring->id);
		return -EINVAL;
	}

	old_offset = ring->rd_offset;

	if (evt_offset) {
		num_elem = evt_offset /
			(sizeof(union mhi_dev_ring_element_type));
	if (ereq) {
		ring->rd_offset += num_elem;
		if (ring->rd_offset >= ring->ring_size)
			ring->rd_offset -= ring->ring_size;
@@ -322,23 +331,47 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring,
		host_addr.device_va = ring->ring_shadow.device_va +
			sizeof(union mhi_dev_ring_element_type) * old_offset;

	if (!ereq) {
		/* We're adding only a single ring element */
		host_addr.virt_addr = element;

	if (evt_offset)
		host_addr.size = evt_offset;
	else
		host_addr.size = sizeof(union mhi_dev_ring_element_type);

	mhi_log(MHI_MSG_VERBOSE, "adding element to ring (%d)\n", ring->id);
		mhi_log(MHI_MSG_VERBOSE, "adding element to ring (%d)\n",
					ring->id);
		mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset);
		mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type);

	if (ereq)
		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
			NULL, MHI_DEV_DMA_SYNC);
		return 0;
	}

	/* Adding multiple ring elements */
	if (ring->rd_offset == 0 || (ring->rd_offset > old_offset)) {
		/* No wrap-around case */
		host_addr.virt_addr = element;
		host_addr.size = size;
		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
			ereq, MHI_DEV_DMA_ASYNC);
	else
	} else {
		/* Wrap-around case - first chunk uses dma sync */
		host_addr.virt_addr = element;
		host_addr.size = (ring->ring_size - old_offset) *
			sizeof(union mhi_dev_ring_element_type);
		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
			NULL, MHI_DEV_DMA_SYNC);

		/* Copy remaining elements */
		if (ring->mhi_dev->use_ipa)
			host_addr.host_pa = ring->ring_shadow.host_pa;
		else
			host_addr.device_va = ring->ring_shadow.device_va;
		host_addr.virt_addr = element + (ring->ring_size - old_offset);
		host_addr.size = ring->rd_offset *
			sizeof(union mhi_dev_ring_element_type);
		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
			ereq, MHI_DEV_DMA_ASYNC);
	}
	return 0;
}
EXPORT_SYMBOL(mhi_dev_add_element);