On Mon, May 11, 2020 at 07:03:05PM -0700, Hemant Kumar wrote: > Remove the system error worker thread and instead have the > execution environment worker handle that transition to serialize > processing and avoid any possible race conditions during > shutdown. > > Signed-off-by: Hemant Kumar <hemantk@xxxxxxxxxxxxxx> > Reviewed-by: Jeffrey Hugo <jhugo@xxxxxxxxxxxxxx> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx> Thanks, Mani > --- > drivers/bus/mhi/core/init.c | 2 +- > drivers/bus/mhi/core/internal.h | 3 ++- > drivers/bus/mhi/core/main.c | 6 +++--- > drivers/bus/mhi/core/pm.c | 32 ++++++++++++++------------------ > include/linux/mhi.h | 2 -- > 5 files changed, 20 insertions(+), 25 deletions(-) > > diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c > index 6882206..3a853c5 100644 > --- a/drivers/bus/mhi/core/init.c > +++ b/drivers/bus/mhi/core/init.c > @@ -34,6 +34,7 @@ > [DEV_ST_TRANSITION_READY] = "READY", > [DEV_ST_TRANSITION_SBL] = "SBL", > [DEV_ST_TRANSITION_MISSION_MODE] = "MISSION_MODE", > + [DEV_ST_TRANSITION_SYS_ERR] = "SYS_ERR", > }; > > const char * const mhi_state_str[MHI_STATE_MAX] = { > @@ -834,7 +835,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, > spin_lock_init(&mhi_cntrl->transition_lock); > spin_lock_init(&mhi_cntrl->wlock); > INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); > - INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker); > init_waitqueue_head(&mhi_cntrl->state_event); > > mhi_cmd = mhi_cntrl->mhi_cmd; > diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h > index 80b32c2..f01283b 100644 > --- a/drivers/bus/mhi/core/internal.h > +++ b/drivers/bus/mhi/core/internal.h > @@ -386,6 +386,7 @@ enum dev_st_transition { > DEV_ST_TRANSITION_READY, > DEV_ST_TRANSITION_SBL, > DEV_ST_TRANSITION_MISSION_MODE, > + DEV_ST_TRANSITION_SYS_ERR, > DEV_ST_TRANSITION_MAX, > }; > > @@ -587,7 +588,7 @@ enum mhi_pm_state __must_check mhi_tryset_pm_state( > int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, > enum dev_st_transition state); > void mhi_pm_st_worker(struct work_struct *work); > -void mhi_pm_sys_err_worker(struct work_struct *work); > +void mhi_pm_sys_err_handler(struct mhi_controller *mhi_cntrl); > void mhi_fw_load_worker(struct work_struct *work); > int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); > void mhi_ctrl_ev_task(unsigned long data); > diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c > index 6a80666..9ec9b36 100644 > --- a/drivers/bus/mhi/core/main.c > +++ b/drivers/bus/mhi/core/main.c > @@ -406,7 +406,7 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *dev) > if (MHI_IN_PBL(ee)) > mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_FATAL_ERROR); > else > - schedule_work(&mhi_cntrl->syserr_worker); > + mhi_pm_sys_err_handler(mhi_cntrl); > } > > exit_intvec: > @@ -734,7 +734,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, > MHI_PM_SYS_ERR_DETECT); > write_unlock_irq(&mhi_cntrl->pm_lock); > if (new_state == MHI_PM_SYS_ERR_DETECT) > - schedule_work(&mhi_cntrl->syserr_worker); > + mhi_pm_sys_err_handler(mhi_cntrl); > break; > } > default: > @@ -920,7 +920,7 @@ void mhi_ctrl_ev_task(unsigned long data) > } > write_unlock_irq(&mhi_cntrl->pm_lock); > if (pm_state == MHI_PM_SYS_ERR_DETECT) > - schedule_work(&mhi_cntrl->syserr_worker); > + mhi_pm_sys_err_handler(mhi_cntrl); > } > } > > diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c > index 3cc238a..d9964d4 100644 > --- a/drivers/bus/mhi/core/pm.c > +++ b/drivers/bus/mhi/core/pm.c > @@ -449,19 +449,8 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, > to_mhi_pm_state_str(transition_state)); > > /* We must notify MHI control driver so it can clean up first */ > - if (transition_state == MHI_PM_SYS_ERR_PROCESS) { > - /* > - * If controller supports RDDM, we do not process > - * SYS error state, instead we will jump directly > - * to RDDM state > - */ > - if (mhi_cntrl->rddm_image) { > - dev_dbg(dev, > - "Controller supports RDDM, so skip SYS_ERR\n"); > - return; > - } > + if (transition_state == MHI_PM_SYS_ERR_PROCESS) > mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_SYS_ERROR); > - } > > mutex_lock(&mhi_cntrl->pm_mutex); > write_lock_irq(&mhi_cntrl->pm_lock); > @@ -527,7 +516,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, > mutex_unlock(&mhi_cntrl->pm_mutex); > dev_dbg(dev, "Waiting for all pending threads to complete\n"); > wake_up_all(&mhi_cntrl->state_event); > - flush_work(&mhi_cntrl->st_worker); > > dev_dbg(dev, "Reset all active channels and remove MHI devices\n"); > device_for_each_child(mhi_cntrl->cntrl_dev, NULL, mhi_destroy_device); > @@ -607,13 +595,17 @@ int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, > } > > /* SYS_ERR worker */ > -void mhi_pm_sys_err_worker(struct work_struct *work) > +void mhi_pm_sys_err_handler(struct mhi_controller *mhi_cntrl) > { > - struct mhi_controller *mhi_cntrl = container_of(work, > - struct mhi_controller, > - syserr_worker); > + struct device *dev = &mhi_cntrl->mhi_dev->dev; > + > + /* skip if controller supports RDDM */ > + if (mhi_cntrl->rddm_image) { > + dev_dbg(dev, "Controller supports RDDM, skip SYS_ERROR\n"); > + return; > + } > > - mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS); > + mhi_queue_state_transition(mhi_cntrl, DEV_ST_TRANSITION_SYS_ERR); > } > > /* Device State Transition worker */ > @@ -661,6 +653,10 @@ void mhi_pm_st_worker(struct work_struct *work) > case DEV_ST_TRANSITION_READY: > mhi_ready_state_transition(mhi_cntrl); > break; > + case DEV_ST_TRANSITION_SYS_ERR: > + mhi_pm_disable_transition > + (mhi_cntrl, MHI_PM_SYS_ERR_PROCESS); > + break; > default: > break; > } > diff --git a/include/linux/mhi.h b/include/linux/mhi.h > index 2b20b9c..b008914 100644 > --- a/include/linux/mhi.h > +++ b/include/linux/mhi.h > @@ -331,7 +331,6 @@ struct mhi_controller_config { > * @wlock: Lock for protecting device wakeup > * @mhi_link_info: Device bandwidth info > * @st_worker: State transition worker > - * @syserr_worker: System error worker > * @state_event: State change event > * @status_cb: CB function to notify power states of the device (required) > * @wake_get: CB function to assert device wake (optional) > @@ -411,7 +410,6 @@ struct mhi_controller { > spinlock_t wlock; > struct mhi_link_info mhi_link_info; > struct work_struct st_worker; > - struct work_struct syserr_worker; > wait_queue_head_t state_event; > > void (*status_cb)(struct mhi_controller *mhi_cntrl, > -- > The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, > a Linux Foundation Collaborative Project