wil6210: fix for oops while stopping interface

When interface stopped while running intensive Rx traffic, the following oops
observed:

[89846.734683] Call trace:
[89846.737117] [<ffffffc00083aa64>] dev_gro_receive+0xac/0x358
[89846.742674] [<ffffffc00083ae94>] napi_gro_receive+0x24/0xa4
[89846.748251] [<ffffffbffc1c2f88>] $x+0xec/0x1f8 [wil6210]         wil_netif_rx_any
[89846.753547] [<ffffffbffc1c4830>] $x+0x34/0x54 [wil6210]          wil_release_reorder_frame
[89846.758755] [<ffffffbffc1c48ac>] wil_release_reorder_frames+0x5c/0x78 [wil6210]
[89846.766044] [<ffffffbffc1c4bf8>] wil_tid_ampdu_rx_free+0x20/0x48 [wil6210]
[89846.772901] [<ffffffbffc1bedc8>] $x+0x190/0x1e8 [wil6210]
[89846.778285] [<ffffffbffc1c0ed4>] wmi_event_worker+0x230/0x2f8 [wil6210]
[89846.784865] [<ffffffc0000b0bc8>] process_one_work+0x278/0x3fc
[89846.790591] [<ffffffc0000b1218>] worker_thread+0x200/0x330
[89846.796060] [<ffffffc0000b6664>] kthread+0xac/0xb8
[89846.800836] Code: b940c661 f9406a62 8b010041 f9400026 (f8636882)
[89846.807008] ---[ end trace d6fdc17cd27d18f6 ]---

Reason is the following: when removing Rx vring
(wil_netdev_ops.ndo_stop -> wil_stop -> wil_down -> __wil_down -> wil_rx_fini),
Rx interrupt occurs. It trigger Rx NAPI, calling wil_rx_handle() that reaps
(already cleaned) buffer, causing skb referring to garbage memory being set into reorder buffer.
Then, network stack trying to access this buffer and fails.

Prevent Rx NAPI from being scheduled if device going to stop. Bit wil_status_napi_en reflects
NAPI enablement state, check it when triggering Rx NAPI.

Testing shows that check for wil_status_napi_en sometimes gets negative, and new error message
get printed - in this case kernel oops would be observed. Original oops is no more reproducible.

This change requires also changes in the AP flows.
Properly enable/disable NAPI for the AP. Make sure Rx VRING is disabled
when resetting target.

For this, promote __wil_up() and __wil_down() to the module scope, and use it
in the relevant flows.

Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 8443d82..21667e0 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -221,10 +221,8 @@
 	case NL80211_IFTYPE_MONITOR:
 		wil_info(wil, "fw error recovery started (try %d)...\n",
 			 wil->recovery_count);
-		wil_reset(wil);
-
-		/* need to re-allocate Rx ring after reset */
-		wil_rx_init(wil);
+		__wil_down(wil);
+		__wil_up(wil);
 		break;
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_P2P_GO:
@@ -480,13 +478,12 @@
 	wil_dbg_misc(wil, "%s()\n", __func__);
 
 	WARN_ON(!mutex_is_locked(&wil->mutex));
+	WARN_ON(test_bit(wil_status_napi_en, &wil->status));
 
 	cancel_work_sync(&wil->disconnect_worker);
 	wil6210_disconnect(wil, NULL);
 
 	wil->status = 0; /* prevent NAPI from being scheduled */
-	if (test_bit(wil_status_napi_en, &wil->status))
-		napi_synchronize(&wil->napi_rx);
 
 	if (wil->scan_request) {
 		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
@@ -575,7 +572,7 @@
 	netif_carrier_off(ndev);
 }
 
-static int __wil_up(struct wil6210_priv *wil)
+int __wil_up(struct wil6210_priv *wil)
 {
 	struct net_device *ndev = wil_to_ndev(wil);
 	struct wireless_dev *wdev = wil->wdev;
@@ -621,7 +618,7 @@
 	/* MAC address - pre-requisite for other commands */
 	wmi_set_mac_address(wil, ndev->dev_addr);
 
-
+	wil_dbg_misc(wil, "NAPI enable\n");
 	napi_enable(&wil->napi_rx);
 	napi_enable(&wil->napi_tx);
 	set_bit(wil_status_napi_en, &wil->status);
@@ -646,7 +643,7 @@
 	return rc;
 }
 
-static int __wil_down(struct wil6210_priv *wil)
+int __wil_down(struct wil6210_priv *wil)
 {
 	int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS /
 			WAIT_FOR_DISCONNECT_INTERVAL_MS;
@@ -656,9 +653,13 @@
 	if (wil->platform_ops.bus_request)
 		wil->platform_ops.bus_request(wil->platform_handle, 0);
 
-	clear_bit(wil_status_napi_en, &wil->status);
-	napi_disable(&wil->napi_rx);
-	napi_disable(&wil->napi_tx);
+	wil_disable_irq(wil);
+	if (test_and_clear_bit(wil_status_napi_en, &wil->status)) {
+		napi_disable(&wil->napi_rx);
+		napi_disable(&wil->napi_tx);
+		wil_dbg_misc(wil, "NAPI disable\n");
+	}
+	wil_enable_irq(wil);
 
 	if (wil->scan_request) {
 		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",