bool wcd9xxx_spmi_lock_sleep() { /* * wcd9xxx_spmi_{lock/unlock}_sleep will be called by wcd9xxx_spmi_irq_thread * and its subroutines only motly. * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and * It can race with wcd9xxx_spmi_irq_thread. * So need to embrace wlock_holders with mutex. */ mutex_lock(&map.pm_lock); if (map.wlock_holders++ == 0) { pr_debug("%s: holding wake lock\n", __func__); pm_qos_update_request(&map.pm_qos_req, msm_cpuidle_get_deep_idle_latency()); #ifdef VENDOR_EDIT //[email protected], 2015/03/19, Add for Qcom patch, //Headset sometime not detected when phone is sleep pm_stay_awake(&map.spmi[0]->dev); #endif /* VENDOR_EDIT */ } mutex_unlock(&map.pm_lock); pr_debug("%s: wake lock counter %d\n", __func__, map.wlock_holders); pr_debug("%s: map.pm_state = %d\n", __func__, map.pm_state); if (!wait_event_timeout(map.pm_wq, ((wcd9xxx_spmi_pm_cmpxchg( WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE)) == WCD9XXX_PM_SLEEPABLE || (wcd9xxx_spmi_pm_cmpxchg( WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE) == 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, map.pm_state, map.wlock_holders); wcd9xxx_spmi_unlock_sleep(); return false; } wake_up_all(&map.pm_wq); pr_debug("%s: leaving pm_state = %d\n", __func__, map.pm_state); return true; }
bool wcd9xxx_spmi_lock_sleep() { /* * wcd9xxx_spmi_{lock/unlock}_sleep will be called by wcd9xxx_spmi_irq_thread * and its subroutines only motly. * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and * It can race with wcd9xxx_spmi_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(&map.pm_lock); if (map.wlock_holders++ == 0) { pr_debug("%s: holding wake lock\n", __func__); pm_qos_update_request(&map.pm_qos_req, msm_cpuidle_get_deep_idle_latency()); } mutex_unlock(&map.pm_lock); pr_debug("%s: wake lock counter %d\n", __func__, map.wlock_holders); if (!wait_event_timeout(map.pm_wq, ((wcd9xxx_spmi_pm_cmpxchg( WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE)) == WCD9XXX_PM_SLEEPABLE || (wcd9xxx_spmi_pm_cmpxchg( WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE) == 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, map.pm_state, map.wlock_holders); wcd9xxx_spmi_unlock_sleep(); return false; } wake_up_all(&map.pm_wq); return true; }
bool wcd9xxx_spmi_lock_sleep() { /* * wcd9xxx_spmi_{lock/unlock}_sleep will be called by * wcd9xxx_spmi_irq_thread * and its subroutines only motly. * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and * It can race with wcd9xxx_spmi_irq_thread. * So need to embrace wlock_holders with mutex. */ pr_info("%s, wlock_holders=%d\n", __func__, map.wlock_holders); mutex_lock(&map.pm_lock); if (map.wlock_holders++ == 0) { pr_info("%s: holding wake lock\n", __func__); pm_qos_update_request(&map.pm_qos_req, msm_cpuidle_get_deep_idle_latency()); pm_stay_awake(&map.spmi[0]->dev); } mutex_unlock(&map.pm_lock); pr_info("%s: wake lock counter %d\n", __func__, map.wlock_holders); pr_info("%s: map.pm_state = %d\n", __func__, map.pm_state); if (!wait_event_timeout(map.pm_wq, ((wcd9xxx_spmi_pm_cmpxchg( WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE)) == WCD9XXX_PM_SLEEPABLE || (wcd9xxx_spmi_pm_cmpxchg( WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_AWAKE) == 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, map.pm_state, map.wlock_holders); wcd9xxx_spmi_unlock_sleep(); return false; } wake_up_all(&map.pm_wq); pr_debug("%s: leaving pm_state = %d\n", __func__, map.pm_state); return true; }
int wcd9xxx_spmi_suspend(pm_message_t pmesg) { int ret = 0; pr_debug("%s: enter\n", __func__); /* * pm_qos_update_request() can be called after this suspend chain call * started. thus suspend can be called while lock is being held */ mutex_lock(&map.pm_lock); if (map.pm_state == WCD9XXX_PM_SLEEPABLE) { pr_debug("%s: suspending system, state %d, wlock %d\n", __func__, map.pm_state, map.wlock_holders); map.pm_state = WCD9XXX_PM_ASLEEP; } else if (map.pm_state == WCD9XXX_PM_AWAKE) { /* * unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE * then set to WCD9XXX_PM_ASLEEP */ pr_debug("%s: waiting to suspend system, state %d, wlock %d\n", __func__, map.pm_state, map.wlock_holders); mutex_unlock(&map.pm_lock); if (!(wait_event_timeout(map.pm_wq, wcd9xxx_spmi_pm_cmpxchg( WCD9XXX_PM_SLEEPABLE, WCD9XXX_PM_ASLEEP) == WCD9XXX_PM_SLEEPABLE, HZ))) { pr_debug("%s: suspend failed state %d, wlock %d\n", __func__, map.pm_state, map.wlock_holders); ret = -EBUSY; } else { pr_debug("%s: done, state %d, wlock %d\n", __func__, map.pm_state, map.wlock_holders); } mutex_lock(&map.pm_lock); } else if (map.pm_state == WCD9XXX_PM_ASLEEP) { pr_warn("%s: system is already suspended, state %d, wlock %dn", __func__, map.pm_state, map.wlock_holders); } mutex_unlock(&map.pm_lock); return ret; }