diff --git a/drivers/bus/mhi/host/pm.c b/drivers/bus/mhi/host/pm.c index 4a42186ff111..b60021d73efc 100644 --- a/drivers/bus/mhi/host/pm.c +++ b/drivers/bus/mhi/host/pm.c @@ -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);