diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c index c137d55ccfa0..bf672de35131 100644 --- a/drivers/bus/mhi/host/init.c +++ b/drivers/bus/mhi/host/init.c @@ -178,6 +178,12 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl) "bhi", mhi_cntrl); if (ret) return ret; + /* + * IRQs should be enabled during mhi_async_power_up(), so disable them explicitly here. + * Due to the use of IRQF_SHARED flag as default while requesting IRQs, we assume that + * IRQ_NOAUTOEN is not applicable. + */ + disable_irq(mhi_cntrl->irq[0]); for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { if (mhi_event->offload_ev) @@ -199,6 +205,8 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl) mhi_cntrl->irq[mhi_event->irq], i); goto error_request; } + + disable_irq(mhi_cntrl->irq[mhi_event->irq]); } return 0; @@ -978,12 +986,16 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, goto err_destroy_wq; } + ret = mhi_init_irq_setup(mhi_cntrl); + if (ret) + goto err_ida_free; + /* Register controller with MHI bus */ mhi_dev = mhi_alloc_device(mhi_cntrl); if (IS_ERR(mhi_dev)) { dev_err(mhi_cntrl->cntrl_dev, "Failed to allocate MHI device\n"); ret = PTR_ERR(mhi_dev); - goto err_ida_free; + goto error_setup_irq; } mhi_dev->dev_type = MHI_DEVICE_CONTROLLER; @@ -1006,6 +1018,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, err_release_dev: put_device(&mhi_dev->dev); +error_setup_irq: + mhi_deinit_free_irq(mhi_cntrl); err_ida_free: ida_free(&mhi_controller_ida, mhi_cntrl->index); err_destroy_wq: @@ -1026,6 +1040,7 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl) struct mhi_chan *mhi_chan = mhi_cntrl->mhi_chan; unsigned int i; + mhi_deinit_free_irq(mhi_cntrl); mhi_destroy_debugfs(mhi_cntrl); destroy_workqueue(mhi_cntrl->hiprio_wq); diff --git a/drivers/bus/mhi/host/pm.c b/drivers/bus/mhi/host/pm.c index dc2e8ff3bff2..4a42186ff111 100644 --- a/drivers/bus/mhi/host/pm.c +++ b/drivers/bus/mhi/host/pm.c @@ -500,7 +500,7 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl) for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { if (mhi_event->offload_ev) continue; - free_irq(mhi_cntrl->irq[mhi_event->irq], mhi_event); + disable_irq(mhi_cntrl->irq[mhi_event->irq]); tasklet_kill(&mhi_event->task); } @@ -1060,12 +1060,13 @@ static void mhi_deassert_dev_wake(struct mhi_controller *mhi_cntrl, int mhi_async_power_up(struct mhi_controller *mhi_cntrl) { + struct mhi_event *mhi_event = mhi_cntrl->mhi_event; enum mhi_state state; enum mhi_ee_type current_ee; enum dev_st_transition next_state; struct device *dev = &mhi_cntrl->mhi_dev->dev; u32 interval_us = 25000; /* poll register field every 25 milliseconds */ - int ret; + int ret, i; dev_info(dev, "Requested to power ON\n"); @@ -1117,9 +1118,15 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0); } - ret = mhi_init_irq_setup(mhi_cntrl); - if (ret) - goto error_exit; + /* IRQs have been requested during probe, so we just need to enable them. */ + enable_irq(mhi_cntrl->irq[0]); + + for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { + if (mhi_event->offload_ev) + continue; + + enable_irq(mhi_cntrl->irq[mhi_event->irq]); + } /* Transition to next state */ next_state = MHI_IN_PBL(current_ee) ? @@ -1182,7 +1189,7 @@ void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful) /* Wait for shutdown to complete */ flush_work(&mhi_cntrl->st_worker); - free_irq(mhi_cntrl->irq[0], mhi_cntrl); + disable_irq(mhi_cntrl->irq[0]); } EXPORT_SYMBOL_GPL(mhi_power_down);