OSDN Git Service

wil6210: prevent XTAL off in device bootloader
authorMaya Erez <merez@codeaurora.org>
Sun, 30 Oct 2016 19:38:14 +0000 (21:38 +0200)
committerMaya Erez <merez@codeaurora.org>
Sun, 30 Oct 2016 19:38:14 +0000 (21:38 +0200)
Device bootloader enters deep sleep and turns off
its clock after 1 second of inactivity.
Waking up from this stage takes several milliseconds
and can cause PCIe timeout.
To prevent that, we need to add HALP vote in the reset
flow which will prevent the BL from turning off its
XTAL.

Change-Id: Id9273e546d3565935a7b1150c27993f02c5734e3
Signed-off-by: Maya Erez <merez@codeaurora.org>
drivers/net/wireless/ath/wil6210/interrupt.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/wil6210.h

index 64046e0..c3853a6 100644 (file)
@@ -141,7 +141,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp)
              unmask_halp ? WIL6210_IMC_MISC : WIL6210_IMC_MISC_NO_HALP);
 }
 
-static void wil6210_unmask_halp(struct wil6210_priv *wil)
+void wil6210_unmask_halp(struct wil6210_priv *wil)
 {
        wil_dbg_irq(wil, "%s()\n", __func__);
 
@@ -149,7 +149,7 @@ static void wil6210_unmask_halp(struct wil6210_priv *wil)
              BIT_DMA_EP_MISC_ICR_HALP);
 }
 
-static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
+void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
 {
        wil_dbg_irq(wil, "%s()\n", __func__);
 
index 5285ebc..94e5b67 100644 (file)
@@ -875,19 +875,29 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
        flush_workqueue(wil->wq_service);
        flush_workqueue(wil->wmi_wq);
 
+       wil6210_unmask_irq_pseudo(wil);
+       wil6210_unmask_halp(wil);
+       wil_halp_vote(wil);
+
        wil_bl_crash_info(wil, false);
        rc = wil_target_reset(wil);
+       /* wil_target_reset clears the HALP IRQ, need to set it again.
+        * Call wil_halp_unvote to clear the HALP reference counter
+        * and unmask the HALP interrupt before setting it again
+        */
+       wil_halp_unvote(wil);
+       wil_halp_vote(wil);
        wil_rx_fini(wil);
        if (rc) {
                wil_bl_crash_info(wil, true);
-               return rc;
+               goto out;
        }
 
        rc = wil_get_bl_info(wil);
        if (rc == -EAGAIN && !load_fw) /* ignore RF error if not going up */
                rc = 0;
        if (rc)
-               return rc;
+               goto out;
 
        wil_set_oob_mode(wil, oob_mode);
        if (load_fw) {
@@ -899,14 +909,19 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
                /* Loading f/w from the file */
                rc = wil_request_firmware(wil, WIL_FW_NAME, true);
                if (rc)
-                       return rc;
+                       goto out;
                rc = wil_request_firmware(wil, WIL_FW2_NAME, true);
                if (rc)
-                       return rc;
+                       goto out;
 
                /* Mark FW as loaded from host */
                wil_s(wil, RGF_USER_USAGE_6, 1);
 
+               /* Clear the HALP while in BL, before clearing all the IRQs
+                * and running the FW.
+                */
+               wil_halp_unvote(wil);
+
                /* clear any interrupts which on-card-firmware
                 * may have set
                 */
@@ -917,6 +932,9 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
                wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
 
                wil_release_cpu(wil);
+       } else {
+               /* Allow XTAL off when going down */
+               wil_halp_unvote(wil);
        }
 
        /* init after reset */
@@ -955,6 +973,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
        }
 
        return rc;
+
+out:
+       wil_halp_unvote(wil);
+       return rc;
 }
 
 void wil_fw_error_recovery(struct wil6210_priv *wil)
index a19dba5..8961b4c 100644 (file)
@@ -837,6 +837,7 @@ void wil_configure_interrupt_moderation(struct wil6210_priv *wil);
 void wil_disable_irq(struct wil6210_priv *wil);
 void wil_enable_irq(struct wil6210_priv *wil);
 void wil6210_mask_halp(struct wil6210_priv *wil);
+void wil6210_unmask_halp(struct wil6210_priv *wil);
 
 /* P2P */
 bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request);
@@ -902,6 +903,8 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil);
 void wil_rx_handle(struct wil6210_priv *wil, int *quota);
 void wil6210_unmask_irq_rx(struct wil6210_priv *wil);
 
+void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil);
+
 int wil_iftype_nl2wmi(enum nl80211_iftype type);
 
 int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd);