wlcore: Simplify runtime resume ELP path
authorTony Lindgren <tony@atomide.com>
Thu, 2 Jul 2020 16:29:48 +0000 (09:29 -0700)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 15 Jul 2020 09:12:27 +0000 (12:12 +0300)
We can simplify the runtime resume ELP path by always setting and
clearing the completion in runtime resume. This way we can test for
WL1271_FLAG_IRQ_RUNNING after the resume write to see if we need
completion at all.

And in wlcore_irq(), we need to take spinlock for running the
completion and for the pm_wakeup_event(). Spinlock is not needed
around the bitops flags check for WL1271_FLAG_SUSPENDED so the
spinlocked sections get shorter.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200702162951.45392-2-tony@atomide.com
drivers/net/wireless/ti/wlcore/main.c

index de6c8a7..437ddb8 100644 (file)
@@ -649,24 +649,26 @@ static irqreturn_t wlcore_irq(int irq, void *cookie)
        unsigned long flags;
        struct wl1271 *wl = cookie;
 
-       /* complete the ELP completion */
-       spin_lock_irqsave(&wl->wl_lock, flags);
        set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
-       if (wl->elp_compl) {
-               complete(wl->elp_compl);
-               wl->elp_compl = NULL;
+
+       /* complete the ELP completion */
+       if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) {
+               spin_lock_irqsave(&wl->wl_lock, flags);
+               if (wl->elp_compl)
+                       complete(wl->elp_compl);
+               spin_unlock_irqrestore(&wl->wl_lock, flags);
        }
 
        if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
                /* don't enqueue a work right now. mark it as pending */
                set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
                wl1271_debug(DEBUG_IRQ, "should not enqueue work");
+               spin_lock_irqsave(&wl->wl_lock, flags);
                disable_irq_nosync(wl->irq);
                pm_wakeup_event(wl->dev, 0);
                spin_unlock_irqrestore(&wl->wl_lock, flags);
                goto out_handled;
        }
-       spin_unlock_irqrestore(&wl->wl_lock, flags);
 
        /* TX might be handled here, avoid redundant work */
        set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
@@ -6732,7 +6734,6 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
        unsigned long flags;
        int ret;
        unsigned long start_time = jiffies;
-       bool pending = false;
        bool recovery = false;
 
        /* Nothing to do if no ELP mode requested */
@@ -6742,49 +6743,35 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
        wl1271_debug(DEBUG_PSM, "waking up chip from elp");
 
        spin_lock_irqsave(&wl->wl_lock, flags);
-       if (test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
-               pending = true;
-       else
-               wl->elp_compl = &compl;
+       wl->elp_compl = &compl;
        spin_unlock_irqrestore(&wl->wl_lock, flags);
 
        ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
        if (ret < 0) {
                recovery = true;
-               goto err;
-       }
-
-       if (!pending) {
+       } else if (!test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) {
                ret = wait_for_completion_timeout(&compl,
                        msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
                if (ret == 0) {
                        wl1271_warning("ELP wakeup timeout!");
-
-                       /* Return no error for runtime PM for recovery */
-                       ret = 0;
                        recovery = true;
-                       goto err;
                }
        }
 
-       clear_bit(WL1271_FLAG_IN_ELP, &wl->flags);
-
-       wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
-                    jiffies_to_msecs(jiffies - start_time));
-
-       return 0;
-
-err:
        spin_lock_irqsave(&wl->wl_lock, flags);
        wl->elp_compl = NULL;
        spin_unlock_irqrestore(&wl->wl_lock, flags);
+       clear_bit(WL1271_FLAG_IN_ELP, &wl->flags);
 
        if (recovery) {
                set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
                wl12xx_queue_recovery_work(wl);
+       } else {
+               wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
+                            jiffies_to_msecs(jiffies - start_time));
        }
 
-       return ret;
+       return 0;
 }
 
 static const struct dev_pm_ops wlcore_pm_ops = {