From 975ca1a62c19378543edc4449fe64f8d1b0a2184 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Tue, 5 May 2020 19:44:42 -0700 Subject: [PATCH] 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 Signed-off-by: Lazarus Motha --- drivers/bus/mhi/host/pm.c | 96 +++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 50 deletions(-) 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);