]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
wil6210: prevent external wmi commands during suspend flow
authorMaya Erez <qca_merez@qca.qualcomm.com>
Tue, 24 Nov 2015 07:30:15 +0000 (09:30 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Tue, 8 Dec 2015 14:50:28 +0000 (16:50 +0200)
In __wmi_send we check if fw is ready at the beginning of the function.
While we wait for the completion of the previous command, system suspend
can be invoked and reset the HW, causing __wmi_send to read from HW
registers while it is not ready.
Taking the wmi_mutex in the reset flow when setting the FW ready bit
to zero will prevent the above race condition.

Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/wmi.c

index 48687f128dc614b31eeaec0a6fe08bfc92413ab4..09b4daebab9d91ec93b5e7491e4b70f2397b00dc 100644 (file)
@@ -781,8 +781,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
        wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
        wil_bcast_fini(wil);
 
-       /* prevent NAPI from being scheduled */
+       /* prevent NAPI from being scheduled and prevent wmi commands */
+       mutex_lock(&wil->wmi_mutex);
        bitmap_zero(wil->status, wil_status_last);
+       mutex_unlock(&wil->wmi_mutex);
 
        if (wil->scan_request) {
                wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
index 6ed26baca0e51bf4266c1edf04aabe801ece6376..e3ea74cdd4aaee066c3d5f034265e63024e7cd6b 100644 (file)
@@ -228,6 +228,10 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
        wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
        /* wait till FW finish with previous command */
        for (retry = 5; retry > 0; retry--) {
+               if (!test_bit(wil_status_fwready, wil->status)) {
+                       wil_err(wil, "WMI: cannot send command while FW not ready\n");
+                       return -EAGAIN;
+               }
                r->tail = wil_r(wil, RGF_MBOX +
                                offsetof(struct wil6210_mbox_ctl, tx.tail));
                if (next_head != r->tail)