aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wil6210
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wil6210')
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/debug.c17
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c8
-rw-r--r--drivers/net/wireless/ath/wil6210/fw.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/fw_inc.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c30
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c63
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c11
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h15
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c8
10 files changed, 120 insertions, 39 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 0fc0b9f8e605..38332a6dfb3a 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -798,7 +798,7 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy,
798 struct wil6210_priv *wil = wiphy_to_wil(wiphy); 798 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
799 799
800 mutex_lock(&wil->mutex); 800 mutex_lock(&wil->mutex);
801 wil6210_disconnect(wil, params->mac, false); 801 wil6210_disconnect(wil, params->mac, params->reason_code, false);
802 mutex_unlock(&wil->mutex); 802 mutex_unlock(&wil->mutex);
803 803
804 return 0; 804 return 0;
diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c
index 8d99021d27a8..3249562d93b4 100644
--- a/drivers/net/wireless/ath/wil6210/debug.c
+++ b/drivers/net/wireless/ath/wil6210/debug.c
@@ -32,6 +32,23 @@ void wil_err(struct wil6210_priv *wil, const char *fmt, ...)
32 va_end(args); 32 va_end(args);
33} 33}
34 34
35void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
36{
37 if (net_ratelimit()) {
38 struct net_device *ndev = wil_to_ndev(wil);
39 struct va_format vaf = {
40 .fmt = fmt,
41 };
42 va_list args;
43
44 va_start(args, fmt);
45 vaf.va = &args;
46 netdev_err(ndev, "%pV", &vaf);
47 trace_wil6210_log_err(&vaf);
48 va_end(args);
49 }
50}
51
35void wil_info(struct wil6210_priv *wil, const char *fmt, ...) 52void wil_info(struct wil6210_priv *wil, const char *fmt, ...)
36{ 53{
37 struct net_device *ndev = wil_to_ndev(wil); 54 struct net_device *ndev = wil_to_ndev(wil);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 54a6ddc6301b..4e6e14501c2f 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -573,8 +573,10 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
573 if (!frame) 573 if (!frame)
574 return -ENOMEM; 574 return -ENOMEM;
575 575
576 if (copy_from_user(frame, buf, len)) 576 if (copy_from_user(frame, buf, len)) {
577 kfree(frame);
577 return -EIO; 578 return -EIO;
579 }
578 580
579 params.buf = frame; 581 params.buf = frame;
580 params.len = len; 582 params.len = len;
@@ -614,8 +616,10 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
614 return -ENOMEM; 616 return -ENOMEM;
615 617
616 rc = simple_write_to_buffer(wmi, len, ppos, buf, len); 618 rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
617 if (rc < 0) 619 if (rc < 0) {
620 kfree(wmi);
618 return rc; 621 return rc;
622 }
619 623
620 cmd = &wmi[1]; 624 cmd = &wmi[1];
621 cmdid = le16_to_cpu(wmi->id); 625 cmdid = le16_to_cpu(wmi->id);
diff --git a/drivers/net/wireless/ath/wil6210/fw.c b/drivers/net/wireless/ath/wil6210/fw.c
index 8c6f3b041f77..93c5cc16c515 100644
--- a/drivers/net/wireless/ath/wil6210/fw.c
+++ b/drivers/net/wireless/ath/wil6210/fw.c
@@ -15,7 +15,6 @@
15 */ 15 */
16#include <linux/firmware.h> 16#include <linux/firmware.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/pci.h>
19#include <linux/crc32.h> 18#include <linux/crc32.h>
20#include "wil6210.h" 19#include "wil6210.h"
21#include "fw.h" 20#include "fw.h"
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index 44cb71f5ea5b..d4acf93a9a02 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -446,7 +446,7 @@ static int wil_fw_load(struct wil6210_priv *wil, const void *data, size_t size)
446 if (size >= sizeof(*hdr)) { 446 if (size >= sizeof(*hdr)) {
447 wil_err_fw(wil, "Stop at offset %ld" 447 wil_err_fw(wil, "Stop at offset %ld"
448 " record type %d [%zd bytes]\n", 448 " record type %d [%zd bytes]\n",
449 (const void *)hdr - data, 449 (long)((const void *)hdr - data),
450 le16_to_cpu(hdr->type), hdr_sz); 450 le16_to_cpu(hdr->type), hdr_sz);
451 } 451 }
452 return -EINVAL; 452 return -EINVAL;
@@ -471,7 +471,7 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name)
471 size_t sz; 471 size_t sz;
472 const void *d; 472 const void *d;
473 473
474 rc = request_firmware(&fw, name, wil_to_pcie_dev(wil)); 474 rc = request_firmware(&fw, name, wil_to_dev(wil));
475 if (rc) { 475 if (rc) {
476 wil_err_fw(wil, "Failed to load firmware %s\n", name); 476 wil_err_fw(wil, "Failed to load firmware %s\n", name);
477 return rc; 477 return rc;
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 90f416f239bd..4bcbd6297b3e 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -36,7 +36,8 @@
36 */ 36 */
37 37
38#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) 38#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL)
39#define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE 39#define WIL6210_IMC_RX (BIT_DMA_EP_RX_ICR_RX_DONE | \
40 BIT_DMA_EP_RX_ICR_RX_HTRSH)
40#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ 41#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
41 BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) 42 BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
42#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \ 43#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \
@@ -171,6 +172,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
171 u32 isr = wil_ioread32_and_clear(wil->csr + 172 u32 isr = wil_ioread32_and_clear(wil->csr +
172 HOSTADDR(RGF_DMA_EP_RX_ICR) + 173 HOSTADDR(RGF_DMA_EP_RX_ICR) +
173 offsetof(struct RGF_ICR, ICR)); 174 offsetof(struct RGF_ICR, ICR));
175 bool need_unmask = true;
174 176
175 trace_wil6210_irq_rx(isr); 177 trace_wil6210_irq_rx(isr);
176 wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr); 178 wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
@@ -182,12 +184,24 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
182 184
183 wil6210_mask_irq_rx(wil); 185 wil6210_mask_irq_rx(wil);
184 186
185 if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { 187 /* RX_DONE and RX_HTRSH interrupts are the same if interrupt
188 * moderation is not used. Interrupt moderation may cause RX
189 * buffer overflow while RX_DONE is delayed. The required
190 * action is always the same - should empty the accumulated
191 * packets from the RX ring.
192 */
193 if (isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH)) {
186 wil_dbg_irq(wil, "RX done\n"); 194 wil_dbg_irq(wil, "RX done\n");
187 isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; 195
196 if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)
197 wil_err_ratelimited(wil, "Received \"Rx buffer is in risk "
198 "of overflow\" interrupt\n");
199
200 isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH);
188 if (test_bit(wil_status_reset_done, &wil->status)) { 201 if (test_bit(wil_status_reset_done, &wil->status)) {
189 if (test_bit(wil_status_napi_en, &wil->status)) { 202 if (test_bit(wil_status_napi_en, &wil->status)) {
190 wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); 203 wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
204 need_unmask = false;
191 napi_schedule(&wil->napi_rx); 205 napi_schedule(&wil->napi_rx);
192 } else { 206 } else {
193 wil_err(wil, "Got Rx interrupt while " 207 wil_err(wil, "Got Rx interrupt while "
@@ -204,6 +218,10 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
204 /* Rx IRQ will be enabled when NAPI processing finished */ 218 /* Rx IRQ will be enabled when NAPI processing finished */
205 219
206 atomic_inc(&wil->isr_count_rx); 220 atomic_inc(&wil->isr_count_rx);
221
222 if (unlikely(need_unmask))
223 wil6210_unmask_irq_rx(wil);
224
207 return IRQ_HANDLED; 225 return IRQ_HANDLED;
208} 226}
209 227
@@ -213,6 +231,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
213 u32 isr = wil_ioread32_and_clear(wil->csr + 231 u32 isr = wil_ioread32_and_clear(wil->csr +
214 HOSTADDR(RGF_DMA_EP_TX_ICR) + 232 HOSTADDR(RGF_DMA_EP_TX_ICR) +
215 offsetof(struct RGF_ICR, ICR)); 233 offsetof(struct RGF_ICR, ICR));
234 bool need_unmask = true;
216 235
217 trace_wil6210_irq_tx(isr); 236 trace_wil6210_irq_tx(isr);
218 wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr); 237 wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
@@ -231,6 +250,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
231 isr &= ~(BIT(25) - 1UL); 250 isr &= ~(BIT(25) - 1UL);
232 if (test_bit(wil_status_reset_done, &wil->status)) { 251 if (test_bit(wil_status_reset_done, &wil->status)) {
233 wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); 252 wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
253 need_unmask = false;
234 napi_schedule(&wil->napi_tx); 254 napi_schedule(&wil->napi_tx);
235 } else { 255 } else {
236 wil_err(wil, "Got Tx interrupt while in reset\n"); 256 wil_err(wil, "Got Tx interrupt while in reset\n");
@@ -243,6 +263,10 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
243 /* Tx IRQ will be enabled when NAPI processing finished */ 263 /* Tx IRQ will be enabled when NAPI processing finished */
244 264
245 atomic_inc(&wil->isr_count_tx); 265 atomic_inc(&wil->isr_count_tx);
266
267 if (unlikely(need_unmask))
268 wil6210_unmask_irq_tx(wil);
269
246 return IRQ_HANDLED; 270 return IRQ_HANDLED;
247} 271}
248 272
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 6212983fede2..8ff3fe34fe05 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -67,6 +67,36 @@ static struct kernel_param_ops mtu_max_ops = {
67module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO); 67module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO);
68MODULE_PARM_DESC(mtu_max, " Max MTU value."); 68MODULE_PARM_DESC(mtu_max, " Max MTU value.");
69 69
70static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT;
71static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT;
72
73static int ring_order_set(const char *val, const struct kernel_param *kp)
74{
75 int ret;
76 uint x;
77
78 ret = kstrtouint(val, 0, &x);
79 if (ret)
80 return ret;
81
82 if ((x < WIL_RING_SIZE_ORDER_MIN) || (x > WIL_RING_SIZE_ORDER_MAX))
83 return -EINVAL;
84
85 *((uint *)kp->arg) = x;
86
87 return 0;
88}
89
90static struct kernel_param_ops ring_order_ops = {
91 .set = ring_order_set,
92 .get = param_get_uint,
93};
94
95module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO);
96MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
97module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO);
98MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
99
70#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ 100#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
71#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ 101#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
72 102
@@ -104,7 +134,7 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
104} 134}
105 135
106static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, 136static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
107 bool from_event) 137 u16 reason_code, bool from_event)
108{ 138{
109 uint i; 139 uint i;
110 struct net_device *ndev = wil_to_ndev(wil); 140 struct net_device *ndev = wil_to_ndev(wil);
@@ -117,8 +147,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
117 sta->data_port_open = false; 147 sta->data_port_open = false;
118 if (sta->status != wil_sta_unused) { 148 if (sta->status != wil_sta_unused) {
119 if (!from_event) 149 if (!from_event)
120 wmi_disconnect_sta(wil, sta->addr, 150 wmi_disconnect_sta(wil, sta->addr, reason_code);
121 WLAN_REASON_DEAUTH_LEAVING);
122 151
123 switch (wdev->iftype) { 152 switch (wdev->iftype) {
124 case NL80211_IFTYPE_AP: 153 case NL80211_IFTYPE_AP:
@@ -152,7 +181,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
152} 181}
153 182
154static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, 183static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
155 bool from_event) 184 u16 reason_code, bool from_event)
156{ 185{
157 int cid = -ENOENT; 186 int cid = -ENOENT;
158 struct net_device *ndev = wil_to_ndev(wil); 187 struct net_device *ndev = wil_to_ndev(wil);
@@ -167,10 +196,10 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
167 } 196 }
168 197
169 if (cid >= 0) /* disconnect 1 peer */ 198 if (cid >= 0) /* disconnect 1 peer */
170 wil_disconnect_cid(wil, cid, from_event); 199 wil_disconnect_cid(wil, cid, reason_code, from_event);
171 else /* disconnect all */ 200 else /* disconnect all */
172 for (cid = 0; cid < WIL6210_MAX_CID; cid++) 201 for (cid = 0; cid < WIL6210_MAX_CID; cid++)
173 wil_disconnect_cid(wil, cid, from_event); 202 wil_disconnect_cid(wil, cid, reason_code, from_event);
174 203
175 /* link state */ 204 /* link state */
176 switch (wdev->iftype) { 205 switch (wdev->iftype) {
@@ -179,8 +208,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
179 wil_link_off(wil); 208 wil_link_off(wil);
180 if (test_bit(wil_status_fwconnected, &wil->status)) { 209 if (test_bit(wil_status_fwconnected, &wil->status)) {
181 clear_bit(wil_status_fwconnected, &wil->status); 210 clear_bit(wil_status_fwconnected, &wil->status);
182 cfg80211_disconnected(ndev, 211 cfg80211_disconnected(ndev, reason_code,
183 WLAN_STATUS_UNSPECIFIED_FAILURE,
184 NULL, 0, GFP_KERNEL); 212 NULL, 0, GFP_KERNEL);
185 } else if (test_bit(wil_status_fwconnecting, &wil->status)) { 213 } else if (test_bit(wil_status_fwconnecting, &wil->status)) {
186 cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, 214 cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
@@ -200,7 +228,7 @@ static void wil_disconnect_worker(struct work_struct *work)
200 struct wil6210_priv, disconnect_worker); 228 struct wil6210_priv, disconnect_worker);
201 229
202 mutex_lock(&wil->mutex); 230 mutex_lock(&wil->mutex);
203 _wil6210_disconnect(wil, NULL, false); 231 _wil6210_disconnect(wil, NULL, WLAN_REASON_UNSPECIFIED, false);
204 mutex_unlock(&wil->mutex); 232 mutex_unlock(&wil->mutex);
205} 233}
206 234
@@ -222,6 +250,7 @@ static void wil_scan_timer_fn(ulong x)
222 250
223 clear_bit(wil_status_fwready, &wil->status); 251 clear_bit(wil_status_fwready, &wil->status);
224 wil_err(wil, "Scan timeout detected, start fw error recovery\n"); 252 wil_err(wil, "Scan timeout detected, start fw error recovery\n");
253 wil->recovery_state = fw_recovery_pending;
225 schedule_work(&wil->fw_error_worker); 254 schedule_work(&wil->fw_error_worker);
226} 255}
227 256
@@ -333,7 +362,7 @@ static void wil_connect_worker(struct work_struct *work)
333 362
334 wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid); 363 wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
335 364
336 rc = wil_vring_init_tx(wil, ringid, WIL6210_TX_RING_SIZE, cid, 0); 365 rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
337 wil->pending_connect_cid = -1; 366 wil->pending_connect_cid = -1;
338 if (rc == 0) { 367 if (rc == 0) {
339 wil->sta[cid].status = wil_sta_connected; 368 wil->sta[cid].status = wil_sta_connected;
@@ -392,18 +421,19 @@ int wil_priv_init(struct wil6210_priv *wil)
392 * wil6210_disconnect - disconnect one connection 421 * wil6210_disconnect - disconnect one connection
393 * @wil: driver context 422 * @wil: driver context
394 * @bssid: peer to disconnect, NULL to disconnect all 423 * @bssid: peer to disconnect, NULL to disconnect all
424 * @reason_code: Reason code for the Disassociation frame
395 * @from_event: whether is invoked from FW event handler 425 * @from_event: whether is invoked from FW event handler
396 * 426 *
397 * Disconnect and release associated resources. If invoked not from the 427 * Disconnect and release associated resources. If invoked not from the
398 * FW event handler, issue WMI command(s) to trigger MAC disconnect. 428 * FW event handler, issue WMI command(s) to trigger MAC disconnect.
399 */ 429 */
400void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, 430void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
401 bool from_event) 431 u16 reason_code, bool from_event)
402{ 432{
403 wil_dbg_misc(wil, "%s()\n", __func__); 433 wil_dbg_misc(wil, "%s()\n", __func__);
404 434
405 del_timer_sync(&wil->connect_timer); 435 del_timer_sync(&wil->connect_timer);
406 _wil6210_disconnect(wil, bssid, from_event); 436 _wil6210_disconnect(wil, bssid, reason_code, from_event);
407} 437}
408 438
409void wil_priv_deinit(struct wil6210_priv *wil) 439void wil_priv_deinit(struct wil6210_priv *wil)
@@ -415,7 +445,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
415 cancel_work_sync(&wil->disconnect_worker); 445 cancel_work_sync(&wil->disconnect_worker);
416 cancel_work_sync(&wil->fw_error_worker); 446 cancel_work_sync(&wil->fw_error_worker);
417 mutex_lock(&wil->mutex); 447 mutex_lock(&wil->mutex);
418 wil6210_disconnect(wil, NULL, false); 448 wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
419 mutex_unlock(&wil->mutex); 449 mutex_unlock(&wil->mutex);
420 wmi_event_flush(wil); 450 wmi_event_flush(wil);
421 destroy_workqueue(wil->wmi_wq_conn); 451 destroy_workqueue(wil->wmi_wq_conn);
@@ -463,6 +493,9 @@ static int wil_target_reset(struct wil6210_priv *wil)
463 493
464 wil_halt_cpu(wil); 494 wil_halt_cpu(wil);
465 495
496 /* Clear Fw Download notification */
497 C(RGF_USER_USAGE_6, BIT(0));
498
466 if (is_sparrow) { 499 if (is_sparrow) {
467 S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN); 500 S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
468 /* XTAL stabilization should take about 3ms */ 501 /* XTAL stabilization should take about 3ms */
@@ -600,7 +633,7 @@ int wil_reset(struct wil6210_priv *wil)
600 WARN_ON(test_bit(wil_status_napi_en, &wil->status)); 633 WARN_ON(test_bit(wil_status_napi_en, &wil->status));
601 634
602 cancel_work_sync(&wil->disconnect_worker); 635 cancel_work_sync(&wil->disconnect_worker);
603 wil6210_disconnect(wil, NULL, false); 636 wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
604 637
605 wil->status = 0; /* prevent NAPI from being scheduled */ 638 wil->status = 0; /* prevent NAPI from being scheduled */
606 639
@@ -705,7 +738,7 @@ int __wil_up(struct wil6210_priv *wil)
705 return rc; 738 return rc;
706 739
707 /* Rx VRING. After MAC and beacon */ 740 /* Rx VRING. After MAC and beacon */
708 rc = wil_rx_init(wil); 741 rc = wil_rx_init(wil, 1 << rx_ring_order);
709 if (rc) 742 if (rc)
710 return rc; 743 return rc;
711 744
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index c680906bc0dc..e3f8bdce5abc 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -210,8 +210,6 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
210 struct vring_rx_desc dd, *d = &dd; 210 struct vring_rx_desc dd, *d = &dd;
211 volatile struct vring_rx_desc *_d = &vring->va[i].rx; 211 volatile struct vring_rx_desc *_d = &vring->va[i].rx;
212 dma_addr_t pa; 212 dma_addr_t pa;
213
214 /* TODO align */
215 struct sk_buff *skb = dev_alloc_skb(sz + headroom); 213 struct sk_buff *skb = dev_alloc_skb(sz + headroom);
216 214
217 if (unlikely(!skb)) 215 if (unlikely(!skb))
@@ -596,7 +594,7 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota)
596 wil_rx_refill(wil, v->size); 594 wil_rx_refill(wil, v->size);
597} 595}
598 596
599int wil_rx_init(struct wil6210_priv *wil) 597int wil_rx_init(struct wil6210_priv *wil, u16 size)
600{ 598{
601 struct vring *vring = &wil->vring_rx; 599 struct vring *vring = &wil->vring_rx;
602 int rc; 600 int rc;
@@ -608,7 +606,7 @@ int wil_rx_init(struct wil6210_priv *wil)
608 return -EINVAL; 606 return -EINVAL;
609 } 607 }
610 608
611 vring->size = WIL6210_RX_RING_SIZE; 609 vring->size = size;
612 rc = wil_vring_alloc(wil, vring); 610 rc = wil_vring_alloc(wil, vring);
613 if (rc) 611 if (rc)
614 return rc; 612 return rc;
@@ -928,8 +926,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
928 wil_dbg_txrx(wil, "%s()\n", __func__); 926 wil_dbg_txrx(wil, "%s()\n", __func__);
929 927
930 if (avail < 1 + nr_frags) { 928 if (avail < 1 + nr_frags) {
931 wil_err(wil, "Tx ring full. No space for %d fragments\n", 929 wil_err_ratelimited(wil,
932 1 + nr_frags); 930 "Tx ring full. No space for %d fragments\n",
931 1 + nr_frags);
933 return -ENOMEM; 932 return -ENOMEM;
934 } 933 }
935 _d = &vring->va[i].tx; 934 _d = &vring->va[i].tx;
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 95d3a062d35c..c6ec5b99ac7d 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -49,8 +49,11 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
49 49
50#define WIL6210_MEM_SIZE (2*1024*1024UL) 50#define WIL6210_MEM_SIZE (2*1024*1024UL)
51 51
52#define WIL6210_RX_RING_SIZE (128) 52#define WIL_RX_RING_SIZE_ORDER_DEFAULT (9)
53#define WIL6210_TX_RING_SIZE (512) 53#define WIL_TX_RING_SIZE_ORDER_DEFAULT (9)
54/* limit ring size in range [32..32k] */
55#define WIL_RING_SIZE_ORDER_MIN (5)
56#define WIL_RING_SIZE_ORDER_MAX (15)
54#define WIL6210_MAX_TX_RINGS (24) /* HW limit */ 57#define WIL6210_MAX_TX_RINGS (24) /* HW limit */
55#define WIL6210_MAX_CID (8) /* HW limit */ 58#define WIL6210_MAX_CID (8) /* HW limit */
56#define WIL6210_NAPI_BUDGET (16) /* arbitrary */ 59#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
@@ -126,6 +129,7 @@ struct RGF_ICR {
126 #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */ 129 #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */
127#define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */ 130#define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */
128 #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0) 131 #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0)
132 #define BIT_DMA_EP_RX_ICR_RX_HTRSH BIT(1)
129#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ 133#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */
130 #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) 134 #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0)
131 #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) 135 #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1)
@@ -468,13 +472,14 @@ struct wil6210_priv {
468#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) 472#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
469#define wil_to_ndev(i) (wil_to_wdev(i)->netdev) 473#define wil_to_ndev(i) (wil_to_wdev(i)->netdev)
470#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) 474#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
471#define wil_to_pcie_dev(i) (&i->pdev->dev)
472 475
473__printf(2, 3) 476__printf(2, 3)
474void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); 477void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
475__printf(2, 3) 478__printf(2, 3)
476void wil_err(struct wil6210_priv *wil, const char *fmt, ...); 479void wil_err(struct wil6210_priv *wil, const char *fmt, ...);
477__printf(2, 3) 480__printf(2, 3)
481void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...);
482__printf(2, 3)
478void wil_info(struct wil6210_priv *wil, const char *fmt, ...); 483void wil_info(struct wil6210_priv *wil, const char *fmt, ...);
479#define wil_dbg(wil, fmt, arg...) do { \ 484#define wil_dbg(wil, fmt, arg...) do { \
480 netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ 485 netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
@@ -586,9 +591,9 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
586int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); 591int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
587int wmi_pcp_stop(struct wil6210_priv *wil); 592int wmi_pcp_stop(struct wil6210_priv *wil);
588void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, 593void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
589 bool from_event); 594 u16 reason_code, bool from_event);
590 595
591int wil_rx_init(struct wil6210_priv *wil); 596int wil_rx_init(struct wil6210_priv *wil, u16 size);
592void wil_rx_fini(struct wil6210_priv *wil); 597void wil_rx_fini(struct wil6210_priv *wil);
593 598
594/* TX API */ 599/* TX API */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index bb1e066f756a..63476c86cd0e 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -478,15 +478,15 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
478 void *d, int len) 478 void *d, int len)
479{ 479{
480 struct wmi_disconnect_event *evt = d; 480 struct wmi_disconnect_event *evt = d;
481 u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
481 482
482 wil_dbg_wmi(wil, "Disconnect %pM reason %d proto %d wmi\n", 483 wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
483 evt->bssid, 484 evt->bssid, reason_code, evt->disconnect_reason);
484 evt->protocol_reason_status, evt->disconnect_reason);
485 485
486 wil->sinfo_gen++; 486 wil->sinfo_gen++;
487 487
488 mutex_lock(&wil->mutex); 488 mutex_lock(&wil->mutex);
489 wil6210_disconnect(wil, evt->bssid, true); 489 wil6210_disconnect(wil, evt->bssid, reason_code, true);
490 mutex_unlock(&wil->mutex); 490 mutex_unlock(&wil->mutex);
491} 491}
492 492