diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/cfg80211.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debug.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debugfs.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/fw.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/fw_inc.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/interrupt.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 63 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 8 |
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 | ||
35 | void 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 | |||
35 | void wil_info(struct wil6210_priv *wil, const char *fmt, ...) | 52 | void 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 = { | |||
67 | module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO); | 67 | module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO); |
68 | MODULE_PARM_DESC(mtu_max, " Max MTU value."); | 68 | MODULE_PARM_DESC(mtu_max, " Max MTU value."); |
69 | 69 | ||
70 | static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT; | ||
71 | static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT; | ||
72 | |||
73 | static 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 | |||
90 | static struct kernel_param_ops ring_order_ops = { | ||
91 | .set = ring_order_set, | ||
92 | .get = param_get_uint, | ||
93 | }; | ||
94 | |||
95 | module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO); | ||
96 | MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order"); | ||
97 | module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO); | ||
98 | MODULE_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 | ||
106 | static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, | 136 | static 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 | ||
154 | static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 183 | static 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 | */ |
400 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 430 | void 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 | ||
409 | void wil_priv_deinit(struct wil6210_priv *wil) | 439 | void 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 = ⅆ | 210 | struct vring_rx_desc dd, *d = ⅆ |
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 | ||
599 | int wil_rx_init(struct wil6210_priv *wil) | 597 | int 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) |
474 | void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); | 477 | void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); |
475 | __printf(2, 3) | 478 | __printf(2, 3) |
476 | void wil_err(struct wil6210_priv *wil, const char *fmt, ...); | 479 | void wil_err(struct wil6210_priv *wil, const char *fmt, ...); |
477 | __printf(2, 3) | 480 | __printf(2, 3) |
481 | void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...); | ||
482 | __printf(2, 3) | ||
478 | void wil_info(struct wil6210_priv *wil, const char *fmt, ...); | 483 | void 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); | |||
586 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); | 591 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); |
587 | int wmi_pcp_stop(struct wil6210_priv *wil); | 592 | int wmi_pcp_stop(struct wil6210_priv *wil); |
588 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 593 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, |
589 | bool from_event); | 594 | u16 reason_code, bool from_event); |
590 | 595 | ||
591 | int wil_rx_init(struct wil6210_priv *wil); | 596 | int wil_rx_init(struct wil6210_priv *wil, u16 size); |
592 | void wil_rx_fini(struct wil6210_priv *wil); | 597 | void 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 | ||