]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/net/wireless/ath/wil6210/main.c
wil6210: fix for memory corruption upon rmmod
[mirror_ubuntu-bionic-kernel.git] / drivers / net / wireless / ath / wil6210 / main.c
index 696be3e71a82ebda77c9477cfe04e97f7879c9e2..22e9b8aeb1cfde5df4fcecb03613d8fa7356e274 100644 (file)
 
 #include "wil6210.h"
 #include "txrx.h"
+#include "wmi.h"
+
+#define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000
+#define WAIT_FOR_DISCONNECT_INTERVAL_MS 10
 
 static bool no_fw_recovery;
 module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR);
@@ -631,6 +635,9 @@ int wil_up(struct wil6210_priv *wil)
 
 static int __wil_down(struct wil6210_priv *wil)
 {
+       int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS /
+                       WAIT_FOR_DISCONNECT_INTERVAL_MS;
+
        WARN_ON(!mutex_is_locked(&wil->mutex));
 
        if (wil->platform_ops.bus_request)
@@ -648,7 +655,24 @@ static int __wil_down(struct wil6210_priv *wil)
                wil->scan_request = NULL;
        }
 
-       wil6210_disconnect(wil, NULL);
+       if (test_bit(wil_status_fwconnected, &wil->status) ||
+           test_bit(wil_status_fwconnecting, &wil->status))
+               wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
+
+       /* make sure wil is idle (not connected) */
+       mutex_unlock(&wil->mutex);
+       while (iter--) {
+               int idle = !test_bit(wil_status_fwconnected, &wil->status) &&
+                          !test_bit(wil_status_fwconnecting, &wil->status);
+               if (idle)
+                       break;
+               msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS);
+       }
+       mutex_lock(&wil->mutex);
+
+       if (!iter)
+               wil_err(wil, "timeout waiting for idle FW/HW\n");
+
        wil_rx_fini(wil);
 
        return 0;