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

Commit d0a49408 authored by Bhaumik Bhatt's avatar Bhaumik Bhatt Committed by Gerrit - the friendly Code Review server
Browse files

mhi: core: fix fast forward recycling of event rings



Some low priority event rings operate on a fast forwarding
mechanism where only the latest event is processed and the rest
are skipped. The recycle API only handles updating the
context write pointer in sequence which causes an out of bounds
doorbell issued to the device due to mismatched values. Add
another API to support handling updates for context write
pointer separately with the fast forwarding use case.

Change-Id: If628b49e063d14920fe734ebd113c9c4c733204b
Signed-off-by: default avatarBhaumik Bhatt <bbhatt@codeaurora.org>
parent cf2a299d
Loading
Loading
Loading
Loading
+24 −1
Original line number Original line Diff line number Diff line
@@ -292,6 +292,29 @@ static void mhi_recycle_ev_ring_element(struct mhi_controller *mhi_cntrl,
	smp_wmb();
	smp_wmb();
}
}


static void mhi_recycle_fwd_ev_ring_element(struct mhi_controller *mhi_cntrl,
					struct mhi_ring *ring)
{
	dma_addr_t ctxt_wp;

	/* update the WP */
	ring->wp += ring->el_size;
	if (ring->wp >= (ring->base + ring->len))
		ring->wp = ring->base;

	/* update the context WP based on the RP to support fast forwarding */
	ctxt_wp = ring->iommu_base + (ring->wp - ring->base);
	*ring->ctxt_wp = ctxt_wp;

	/* update the RP */
	ring->rp += ring->el_size;
	if (ring->rp >= (ring->base + ring->len))
		ring->rp = ring->base;

	/* visible to other cores */
	smp_wmb();
}

static bool mhi_is_ring_full(struct mhi_controller *mhi_cntrl,
static bool mhi_is_ring_full(struct mhi_controller *mhi_cntrl,
			     struct mhi_ring *ring)
			     struct mhi_ring *ring)
{
{
@@ -1451,7 +1474,7 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl,
	ev_ring->wp = dev_rp - 1;
	ev_ring->wp = dev_rp - 1;
	if (ev_ring->wp < ev_ring->base)
	if (ev_ring->wp < ev_ring->base)
		ev_ring->wp = ev_ring->base + ev_ring->len - ev_ring->el_size;
		ev_ring->wp = ev_ring->base + ev_ring->len - ev_ring->el_size;
	mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring);
	mhi_recycle_fwd_ev_ring_element(mhi_cntrl, ev_ring);


	read_lock_bh(&mhi_cntrl->pm_lock);
	read_lock_bh(&mhi_cntrl->pm_lock);
	if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl)))
	if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl)))