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. */ 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; }
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; }
static irqreturn_t wcd9xxx_spmi_irq_handler(int linux_irq, void *data) { int irq, i, j; unsigned long status[NUM_IRQ_REGS] = {0}; printk("%s\n", __func__); if (unlikely(wcd9xxx_spmi_lock_sleep() == false)) { pr_err("Failed to hold suspend\n"); return IRQ_NONE; } irq = get_irq_bit(linux_irq); if (irq == MAX_NUM_IRQS) return IRQ_HANDLED; status[BIT_BYTE(irq)] |= BYTE_BIT_MASK(irq); for (i = 0; i < NUM_IRQ_REGS; i++) { status[i] |= snd_soc_read(map.codec, BIT_BYTE(irq) * 0x100 + MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS); status[i] &= ~map.mask[i]; } for (i = 0; i < MAX_NUM_IRQS; i++) { j = get_order_irq(i); if ((status[BIT_BYTE(j)] & BYTE_BIT_MASK(j)) && ((map.handled[BIT_BYTE(j)] & BYTE_BIT_MASK(j)) == 0)) { map.handler[j](irq, data); map.handled[BIT_BYTE(j)] |= BYTE_BIT_MASK(j); } } map.handled[BIT_BYTE(irq)] &= ~BYTE_BIT_MASK(irq); wcd9xxx_spmi_unlock_sleep(); return IRQ_HANDLED; }