bool wcd9xxx_lock_sleep( struct wcd9xxx_core_resource *wcd9xxx_res) { enum wcd9xxx_pm_state os; mutex_lock(&wcd9xxx_res->pm_lock); if (wcd9xxx_res->wlock_holders++ == 0) { pr_debug("%s: holding wake lock\n", __func__); pm_qos_update_request(&wcd9xxx_res->pm_qos_req, msm_cpuidle_get_deep_idle_latency()); } mutex_unlock(&wcd9xxx_res->pm_lock); if (!wait_event_timeout(wcd9xxx_res->pm_wq, ((os = wcd9xxx_pm_cmpxchg(wcd9xxx_res, WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE)) == WCD9XXX_PM_SLEEPABLE || (os == WCD9XXX_PM_AWAKE)), msecs_to_jiffies( WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) { pr_warn("%s: system didn't resume within %dms, s %d, w %d\n", __func__, WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx_res->pm_state, wcd9xxx_res->wlock_holders); wcd9xxx_unlock_sleep(wcd9xxx_res); return false; } wake_up_all(&wcd9xxx_res->pm_wq); return true; }
bool wcd9xxx_lock_sleep( struct wcd9xxx_core_resource *wcd9xxx_res) { enum wcd9xxx_pm_state os; /* * wcd9xxx_{lock/unlock}_sleep will be called by wcd9xxx_irq_thread * and its subroutines only motly. * but btn0_lpress_fn is not wcd9xxx_irq_thread's subroutine and * It can race with wcd9xxx_irq_thread. * So need to embrace wlock_holders with mutex. * * If system didn't resume, we can simply return false so codec driver's * IRQ handler can return without handling IRQ. * As interrupt line is still active, codec will have another IRQ to * retry shortly. */ mutex_lock(&wcd9xxx_res->pm_lock); if (wcd9xxx_res->wlock_holders++ == 0) { pr_debug("%s: holding wake lock\n", __func__); pm_qos_update_request(&wcd9xxx_res->pm_qos_req, msm_cpuidle_get_deep_idle_latency()); } mutex_unlock(&wcd9xxx_res->pm_lock); if (!wait_event_timeout(wcd9xxx_res->pm_wq, ((os = wcd9xxx_pm_cmpxchg(wcd9xxx_res, WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE)) == WCD9XXX_PM_SLEEPABLE || (os == WCD9XXX_PM_AWAKE)), msecs_to_jiffies( WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) { pr_warn("%s: system didn't resume within %dms, s %d, w %d\n", __func__, WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx_res->pm_state, wcd9xxx_res->wlock_holders); wcd9xxx_unlock_sleep(wcd9xxx_res); return false; } wake_up_all(&wcd9xxx_res->pm_wq); return true; }