summaryrefslogtreecommitdiffstats
path: root/drivers/bus/mhi/ep/ring.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bus/mhi/ep/ring.c')
-rw-r--r--drivers/bus/mhi/ep/ring.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/bus/mhi/ep/ring.c b/drivers/bus/mhi/ep/ring.c
index c673d7200b..aeb53b2c34 100644
--- a/drivers/bus/mhi/ep/ring.c
+++ b/drivers/bus/mhi/ep/ring.c
@@ -48,7 +48,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end)
buf_info.host_addr = ring->rbase + (start * sizeof(struct mhi_ring_element));
buf_info.dev_addr = &ring->ring_cache[start];
- ret = mhi_cntrl->read_from_host(mhi_cntrl, &buf_info);
+ ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info);
if (ret < 0)
return ret;
} else {
@@ -56,7 +56,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end)
buf_info.host_addr = ring->rbase + (start * sizeof(struct mhi_ring_element));
buf_info.dev_addr = &ring->ring_cache[start];
- ret = mhi_cntrl->read_from_host(mhi_cntrl, &buf_info);
+ ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info);
if (ret < 0)
return ret;
@@ -65,7 +65,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end)
buf_info.dev_addr = &ring->ring_cache[0];
buf_info.size = end * sizeof(struct mhi_ring_element);
- ret = mhi_cntrl->read_from_host(mhi_cntrl, &buf_info);
+ ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info);
if (ret < 0)
return ret;
}
@@ -143,7 +143,7 @@ int mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *e
buf_info.dev_addr = el;
buf_info.size = sizeof(*el);
- return mhi_cntrl->write_to_host(mhi_cntrl, &buf_info);
+ return mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
}
void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id)
@@ -162,6 +162,15 @@ void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32
}
}
+static void mhi_ep_raise_irq(struct work_struct *work)
+{
+ struct mhi_ep_ring *ring = container_of(work, struct mhi_ep_ring, intmodt_work.work);
+ struct mhi_ep_cntrl *mhi_cntrl = ring->mhi_cntrl;
+
+ mhi_cntrl->raise_irq(mhi_cntrl, ring->irq_vector);
+ WRITE_ONCE(ring->irq_pending, false);
+}
+
int mhi_ep_ring_start(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring,
union mhi_ep_ring_ctx *ctx)
{
@@ -178,8 +187,13 @@ int mhi_ep_ring_start(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring,
if (ring->type == RING_TYPE_CH)
ring->er_index = le32_to_cpu(ring->ring_ctx->ch.erindex);
- if (ring->type == RING_TYPE_ER)
+ if (ring->type == RING_TYPE_ER) {
ring->irq_vector = le32_to_cpu(ring->ring_ctx->ev.msivec);
+ ring->intmodt = FIELD_GET(EV_CTX_INTMODT_MASK,
+ le32_to_cpu(ring->ring_ctx->ev.intmod));
+
+ INIT_DELAYED_WORK(&ring->intmodt_work, mhi_ep_raise_irq);
+ }
/* During ring init, both rp and wp are equal */
memcpy_fromio(&val, (void __iomem *) &ring->ring_ctx->generic.rp, sizeof(u64));
@@ -206,6 +220,9 @@ int mhi_ep_ring_start(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring,
void mhi_ep_ring_reset(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring)
{
+ if (ring->type == RING_TYPE_ER)
+ cancel_delayed_work_sync(&ring->intmodt_work);
+
ring->started = false;
kfree(ring->ring_cache);
ring->ring_cache = NULL;