1 /*
2  * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
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 
17 #include <linux/moduleparam.h>
18 #include <linux/if_arp.h>
19 #include <linux/etherdevice.h>
20 
21 #include "wil6210.h"
22 #include "txrx.h"
23 #include "wmi.h"
24 
25 #define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000
26 #define WAIT_FOR_DISCONNECT_INTERVAL_MS 10
27 
28 static bool no_fw_recovery;
29 module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR);
30 MODULE_PARM_DESC(no_fw_recovery, " disable FW error recovery");
31 
32 static bool no_fw_load = true;
33 module_param(no_fw_load, bool, S_IRUGO | S_IWUSR);
34 MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash.");
35 
36 #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
37 #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
38 
39 /*
40  * Due to a hardware issue,
41  * one has to read/write to/from NIC in 32-bit chunks;
42  * regular memcpy_fromio and siblings will
43  * not work on 64-bit platform - it uses 64-bit transactions
44  *
45  * Force 32-bit transactions to enable NIC on 64-bit platforms
46  *
47  * To avoid byte swap on big endian host, __raw_{read|write}l
48  * should be used - {read|write}l would swap bytes to provide
49  * little endian on PCI value in host endianness.
50  */
51 void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
52 			  size_t count)
53 {
54 	u32 *d = dst;
55 	const volatile u32 __iomem *s = src;
56 
57 	/* size_t is unsigned, if (count%4 != 0) it will wrap */
58 	for (count += 4; count > 4; count -= 4)
59 		*d++ = __raw_readl(s++);
60 }
61 
62 void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
63 			size_t count)
64 {
65 	volatile u32 __iomem *d = dst;
66 	const u32 *s = src;
67 
68 	for (count += 4; count > 4; count -= 4)
69 		__raw_writel(*s++, d++);
70 }
71 
72 static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
73 {
74 	uint i;
75 	struct net_device *ndev = wil_to_ndev(wil);
76 	struct wireless_dev *wdev = wil->wdev;
77 	struct wil_sta_info *sta = &wil->sta[cid];
78 
79 	wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid,
80 		     sta->status);
81 
82 	sta->data_port_open = false;
83 	if (sta->status != wil_sta_unused) {
84 		wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING);
85 		switch (wdev->iftype) {
86 		case NL80211_IFTYPE_AP:
87 		case NL80211_IFTYPE_P2P_GO:
88 			/* AP-like interface */
89 			cfg80211_del_sta(ndev, sta->addr, GFP_KERNEL);
90 			break;
91 		default:
92 			break;
93 		}
94 		sta->status = wil_sta_unused;
95 	}
96 
97 	for (i = 0; i < WIL_STA_TID_NUM; i++) {
98 		struct wil_tid_ampdu_rx *r;
99 		unsigned long flags;
100 
101 		spin_lock_irqsave(&sta->tid_rx_lock, flags);
102 
103 		r = sta->tid_rx[i];
104 		sta->tid_rx[i] = NULL;
105 		wil_tid_ampdu_rx_free(wil, r);
106 
107 		spin_unlock_irqrestore(&sta->tid_rx_lock, flags);
108 	}
109 	for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
110 		if (wil->vring2cid_tid[i][0] == cid)
111 			wil_vring_fini_tx(wil, i);
112 	}
113 	memset(&sta->stats, 0, sizeof(sta->stats));
114 }
115 
116 static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
117 {
118 	int cid = -ENOENT;
119 	struct net_device *ndev = wil_to_ndev(wil);
120 	struct wireless_dev *wdev = wil->wdev;
121 
122 	might_sleep();
123 	if (bssid) {
124 		cid = wil_find_cid(wil, bssid);
125 		wil_dbg_misc(wil, "%s(%pM, CID %d)\n", __func__, bssid, cid);
126 	} else {
127 		wil_dbg_misc(wil, "%s(all)\n", __func__);
128 	}
129 
130 	if (cid >= 0) /* disconnect 1 peer */
131 		wil_disconnect_cid(wil, cid);
132 	else /* disconnect all */
133 		for (cid = 0; cid < WIL6210_MAX_CID; cid++)
134 			wil_disconnect_cid(wil, cid);
135 
136 	/* link state */
137 	switch (wdev->iftype) {
138 	case NL80211_IFTYPE_STATION:
139 	case NL80211_IFTYPE_P2P_CLIENT:
140 		wil_link_off(wil);
141 		if (test_bit(wil_status_fwconnected, &wil->status)) {
142 			clear_bit(wil_status_fwconnected, &wil->status);
143 			cfg80211_disconnected(ndev,
144 					      WLAN_STATUS_UNSPECIFIED_FAILURE,
145 					      NULL, 0, GFP_KERNEL);
146 		} else if (test_bit(wil_status_fwconnecting, &wil->status)) {
147 			cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
148 						WLAN_STATUS_UNSPECIFIED_FAILURE,
149 						GFP_KERNEL);
150 		}
151 		clear_bit(wil_status_fwconnecting, &wil->status);
152 		break;
153 	default:
154 		break;
155 	}
156 }
157 
158 static void wil_disconnect_worker(struct work_struct *work)
159 {
160 	struct wil6210_priv *wil = container_of(work,
161 			struct wil6210_priv, disconnect_worker);
162 
163 	mutex_lock(&wil->mutex);
164 	_wil6210_disconnect(wil, NULL);
165 	mutex_unlock(&wil->mutex);
166 }
167 
168 static void wil_connect_timer_fn(ulong x)
169 {
170 	struct wil6210_priv *wil = (void *)x;
171 
172 	wil_dbg_misc(wil, "Connect timeout\n");
173 
174 	/* reschedule to thread context - disconnect won't
175 	 * run from atomic context
176 	 */
177 	schedule_work(&wil->disconnect_worker);
178 }
179 
180 static void wil_scan_timer_fn(ulong x)
181 {
182 	struct wil6210_priv *wil = (void *)x;
183 
184 	clear_bit(wil_status_fwready, &wil->status);
185 	wil_err(wil, "Scan timeout detected, start fw error recovery\n");
186 	schedule_work(&wil->fw_error_worker);
187 }
188 
189 static void wil_fw_error_worker(struct work_struct *work)
190 {
191 	struct wil6210_priv *wil = container_of(work,
192 			struct wil6210_priv, fw_error_worker);
193 	struct wireless_dev *wdev = wil->wdev;
194 
195 	wil_dbg_misc(wil, "fw error worker\n");
196 
197 	if (no_fw_recovery)
198 		return;
199 
200 	/* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO
201 	 * passed since last recovery attempt
202 	 */
203 	if (time_is_after_jiffies(wil->last_fw_recovery +
204 				  WIL6210_FW_RECOVERY_TO))
205 		wil->recovery_count++;
206 	else
207 		wil->recovery_count = 1; /* fw was alive for a long time */
208 
209 	if (wil->recovery_count > WIL6210_FW_RECOVERY_RETRIES) {
210 		wil_err(wil, "too many recovery attempts (%d), giving up\n",
211 			wil->recovery_count);
212 		return;
213 	}
214 
215 	wil->last_fw_recovery = jiffies;
216 
217 	mutex_lock(&wil->mutex);
218 	switch (wdev->iftype) {
219 	case NL80211_IFTYPE_STATION:
220 	case NL80211_IFTYPE_P2P_CLIENT:
221 	case NL80211_IFTYPE_MONITOR:
222 		wil_info(wil, "fw error recovery started (try %d)...\n",
223 			 wil->recovery_count);
224 		wil_reset(wil);
225 
226 		/* need to re-allocate Rx ring after reset */
227 		wil_rx_init(wil);
228 		break;
229 	case NL80211_IFTYPE_AP:
230 	case NL80211_IFTYPE_P2P_GO:
231 		/* recovery in these modes is done by upper layers */
232 		break;
233 	default:
234 		break;
235 	}
236 	mutex_unlock(&wil->mutex);
237 }
238 
239 static int wil_find_free_vring(struct wil6210_priv *wil)
240 {
241 	int i;
242 
243 	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
244 		if (!wil->vring_tx[i].va)
245 			return i;
246 	}
247 	return -EINVAL;
248 }
249 
250 static void wil_connect_worker(struct work_struct *work)
251 {
252 	int rc;
253 	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
254 						connect_worker);
255 	int cid = wil->pending_connect_cid;
256 	int ringid = wil_find_free_vring(wil);
257 
258 	if (cid < 0) {
259 		wil_err(wil, "No connection pending\n");
260 		return;
261 	}
262 
263 	wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
264 
265 	rc = wil_vring_init_tx(wil, ringid, WIL6210_TX_RING_SIZE, cid, 0);
266 	wil->pending_connect_cid = -1;
267 	if (rc == 0) {
268 		wil->sta[cid].status = wil_sta_connected;
269 		wil_link_on(wil);
270 	} else {
271 		wil->sta[cid].status = wil_sta_unused;
272 	}
273 }
274 
275 int wil_priv_init(struct wil6210_priv *wil)
276 {
277 	uint i;
278 
279 	wil_dbg_misc(wil, "%s()\n", __func__);
280 
281 	memset(wil->sta, 0, sizeof(wil->sta));
282 	for (i = 0; i < WIL6210_MAX_CID; i++)
283 		spin_lock_init(&wil->sta[i].tid_rx_lock);
284 
285 	mutex_init(&wil->mutex);
286 	mutex_init(&wil->wmi_mutex);
287 
288 	init_completion(&wil->wmi_ready);
289 
290 	wil->pending_connect_cid = -1;
291 	setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
292 	setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil);
293 
294 	INIT_WORK(&wil->connect_worker, wil_connect_worker);
295 	INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
296 	INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
297 	INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
298 
299 	INIT_LIST_HEAD(&wil->pending_wmi_ev);
300 	spin_lock_init(&wil->wmi_ev_lock);
301 
302 	wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi");
303 	if (!wil->wmi_wq)
304 		return -EAGAIN;
305 
306 	wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect");
307 	if (!wil->wmi_wq_conn) {
308 		destroy_workqueue(wil->wmi_wq);
309 		return -EAGAIN;
310 	}
311 
312 	wil->last_fw_recovery = jiffies;
313 
314 	return 0;
315 }
316 
317 void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
318 {
319 	wil_dbg_misc(wil, "%s()\n", __func__);
320 
321 	del_timer_sync(&wil->connect_timer);
322 	_wil6210_disconnect(wil, bssid);
323 }
324 
325 void wil_priv_deinit(struct wil6210_priv *wil)
326 {
327 	wil_dbg_misc(wil, "%s()\n", __func__);
328 
329 	del_timer_sync(&wil->scan_timer);
330 	cancel_work_sync(&wil->disconnect_worker);
331 	cancel_work_sync(&wil->fw_error_worker);
332 	mutex_lock(&wil->mutex);
333 	wil6210_disconnect(wil, NULL);
334 	mutex_unlock(&wil->mutex);
335 	wmi_event_flush(wil);
336 	destroy_workqueue(wil->wmi_wq_conn);
337 	destroy_workqueue(wil->wmi_wq);
338 }
339 
340 /* target operations */
341 /* register read */
342 #define R(a) ioread32(wil->csr + HOSTADDR(a))
343 /* register write. wmb() to make sure it is completed */
344 #define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0)
345 /* register set = read, OR, write */
346 #define S(a, v) W(a, R(a) | v)
347 /* register clear = read, AND with inverted, write */
348 #define C(a, v) W(a, R(a) & ~v)
349 
350 static inline void wil_halt_cpu(struct wil6210_priv *wil)
351 {
352 	W(RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
353 	W(RGF_USER_MAC_CPU_0,  BIT_USER_MAC_CPU_MAN_RST);
354 }
355 
356 static inline void wil_release_cpu(struct wil6210_priv *wil)
357 {
358 	/* Start CPU */
359 	W(RGF_USER_USER_CPU_0, 1);
360 }
361 
362 static int wil_target_reset(struct wil6210_priv *wil)
363 {
364 	int delay = 0;
365 	u32 hw_state;
366 	u32 rev_id;
367 	bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
368 
369 	wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name);
370 
371 	wil->hw_version = R(RGF_USER_FW_REV_ID);
372 	rev_id = wil->hw_version & 0xff;
373 
374 	/* Clear MAC link up */
375 	S(RGF_HP_CTRL, BIT(15));
376 	S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_HPAL_PERST_FROM_PAD);
377 	S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST);
378 
379 	wil_halt_cpu(wil);
380 	C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); /* 40 MHz */
381 
382 	if (is_sparrow) {
383 		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
384 		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
385 	}
386 
387 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
388 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
389 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000f0 : 0x00000170);
390 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00);
391 
392 	if (is_sparrow) {
393 		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
394 		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
395 	}
396 
397 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
398 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
399 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
400 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
401 
402 	if (is_sparrow) {
403 		W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
404 		/* reset A2 PCIE AHB */
405 		W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
406 	} else {
407 		W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
408 		if (rev_id == 1) {
409 			/* reset A1 BOTH PCIE AHB & PCIE RGF */
410 			W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
411 		} else {
412 			W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
413 			W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
414 		}
415 	}
416 
417 	/* TODO: check order here!!! Erez code is different */
418 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
419 
420 	/* wait until device ready. typical time is 200..250 msec */
421 	do {
422 		msleep(RST_DELAY);
423 		hw_state = R(RGF_USER_HW_MACHINE_STATE);
424 		if (delay++ > RST_COUNT) {
425 			wil_err(wil, "Reset not completed, hw_state 0x%08x\n",
426 				hw_state);
427 			return -ETIME;
428 		}
429 	} while (hw_state != HW_MACHINE_BOOT_DONE);
430 
431 	/* TODO: Erez check rev_id != 1 */
432 	if (!is_sparrow && (rev_id != 1))
433 		W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
434 
435 	C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
436 
437 	wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
438 	return 0;
439 }
440 
441 #undef R
442 #undef W
443 #undef S
444 #undef C
445 
446 void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
447 {
448 	le32_to_cpus(&r->base);
449 	le16_to_cpus(&r->entry_size);
450 	le16_to_cpus(&r->size);
451 	le32_to_cpus(&r->tail);
452 	le32_to_cpus(&r->head);
453 }
454 
455 static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
456 {
457 	ulong to = msecs_to_jiffies(1000);
458 	ulong left = wait_for_completion_timeout(&wil->wmi_ready, to);
459 
460 	if (0 == left) {
461 		wil_err(wil, "Firmware not ready\n");
462 		return -ETIME;
463 	} else {
464 		wil_info(wil, "FW ready after %d ms. HW version 0x%08x\n",
465 			 jiffies_to_msecs(to-left), wil->hw_version);
466 	}
467 	return 0;
468 }
469 
470 /*
471  * We reset all the structures, and we reset the UMAC.
472  * After calling this routine, you're expected to reload
473  * the firmware.
474  */
475 int wil_reset(struct wil6210_priv *wil)
476 {
477 	int rc;
478 
479 	wil_dbg_misc(wil, "%s()\n", __func__);
480 
481 	WARN_ON(!mutex_is_locked(&wil->mutex));
482 
483 	cancel_work_sync(&wil->disconnect_worker);
484 	wil6210_disconnect(wil, NULL);
485 
486 	wil->status = 0; /* prevent NAPI from being scheduled */
487 	if (test_bit(wil_status_napi_en, &wil->status))
488 		napi_synchronize(&wil->napi_rx);
489 
490 	if (wil->scan_request) {
491 		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
492 			     wil->scan_request);
493 		del_timer_sync(&wil->scan_timer);
494 		cfg80211_scan_done(wil->scan_request, true);
495 		wil->scan_request = NULL;
496 	}
497 
498 	wil6210_disable_irq(wil);
499 
500 	wmi_event_flush(wil);
501 
502 	flush_workqueue(wil->wmi_wq_conn);
503 	flush_workqueue(wil->wmi_wq);
504 
505 	rc = wil_target_reset(wil);
506 	wil_rx_fini(wil);
507 	if (rc)
508 		return rc;
509 
510 	if (!no_fw_load) {
511 		wil_info(wil, "Use firmware <%s>\n", WIL_FW_NAME);
512 		wil_halt_cpu(wil);
513 		/* Loading f/w from the file */
514 		rc = wil_request_firmware(wil, WIL_FW_NAME);
515 		if (rc)
516 			return rc;
517 
518 		/* clear any interrupts which on-card-firmware may have set */
519 		wil6210_clear_irq(wil);
520 		{ /* CAF_ICR - clear and mask */
521 			u32 a = HOSTADDR(RGF_CAF_ICR) +
522 				offsetof(struct RGF_ICR, ICR);
523 			u32 m = HOSTADDR(RGF_CAF_ICR) +
524 				offsetof(struct RGF_ICR, IMV);
525 			u32 icr = ioread32(wil->csr + a);
526 
527 			iowrite32(icr, wil->csr + a); /* W1C */
528 			iowrite32(~0, wil->csr + m);
529 			wmb(); /* wait for completion */
530 		}
531 		wil_release_cpu(wil);
532 	} else {
533 		wil_info(wil, "Use firmware from on-card flash\n");
534 	}
535 
536 	/* init after reset */
537 	wil->pending_connect_cid = -1;
538 	reinit_completion(&wil->wmi_ready);
539 
540 	wil6210_enable_irq(wil);
541 
542 	/* we just started MAC, wait for FW ready */
543 	rc = wil_wait_for_fw_ready(wil);
544 
545 	return rc;
546 }
547 
548 void wil_fw_error_recovery(struct wil6210_priv *wil)
549 {
550 	wil_dbg_misc(wil, "starting fw error recovery\n");
551 	schedule_work(&wil->fw_error_worker);
552 }
553 
554 void wil_link_on(struct wil6210_priv *wil)
555 {
556 	struct net_device *ndev = wil_to_ndev(wil);
557 
558 	wil_dbg_misc(wil, "%s()\n", __func__);
559 
560 	netif_carrier_on(ndev);
561 	wil_dbg_misc(wil, "netif_tx_wake : link on\n");
562 	netif_tx_wake_all_queues(ndev);
563 }
564 
565 void wil_link_off(struct wil6210_priv *wil)
566 {
567 	struct net_device *ndev = wil_to_ndev(wil);
568 
569 	wil_dbg_misc(wil, "%s()\n", __func__);
570 
571 	netif_tx_stop_all_queues(ndev);
572 	wil_dbg_misc(wil, "netif_tx_stop : link off\n");
573 	netif_carrier_off(ndev);
574 }
575 
576 static int __wil_up(struct wil6210_priv *wil)
577 {
578 	struct net_device *ndev = wil_to_ndev(wil);
579 	struct wireless_dev *wdev = wil->wdev;
580 	int rc;
581 
582 	WARN_ON(!mutex_is_locked(&wil->mutex));
583 
584 	rc = wil_reset(wil);
585 	if (rc)
586 		return rc;
587 
588 	/* Rx VRING. After MAC and beacon */
589 	rc = wil_rx_init(wil);
590 	if (rc)
591 		return rc;
592 
593 	switch (wdev->iftype) {
594 	case NL80211_IFTYPE_STATION:
595 		wil_dbg_misc(wil, "type: STATION\n");
596 		ndev->type = ARPHRD_ETHER;
597 		break;
598 	case NL80211_IFTYPE_AP:
599 		wil_dbg_misc(wil, "type: AP\n");
600 		ndev->type = ARPHRD_ETHER;
601 		break;
602 	case NL80211_IFTYPE_P2P_CLIENT:
603 		wil_dbg_misc(wil, "type: P2P_CLIENT\n");
604 		ndev->type = ARPHRD_ETHER;
605 		break;
606 	case NL80211_IFTYPE_P2P_GO:
607 		wil_dbg_misc(wil, "type: P2P_GO\n");
608 		ndev->type = ARPHRD_ETHER;
609 		break;
610 	case NL80211_IFTYPE_MONITOR:
611 		wil_dbg_misc(wil, "type: Monitor\n");
612 		ndev->type = ARPHRD_IEEE80211_RADIOTAP;
613 		/* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
614 		break;
615 	default:
616 		return -EOPNOTSUPP;
617 	}
618 
619 	/* MAC address - pre-requisite for other commands */
620 	wmi_set_mac_address(wil, ndev->dev_addr);
621 
622 
623 	napi_enable(&wil->napi_rx);
624 	napi_enable(&wil->napi_tx);
625 	set_bit(wil_status_napi_en, &wil->status);
626 
627 	if (wil->platform_ops.bus_request)
628 		wil->platform_ops.bus_request(wil->platform_handle,
629 					      WIL_MAX_BUS_REQUEST_KBPS);
630 
631 	return 0;
632 }
633 
634 int wil_up(struct wil6210_priv *wil)
635 {
636 	int rc;
637 
638 	wil_dbg_misc(wil, "%s()\n", __func__);
639 
640 	mutex_lock(&wil->mutex);
641 	rc = __wil_up(wil);
642 	mutex_unlock(&wil->mutex);
643 
644 	return rc;
645 }
646 
647 static int __wil_down(struct wil6210_priv *wil)
648 {
649 	int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS /
650 			WAIT_FOR_DISCONNECT_INTERVAL_MS;
651 
652 	WARN_ON(!mutex_is_locked(&wil->mutex));
653 
654 	if (wil->platform_ops.bus_request)
655 		wil->platform_ops.bus_request(wil->platform_handle, 0);
656 
657 	clear_bit(wil_status_napi_en, &wil->status);
658 	napi_disable(&wil->napi_rx);
659 	napi_disable(&wil->napi_tx);
660 
661 	if (wil->scan_request) {
662 		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
663 			     wil->scan_request);
664 		del_timer_sync(&wil->scan_timer);
665 		cfg80211_scan_done(wil->scan_request, true);
666 		wil->scan_request = NULL;
667 	}
668 
669 	if (test_bit(wil_status_fwconnected, &wil->status) ||
670 	    test_bit(wil_status_fwconnecting, &wil->status))
671 		wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
672 
673 	/* make sure wil is idle (not connected) */
674 	mutex_unlock(&wil->mutex);
675 	while (iter--) {
676 		int idle = !test_bit(wil_status_fwconnected, &wil->status) &&
677 			   !test_bit(wil_status_fwconnecting, &wil->status);
678 		if (idle)
679 			break;
680 		msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS);
681 	}
682 	mutex_lock(&wil->mutex);
683 
684 	if (!iter)
685 		wil_err(wil, "timeout waiting for idle FW/HW\n");
686 
687 	wil_rx_fini(wil);
688 
689 	return 0;
690 }
691 
692 int wil_down(struct wil6210_priv *wil)
693 {
694 	int rc;
695 
696 	wil_dbg_misc(wil, "%s()\n", __func__);
697 
698 	mutex_lock(&wil->mutex);
699 	rc = __wil_down(wil);
700 	mutex_unlock(&wil->mutex);
701 
702 	return rc;
703 }
704 
705 int wil_find_cid(struct wil6210_priv *wil, const u8 *mac)
706 {
707 	int i;
708 	int rc = -ENOENT;
709 
710 	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
711 		if ((wil->sta[i].status != wil_sta_unused) &&
712 		    ether_addr_equal(wil->sta[i].addr, mac)) {
713 			rc = i;
714 			break;
715 		}
716 	}
717 
718 	return rc;
719 }
720