bus: mhi: host: Add helper API to ring event ring doorbells

SW event ring elements are added and doorbells are rung during
ready state transition from host. HW event ring elements are
added and doorbells are rung in mission mode transition. All
event ring doorbells are rung in M0 state change transition.
Move this common code to a helper API mhi_setup_event_rings().
Pass a boolean for adding event ring elements. When this flag
is false, only ring doorbells for all event rings and do not
populate the event rings.

Change-Id: Ib201007179c2cb772decb2456d3510602ea63fd6
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Signed-off-by: Lazarus Motha <quic_lmotha@quicinc.com>
This commit is contained in:
Hemant Kumar 2020-05-05 19:44:42 -07:00 committed by Lazarus Motha
parent 955a4b15ab
commit 975ca1a62c

View File

@ -156,14 +156,52 @@ static void mhi_toggle_dev_wake(struct mhi_controller *mhi_cntrl)
mhi_cntrl->wake_put(mhi_cntrl, true);
}
/* Add event ring elements and ring er db */
static void mhi_setup_event_rings(struct mhi_controller *mhi_cntrl, bool add_el)
{
struct mhi_event *mhi_event;
int i;
bool skip_er_setup;
mhi_event = mhi_cntrl->mhi_event;
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
struct mhi_ring *ring = &mhi_event->ring;
if (mhi_event->offload_ev)
continue;
/* skip HW event ring setup in ready state */
if (mhi_cntrl->dev_state == MHI_STATE_READY)
skip_er_setup = mhi_event->hw_ring;
else
skip_er_setup = !mhi_event->hw_ring;
/* if no er element to add, ring all er dbs */
if (add_el && skip_er_setup)
continue;
if (add_el) {
ring->wp = ring->base + ring->len - ring->el_size;
*ring->ctxt_wp =
ring->iommu_base + ring->len - ring->el_size;
/* Update all cores */
smp_wmb();
}
/* Ring the event ring db */
spin_lock_irq(&mhi_event->lock);
mhi_ring_er_db(mhi_event);
spin_unlock_irq(&mhi_event->lock);
}
}
/* Handle device ready state transition */
int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl)
{
struct mhi_event *mhi_event;
enum mhi_pm_state cur_state;
struct device *dev = &mhi_cntrl->mhi_dev->dev;
u32 interval_us = 25000; /* poll register field every 25 milliseconds */
int ret, i;
int ret = -EINVAL;
/* Check if device entered error state */
if (MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state)) {
@ -212,25 +250,8 @@ int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl)
goto error_mmio;
}
/* Add elements to all SW event rings */
mhi_event = mhi_cntrl->mhi_event;
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
struct mhi_ring *ring = &mhi_event->ring;
/* Skip if this is an offload or HW event */
if (mhi_event->offload_ev || mhi_event->hw_ring)
continue;
ring->wp = ring->base + ring->len - ring->el_size;
*ring->ctxt_wp = cpu_to_le64(ring->iommu_base + ring->len - ring->el_size);
/* Update all cores */
smp_wmb();
/* Ring the event ring db */
spin_lock_irq(&mhi_event->lock);
mhi_ring_er_db(mhi_event);
spin_unlock_irq(&mhi_event->lock);
}
/* add SW event ring elements and ring SW event ring dbs */
mhi_setup_event_rings(mhi_cntrl, true);
/* Set MHI to M0 state */
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M0);
@ -267,18 +288,10 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
/* Ring all event rings and CMD ring only if we're in mission mode */
if (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) {
struct mhi_event *mhi_event = mhi_cntrl->mhi_event;
struct mhi_cmd *mhi_cmd =
&mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING];
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
if (mhi_event->offload_ev)
continue;
spin_lock_irq(&mhi_event->lock);
mhi_ring_er_db(mhi_event);
spin_unlock_irq(&mhi_event->lock);
}
mhi_setup_event_rings(mhi_cntrl, false);
/* Only ring primary cmd ring if ring is not empty */
spin_lock_irq(&mhi_cmd->lock);
@ -377,10 +390,9 @@ int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl)
/* Handle device Mission Mode transition */
static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)
{
struct mhi_event *mhi_event;
struct device *dev = &mhi_cntrl->mhi_dev->dev;
enum mhi_ee_type ee = MHI_EE_MAX, current_ee = mhi_cntrl->ee;
int i, ret;
int ret;
dev_dbg(dev, "Processing Mission Mode transition\n");
@ -415,24 +427,8 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)
goto error_mission_mode;
}
/* Add elements to all HW event rings */
mhi_event = mhi_cntrl->mhi_event;
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
struct mhi_ring *ring = &mhi_event->ring;
if (mhi_event->offload_ev || !mhi_event->hw_ring)
continue;
ring->wp = ring->base + ring->len - ring->el_size;
*ring->ctxt_wp = cpu_to_le64(ring->iommu_base + ring->len - ring->el_size);
/* Update to all cores */
smp_wmb();
spin_lock_irq(&mhi_event->lock);
if (MHI_DB_ACCESS_VALID(mhi_cntrl))
mhi_ring_er_db(mhi_event);
spin_unlock_irq(&mhi_event->lock);
}
/* Add elements to all HW event rings and ring HW event ring dbs */
mhi_setup_event_rings(mhi_cntrl, true);
read_unlock_bh(&mhi_cntrl->pm_lock);