Message ID | 20180529180605.73622-7-tony@atomide.com (mailing list archive) |
---|---|
State | RFC |
Delegated to: | Kalle Valo |
Headers | show |
On 05/29/2018 01:06 PM, Tony Lindgren wrote: > From: Eyal Reizer <eyalreizer@gmail.com> > > With runtime PM enabled, we can now use generic calls to > pm_generic_runtime_suspend and pm_generic_runtime_resume for enabling elp > during suspend when wowlan is enabled and waking the chip from elp > on resume. Sry, but not sure you can :( These functions are not used by drivers directly because system suspend are not synchronized with PM runtime, so if you call pm_generic_runtime_suspend() and, at the same time, there is pm_runtime_get_() in progress --> race ... The pm_runtime_force_() APIs have to be used, or PM runtime drivers functions can be called directly, but only if it possible to be sure no other PM runtime calls active which is usually true at suspend_noirq stage. > > Remove the custom API that was used to ensure that the command > that is used to allow ELP during suspend is completed before the system > suspend. > > Signed-off-by: Eyal Reizer <eyalr@ti.com> > Signed-off-by: Tony Lindgren <tony@atomide.com> > --- > drivers/net/wireless/ti/wlcore/main.c | 51 +++++++-------------------- > 1 file changed, 13 insertions(+), 38 deletions(-) > > diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c > --- a/drivers/net/wireless/ti/wlcore/main.c > +++ b/drivers/net/wireless/ti/wlcore/main.c > @@ -998,24 +998,6 @@ static int wlcore_fw_wakeup(struct wl1271 *wl) > return wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); > } > > -static int wlcore_fw_sleep(struct wl1271 *wl) [...]
* Grygorii Strashko <grygorii.strashko@ti.com> [180529 19:25]: > On 05/29/2018 01:06 PM, Tony Lindgren wrote: > > From: Eyal Reizer <eyalreizer@gmail.com> > > > > With runtime PM enabled, we can now use generic calls to > > pm_generic_runtime_suspend and pm_generic_runtime_resume for enabling elp > > during suspend when wowlan is enabled and waking the chip from elp > > on resume. > > Sry, but not sure you can :( > > These functions are not used by drivers directly because system suspend > are not synchronized with PM runtime, so if you call pm_generic_runtime_suspend() > and, at the same time, there is pm_runtime_get_() in progress --> race ... > > The pm_runtime_force_() APIs have to be used, or > PM runtime drivers functions can be called directly, but only if it possible to be > sure no other PM runtime calls active which is usually true at suspend_noirq stage. Oh right, those are subsystem calls. Seems like pm_runtime_force_suspend/resume() should work here, Eyal? Regards, Tony
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -998,24 +998,6 @@ static int wlcore_fw_wakeup(struct wl1271 *wl) return wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); } -static int wlcore_fw_sleep(struct wl1271 *wl) -{ - int ret; - - mutex_lock(&wl->mutex); - ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); - if (ret < 0) { - wl12xx_queue_recovery_work(wl); - goto out; - } - set_bit(WL1271_FLAG_IN_ELP, &wl->flags); -out: - mutex_unlock(&wl->mutex); - mdelay(WL1271_SUSPEND_SLEEP); - - return 0; -} - static int wl1271_setup(struct wl1271 *wl) { wl->raw_fw_status = kzalloc(wl->fw_status_len, GFP_KERNEL); @@ -1738,6 +1720,7 @@ static int __maybe_unused wl1271_op_suspend(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif; + unsigned long flags; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); @@ -1796,19 +1779,6 @@ static int __maybe_unused wl1271_op_suspend(struct ieee80211_hw *hw, /* flush any remaining work */ wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); - /* - * disable and re-enable interrupts in order to flush - * the threaded_irq - */ - wlcore_disable_interrupts(wl); - - /* - * set suspended flag to avoid triggering a new threaded_irq - * work. no need for spinlock as interrupts are disabled. - */ - set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); - - wlcore_enable_interrupts(wl); flush_work(&wl->tx_work); /* @@ -1818,15 +1788,14 @@ static int __maybe_unused wl1271_op_suspend(struct ieee80211_hw *hw, cancel_delayed_work(&wl->tx_watchdog_work); /* - * Use an immediate call for allowing the firmware to go into power - * save during suspend. - * Using a workque for this last write was only hapenning on resume - * leaving the firmware with power save disabled during suspend, - * while consuming full power during wowlan suspend. + * set suspended flag to avoid triggering a new threaded_irq + * work. */ - wlcore_fw_sleep(wl); + spin_lock_irqsave(&wl->wl_lock, flags); + set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); - return 0; + return pm_generic_runtime_suspend(wl->dev); } static int __maybe_unused wl1271_op_resume(struct ieee80211_hw *hw) @@ -1841,6 +1810,12 @@ static int __maybe_unused wl1271_op_resume(struct ieee80211_hw *hw) wl->wow_enabled); WARN_ON(!wl->wow_enabled); + ret = pm_generic_runtime_resume(wl->dev); + if (ret < 0) { + wl1271_error("ELP wakeup failure!"); + goto out_sleep; + } + /* * re-enable irq_work enqueuing, and call irq_work directly if * there is a pending work.