]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/wireless/ath/wil6210/main.c
UBUNTU: Ubuntu-4.13.0-45.50
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / ath / wil6210 / main.c
CommitLineData
2be7d22f 1/*
849a564b 2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
2be7d22f
VK
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
2be7d22f
VK
17#include <linux/moduleparam.h>
18#include <linux/if_arp.h>
108d1eb6 19#include <linux/etherdevice.h>
2be7d22f
VK
20
21#include "wil6210.h"
b4490f42 22#include "txrx.h"
f172b563 23#include "wmi.h"
f1ad8c93 24#include "boot_loader.h"
f172b563 25
349214c1 26#define WAIT_FOR_HALP_VOTE_MS 100
035859a5 27#define WAIT_FOR_SCAN_ABORT_MS 1000
349214c1 28
bfc2dc7a 29bool debug_fw; /* = false; */
78484c44 30module_param(debug_fw, bool, 0444);
bfc2dc7a
VK
31MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
32
b8c31b5d
LD
33static u8 oob_mode;
34module_param(oob_mode, byte, 0444);
1f1a361a
LD
35MODULE_PARM_DESC(oob_mode,
36 " enable out of the box (OOB) mode in FW, for diagnostics and certification");
37
c33407a8 38bool no_fw_recovery;
78484c44 39module_param(no_fw_recovery, bool, 0644);
c33407a8 40MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery");
ed6f9dc6 41
ab954628
VK
42/* if not set via modparam, will be set to default value of 1/8 of
43 * rx ring size during init flow
44 */
45unsigned short rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_INIT;
78484c44 46module_param(rx_ring_overflow_thrsh, ushort, 0444);
ab954628
VK
47MODULE_PARM_DESC(rx_ring_overflow_thrsh,
48 " RX ring overflow threshold in descriptors.");
b6b1b0ec 49
9a06bec9
VK
50/* We allow allocation of more than 1 page buffers to support large packets.
51 * It is suboptimal behavior performance wise in case MTU above page size.
52 */
c44690a1 53unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - WIL_MAX_MPDU_OVERHEAD;
9a06bec9
VK
54static int mtu_max_set(const char *val, const struct kernel_param *kp)
55{
56 int ret;
57
58 /* sets mtu_max directly. no need to restore it in case of
59 * illegal value since we assume this will fail insmod
60 */
61 ret = param_set_uint(val, kp);
62 if (ret)
63 return ret;
64
4590d812 65 if (mtu_max < 68 || mtu_max > WIL_MAX_ETH_MTU)
9a06bec9
VK
66 ret = -EINVAL;
67
68 return ret;
69}
70
9c27847d 71static const struct kernel_param_ops mtu_max_ops = {
9a06bec9
VK
72 .set = mtu_max_set,
73 .get = param_get_uint,
74};
75
78484c44 76module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, 0444);
9a06bec9
VK
77MODULE_PARM_DESC(mtu_max, " Max MTU value.");
78
d3762b40
VK
79static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT;
80static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT;
41d6b093 81static uint bcast_ring_order = WIL_BCAST_RING_SIZE_ORDER_DEFAULT;
d3762b40
VK
82
83static int ring_order_set(const char *val, const struct kernel_param *kp)
84{
85 int ret;
86 uint x;
87
88 ret = kstrtouint(val, 0, &x);
89 if (ret)
90 return ret;
91
92 if ((x < WIL_RING_SIZE_ORDER_MIN) || (x > WIL_RING_SIZE_ORDER_MAX))
93 return -EINVAL;
94
95 *((uint *)kp->arg) = x;
96
97 return 0;
98}
99
9c27847d 100static const struct kernel_param_ops ring_order_ops = {
d3762b40
VK
101 .set = ring_order_set,
102 .get = param_get_uint,
103};
104
78484c44 105module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, 0444);
d3762b40 106MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
78484c44 107module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, 0444);
d3762b40 108MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
78484c44 109module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, 0444);
d507d1b7 110MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order");
d3762b40 111
520d68e7
VK
112#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
113#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
114
2be7d22f
VK
115/*
116 * Due to a hardware issue,
117 * one has to read/write to/from NIC in 32-bit chunks;
118 * regular memcpy_fromio and siblings will
119 * not work on 64-bit platform - it uses 64-bit transactions
120 *
121 * Force 32-bit transactions to enable NIC on 64-bit platforms
122 *
123 * To avoid byte swap on big endian host, __raw_{read|write}l
124 * should be used - {read|write}l would swap bytes to provide
125 * little endian on PCI value in host endianness.
126 */
127void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
128 size_t count)
129{
130 u32 *d = dst;
131 const volatile u32 __iomem *s = src;
132
0f6edfe2 133 for (; count >= 4; count -= 4)
2be7d22f 134 *d++ = __raw_readl(s++);
0f6edfe2
DL
135
136 if (unlikely(count)) {
137 /* count can be 1..3 */
138 u32 tmp = __raw_readl(s);
139
140 memcpy(d, &tmp, count);
141 }
2be7d22f
VK
142}
143
144void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
145 size_t count)
146{
147 volatile u32 __iomem *d = dst;
148 const u32 *s = src;
149
0f6edfe2 150 for (; count >= 4; count -= 4)
2be7d22f 151 __raw_writel(*s++, d++);
0f6edfe2
DL
152
153 if (unlikely(count)) {
154 /* count can be 1..3 */
155 u32 tmp = 0;
156
157 memcpy(&tmp, s, count);
158 __raw_writel(tmp, d);
159 }
2be7d22f
VK
160}
161
b516fcc5 162static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
4821e6d8 163 u16 reason_code, bool from_event)
bd33273b 164__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
91886b0b
VK
165{
166 uint i;
fc58f681
VK
167 struct net_device *ndev = wil_to_ndev(wil);
168 struct wireless_dev *wdev = wil->wdev;
91886b0b 169 struct wil_sta_info *sta = &wil->sta[cid];
8fe59627 170
bd33273b 171 might_sleep();
af3db60a
LA
172 wil_dbg_misc(wil, "disconnect_cid: CID %d, status %d\n",
173 cid, sta->status);
58527421 174 /* inform upper/lower layers */
4d55a0a1 175 if (sta->status != wil_sta_unused) {
849a564b
DL
176 if (!from_event) {
177 bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ?
178 disable_ap_sme : false;
179 wmi_disconnect_sta(wil, sta->addr, reason_code,
180 true, del_sta);
181 }
b516fcc5 182
fc58f681
VK
183 switch (wdev->iftype) {
184 case NL80211_IFTYPE_AP:
185 case NL80211_IFTYPE_P2P_GO:
186 /* AP-like interface */
187 cfg80211_del_sta(ndev, sta->addr, GFP_KERNEL);
188 break;
189 default:
190 break;
191 }
4d55a0a1
VK
192 sta->status = wil_sta_unused;
193 }
58527421 194 /* reorder buffers */
91886b0b 195 for (i = 0; i < WIL_STA_TID_NUM; i++) {
ec81b5ad 196 struct wil_tid_ampdu_rx *r;
ec81b5ad 197
bd33273b 198 spin_lock_bh(&sta->tid_rx_lock);
ec81b5ad
DL
199
200 r = sta->tid_rx[i];
91886b0b
VK
201 sta->tid_rx[i] = NULL;
202 wil_tid_ampdu_rx_free(wil, r);
ec81b5ad 203
bd33273b 204 spin_unlock_bh(&sta->tid_rx_lock);
91886b0b 205 }
58527421
VK
206 /* crypto context */
207 memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx));
208 memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx));
209 /* release vrings */
91886b0b
VK
210 for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
211 if (wil->vring2cid_tid[i][0] == cid)
212 wil_vring_fini_tx(wil, i);
213 }
58527421 214 /* statistics */
91886b0b
VK
215 memset(&sta->stats, 0, sizeof(sta->stats));
216}
217
f9e3033f 218static bool wil_is_connected(struct wil6210_priv *wil)
54eaa8c6
ME
219{
220 int i;
221
222 for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
223 if (wil->sta[i].status == wil_sta_connected)
224 return true;
225 }
226
227 return false;
228}
229
b516fcc5 230static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
4821e6d8 231 u16 reason_code, bool from_event)
2be7d22f 232{
91886b0b 233 int cid = -ENOENT;
2be7d22f 234 struct net_device *ndev = wil_to_ndev(wil);
91886b0b
VK
235 struct wireless_dev *wdev = wil->wdev;
236
2690c4c0
LD
237 if (unlikely(!ndev))
238 return;
239
91886b0b 240 might_sleep();
af3db60a 241 wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid,
0916d9f2 242 reason_code, from_event ? "+" : "-");
100106d7
VK
243
244 /* Cases are:
245 * - disconnect single STA, still connected
246 * - disconnect single STA, already disconnected
247 * - disconnect all
248 *
68682b41 249 * For "disconnect all", there are 3 options:
100106d7 250 * - bssid == NULL
68682b41 251 * - bssid is broadcast address (ff:ff:ff:ff:ff:ff)
100106d7
VK
252 * - bssid is our MAC address
253 */
68682b41
VK
254 if (bssid && !is_broadcast_ether_addr(bssid) &&
255 !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) {
91886b0b 256 cid = wil_find_cid(wil, bssid);
100106d7
VK
257 wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n",
258 bssid, cid, reason_code);
259 if (cid >= 0) /* disconnect 1 peer */
260 wil_disconnect_cid(wil, cid, reason_code, from_event);
261 } else { /* all */
262 wil_dbg_misc(wil, "Disconnect all\n");
91886b0b 263 for (cid = 0; cid < WIL6210_MAX_CID; cid++)
4821e6d8 264 wil_disconnect_cid(wil, cid, reason_code, from_event);
100106d7 265 }
91886b0b
VK
266
267 /* link state */
268 switch (wdev->iftype) {
269 case NL80211_IFTYPE_STATION:
270 case NL80211_IFTYPE_P2P_CLIENT:
41d6b093 271 wil_bcast_fini(wil);
f9e3033f 272 wil_update_net_queues_bh(wil, NULL, true);
c5e96c91 273 netif_carrier_off(ndev);
9953a782 274 wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
c5e96c91 275
9419b6a2
VK
276 if (test_bit(wil_status_fwconnected, wil->status)) {
277 clear_bit(wil_status_fwconnected, wil->status);
4821e6d8 278 cfg80211_disconnected(ndev, reason_code,
3b56c15f
DL
279 NULL, 0,
280 wil->locally_generated_disc,
281 GFP_KERNEL);
282 wil->locally_generated_disc = false;
9419b6a2 283 } else if (test_bit(wil_status_fwconnecting, wil->status)) {
91886b0b
VK
284 cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
285 WLAN_STATUS_UNSPECIFIED_FAILURE,
286 GFP_KERNEL);
bcdd49b0 287 wil->bss = NULL;
91886b0b 288 }
9419b6a2 289 clear_bit(wil_status_fwconnecting, wil->status);
91886b0b 290 break;
54eaa8c6
ME
291 case NL80211_IFTYPE_AP:
292 case NL80211_IFTYPE_P2P_GO:
f9e3033f
DL
293 if (!wil_is_connected(wil)) {
294 wil_update_net_queues_bh(wil, NULL, true);
54eaa8c6 295 clear_bit(wil_status_fwconnected, wil->status);
f9e3033f
DL
296 } else {
297 wil_update_net_queues_bh(wil, NULL, false);
298 }
54eaa8c6 299 break;
91886b0b 300 default:
91886b0b 301 break;
2be7d22f 302 }
2be7d22f
VK
303}
304
305static void wil_disconnect_worker(struct work_struct *work)
306{
307 struct wil6210_priv *wil = container_of(work,
308 struct wil6210_priv, disconnect_worker);
628639b1
DL
309 struct net_device *ndev = wil_to_ndev(wil);
310 int rc;
311 struct {
312 struct wmi_cmd_hdr wmi;
313 struct wmi_disconnect_event evt;
314 } __packed reply;
315
316 if (test_bit(wil_status_fwconnected, wil->status))
317 /* connect succeeded after all */
318 return;
319
320 if (!test_bit(wil_status_fwconnecting, wil->status))
321 /* already disconnected */
322 return;
323
324 rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
325 WMI_DISCONNECT_EVENTID, &reply, sizeof(reply),
326 WIL6210_DISCONNECT_TO_MS);
327 if (rc) {
328 wil_err(wil, "disconnect error %d\n", rc);
329 return;
330 }
2be7d22f 331
628639b1
DL
332 wil_update_net_queues_bh(wil, NULL, true);
333 netif_carrier_off(ndev);
334 cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0,
335 WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL);
336 clear_bit(wil_status_fwconnecting, wil->status);
2be7d22f
VK
337}
338
339static void wil_connect_timer_fn(ulong x)
340{
341 struct wil6210_priv *wil = (void *)x;
0916d9f2 342 bool q;
2be7d22f 343
0916d9f2 344 wil_err(wil, "Connect timeout detected, disconnect station\n");
2be7d22f
VK
345
346 /* reschedule to thread context - disconnect won't
0916d9f2
ME
347 * run from atomic context.
348 * queue on wmi_wq to prevent race with connect event.
2be7d22f 349 */
0916d9f2
ME
350 q = queue_work(wil->wmi_wq, &wil->disconnect_worker);
351 wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q);
2be7d22f
VK
352}
353
047e5d74
VK
354static void wil_scan_timer_fn(ulong x)
355{
356 struct wil6210_priv *wil = (void *)x;
357
9419b6a2 358 clear_bit(wil_status_fwready, wil->status);
047e5d74 359 wil_err(wil, "Scan timeout detected, start fw error recovery\n");
8ad6600f 360 wil_fw_error_recovery(wil);
047e5d74
VK
361}
362
c33407a8
VK
363static int wil_wait_for_recovery(struct wil6210_priv *wil)
364{
365 if (wait_event_interruptible(wil->wq, wil->recovery_state !=
366 fw_recovery_pending)) {
367 wil_err(wil, "Interrupt, canceling recovery\n");
368 return -ERESTARTSYS;
369 }
370 if (wil->recovery_state != fw_recovery_running) {
371 wil_info(wil, "Recovery cancelled\n");
372 return -EINTR;
373 }
374 wil_info(wil, "Proceed with recovery\n");
375 return 0;
376}
377
378void wil_set_recovery_state(struct wil6210_priv *wil, int state)
379{
af3db60a 380 wil_dbg_misc(wil, "set_recovery_state: %d -> %d\n",
c33407a8
VK
381 wil->recovery_state, state);
382
383 wil->recovery_state = state;
384 wake_up_interruptible(&wil->wq);
385}
386
375a173f
LD
387bool wil_is_recovery_blocked(struct wil6210_priv *wil)
388{
389 return no_fw_recovery && (wil->recovery_state == fw_recovery_pending);
390}
391
ed6f9dc6
VK
392static void wil_fw_error_worker(struct work_struct *work)
393{
c33407a8
VK
394 struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
395 fw_error_worker);
ed6f9dc6
VK
396 struct wireless_dev *wdev = wil->wdev;
397
398 wil_dbg_misc(wil, "fw error worker\n");
399
cded9369
VK
400 if (!netif_running(wil_to_ndev(wil))) {
401 wil_info(wil, "No recovery - interface is down\n");
402 return;
403 }
404
fc219eed
VK
405 /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO
406 * passed since last recovery attempt
407 */
408 if (time_is_after_jiffies(wil->last_fw_recovery +
409 WIL6210_FW_RECOVERY_TO))
410 wil->recovery_count++;
411 else
412 wil->recovery_count = 1; /* fw was alive for a long time */
413
414 if (wil->recovery_count > WIL6210_FW_RECOVERY_RETRIES) {
415 wil_err(wil, "too many recovery attempts (%d), giving up\n",
416 wil->recovery_count);
417 return;
418 }
419
420 wil->last_fw_recovery = jiffies;
421
dfb5b098
LD
422 wil_info(wil, "fw error recovery requested (try %d)...\n",
423 wil->recovery_count);
424 if (!no_fw_recovery)
425 wil->recovery_state = fw_recovery_running;
426 if (wil_wait_for_recovery(wil) != 0)
427 return;
428
9c3bde56 429 mutex_lock(&wil->mutex);
ed6f9dc6
VK
430 switch (wdev->iftype) {
431 case NL80211_IFTYPE_STATION:
432 case NL80211_IFTYPE_P2P_CLIENT:
433 case NL80211_IFTYPE_MONITOR:
dfb5b098 434 /* silent recovery, upper layers will see disconnect */
73d839ae
VK
435 __wil_down(wil);
436 __wil_up(wil);
ed6f9dc6
VK
437 break;
438 case NL80211_IFTYPE_AP:
439 case NL80211_IFTYPE_P2P_GO:
e240537b 440 wil_info(wil, "No recovery for AP-like interface\n");
ed6f9dc6
VK
441 /* recovery in these modes is done by upper layers */
442 break;
443 default:
e240537b
VK
444 wil_err(wil, "No recovery - unknown interface type %d\n",
445 wdev->iftype);
ed6f9dc6
VK
446 break;
447 }
9c3bde56 448 mutex_unlock(&wil->mutex);
ed6f9dc6
VK
449}
450
9a177384
VK
451static int wil_find_free_vring(struct wil6210_priv *wil)
452{
453 int i;
8fe59627 454
9a177384
VK
455 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
456 if (!wil->vring_tx[i].va)
457 return i;
458 }
459 return -EINVAL;
460}
461
0916d9f2
ME
462int wil_tx_init(struct wil6210_priv *wil, int cid)
463{
464 int rc = -EINVAL, ringid;
465
466 if (cid < 0) {
467 wil_err(wil, "No connection pending\n");
468 goto out;
469 }
470 ringid = wil_find_free_vring(wil);
471 if (ringid < 0) {
472 wil_err(wil, "No free vring found\n");
473 goto out;
474 }
475
476 wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n",
477 cid, ringid);
478
479 rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
480 if (rc)
481 wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n",
482 cid, ringid);
483
484out:
485 return rc;
486}
487
41d6b093
VK
488int wil_bcast_init(struct wil6210_priv *wil)
489{
490 int ri = wil->bcast_vring, rc;
491
492 if ((ri >= 0) && wil->vring_tx[ri].va)
493 return 0;
494
495 ri = wil_find_free_vring(wil);
496 if (ri < 0)
497 return ri;
498
230d8442 499 wil->bcast_vring = ri;
41d6b093 500 rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order);
230d8442
VK
501 if (rc)
502 wil->bcast_vring = -1;
41d6b093
VK
503
504 return rc;
505}
506
507void wil_bcast_fini(struct wil6210_priv *wil)
508{
509 int ri = wil->bcast_vring;
510
511 if (ri < 0)
512 return;
513
514 wil->bcast_vring = -1;
515 wil_vring_fini_tx(wil, ri);
516}
517
2be7d22f
VK
518int wil_priv_init(struct wil6210_priv *wil)
519{
ec81b5ad
DL
520 uint i;
521
af3db60a 522 wil_dbg_misc(wil, "priv_init\n");
2be7d22f 523
3df2cd36 524 memset(wil->sta, 0, sizeof(wil->sta));
ec81b5ad
DL
525 for (i = 0; i < WIL6210_MAX_CID; i++)
526 spin_lock_init(&wil->sta[i].tid_rx_lock);
3df2cd36 527
875e9439
ME
528 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
529 spin_lock_init(&wil->vring_tx_data[i].lock);
530
2be7d22f
VK
531 mutex_init(&wil->mutex);
532 mutex_init(&wil->wmi_mutex);
40822a90 533 mutex_init(&wil->probe_client_mutex);
4332cac1 534 mutex_init(&wil->p2p_wdev_mutex);
349214c1 535 mutex_init(&wil->halp.lock);
2be7d22f
VK
536
537 init_completion(&wil->wmi_ready);
59502647 538 init_completion(&wil->wmi_call);
349214c1 539 init_completion(&wil->halp.comp);
2be7d22f 540
41d6b093 541 wil->bcast_vring = -1;
2be7d22f 542 setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
047e5d74 543 setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil);
e6d68341
DL
544 setup_timer(&wil->p2p.discovery_timer, wil_p2p_discovery_timer_fn,
545 (ulong)wil);
2be7d22f 546
2be7d22f
VK
547 INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
548 INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
ed6f9dc6 549 INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
40822a90 550 INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker);
bb6743f7 551 INIT_WORK(&wil->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);
2be7d22f
VK
552
553 INIT_LIST_HEAD(&wil->pending_wmi_ev);
40822a90 554 INIT_LIST_HEAD(&wil->probe_client_pending);
2be7d22f 555 spin_lock_init(&wil->wmi_ev_lock);
f9e3033f
DL
556 spin_lock_init(&wil->net_queue_lock);
557 wil->net_queue_stopped = 1;
c33407a8 558 init_waitqueue_head(&wil->wq);
2be7d22f 559
3277213f 560 wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi");
2be7d22f
VK
561 if (!wil->wmi_wq)
562 return -EAGAIN;
563
3277213f
VK
564 wil->wq_service = create_singlethread_workqueue(WIL_NAME "_service");
565 if (!wil->wq_service)
566 goto out_wmi_wq;
2be7d22f 567
fc219eed 568 wil->last_fw_recovery = jiffies;
1f80af2e
VS
569 wil->tx_interframe_timeout = WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT;
570 wil->rx_interframe_timeout = WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT;
571 wil->tx_max_burst_duration = WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT;
572 wil->rx_max_burst_duration = WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT;
fc219eed 573
ab954628
VK
574 if (rx_ring_overflow_thrsh == WIL6210_RX_HIGH_TRSH_INIT)
575 rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_DEFAULT;
8b068c03
LA
576
577 wil->ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
578
fe9ee51e
ME
579 wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
580 WMI_WAKEUP_TRIGGER_BCAST;
581
2be7d22f 582 return 0;
3277213f
VK
583
584out_wmi_wq:
585 destroy_workqueue(wil->wmi_wq);
586
587 return -EAGAIN;
2be7d22f
VK
588}
589
9953a782
LD
590void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
591{
fe9ee51e
ME
592 if (wil->platform_ops.bus_request) {
593 wil->bus_request_kbps = kbps;
9953a782 594 wil->platform_ops.bus_request(wil->platform_handle, kbps);
fe9ee51e 595 }
9953a782
LD
596}
597
b516fcc5
VK
598/**
599 * wil6210_disconnect - disconnect one connection
600 * @wil: driver context
601 * @bssid: peer to disconnect, NULL to disconnect all
4821e6d8 602 * @reason_code: Reason code for the Disassociation frame
b516fcc5
VK
603 * @from_event: whether is invoked from FW event handler
604 *
605 * Disconnect and release associated resources. If invoked not from the
606 * FW event handler, issue WMI command(s) to trigger MAC disconnect.
607 */
608void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
4821e6d8 609 u16 reason_code, bool from_event)
2be7d22f 610{
af3db60a 611 wil_dbg_misc(wil, "disconnect\n");
9cf10d62 612
2be7d22f 613 del_timer_sync(&wil->connect_timer);
4821e6d8 614 _wil6210_disconnect(wil, bssid, reason_code, from_event);
2be7d22f
VK
615}
616
617void wil_priv_deinit(struct wil6210_priv *wil)
618{
af3db60a 619 wil_dbg_misc(wil, "priv_deinit\n");
9cf10d62 620
c33407a8 621 wil_set_recovery_state(wil, fw_recovery_idle);
047e5d74 622 del_timer_sync(&wil->scan_timer);
e6d68341 623 del_timer_sync(&wil->p2p.discovery_timer);
2be7d22f 624 cancel_work_sync(&wil->disconnect_worker);
ed6f9dc6 625 cancel_work_sync(&wil->fw_error_worker);
e6d68341 626 cancel_work_sync(&wil->p2p.discovery_expired_work);
bb6743f7 627 cancel_work_sync(&wil->p2p.delayed_listen_work);
097638a0 628 mutex_lock(&wil->mutex);
4821e6d8 629 wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
097638a0 630 mutex_unlock(&wil->mutex);
2be7d22f 631 wmi_event_flush(wil);
40822a90
VK
632 wil_probe_client_flush(wil);
633 cancel_work_sync(&wil->probe_client_worker);
3277213f 634 destroy_workqueue(wil->wq_service);
2be7d22f
VK
635 destroy_workqueue(wil->wmi_wq);
636}
637
151a9706
VK
638static inline void wil_halt_cpu(struct wil6210_priv *wil)
639{
b9eeb512
VK
640 wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
641 wil_w(wil, RGF_USER_MAC_CPU_0, BIT_USER_MAC_CPU_MAN_RST);
151a9706
VK
642}
643
644static inline void wil_release_cpu(struct wil6210_priv *wil)
645{
646 /* Start CPU */
b9eeb512 647 wil_w(wil, RGF_USER_USER_CPU_0, 1);
151a9706
VK
648}
649
b8c31b5d 650static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
1f1a361a 651{
b8c31b5d
LD
652 wil_info(wil, "oob_mode to %d\n", mode);
653 switch (mode) {
654 case 0:
655 wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE |
656 BIT_USER_OOB_R2_MODE);
657 break;
658 case 1:
659 wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_R2_MODE);
1f1a361a 660 wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
b8c31b5d
LD
661 break;
662 case 2:
1f1a361a 663 wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
b8c31b5d
LD
664 wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_R2_MODE);
665 break;
666 default:
667 wil_err(wil, "invalid oob_mode: %d\n", mode);
668 }
1f1a361a
LD
669}
670
bbb2adc7 671static int wil_target_reset(struct wil6210_priv *wil)
2be7d22f 672{
98a65b59 673 int delay = 0;
bb6c8dcc 674 u32 x, x1 = 0;
36b10a72 675
1aeda13b 676 wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name);
6508281b
VK
677
678 /* Clear MAC link up */
b9eeb512
VK
679 wil_s(wil, RGF_HP_CTRL, BIT(15));
680 wil_s(wil, RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_HPAL_PERST_FROM_PAD);
681 wil_s(wil, RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST);
151a9706
VK
682
683 wil_halt_cpu(wil);
2be7d22f 684
2cd0f021 685 /* clear all boot loader "ready" bits */
b9eeb512
VK
686 wil_w(wil, RGF_USER_BL +
687 offsetof(struct bl_dedicated_registers_v0, boot_loader_ready), 0);
cce47711 688 /* Clear Fw Download notification */
b9eeb512 689 wil_c(wil, RGF_USER_USAGE_6, BIT(0));
cce47711 690
b9eeb512 691 wil_s(wil, RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
9a5511b5
VK
692 /* XTAL stabilization should take about 3ms */
693 usleep_range(5000, 7000);
b9eeb512 694 x = wil_r(wil, RGF_CAF_PLL_LOCK_STATUS);
9a5511b5
VK
695 if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) {
696 wil_err(wil, "Xtal stabilization timeout\n"
697 "RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x);
698 return -ETIME;
6508281b 699 }
9a5511b5 700 /* switch 10k to XTAL*/
b9eeb512 701 wil_c(wil, RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF);
9a5511b5 702 /* 40 MHz */
b9eeb512 703 wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL);
9a5511b5 704
b9eeb512
VK
705 wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
706 wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
6508281b 707
b9eeb512
VK
708 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
709 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
710 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x000000f0);
711 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00);
2be7d22f 712
b9eeb512
VK
713 wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
714 wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
6508281b 715
b9eeb512
VK
716 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
717 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
718 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
719 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
2be7d22f 720
b9eeb512
VK
721 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
722 /* reset A2 PCIE AHB */
723 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
6508281b 724
b9eeb512 725 wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
2be7d22f 726
2cd0f021 727 /* wait until device ready. typical time is 20..80 msec */
36b10a72 728 do {
520d68e7 729 msleep(RST_DELAY);
b9eeb512
VK
730 x = wil_r(wil, RGF_USER_BL +
731 offsetof(struct bl_dedicated_registers_v0,
732 boot_loader_ready));
bb6c8dcc
VK
733 if (x1 != x) {
734 wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n", x1, x);
735 x1 = x;
736 }
520d68e7 737 if (delay++ > RST_COUNT) {
2cd0f021 738 wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
48516298 739 x);
bbb2adc7 740 return -ETIME;
36b10a72 741 }
f1ad8c93 742 } while (x != BL_READY);
36b10a72 743
b9eeb512 744 wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
972072aa 745
e3351277 746 /* enable fix for HW bug related to the SA/DA swap in AP Rx */
b9eeb512
VK
747 wil_s(wil, RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN |
748 BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC);
e3351277 749
520d68e7 750 wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
bbb2adc7 751 return 0;
151a9706 752}
2be7d22f 753
3fea18d0
LD
754static void wil_collect_fw_info(struct wil6210_priv *wil)
755{
756 struct wiphy *wiphy = wil_to_wiphy(wil);
757 u8 retry_short;
758 int rc;
759
760 rc = wmi_get_mgmt_retry(wil, &retry_short);
761 if (!rc) {
762 wiphy->retry_short = retry_short;
763 wil_dbg_misc(wil, "FW retry_short: %d\n", retry_short);
764 }
765}
766
2be7d22f
VK
767void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
768{
769 le32_to_cpus(&r->base);
770 le16_to_cpus(&r->entry_size);
771 le16_to_cpus(&r->size);
772 le32_to_cpus(&r->tail);
773 le32_to_cpus(&r->head);
774}
775
2cd0f021
VK
776static int wil_get_bl_info(struct wil6210_priv *wil)
777{
778 struct net_device *ndev = wil_to_ndev(wil);
b42f1196 779 struct wiphy *wiphy = wil_to_wiphy(wil);
f1ad8c93
VK
780 union {
781 struct bl_dedicated_registers_v0 bl0;
782 struct bl_dedicated_registers_v1 bl1;
783 } bl;
784 u32 bl_ver;
785 u8 *mac;
786 u16 rf_status;
787
19c871ce
VK
788 wil_memcpy_fromio_32(&bl, wil->csr + HOSTADDR(RGF_USER_BL),
789 sizeof(bl));
790 bl_ver = le32_to_cpu(bl.bl0.boot_loader_struct_version);
791 mac = bl.bl0.mac_address;
792
793 if (bl_ver == 0) {
f1ad8c93
VK
794 le32_to_cpus(&bl.bl0.rf_type);
795 le32_to_cpus(&bl.bl0.baseband_type);
f1ad8c93
VK
796 rf_status = 0; /* actually, unknown */
797 wil_info(wil,
798 "Boot Loader struct v%d: MAC = %pM RF = 0x%08x bband = 0x%08x\n",
799 bl_ver, mac,
800 bl.bl0.rf_type, bl.bl0.baseband_type);
801 wil_info(wil, "Boot Loader build unknown for struct v0\n");
19c871ce 802 } else {
f1ad8c93
VK
803 le16_to_cpus(&bl.bl1.rf_type);
804 rf_status = le16_to_cpu(bl.bl1.rf_status);
805 le32_to_cpus(&bl.bl1.baseband_type);
806 le16_to_cpus(&bl.bl1.bl_version_subminor);
807 le16_to_cpus(&bl.bl1.bl_version_build);
f1ad8c93
VK
808 wil_info(wil,
809 "Boot Loader struct v%d: MAC = %pM RF = 0x%04x (status 0x%04x) bband = 0x%08x\n",
810 bl_ver, mac,
811 bl.bl1.rf_type, rf_status,
812 bl.bl1.baseband_type);
813 wil_info(wil, "Boot Loader build %d.%d.%d.%d\n",
814 bl.bl1.bl_version_major, bl.bl1.bl_version_minor,
815 bl.bl1.bl_version_subminor, bl.bl1.bl_version_build);
f1ad8c93 816 }
2cd0f021 817
f1ad8c93
VK
818 if (!is_valid_ether_addr(mac)) {
819 wil_err(wil, "BL: Invalid MAC %pM\n", mac);
2cd0f021
VK
820 return -EINVAL;
821 }
822
f1ad8c93 823 ether_addr_copy(ndev->perm_addr, mac);
b42f1196 824 ether_addr_copy(wiphy->perm_addr, mac);
2cd0f021 825 if (!is_valid_ether_addr(ndev->dev_addr))
f1ad8c93
VK
826 ether_addr_copy(ndev->dev_addr, mac);
827
828 if (rf_status) {/* bad RF cable? */
829 wil_err(wil, "RF communication error 0x%04x",
830 rf_status);
831 return -EAGAIN;
832 }
2cd0f021
VK
833
834 return 0;
835}
836
409ead54
VK
837static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err)
838{
839 u32 bl_assert_code, bl_assert_blink, bl_magic_number;
840 u32 bl_ver = wil_r(wil, RGF_USER_BL +
841 offsetof(struct bl_dedicated_registers_v0,
842 boot_loader_struct_version));
843
844 if (bl_ver < 2)
845 return;
846
847 bl_assert_code = wil_r(wil, RGF_USER_BL +
848 offsetof(struct bl_dedicated_registers_v1,
849 bl_assert_code));
850 bl_assert_blink = wil_r(wil, RGF_USER_BL +
851 offsetof(struct bl_dedicated_registers_v1,
852 bl_assert_blink));
853 bl_magic_number = wil_r(wil, RGF_USER_BL +
854 offsetof(struct bl_dedicated_registers_v1,
855 bl_magic_number));
856
857 if (is_err) {
858 wil_err(wil,
859 "BL assert code 0x%08x blink 0x%08x magic 0x%08x\n",
860 bl_assert_code, bl_assert_blink, bl_magic_number);
861 } else {
862 wil_dbg_misc(wil,
863 "BL assert code 0x%08x blink 0x%08x magic 0x%08x\n",
864 bl_assert_code, bl_assert_blink, bl_magic_number);
865 }
866}
867
2be7d22f
VK
868static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
869{
870 ulong to = msecs_to_jiffies(1000);
871 ulong left = wait_for_completion_timeout(&wil->wmi_ready, to);
8fe59627 872
2be7d22f
VK
873 if (0 == left) {
874 wil_err(wil, "Firmware not ready\n");
875 return -ETIME;
876 } else {
15e23124
VK
877 wil_info(wil, "FW ready after %d ms. HW version 0x%08x\n",
878 jiffies_to_msecs(to-left), wil->hw_version);
2be7d22f
VK
879 }
880 return 0;
881}
882
035859a5
ME
883void wil_abort_scan(struct wil6210_priv *wil, bool sync)
884{
885 int rc;
886 struct cfg80211_scan_info info = {
887 .aborted = true,
888 };
889
890 lockdep_assert_held(&wil->p2p_wdev_mutex);
891
892 if (!wil->scan_request)
893 return;
894
895 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request);
896 del_timer_sync(&wil->scan_timer);
897 mutex_unlock(&wil->p2p_wdev_mutex);
898 rc = wmi_abort_scan(wil);
899 if (!rc && sync)
900 wait_event_interruptible_timeout(wil->wq, !wil->scan_request,
901 msecs_to_jiffies(
902 WAIT_FOR_SCAN_ABORT_MS));
903
904 mutex_lock(&wil->p2p_wdev_mutex);
905 if (wil->scan_request) {
906 cfg80211_scan_done(wil->scan_request, &info);
907 wil->scan_request = NULL;
908 }
909}
910
8b068c03
LA
911int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile)
912{
913 int rc;
914
915 if (!test_bit(WMI_FW_CAPABILITY_PS_CONFIG, wil->fw_capabilities)) {
916 wil_err(wil, "set_power_mgmt not supported\n");
917 return -EOPNOTSUPP;
918 }
919
920 rc = wmi_ps_dev_profile_cfg(wil, ps_profile);
921 if (rc)
922 wil_err(wil, "wmi_ps_dev_profile_cfg failed (%d)\n", rc);
923 else
924 wil->ps_profile = ps_profile;
925
926 return rc;
927}
928
2be7d22f
VK
929/*
930 * We reset all the structures, and we reset the UMAC.
931 * After calling this routine, you're expected to reload
932 * the firmware.
933 */
2cd0f021 934int wil_reset(struct wil6210_priv *wil, bool load_fw)
2be7d22f
VK
935{
936 int rc;
937
af3db60a 938 wil_dbg_misc(wil, "reset\n");
9cf10d62 939
097638a0 940 WARN_ON(!mutex_is_locked(&wil->mutex));
9419b6a2 941 WARN_ON(test_bit(wil_status_napi_en, wil->status));
097638a0 942
bfc2dc7a
VK
943 if (debug_fw) {
944 static const u8 mac[ETH_ALEN] = {
945 0x00, 0xde, 0xad, 0x12, 0x34, 0x56,
946 };
947 struct net_device *ndev = wil_to_ndev(wil);
948
949 ether_addr_copy(ndev->perm_addr, mac);
950 ether_addr_copy(ndev->dev_addr, ndev->perm_addr);
951 return 0;
952 }
953
67131a1d
VK
954 if (wil->hw_version == HW_VER_UNKNOWN)
955 return -ENODEV;
956
5f0823ef
ME
957 if (wil->platform_ops.notify) {
958 rc = wil->platform_ops.notify(wil->platform_handle,
959 WIL_PLATFORM_EVT_PRE_RESET);
960 if (rc)
af3db60a
LA
961 wil_err(wil, "PRE_RESET platform notify failed, rc %d\n",
962 rc);
5f0823ef
ME
963 }
964
f13e0630
HK
965 set_bit(wil_status_resetting, wil->status);
966
097638a0 967 cancel_work_sync(&wil->disconnect_worker);
4821e6d8 968 wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
41d6b093 969 wil_bcast_fini(wil);
097638a0 970
10d599ad
ME
971 /* Disable device led before reset*/
972 wmi_led_cfg(wil, false);
973
82e9f646
HK
974 mutex_lock(&wil->p2p_wdev_mutex);
975 wil_abort_scan(wil, false);
976 mutex_unlock(&wil->p2p_wdev_mutex);
977
452133a7
ME
978 /* prevent NAPI from being scheduled and prevent wmi commands */
979 mutex_lock(&wil->wmi_mutex);
9419b6a2 980 bitmap_zero(wil->status, wil_status_last);
452133a7 981 mutex_unlock(&wil->wmi_mutex);
0fef1818 982
e4dbb093 983 wil_mask_irq(wil);
e08b5906 984
2be7d22f
VK
985 wmi_event_flush(wil);
986
3277213f 987 flush_workqueue(wil->wq_service);
e08b5906 988 flush_workqueue(wil->wmi_wq);
2be7d22f 989
409ead54 990 wil_bl_crash_info(wil, false);
3ee908dc 991 wil_disable_irq(wil);
bbb2adc7 992 rc = wil_target_reset(wil);
3ee908dc
HK
993 wil6210_clear_irq(wil);
994 wil_enable_irq(wil);
8bf6adb9 995 wil_rx_fini(wil);
409ead54
VK
996 if (rc) {
997 wil_bl_crash_info(wil, true);
bbb2adc7 998 return rc;
409ead54 999 }
bbb2adc7 1000
2cd0f021 1001 rc = wil_get_bl_info(wil);
f1ad8c93
VK
1002 if (rc == -EAGAIN && !load_fw) /* ignore RF error if not going up */
1003 rc = 0;
2cd0f021
VK
1004 if (rc)
1005 return rc;
1006
1f1a361a 1007 wil_set_oob_mode(wil, oob_mode);
2cd0f021 1008 if (load_fw) {
a351f2f5
LA
1009 wil_info(wil, "Use firmware <%s> + board <%s>\n",
1010 wil->wil_fw_name, WIL_BOARD_FILE_NAME);
2cd0f021 1011
151a9706 1012 wil_halt_cpu(wil);
13cd9f75 1013 memset(wil->fw_version, 0, sizeof(wil->fw_version));
151a9706 1014 /* Loading f/w from the file */
a351f2f5 1015 rc = wil_request_firmware(wil, wil->wil_fw_name, true);
151a9706
VK
1016 if (rc)
1017 return rc;
a351f2f5 1018 rc = wil_request_firmware(wil, WIL_BOARD_FILE_NAME, true);
2cd0f021
VK
1019 if (rc)
1020 return rc;
1021
1022 /* Mark FW as loaded from host */
b9eeb512 1023 wil_s(wil, RGF_USER_USAGE_6, 1);
151a9706 1024
2cd0f021
VK
1025 /* clear any interrupts which on-card-firmware
1026 * may have set
1027 */
151a9706 1028 wil6210_clear_irq(wil);
2cd0f021
VK
1029 /* CAF_ICR - clear and mask */
1030 /* it is W1C, clear by writing back same value */
b9eeb512
VK
1031 wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
1032 wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
2cd0f021 1033
151a9706 1034 wil_release_cpu(wil);
151a9706 1035 }
8bf6adb9 1036
2be7d22f 1037 /* init after reset */
02beaf1a 1038 wil->ap_isolate = 0;
16735d02 1039 reinit_completion(&wil->wmi_ready);
59502647 1040 reinit_completion(&wil->wmi_call);
349214c1 1041 reinit_completion(&wil->halp.comp);
2be7d22f 1042
2cd0f021
VK
1043 if (load_fw) {
1044 wil_configure_interrupt_moderation(wil);
1045 wil_unmask_irq(wil);
2be7d22f 1046
2cd0f021
VK
1047 /* we just started MAC, wait for FW ready */
1048 rc = wil_wait_for_fw_ready(wil);
5f0823ef
ME
1049 if (rc)
1050 return rc;
1051
1052 /* check FW is responsive */
1053 rc = wmi_echo(wil);
1054 if (rc) {
af3db60a 1055 wil_err(wil, "wmi_echo failed, rc %d\n", rc);
5f0823ef
ME
1056 return rc;
1057 }
1058
8b068c03
LA
1059 if (wil->ps_profile != WMI_PS_PROFILE_TYPE_DEFAULT)
1060 wil_ps_update(wil, wil->ps_profile);
1061
3fea18d0
LD
1062 wil_collect_fw_info(wil);
1063
5f0823ef
ME
1064 if (wil->platform_ops.notify) {
1065 rc = wil->platform_ops.notify(wil->platform_handle,
1066 WIL_PLATFORM_EVT_FW_RDY);
1067 if (rc) {
af3db60a
LA
1068 wil_err(wil, "FW_RDY notify failed, rc %d\n",
1069 rc);
5f0823ef
ME
1070 rc = 0;
1071 }
1072 }
2cd0f021 1073 }
2be7d22f
VK
1074
1075 return rc;
1076}
1077
ed6f9dc6
VK
1078void wil_fw_error_recovery(struct wil6210_priv *wil)
1079{
1080 wil_dbg_misc(wil, "starting fw error recovery\n");
f13e0630
HK
1081
1082 if (test_bit(wil_status_resetting, wil->status)) {
1083 wil_info(wil, "Reset already in progress\n");
1084 return;
1085 }
1086
c33407a8 1087 wil->recovery_state = fw_recovery_pending;
ed6f9dc6
VK
1088 schedule_work(&wil->fw_error_worker);
1089}
2be7d22f 1090
73d839ae 1091int __wil_up(struct wil6210_priv *wil)
2be7d22f
VK
1092{
1093 struct net_device *ndev = wil_to_ndev(wil);
1094 struct wireless_dev *wdev = wil->wdev;
2be7d22f 1095 int rc;
2be7d22f 1096
097638a0
VK
1097 WARN_ON(!mutex_is_locked(&wil->mutex));
1098
2cd0f021 1099 rc = wil_reset(wil, true);
2be7d22f
VK
1100 if (rc)
1101 return rc;
1102
e31b2562 1103 /* Rx VRING. After MAC and beacon */
d3762b40 1104 rc = wil_rx_init(wil, 1 << rx_ring_order);
e31b2562
VK
1105 if (rc)
1106 return rc;
1107
2be7d22f
VK
1108 switch (wdev->iftype) {
1109 case NL80211_IFTYPE_STATION:
7743882d 1110 wil_dbg_misc(wil, "type: STATION\n");
2be7d22f
VK
1111 ndev->type = ARPHRD_ETHER;
1112 break;
1113 case NL80211_IFTYPE_AP:
7743882d 1114 wil_dbg_misc(wil, "type: AP\n");
2be7d22f
VK
1115 ndev->type = ARPHRD_ETHER;
1116 break;
1117 case NL80211_IFTYPE_P2P_CLIENT:
7743882d 1118 wil_dbg_misc(wil, "type: P2P_CLIENT\n");
2be7d22f
VK
1119 ndev->type = ARPHRD_ETHER;
1120 break;
1121 case NL80211_IFTYPE_P2P_GO:
7743882d 1122 wil_dbg_misc(wil, "type: P2P_GO\n");
2be7d22f
VK
1123 ndev->type = ARPHRD_ETHER;
1124 break;
1125 case NL80211_IFTYPE_MONITOR:
7743882d 1126 wil_dbg_misc(wil, "type: Monitor\n");
2be7d22f
VK
1127 ndev->type = ARPHRD_IEEE80211_RADIOTAP;
1128 /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
1129 break;
1130 default:
1131 return -EOPNOTSUPP;
1132 }
1133
2be7d22f
VK
1134 /* MAC address - pre-requisite for other commands */
1135 wmi_set_mac_address(wil, ndev->dev_addr);
1136
73d839ae 1137 wil_dbg_misc(wil, "NAPI enable\n");
e0287c4a
VK
1138 napi_enable(&wil->napi_rx);
1139 napi_enable(&wil->napi_tx);
9419b6a2 1140 set_bit(wil_status_napi_en, wil->status);
e0287c4a 1141
9953a782 1142 wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
f772ebfb 1143
2be7d22f
VK
1144 return 0;
1145}
1146
1147int wil_up(struct wil6210_priv *wil)
1148{
1149 int rc;
1150
af3db60a 1151 wil_dbg_misc(wil, "up\n");
9cf10d62 1152
2be7d22f
VK
1153 mutex_lock(&wil->mutex);
1154 rc = __wil_up(wil);
1155 mutex_unlock(&wil->mutex);
1156
1157 return rc;
1158}
1159
73d839ae 1160int __wil_down(struct wil6210_priv *wil)
2be7d22f 1161{
097638a0
VK
1162 WARN_ON(!mutex_is_locked(&wil->mutex));
1163
b0c0e688
LA
1164 set_bit(wil_status_resetting, wil->status);
1165
9953a782 1166 wil6210_bus_request(wil, 0);
f772ebfb 1167
73d839ae 1168 wil_disable_irq(wil);
9419b6a2 1169 if (test_and_clear_bit(wil_status_napi_en, wil->status)) {
73d839ae
VK
1170 napi_disable(&wil->napi_rx);
1171 napi_disable(&wil->napi_tx);
1172 wil_dbg_misc(wil, "NAPI disable\n");
1173 }
1174 wil_enable_irq(wil);
e0287c4a 1175
5ffae432 1176 mutex_lock(&wil->p2p_wdev_mutex);
035859a5
ME
1177 wil_p2p_stop_radio_operations(wil);
1178 wil_abort_scan(wil, false);
5ffae432 1179 mutex_unlock(&wil->p2p_wdev_mutex);
2be7d22f 1180
2cd0f021 1181 wil_reset(wil, false);
2be7d22f
VK
1182
1183 return 0;
1184}
1185
1186int wil_down(struct wil6210_priv *wil)
1187{
1188 int rc;
1189
af3db60a 1190 wil_dbg_misc(wil, "down\n");
9cf10d62 1191
c33407a8 1192 wil_set_recovery_state(wil, fw_recovery_idle);
2be7d22f
VK
1193 mutex_lock(&wil->mutex);
1194 rc = __wil_down(wil);
1195 mutex_unlock(&wil->mutex);
1196
1197 return rc;
1198}
3df2cd36
VK
1199
1200int wil_find_cid(struct wil6210_priv *wil, const u8 *mac)
1201{
1202 int i;
1203 int rc = -ENOENT;
1204
1205 for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
1206 if ((wil->sta[i].status != wil_sta_unused) &&
108d1eb6 1207 ether_addr_equal(wil->sta[i].addr, mac)) {
3df2cd36
VK
1208 rc = i;
1209 break;
1210 }
1211 }
1212
1213 return rc;
1214}
349214c1
ME
1215
1216void wil_halp_vote(struct wil6210_priv *wil)
1217{
1218 unsigned long rc;
1219 unsigned long to_jiffies = msecs_to_jiffies(WAIT_FOR_HALP_VOTE_MS);
1220
1221 mutex_lock(&wil->halp.lock);
1222
af3db60a 1223 wil_dbg_irq(wil, "halp_vote: start, HALP ref_cnt (%d)\n",
ef86f249 1224 wil->halp.ref_cnt);
349214c1
ME
1225
1226 if (++wil->halp.ref_cnt == 1) {
18618a9f 1227 reinit_completion(&wil->halp.comp);
349214c1
ME
1228 wil6210_set_halp(wil);
1229 rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
f1b7764f 1230 if (!rc) {
af3db60a 1231 wil_err(wil, "HALP vote timed out\n");
f1b7764f
ME
1232 /* Mask HALP as done in case the interrupt is raised */
1233 wil6210_mask_halp(wil);
1234 } else {
ef86f249 1235 wil_dbg_irq(wil,
af3db60a 1236 "halp_vote: HALP vote completed after %d ms\n",
ef86f249 1237 jiffies_to_msecs(to_jiffies - rc));
f1b7764f 1238 }
349214c1
ME
1239 }
1240
af3db60a 1241 wil_dbg_irq(wil, "halp_vote: end, HALP ref_cnt (%d)\n",
ef86f249 1242 wil->halp.ref_cnt);
349214c1
ME
1243
1244 mutex_unlock(&wil->halp.lock);
1245}
1246
1247void wil_halp_unvote(struct wil6210_priv *wil)
1248{
1249 WARN_ON(wil->halp.ref_cnt == 0);
1250
1251 mutex_lock(&wil->halp.lock);
1252
af3db60a 1253 wil_dbg_irq(wil, "halp_unvote: start, HALP ref_cnt (%d)\n",
ef86f249 1254 wil->halp.ref_cnt);
349214c1
ME
1255
1256 if (--wil->halp.ref_cnt == 0) {
1257 wil6210_clear_halp(wil);
af3db60a 1258 wil_dbg_irq(wil, "HALP unvote\n");
349214c1
ME
1259 }
1260
af3db60a 1261 wil_dbg_irq(wil, "halp_unvote:end, HALP ref_cnt (%d)\n",
ef86f249 1262 wil->halp.ref_cnt);
349214c1
ME
1263
1264 mutex_unlock(&wil->halp.lock);
1265}