diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-02-03 08:58:55 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-02-03 08:58:55 +0300 |
commit | cbce3de28c37fdd7531526d8dbb0ae2187667dfe (patch) | |
tree | d855f035af806dd91184812e6361a16d6455c2d5 /drivers/bus/mhi/ep/sm.c | |
parent | d45fed4ff61c48890e55a590bdd7a9fb22457be8 (diff) | |
parent | 3c54a3ff0a2cdcd902482a62fef813f1d46e5eaf (diff) | |
download | linux-cbce3de28c37fdd7531526d8dbb0ae2187667dfe.tar.xz |
Merge tag 'mhi-for-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi into char-misc-next
Manivannan writes:
MHI Host
========
- Fixed the module description
MHI Endpoint
============
- Powered down the MHI EP stack completely during MHI RESET instead of just
doing transfer abort as the MMIO register access will be prohibited
afterwards. EP stack will also be powered on again in case the RESET
happened due to SYS_ERR.
- Added a sanity check before processing the command ring to make sure that
the channel is supported by the controller.
- Added a check to make sure the xfer_cb is available for the channel
before trying to send the error status to the client drivers. This
helps in avoiding a potential null pointer dereference.
- Fixed the debug log of RESET command
- Modified the channel ring handler lock to protect the whole handler
instead of locking it partially. This helps in avoiding a race that may
happen if a channel STOP/RESET command is issued by the host parallely.
- Saved the MHI state locally during suspend and resume. Otherwise, the MHI
EP stack will not be aware of a channel that got disabled and may try to
access it later.
- Changed the MHI state_lock to mutex instead of spinlock. This helps in
avoiding the sleeping in atomic bug reported by Dan Carpenter and also
allows the lock to be held throughout the state change.
- Fixed the off by one error while doing the MHI channel check during
command ring processing.
MHI Generic
===========
- Updated the MHI toplevel Makefile to use Kconfig flags for building the
host and endpoint sub-directories conditionally.
* tag 'mhi-for-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi:
bus: mhi: ep: Fix off by one in mhi_ep_process_cmd_ring()
bus: mhi: ep: Change state_lock to mutex
bus: mhi: ep: Save channel state locally during suspend and resume
bus: mhi: ep: Move chan->lock to the start of processing queued ch ring
bus: mhi: ep: Fix the debug message for MHI_PKT_TYPE_RESET_CHAN_CMD cmd
bus: mhi: ep: Only send -ENOTCONN status if client driver is available
bus: mhi: ep: Check if the channel is supported by the controller
bus: mhi: ep: Power up/down MHI stack during MHI RESET
bus: mhi: host: Update mhi driver description
bus: mhi: Update Makefile to used Kconfig flags
Diffstat (limited to 'drivers/bus/mhi/ep/sm.c')
-rw-r--r-- | drivers/bus/mhi/ep/sm.c | 42 |
1 files changed, 24 insertions, 18 deletions
diff --git a/drivers/bus/mhi/ep/sm.c b/drivers/bus/mhi/ep/sm.c index 3655c19e23c7..fd200b2ac0bb 100644 --- a/drivers/bus/mhi/ep/sm.c +++ b/drivers/bus/mhi/ep/sm.c @@ -63,24 +63,23 @@ int mhi_ep_set_m0_state(struct mhi_ep_cntrl *mhi_cntrl) int ret; /* If MHI is in M3, resume suspended channels */ - spin_lock_bh(&mhi_cntrl->state_lock); + mutex_lock(&mhi_cntrl->state_lock); + old_state = mhi_cntrl->mhi_state; if (old_state == MHI_STATE_M3) mhi_ep_resume_channels(mhi_cntrl); ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_M0); - spin_unlock_bh(&mhi_cntrl->state_lock); - if (ret) { mhi_ep_handle_syserr(mhi_cntrl); - return ret; + goto err_unlock; } /* Signal host that the device moved to M0 */ ret = mhi_ep_send_state_change_event(mhi_cntrl, MHI_STATE_M0); if (ret) { dev_err(dev, "Failed sending M0 state change event\n"); - return ret; + goto err_unlock; } if (old_state == MHI_STATE_READY) { @@ -88,11 +87,14 @@ int mhi_ep_set_m0_state(struct mhi_ep_cntrl *mhi_cntrl) ret = mhi_ep_send_ee_event(mhi_cntrl, MHI_EE_AMSS); if (ret) { dev_err(dev, "Failed sending AMSS EE event\n"); - return ret; + goto err_unlock; } } - return 0; +err_unlock: + mutex_unlock(&mhi_cntrl->state_lock); + + return ret; } int mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl) @@ -100,13 +102,12 @@ int mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl) struct device *dev = &mhi_cntrl->mhi_dev->dev; int ret; - spin_lock_bh(&mhi_cntrl->state_lock); - ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_M3); - spin_unlock_bh(&mhi_cntrl->state_lock); + mutex_lock(&mhi_cntrl->state_lock); + ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_M3); if (ret) { mhi_ep_handle_syserr(mhi_cntrl); - return ret; + goto err_unlock; } mhi_ep_suspend_channels(mhi_cntrl); @@ -115,10 +116,13 @@ int mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl) ret = mhi_ep_send_state_change_event(mhi_cntrl, MHI_STATE_M3); if (ret) { dev_err(dev, "Failed sending M3 state change event\n"); - return ret; + goto err_unlock; } - return 0; +err_unlock: + mutex_unlock(&mhi_cntrl->state_lock); + + return ret; } int mhi_ep_set_ready_state(struct mhi_ep_cntrl *mhi_cntrl) @@ -127,22 +131,24 @@ int mhi_ep_set_ready_state(struct mhi_ep_cntrl *mhi_cntrl) enum mhi_state mhi_state; int ret, is_ready; - spin_lock_bh(&mhi_cntrl->state_lock); + mutex_lock(&mhi_cntrl->state_lock); + /* Ensure that the MHISTATUS is set to RESET by host */ mhi_state = mhi_ep_mmio_masked_read(mhi_cntrl, EP_MHISTATUS, MHISTATUS_MHISTATE_MASK); is_ready = mhi_ep_mmio_masked_read(mhi_cntrl, EP_MHISTATUS, MHISTATUS_READY_MASK); if (mhi_state != MHI_STATE_RESET || is_ready) { dev_err(dev, "READY state transition failed. MHI host not in RESET state\n"); - spin_unlock_bh(&mhi_cntrl->state_lock); - return -EIO; + ret = -EIO; + goto err_unlock; } ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_READY); - spin_unlock_bh(&mhi_cntrl->state_lock); - if (ret) mhi_ep_handle_syserr(mhi_cntrl); +err_unlock: + mutex_unlock(&mhi_cntrl->state_lock); + return ret; } |