wil6210: new SW reset
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Wed, 13 Mar 2013 12:12:49 +0000 (14:12 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 13 Mar 2013 18:26:21 +0000 (14:26 -0400)
New firmware allows for shorter SW reset procedure.
After SW reset, FW raises "fw done" IRQ, at this
moment mailbox control structures are initialized, driver caches it.

New status bit wil_status_reset_done introduced to track completion
of the reset. It is set by "fw ready" irq, and required for WMI rx flow
to access control structures.

WMI Tx flow protected by other status bit, wil_status_fwready. It can't
be set before wil_status_reset_done is set by design.

Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/wil6210/interrupt.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/ath/wil6210/wmi.c

index de9b971ea159a71d4b336cfe0c5e008db33ceaf2..e3c1e7684f9c6874772484f69e8687d27b8722b7 100644 (file)
@@ -240,6 +240,15 @@ static void wil_notify_fw_error(struct wil6210_priv *wil)
        kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 }
 
+static void wil_cache_mbox_regs(struct wil6210_priv *wil)
+{
+       /* make shadow copy of registers that should not change on run time */
+       wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
+                            sizeof(struct wil6210_mbox_ctl));
+       wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
+       wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
+}
+
 static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
 {
        struct wil6210_priv *wil = cookie;
@@ -268,6 +277,8 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
 
        if (isr & ISR_MISC_FW_READY) {
                wil_dbg_irq(wil, "IRQ: FW ready\n");
+               wil_cache_mbox_regs(wil);
+               set_bit(wil_status_reset_done, &wil->status);
                /**
                 * Actual FW ready indicated by the
                 * WMI_FW_READY_EVENTID
index f11efa4d6ab847279dc9dbec06caa3f9070c8d3d..9d05628e450dbfca1827c987d37d4295343e9c2e 100644 (file)
@@ -103,15 +103,6 @@ static void wil_connect_timer_fn(ulong x)
        schedule_work(&wil->disconnect_worker);
 }
 
-static void wil_cache_mbox_regs(struct wil6210_priv *wil)
-{
-       /* make shadow copy of registers that should not change on run time */
-       wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
-                            sizeof(struct wil6210_mbox_ctl));
-       wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
-       wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
-}
-
 static void wil_connect_worker(struct work_struct *work)
 {
        int rc;
@@ -161,8 +152,6 @@ int wil_priv_init(struct wil6210_priv *wil)
                return -EAGAIN;
        }
 
-       wil_cache_mbox_regs(wil);
-
        return 0;
 }
 
@@ -199,15 +188,11 @@ static void wil_target_reset(struct wil6210_priv *wil)
        W(RGF_USER_MAC_CPU_0,  BIT(1)); /* mac_cpu_man_rst */
        W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
 
-       msleep(100);
-
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170);
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
 
-       msleep(100);
-
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
@@ -217,12 +202,6 @@ static void wil_target_reset(struct wil6210_priv *wil)
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
        W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
 
-       msleep(2000);
-
-       W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */
-
-       msleep(2000);
-
        wil_dbg_misc(wil, "Reset completed\n");
 
 #undef W
@@ -279,8 +258,6 @@ int wil_reset(struct wil6210_priv *wil)
        wil->pending_connect_cid = -1;
        INIT_COMPLETION(wil->wmi_ready);
 
-       wil_cache_mbox_regs(wil);
-
        /* TODO: release MAC reset */
        wil6210_enable_irq(wil);
 
index 5f500de957fe17df83d8965e68da8d7185b2e50c..2ec7258b191caa51975f9c92db7fcc1f80fed49a 100644 (file)
@@ -186,6 +186,7 @@ enum { /* for wil6210_priv.status */
        wil_status_fwready = 0,
        wil_status_fwconnected,
        wil_status_dontscan,
+       wil_status_reset_done,
        wil_status_irqen, /* FIXME: interrupts enabled - for debug */
 };
 
index 8d9e145f0983c99da36343382fa3091fb02a039b..ed2b097ee02a5368e2aab40defed37cfb0f6c829 100644 (file)
@@ -585,6 +585,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
        void __iomem *src;
        ulong flags;
 
+       if (!test_bit(wil_status_reset_done, &wil->status)) {
+               wil_err(wil, "Reset not completed\n");
+               return;
+       }
+
        for (;;) {
                u16 len;