From 649971df7ac1a1e745958e8447fbe16cf6cc3698 Mon Sep 17 00:00:00 2001 From: Bhaumik Bhatt Date: Fri, 3 Apr 2020 14:13:12 -0700 Subject: [PATCH] mhi: core: improve bandwidth switch events processing We may unnecessarily wake up the device when there is no pending bandwidth switch request. Avoid that by only asserting device wake if one is pending. We can also have the underlying MHI bus go to suspend while a device requested bandwidth switch is yet to be processed. Prevent host suspends by capturing both bus and device votes and increment pending packets to reject suspends while the processing is ongoing. Change-Id: I4eddb6bf9eaa973be5c0b0ac516269e54599b9f2 Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/core/mhi_main.c | 57 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index aa55ad065641..4ba83b09dc0c 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -1437,29 +1437,12 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, struct mhi_link_info link_info, *cur_info = &mhi_cntrl->mhi_link_info; int result, ret = 0; - if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) { - MHI_LOG("No EV access, PM_STATE:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - ret = -EIO; - goto exit_no_lock; - } - - ret = __mhi_device_get_sync(mhi_cntrl); - if (ret) - goto exit_no_lock; - - mutex_lock(&mhi_cntrl->pm_mutex); - spin_lock_bh(&mhi_event->lock); dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); if (ev_ring->rp == dev_rp) { spin_unlock_bh(&mhi_event->lock); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - MHI_VERB("no pending event found\n"); - goto exit_bw_process; + goto exit_bw_scale_process; } /* if rp points to base, we need to wrap it around */ @@ -1467,6 +1450,13 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, dev_rp = ev_ring->base + ev_ring->len; dev_rp--; + /* fast forward to currently processed element and recycle er */ + ev_ring->rp = dev_rp; + ev_ring->wp = dev_rp - 1; + if (ev_ring->wp < ev_ring->base) + ev_ring->wp = ev_ring->base + ev_ring->len - ev_ring->el_size; + mhi_recycle_fwd_ev_ring_element(mhi_cntrl, ev_ring); + MHI_ASSERT(MHI_TRE_GET_EV_TYPE(dev_rp) != MHI_PKT_TYPE_BW_REQ_EVENT, "!BW SCALE REQ event"); @@ -1479,19 +1469,22 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, link_info.target_link_speed, link_info.target_link_width); - /* fast forward to currently processed element and recycle er */ - ev_ring->rp = dev_rp; - ev_ring->wp = dev_rp - 1; - if (ev_ring->wp < ev_ring->base) - ev_ring->wp = ev_ring->base + ev_ring->len - ev_ring->el_size; - mhi_recycle_fwd_ev_ring_element(mhi_cntrl, ev_ring); - read_lock_bh(&mhi_cntrl->pm_lock); if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl))) mhi_ring_er_db(mhi_event); read_unlock_bh(&mhi_cntrl->pm_lock); spin_unlock_bh(&mhi_event->lock); + atomic_inc(&mhi_cntrl->pending_pkts); + ret = mhi_device_get_sync(mhi_cntrl->mhi_dev, + MHI_VOTE_DEVICE | MHI_VOTE_BUS); + if (ret) { + atomic_dec(&mhi_cntrl->pending_pkts); + goto exit_bw_scale_process; + } + + mutex_lock(&mhi_cntrl->pm_mutex); + ret = mhi_cntrl->bw_scale(mhi_cntrl, &link_info); if (!ret) *cur_info = link_info; @@ -1501,17 +1494,17 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, read_lock_bh(&mhi_cntrl->pm_lock); if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl))) mhi_cntrl->write_reg(mhi_cntrl, mhi_cntrl->bw_scale_db, 0, - MHI_BW_SCALE_RESULT(result, - link_info.sequence_num)); - - mhi_cntrl->wake_put(mhi_cntrl, false); + MHI_BW_SCALE_RESULT(result, + link_info.sequence_num)); read_unlock_bh(&mhi_cntrl->pm_lock); -exit_bw_process: + mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); + atomic_dec(&mhi_cntrl->pending_pkts); + mutex_unlock(&mhi_cntrl->pm_mutex); -exit_no_lock: - MHI_VERB("exit er_index:%u\n", mhi_event->er_index); +exit_bw_scale_process: + MHI_VERB("exit er_index:%u ret:%d\n", mhi_event->er_index, ret); return ret; }