1 /*
2  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
3  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <linux/moduleparam.h>
19 #include <linux/etherdevice.h>
20 #include <linux/if_arp.h>
21 
22 #include "wil6210.h"
23 #include "txrx.h"
24 #include "wmi.h"
25 #include "trace.h"
26 
27 static uint max_assoc_sta = WIL6210_MAX_CID;
28 module_param(max_assoc_sta, uint, 0644);
29 MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
30 
31 int agg_wsize; /* = 0; */
32 module_param(agg_wsize, int, 0644);
33 MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
34 		 " 0 - use default; < 0 - don't auto-establish");
35 
36 u8 led_id = WIL_LED_INVALID_ID;
37 module_param(led_id, byte, 0444);
38 MODULE_PARM_DESC(led_id,
39 		 " 60G device led enablement. Set the led ID (0-2) to enable");
40 
41 #define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
42 #define WIL_WMI_CALL_GENERAL_TO_MS 100
43 
44 /**
45  * WMI event receiving - theory of operations
46  *
47  * When firmware about to report WMI event, it fills memory area
48  * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
49  * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
50  *
51  * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
52  * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
53  * and handles events within the @wmi_event_worker. Every event get detached
54  * from list, processed and deleted.
55  *
56  * Purpose for this mechanism is to release IRQ thread; otherwise,
57  * if WMI event handling involves another WMI command flow, this 2-nd flow
58  * won't be completed because of blocked IRQ thread.
59  */
60 
61 /**
62  * Addressing - theory of operations
63  *
64  * There are several buses present on the WIL6210 card.
65  * Same memory areas are visible at different address on
66  * the different busses. There are 3 main bus masters:
67  *  - MAC CPU (ucode)
68  *  - User CPU (firmware)
69  *  - AHB (host)
70  *
71  * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
72  * AHB addresses starting from 0x880000
73  *
74  * Internally, firmware uses addresses that allow faster access but
75  * are invisible from the host. To read from these addresses, alternative
76  * AHB address must be used.
77  */
78 
79 /**
80  * @sparrow_fw_mapping provides memory remapping table for sparrow
81  *
82  * array size should be in sync with the declaration in the wil6210.h
83  *
84  * Sparrow memory mapping:
85  * Linker address         PCI/Host address
86  *                        0x880000 .. 0xa80000  2Mb BAR0
87  * 0x800000 .. 0x808000   0x900000 .. 0x908000  32k DCCM
88  * 0x840000 .. 0x860000   0x908000 .. 0x928000  128k PERIPH
89  */
90 const struct fw_map sparrow_fw_mapping[] = {
91 	/* FW code RAM 256k */
92 	{0x000000, 0x040000, 0x8c0000, "fw_code", true},
93 	/* FW data RAM 32k */
94 	{0x800000, 0x808000, 0x900000, "fw_data", true},
95 	/* periph data 128k */
96 	{0x840000, 0x860000, 0x908000, "fw_peri", true},
97 	/* various RGF 40k */
98 	{0x880000, 0x88a000, 0x880000, "rgf", true},
99 	/* AGC table   4k */
100 	{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
101 	/* Pcie_ext_rgf 4k */
102 	{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
103 	/* mac_ext_rgf 512b */
104 	{0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true},
105 	/* upper area 548k */
106 	{0x8c0000, 0x949000, 0x8c0000, "upper", true},
107 	/* UCODE areas - accessible by debugfs blobs but not by
108 	 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
109 	 */
110 	/* ucode code RAM 128k */
111 	{0x000000, 0x020000, 0x920000, "uc_code", false},
112 	/* ucode data RAM 16k */
113 	{0x800000, 0x804000, 0x940000, "uc_data", false},
114 };
115 
116 /**
117  * @sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
118  * it is a bit larger to support extra features
119  */
120 const struct fw_map sparrow_d0_mac_rgf_ext = {
121 	0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true
122 };
123 
124 /**
125  * @talyn_fw_mapping provides memory remapping table for Talyn
126  *
127  * array size should be in sync with the declaration in the wil6210.h
128  *
129  * Talyn memory mapping:
130  * Linker address         PCI/Host address
131  *                        0x880000 .. 0xc80000  4Mb BAR0
132  * 0x800000 .. 0x820000   0xa00000 .. 0xa20000  128k DCCM
133  * 0x840000 .. 0x858000   0xa20000 .. 0xa38000  96k PERIPH
134  */
135 const struct fw_map talyn_fw_mapping[] = {
136 	/* FW code RAM 1M */
137 	{0x000000, 0x100000, 0x900000, "fw_code", true},
138 	/* FW data RAM 128k */
139 	{0x800000, 0x820000, 0xa00000, "fw_data", true},
140 	/* periph. data RAM 96k */
141 	{0x840000, 0x858000, 0xa20000, "fw_peri", true},
142 	/* various RGF 40k */
143 	{0x880000, 0x88a000, 0x880000, "rgf", true},
144 	/* AGC table 4k */
145 	{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
146 	/* Pcie_ext_rgf 4k */
147 	{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
148 	/* mac_ext_rgf 1344b */
149 	{0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true},
150 	/* ext USER RGF 4k */
151 	{0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true},
152 	/* OTP 4k */
153 	{0x8a0000, 0x8a1000, 0x8a0000, "otp", true},
154 	/* DMA EXT RGF 64k */
155 	{0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true},
156 	/* upper area 1536k */
157 	{0x900000, 0xa80000, 0x900000, "upper", true},
158 	/* UCODE areas - accessible by debugfs blobs but not by
159 	 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
160 	 */
161 	/* ucode code RAM 256k */
162 	{0x000000, 0x040000, 0xa38000, "uc_code", false},
163 	/* ucode data RAM 32k */
164 	{0x800000, 0x808000, 0xa78000, "uc_data", false},
165 };
166 
167 struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
168 
169 struct blink_on_off_time led_blink_time[] = {
170 	{WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS},
171 	{WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS},
172 	{WIL_LED_BLINK_ON_FAST_MS, WIL_LED_BLINK_OFF_FAST_MS},
173 };
174 
175 u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
176 
177 /**
178  * return AHB address for given firmware internal (linker) address
179  * @x - internal address
180  * If address have no valid AHB mapping, return 0
181  */
182 static u32 wmi_addr_remap(u32 x)
183 {
184 	uint i;
185 
186 	for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
187 		if (fw_mapping[i].fw &&
188 		    ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)))
189 			return x + fw_mapping[i].host - fw_mapping[i].from;
190 	}
191 
192 	return 0;
193 }
194 
195 /**
196  * find fw_mapping entry by section name
197  * @section - section name
198  *
199  * Return pointer to section or NULL if not found
200  */
201 struct fw_map *wil_find_fw_mapping(const char *section)
202 {
203 	int i;
204 
205 	for (i = 0; i < ARRAY_SIZE(fw_mapping); i++)
206 		if (fw_mapping[i].name &&
207 		    !strcmp(section, fw_mapping[i].name))
208 			return &fw_mapping[i];
209 
210 	return NULL;
211 }
212 
213 /**
214  * Check address validity for WMI buffer; remap if needed
215  * @ptr - internal (linker) fw/ucode address
216  * @size - if non zero, validate the block does not
217  *  exceed the device memory (bar)
218  *
219  * Valid buffer should be DWORD aligned
220  *
221  * return address for accessing buffer from the host;
222  * if buffer is not valid, return NULL.
223  */
224 void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size)
225 {
226 	u32 off;
227 	u32 ptr = le32_to_cpu(ptr_);
228 
229 	if (ptr % 4)
230 		return NULL;
231 
232 	ptr = wmi_addr_remap(ptr);
233 	if (ptr < WIL6210_FW_HOST_OFF)
234 		return NULL;
235 
236 	off = HOSTADDR(ptr);
237 	if (off > wil->bar_size - 4)
238 		return NULL;
239 	if (size && ((off + size > wil->bar_size) || (off + size < off)))
240 		return NULL;
241 
242 	return wil->csr + off;
243 }
244 
245 void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
246 {
247 	return wmi_buffer_block(wil, ptr_, 0);
248 }
249 
250 /**
251  * Check address validity
252  */
253 void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
254 {
255 	u32 off;
256 
257 	if (ptr % 4)
258 		return NULL;
259 
260 	if (ptr < WIL6210_FW_HOST_OFF)
261 		return NULL;
262 
263 	off = HOSTADDR(ptr);
264 	if (off > wil->bar_size - 4)
265 		return NULL;
266 
267 	return wil->csr + off;
268 }
269 
270 int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
271 		 struct wil6210_mbox_hdr *hdr)
272 {
273 	void __iomem *src = wmi_buffer(wil, ptr);
274 
275 	if (!src)
276 		return -EINVAL;
277 
278 	wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
279 
280 	return 0;
281 }
282 
283 static const char *cmdid2name(u16 cmdid)
284 {
285 	switch (cmdid) {
286 	case WMI_NOTIFY_REQ_CMDID:
287 		return "WMI_NOTIFY_REQ_CMD";
288 	case WMI_START_SCAN_CMDID:
289 		return "WMI_START_SCAN_CMD";
290 	case WMI_CONNECT_CMDID:
291 		return "WMI_CONNECT_CMD";
292 	case WMI_DISCONNECT_CMDID:
293 		return "WMI_DISCONNECT_CMD";
294 	case WMI_SW_TX_REQ_CMDID:
295 		return "WMI_SW_TX_REQ_CMD";
296 	case WMI_GET_RF_SECTOR_PARAMS_CMDID:
297 		return "WMI_GET_RF_SECTOR_PARAMS_CMD";
298 	case WMI_SET_RF_SECTOR_PARAMS_CMDID:
299 		return "WMI_SET_RF_SECTOR_PARAMS_CMD";
300 	case WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID:
301 		return "WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD";
302 	case WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID:
303 		return "WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD";
304 	case WMI_BRP_SET_ANT_LIMIT_CMDID:
305 		return "WMI_BRP_SET_ANT_LIMIT_CMD";
306 	case WMI_TOF_SESSION_START_CMDID:
307 		return "WMI_TOF_SESSION_START_CMD";
308 	case WMI_AOA_MEAS_CMDID:
309 		return "WMI_AOA_MEAS_CMD";
310 	case WMI_PMC_CMDID:
311 		return "WMI_PMC_CMD";
312 	case WMI_TOF_GET_TX_RX_OFFSET_CMDID:
313 		return "WMI_TOF_GET_TX_RX_OFFSET_CMD";
314 	case WMI_TOF_SET_TX_RX_OFFSET_CMDID:
315 		return "WMI_TOF_SET_TX_RX_OFFSET_CMD";
316 	case WMI_VRING_CFG_CMDID:
317 		return "WMI_VRING_CFG_CMD";
318 	case WMI_BCAST_VRING_CFG_CMDID:
319 		return "WMI_BCAST_VRING_CFG_CMD";
320 	case WMI_TRAFFIC_SUSPEND_CMDID:
321 		return "WMI_TRAFFIC_SUSPEND_CMD";
322 	case WMI_TRAFFIC_RESUME_CMDID:
323 		return "WMI_TRAFFIC_RESUME_CMD";
324 	case WMI_ECHO_CMDID:
325 		return "WMI_ECHO_CMD";
326 	case WMI_SET_MAC_ADDRESS_CMDID:
327 		return "WMI_SET_MAC_ADDRESS_CMD";
328 	case WMI_LED_CFG_CMDID:
329 		return "WMI_LED_CFG_CMD";
330 	case WMI_PCP_START_CMDID:
331 		return "WMI_PCP_START_CMD";
332 	case WMI_PCP_STOP_CMDID:
333 		return "WMI_PCP_STOP_CMD";
334 	case WMI_SET_SSID_CMDID:
335 		return "WMI_SET_SSID_CMD";
336 	case WMI_GET_SSID_CMDID:
337 		return "WMI_GET_SSID_CMD";
338 	case WMI_SET_PCP_CHANNEL_CMDID:
339 		return "WMI_SET_PCP_CHANNEL_CMD";
340 	case WMI_GET_PCP_CHANNEL_CMDID:
341 		return "WMI_GET_PCP_CHANNEL_CMD";
342 	case WMI_P2P_CFG_CMDID:
343 		return "WMI_P2P_CFG_CMD";
344 	case WMI_START_LISTEN_CMDID:
345 		return "WMI_START_LISTEN_CMD";
346 	case WMI_START_SEARCH_CMDID:
347 		return "WMI_START_SEARCH_CMD";
348 	case WMI_DISCOVERY_STOP_CMDID:
349 		return "WMI_DISCOVERY_STOP_CMD";
350 	case WMI_DELETE_CIPHER_KEY_CMDID:
351 		return "WMI_DELETE_CIPHER_KEY_CMD";
352 	case WMI_ADD_CIPHER_KEY_CMDID:
353 		return "WMI_ADD_CIPHER_KEY_CMD";
354 	case WMI_SET_APPIE_CMDID:
355 		return "WMI_SET_APPIE_CMD";
356 	case WMI_CFG_RX_CHAIN_CMDID:
357 		return "WMI_CFG_RX_CHAIN_CMD";
358 	case WMI_TEMP_SENSE_CMDID:
359 		return "WMI_TEMP_SENSE_CMD";
360 	case WMI_DEL_STA_CMDID:
361 		return "WMI_DEL_STA_CMD";
362 	case WMI_DISCONNECT_STA_CMDID:
363 		return "WMI_DISCONNECT_STA_CMD";
364 	case WMI_VRING_BA_EN_CMDID:
365 		return "WMI_VRING_BA_EN_CMD";
366 	case WMI_VRING_BA_DIS_CMDID:
367 		return "WMI_VRING_BA_DIS_CMD";
368 	case WMI_RCP_DELBA_CMDID:
369 		return "WMI_RCP_DELBA_CMD";
370 	case WMI_RCP_ADDBA_RESP_CMDID:
371 		return "WMI_RCP_ADDBA_RESP_CMD";
372 	case WMI_PS_DEV_PROFILE_CFG_CMDID:
373 		return "WMI_PS_DEV_PROFILE_CFG_CMD";
374 	case WMI_SET_MGMT_RETRY_LIMIT_CMDID:
375 		return "WMI_SET_MGMT_RETRY_LIMIT_CMD";
376 	case WMI_GET_MGMT_RETRY_LIMIT_CMDID:
377 		return "WMI_GET_MGMT_RETRY_LIMIT_CMD";
378 	case WMI_ABORT_SCAN_CMDID:
379 		return "WMI_ABORT_SCAN_CMD";
380 	case WMI_NEW_STA_CMDID:
381 		return "WMI_NEW_STA_CMD";
382 	case WMI_SET_THERMAL_THROTTLING_CFG_CMDID:
383 		return "WMI_SET_THERMAL_THROTTLING_CFG_CMD";
384 	case WMI_GET_THERMAL_THROTTLING_CFG_CMDID:
385 		return "WMI_GET_THERMAL_THROTTLING_CFG_CMD";
386 	case WMI_LINK_MAINTAIN_CFG_WRITE_CMDID:
387 		return "WMI_LINK_MAINTAIN_CFG_WRITE_CMD";
388 	case WMI_LO_POWER_CALIB_FROM_OTP_CMDID:
389 		return "WMI_LO_POWER_CALIB_FROM_OTP_CMD";
390 	case WMI_START_SCHED_SCAN_CMDID:
391 		return "WMI_START_SCHED_SCAN_CMD";
392 	case WMI_STOP_SCHED_SCAN_CMDID:
393 		return "WMI_STOP_SCHED_SCAN_CMD";
394 	default:
395 		return "Untracked CMD";
396 	}
397 }
398 
399 static const char *eventid2name(u16 eventid)
400 {
401 	switch (eventid) {
402 	case WMI_NOTIFY_REQ_DONE_EVENTID:
403 		return "WMI_NOTIFY_REQ_DONE_EVENT";
404 	case WMI_DISCONNECT_EVENTID:
405 		return "WMI_DISCONNECT_EVENT";
406 	case WMI_SW_TX_COMPLETE_EVENTID:
407 		return "WMI_SW_TX_COMPLETE_EVENT";
408 	case WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID:
409 		return "WMI_GET_RF_SECTOR_PARAMS_DONE_EVENT";
410 	case WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID:
411 		return "WMI_SET_RF_SECTOR_PARAMS_DONE_EVENT";
412 	case WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID:
413 		return "WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
414 	case WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID:
415 		return "WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
416 	case WMI_BRP_SET_ANT_LIMIT_EVENTID:
417 		return "WMI_BRP_SET_ANT_LIMIT_EVENT";
418 	case WMI_FW_READY_EVENTID:
419 		return "WMI_FW_READY_EVENT";
420 	case WMI_TRAFFIC_RESUME_EVENTID:
421 		return "WMI_TRAFFIC_RESUME_EVENT";
422 	case WMI_TOF_GET_TX_RX_OFFSET_EVENTID:
423 		return "WMI_TOF_GET_TX_RX_OFFSET_EVENT";
424 	case WMI_TOF_SET_TX_RX_OFFSET_EVENTID:
425 		return "WMI_TOF_SET_TX_RX_OFFSET_EVENT";
426 	case WMI_VRING_CFG_DONE_EVENTID:
427 		return "WMI_VRING_CFG_DONE_EVENT";
428 	case WMI_READY_EVENTID:
429 		return "WMI_READY_EVENT";
430 	case WMI_RX_MGMT_PACKET_EVENTID:
431 		return "WMI_RX_MGMT_PACKET_EVENT";
432 	case WMI_TX_MGMT_PACKET_EVENTID:
433 		return "WMI_TX_MGMT_PACKET_EVENT";
434 	case WMI_SCAN_COMPLETE_EVENTID:
435 		return "WMI_SCAN_COMPLETE_EVENT";
436 	case WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID:
437 		return "WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT";
438 	case WMI_CONNECT_EVENTID:
439 		return "WMI_CONNECT_EVENT";
440 	case WMI_EAPOL_RX_EVENTID:
441 		return "WMI_EAPOL_RX_EVENT";
442 	case WMI_BA_STATUS_EVENTID:
443 		return "WMI_BA_STATUS_EVENT";
444 	case WMI_RCP_ADDBA_REQ_EVENTID:
445 		return "WMI_RCP_ADDBA_REQ_EVENT";
446 	case WMI_DELBA_EVENTID:
447 		return "WMI_DELBA_EVENT";
448 	case WMI_VRING_EN_EVENTID:
449 		return "WMI_VRING_EN_EVENT";
450 	case WMI_DATA_PORT_OPEN_EVENTID:
451 		return "WMI_DATA_PORT_OPEN_EVENT";
452 	case WMI_AOA_MEAS_EVENTID:
453 		return "WMI_AOA_MEAS_EVENT";
454 	case WMI_TOF_SESSION_END_EVENTID:
455 		return "WMI_TOF_SESSION_END_EVENT";
456 	case WMI_TOF_GET_CAPABILITIES_EVENTID:
457 		return "WMI_TOF_GET_CAPABILITIES_EVENT";
458 	case WMI_TOF_SET_LCR_EVENTID:
459 		return "WMI_TOF_SET_LCR_EVENT";
460 	case WMI_TOF_SET_LCI_EVENTID:
461 		return "WMI_TOF_SET_LCI_EVENT";
462 	case WMI_TOF_FTM_PER_DEST_RES_EVENTID:
463 		return "WMI_TOF_FTM_PER_DEST_RES_EVENT";
464 	case WMI_TOF_CHANNEL_INFO_EVENTID:
465 		return "WMI_TOF_CHANNEL_INFO_EVENT";
466 	case WMI_TRAFFIC_SUSPEND_EVENTID:
467 		return "WMI_TRAFFIC_SUSPEND_EVENT";
468 	case WMI_ECHO_RSP_EVENTID:
469 		return "WMI_ECHO_RSP_EVENT";
470 	case WMI_LED_CFG_DONE_EVENTID:
471 		return "WMI_LED_CFG_DONE_EVENT";
472 	case WMI_PCP_STARTED_EVENTID:
473 		return "WMI_PCP_STARTED_EVENT";
474 	case WMI_PCP_STOPPED_EVENTID:
475 		return "WMI_PCP_STOPPED_EVENT";
476 	case WMI_GET_SSID_EVENTID:
477 		return "WMI_GET_SSID_EVENT";
478 	case WMI_GET_PCP_CHANNEL_EVENTID:
479 		return "WMI_GET_PCP_CHANNEL_EVENT";
480 	case WMI_P2P_CFG_DONE_EVENTID:
481 		return "WMI_P2P_CFG_DONE_EVENT";
482 	case WMI_LISTEN_STARTED_EVENTID:
483 		return "WMI_LISTEN_STARTED_EVENT";
484 	case WMI_SEARCH_STARTED_EVENTID:
485 		return "WMI_SEARCH_STARTED_EVENT";
486 	case WMI_DISCOVERY_STOPPED_EVENTID:
487 		return "WMI_DISCOVERY_STOPPED_EVENT";
488 	case WMI_CFG_RX_CHAIN_DONE_EVENTID:
489 		return "WMI_CFG_RX_CHAIN_DONE_EVENT";
490 	case WMI_TEMP_SENSE_DONE_EVENTID:
491 		return "WMI_TEMP_SENSE_DONE_EVENT";
492 	case WMI_RCP_ADDBA_RESP_SENT_EVENTID:
493 		return "WMI_RCP_ADDBA_RESP_SENT_EVENT";
494 	case WMI_PS_DEV_PROFILE_CFG_EVENTID:
495 		return "WMI_PS_DEV_PROFILE_CFG_EVENT";
496 	case WMI_SET_MGMT_RETRY_LIMIT_EVENTID:
497 		return "WMI_SET_MGMT_RETRY_LIMIT_EVENT";
498 	case WMI_GET_MGMT_RETRY_LIMIT_EVENTID:
499 		return "WMI_GET_MGMT_RETRY_LIMIT_EVENT";
500 	case WMI_SET_THERMAL_THROTTLING_CFG_EVENTID:
501 		return "WMI_SET_THERMAL_THROTTLING_CFG_EVENT";
502 	case WMI_GET_THERMAL_THROTTLING_CFG_EVENTID:
503 		return "WMI_GET_THERMAL_THROTTLING_CFG_EVENT";
504 	case WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID:
505 		return "WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENT";
506 	case WMI_LO_POWER_CALIB_FROM_OTP_EVENTID:
507 		return "WMI_LO_POWER_CALIB_FROM_OTP_EVENT";
508 	case WMI_START_SCHED_SCAN_EVENTID:
509 		return "WMI_START_SCHED_SCAN_EVENT";
510 	case WMI_STOP_SCHED_SCAN_EVENTID:
511 		return "WMI_STOP_SCHED_SCAN_EVENT";
512 	case WMI_SCHED_SCAN_RESULT_EVENTID:
513 		return "WMI_SCHED_SCAN_RESULT_EVENT";
514 	default:
515 		return "Untracked EVENT";
516 	}
517 }
518 
519 static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
520 {
521 	struct {
522 		struct wil6210_mbox_hdr hdr;
523 		struct wmi_cmd_hdr wmi;
524 	} __packed cmd = {
525 		.hdr = {
526 			.type = WIL_MBOX_HDR_TYPE_WMI,
527 			.flags = 0,
528 			.len = cpu_to_le16(sizeof(cmd.wmi) + len),
529 		},
530 		.wmi = {
531 			.mid = 0,
532 			.command_id = cpu_to_le16(cmdid),
533 		},
534 	};
535 	struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
536 	struct wil6210_mbox_ring_desc d_head;
537 	u32 next_head;
538 	void __iomem *dst;
539 	void __iomem *head = wmi_addr(wil, r->head);
540 	uint retry;
541 	int rc = 0;
542 
543 	if (len > r->entry_size - sizeof(cmd)) {
544 		wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
545 			(int)(sizeof(cmd) + len), r->entry_size);
546 		return -ERANGE;
547 	}
548 
549 	might_sleep();
550 
551 	if (!test_bit(wil_status_fwready, wil->status)) {
552 		wil_err(wil, "WMI: cannot send command while FW not ready\n");
553 		return -EAGAIN;
554 	}
555 
556 	/* Allow sending only suspend / resume commands during susepnd flow */
557 	if ((test_bit(wil_status_suspending, wil->status) ||
558 	     test_bit(wil_status_suspended, wil->status) ||
559 	     test_bit(wil_status_resuming, wil->status)) &&
560 	     ((cmdid != WMI_TRAFFIC_SUSPEND_CMDID) &&
561 	      (cmdid != WMI_TRAFFIC_RESUME_CMDID))) {
562 		wil_err(wil, "WMI: reject send_command during suspend\n");
563 		return -EINVAL;
564 	}
565 
566 	if (!head) {
567 		wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
568 		return -EINVAL;
569 	}
570 
571 	wil_halp_vote(wil);
572 
573 	/* read Tx head till it is not busy */
574 	for (retry = 5; retry > 0; retry--) {
575 		wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
576 		if (d_head.sync == 0)
577 			break;
578 		msleep(20);
579 	}
580 	if (d_head.sync != 0) {
581 		wil_err(wil, "WMI head busy\n");
582 		rc = -EBUSY;
583 		goto out;
584 	}
585 	/* next head */
586 	next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
587 	wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
588 	/* wait till FW finish with previous command */
589 	for (retry = 5; retry > 0; retry--) {
590 		if (!test_bit(wil_status_fwready, wil->status)) {
591 			wil_err(wil, "WMI: cannot send command while FW not ready\n");
592 			rc = -EAGAIN;
593 			goto out;
594 		}
595 		r->tail = wil_r(wil, RGF_MBOX +
596 				offsetof(struct wil6210_mbox_ctl, tx.tail));
597 		if (next_head != r->tail)
598 			break;
599 		msleep(20);
600 	}
601 	if (next_head == r->tail) {
602 		wil_err(wil, "WMI ring full\n");
603 		rc = -EBUSY;
604 		goto out;
605 	}
606 	dst = wmi_buffer(wil, d_head.addr);
607 	if (!dst) {
608 		wil_err(wil, "invalid WMI buffer: 0x%08x\n",
609 			le32_to_cpu(d_head.addr));
610 		rc = -EAGAIN;
611 		goto out;
612 	}
613 	cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
614 	/* set command */
615 	wil_dbg_wmi(wil, "sending %s (0x%04x) [%d]\n",
616 		    cmdid2name(cmdid), cmdid, len);
617 	wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
618 			 sizeof(cmd), true);
619 	wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
620 			 len, true);
621 	wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
622 	wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
623 	/* mark entry as full */
624 	wil_w(wil, r->head + offsetof(struct wil6210_mbox_ring_desc, sync), 1);
625 	/* advance next ptr */
626 	wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, tx.head),
627 	      r->head = next_head);
628 
629 	trace_wil6210_wmi_cmd(&cmd.wmi, buf, len);
630 
631 	/* interrupt to FW */
632 	wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS),
633 	      SW_INT_MBOX);
634 
635 out:
636 	wil_halp_unvote(wil);
637 	return rc;
638 }
639 
640 int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
641 {
642 	int rc;
643 
644 	mutex_lock(&wil->wmi_mutex);
645 	rc = __wmi_send(wil, cmdid, buf, len);
646 	mutex_unlock(&wil->wmi_mutex);
647 
648 	return rc;
649 }
650 
651 /*=== Event handlers ===*/
652 static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
653 {
654 	struct wireless_dev *wdev = wil->wdev;
655 	struct wmi_ready_event *evt = d;
656 
657 	wil->n_mids = evt->numof_additional_mids;
658 
659 	wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
660 		 wil->fw_version, le32_to_cpu(evt->sw_version),
661 		 evt->mac, wil->n_mids);
662 	/* ignore MAC address, we already have it from the boot loader */
663 	strlcpy(wdev->wiphy->fw_version, wil->fw_version,
664 		sizeof(wdev->wiphy->fw_version));
665 
666 	if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) {
667 		wil_dbg_wmi(wil, "rfc calibration result %d\n",
668 			    evt->rfc_read_calib_result);
669 		wil->fw_calib_result = evt->rfc_read_calib_result;
670 	}
671 	wil_set_recovery_state(wil, fw_recovery_idle);
672 	set_bit(wil_status_fwready, wil->status);
673 	/* let the reset sequence continue */
674 	complete(&wil->wmi_ready);
675 }
676 
677 static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
678 {
679 	struct wmi_rx_mgmt_packet_event *data = d;
680 	struct wiphy *wiphy = wil_to_wiphy(wil);
681 	struct ieee80211_mgmt *rx_mgmt_frame =
682 			(struct ieee80211_mgmt *)data->payload;
683 	int flen = len - offsetof(struct wmi_rx_mgmt_packet_event, payload);
684 	int ch_no;
685 	u32 freq;
686 	struct ieee80211_channel *channel;
687 	s32 signal;
688 	__le16 fc;
689 	u32 d_len;
690 	u16 d_status;
691 
692 	if (flen < 0) {
693 		wil_err(wil, "MGMT Rx: short event, len %d\n", len);
694 		return;
695 	}
696 
697 	d_len = le32_to_cpu(data->info.len);
698 	if (d_len != flen) {
699 		wil_err(wil,
700 			"MGMT Rx: length mismatch, d_len %d should be %d\n",
701 			d_len, flen);
702 		return;
703 	}
704 
705 	ch_no = data->info.channel + 1;
706 	freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ);
707 	channel = ieee80211_get_channel(wiphy, freq);
708 	if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities))
709 		signal = 100 * data->info.rssi;
710 	else
711 		signal = data->info.sqi;
712 	d_status = le16_to_cpu(data->info.status);
713 	fc = rx_mgmt_frame->frame_control;
714 
715 	wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n",
716 		    data->info.channel, data->info.mcs, data->info.rssi,
717 		    data->info.sqi);
718 	wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
719 		    le16_to_cpu(fc));
720 	wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
721 		    data->info.qid, data->info.mid, data->info.cid);
722 	wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
723 			 d_len, true);
724 
725 	if (!channel) {
726 		wil_err(wil, "Frame on unsupported channel\n");
727 		return;
728 	}
729 
730 	if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
731 		struct cfg80211_bss *bss;
732 		u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
733 		u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
734 		u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
735 		const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
736 		size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
737 						 u.beacon.variable);
738 		wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
739 		wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
740 		wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
741 		wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
742 				 ie_len, true);
743 
744 		wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
745 
746 		bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
747 						d_len, signal, GFP_KERNEL);
748 		if (bss) {
749 			wil_dbg_wmi(wil, "Added BSS %pM\n",
750 				    rx_mgmt_frame->bssid);
751 			cfg80211_put_bss(wiphy, bss);
752 		} else {
753 			wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
754 		}
755 	} else {
756 		mutex_lock(&wil->p2p_wdev_mutex);
757 		cfg80211_rx_mgmt(wil->radio_wdev, freq, signal,
758 				 (void *)rx_mgmt_frame, d_len, 0);
759 		mutex_unlock(&wil->p2p_wdev_mutex);
760 	}
761 }
762 
763 static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
764 {
765 	struct wmi_tx_mgmt_packet_event *data = d;
766 	struct ieee80211_mgmt *mgmt_frame =
767 			(struct ieee80211_mgmt *)data->payload;
768 	int flen = len - offsetof(struct wmi_tx_mgmt_packet_event, payload);
769 
770 	wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET, 16, 1, mgmt_frame,
771 			 flen, true);
772 }
773 
774 static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
775 				  void *d, int len)
776 {
777 	mutex_lock(&wil->p2p_wdev_mutex);
778 	if (wil->scan_request) {
779 		struct wmi_scan_complete_event *data = d;
780 		int status = le32_to_cpu(data->status);
781 		struct cfg80211_scan_info info = {
782 			.aborted = ((status != WMI_SCAN_SUCCESS) &&
783 				(status != WMI_SCAN_ABORT_REJECTED)),
784 		};
785 
786 		wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status);
787 		wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
788 			     wil->scan_request, info.aborted);
789 		del_timer_sync(&wil->scan_timer);
790 		cfg80211_scan_done(wil->scan_request, &info);
791 		wil->radio_wdev = wil->wdev;
792 		wil->scan_request = NULL;
793 		wake_up_interruptible(&wil->wq);
794 		if (wil->p2p.pending_listen_wdev) {
795 			wil_dbg_misc(wil, "Scheduling delayed listen\n");
796 			schedule_work(&wil->p2p.delayed_listen_work);
797 		}
798 	} else {
799 		wil_err(wil, "SCAN_COMPLETE while not scanning\n");
800 	}
801 	mutex_unlock(&wil->p2p_wdev_mutex);
802 }
803 
804 static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
805 {
806 	struct net_device *ndev = wil_to_ndev(wil);
807 	struct wireless_dev *wdev = wil->wdev;
808 	struct wmi_connect_event *evt = d;
809 	int ch; /* channel number */
810 	struct station_info sinfo;
811 	u8 *assoc_req_ie, *assoc_resp_ie;
812 	size_t assoc_req_ielen, assoc_resp_ielen;
813 	/* capinfo(u16) + listen_interval(u16) + IEs */
814 	const size_t assoc_req_ie_offset = sizeof(u16) * 2;
815 	/* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
816 	const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
817 	int rc;
818 
819 	if (len < sizeof(*evt)) {
820 		wil_err(wil, "Connect event too short : %d bytes\n", len);
821 		return;
822 	}
823 	if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
824 		   evt->assoc_resp_len) {
825 		wil_err(wil,
826 			"Connect event corrupted : %d != %d + %d + %d + %d\n",
827 			len, (int)sizeof(*evt), evt->beacon_ie_len,
828 			evt->assoc_req_len, evt->assoc_resp_len);
829 		return;
830 	}
831 	if (evt->cid >= WIL6210_MAX_CID) {
832 		wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
833 		return;
834 	}
835 
836 	ch = evt->channel + 1;
837 	wil_info(wil, "Connect %pM channel [%d] cid %d aid %d\n",
838 		 evt->bssid, ch, evt->cid, evt->aid);
839 	wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
840 			 evt->assoc_info, len - sizeof(*evt), true);
841 
842 	/* figure out IE's */
843 	assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
844 					assoc_req_ie_offset];
845 	assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
846 	if (evt->assoc_req_len <= assoc_req_ie_offset) {
847 		assoc_req_ie = NULL;
848 		assoc_req_ielen = 0;
849 	}
850 
851 	assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
852 					 evt->assoc_req_len +
853 					 assoc_resp_ie_offset];
854 	assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
855 	if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
856 		assoc_resp_ie = NULL;
857 		assoc_resp_ielen = 0;
858 	}
859 
860 	if (test_bit(wil_status_resetting, wil->status) ||
861 	    !test_bit(wil_status_fwready, wil->status)) {
862 		wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
863 			evt->cid);
864 		/* no need for cleanup, wil_reset will do that */
865 		return;
866 	}
867 
868 	mutex_lock(&wil->mutex);
869 
870 	if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
871 	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
872 		if (!test_bit(wil_status_fwconnecting, wil->status)) {
873 			wil_err(wil, "Not in connecting state\n");
874 			mutex_unlock(&wil->mutex);
875 			return;
876 		}
877 		del_timer_sync(&wil->connect_timer);
878 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
879 		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
880 		if (wil->sta[evt->cid].status != wil_sta_unused) {
881 			wil_err(wil, "AP: Invalid status %d for CID %d\n",
882 				wil->sta[evt->cid].status, evt->cid);
883 			mutex_unlock(&wil->mutex);
884 			return;
885 		}
886 	}
887 
888 	ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
889 	wil->sta[evt->cid].status = wil_sta_conn_pending;
890 
891 	rc = wil_tx_init(wil, evt->cid);
892 	if (rc) {
893 		wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n",
894 			evt->cid, rc);
895 		wmi_disconnect_sta(wil, wil->sta[evt->cid].addr,
896 				   WLAN_REASON_UNSPECIFIED, false, false);
897 	} else {
898 		wil_info(wil, "successful connection to CID %d\n", evt->cid);
899 	}
900 
901 	if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
902 	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
903 		if (rc) {
904 			netif_carrier_off(ndev);
905 			wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
906 			wil_err(wil, "cfg80211_connect_result with failure\n");
907 			cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
908 						NULL, 0,
909 						WLAN_STATUS_UNSPECIFIED_FAILURE,
910 						GFP_KERNEL);
911 			goto out;
912 		} else {
913 			struct wiphy *wiphy = wil_to_wiphy(wil);
914 
915 			cfg80211_ref_bss(wiphy, wil->bss);
916 			cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
917 					     assoc_req_ie, assoc_req_ielen,
918 					     assoc_resp_ie, assoc_resp_ielen,
919 					     WLAN_STATUS_SUCCESS, GFP_KERNEL,
920 					     NL80211_TIMEOUT_UNSPECIFIED);
921 		}
922 		wil->bss = NULL;
923 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
924 		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
925 		if (rc) {
926 			if (disable_ap_sme)
927 				/* notify new_sta has failed */
928 				cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL);
929 			goto out;
930 		}
931 
932 		memset(&sinfo, 0, sizeof(sinfo));
933 
934 		sinfo.generation = wil->sinfo_gen++;
935 
936 		if (assoc_req_ie) {
937 			sinfo.assoc_req_ies = assoc_req_ie;
938 			sinfo.assoc_req_ies_len = assoc_req_ielen;
939 		}
940 
941 		cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
942 	} else {
943 		wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype,
944 			evt->cid);
945 		goto out;
946 	}
947 
948 	wil->sta[evt->cid].status = wil_sta_connected;
949 	wil->sta[evt->cid].aid = evt->aid;
950 	set_bit(wil_status_fwconnected, wil->status);
951 	wil_update_net_queues_bh(wil, NULL, false);
952 
953 out:
954 	if (rc)
955 		wil->sta[evt->cid].status = wil_sta_unused;
956 	clear_bit(wil_status_fwconnecting, wil->status);
957 	mutex_unlock(&wil->mutex);
958 }
959 
960 static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
961 			       void *d, int len)
962 {
963 	struct wmi_disconnect_event *evt = d;
964 	u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
965 
966 	wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
967 		 evt->bssid, reason_code, evt->disconnect_reason);
968 
969 	wil->sinfo_gen++;
970 
971 	if (test_bit(wil_status_resetting, wil->status) ||
972 	    !test_bit(wil_status_fwready, wil->status)) {
973 		wil_err(wil, "status_resetting, cancel disconnect event\n");
974 		/* no need for cleanup, wil_reset will do that */
975 		return;
976 	}
977 
978 	mutex_lock(&wil->mutex);
979 	wil6210_disconnect(wil, evt->bssid, reason_code, true);
980 	mutex_unlock(&wil->mutex);
981 }
982 
983 /*
984  * Firmware reports EAPOL frame using WME event.
985  * Reconstruct Ethernet frame and deliver it via normal Rx
986  */
987 static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
988 			     void *d, int len)
989 {
990 	struct net_device *ndev = wil_to_ndev(wil);
991 	struct wmi_eapol_rx_event *evt = d;
992 	u16 eapol_len = le16_to_cpu(evt->eapol_len);
993 	int sz = eapol_len + ETH_HLEN;
994 	struct sk_buff *skb;
995 	struct ethhdr *eth;
996 	int cid;
997 	struct wil_net_stats *stats = NULL;
998 
999 	wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
1000 		    evt->src_mac);
1001 
1002 	cid = wil_find_cid(wil, evt->src_mac);
1003 	if (cid >= 0)
1004 		stats = &wil->sta[cid].stats;
1005 
1006 	if (eapol_len > 196) { /* TODO: revisit size limit */
1007 		wil_err(wil, "EAPOL too large\n");
1008 		return;
1009 	}
1010 
1011 	skb = alloc_skb(sz, GFP_KERNEL);
1012 	if (!skb) {
1013 		wil_err(wil, "Failed to allocate skb\n");
1014 		return;
1015 	}
1016 
1017 	eth = skb_put(skb, ETH_HLEN);
1018 	ether_addr_copy(eth->h_dest, ndev->dev_addr);
1019 	ether_addr_copy(eth->h_source, evt->src_mac);
1020 	eth->h_proto = cpu_to_be16(ETH_P_PAE);
1021 	skb_put_data(skb, evt->eapol, eapol_len);
1022 	skb->protocol = eth_type_trans(skb, ndev);
1023 	if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
1024 		ndev->stats.rx_packets++;
1025 		ndev->stats.rx_bytes += sz;
1026 		if (stats) {
1027 			stats->rx_packets++;
1028 			stats->rx_bytes += sz;
1029 		}
1030 	} else {
1031 		ndev->stats.rx_dropped++;
1032 		if (stats)
1033 			stats->rx_dropped++;
1034 	}
1035 }
1036 
1037 static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
1038 {
1039 	struct wmi_vring_en_event *evt = d;
1040 	u8 vri = evt->vring_index;
1041 	struct wireless_dev *wdev = wil_to_wdev(wil);
1042 
1043 	wil_dbg_wmi(wil, "Enable vring %d\n", vri);
1044 
1045 	if (vri >= ARRAY_SIZE(wil->vring_tx)) {
1046 		wil_err(wil, "Enable for invalid vring %d\n", vri);
1047 		return;
1048 	}
1049 
1050 	if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme)
1051 		/* in AP mode with disable_ap_sme, this is done by
1052 		 * wil_cfg80211_change_station()
1053 		 */
1054 		wil->vring_tx_data[vri].dot1x_open = true;
1055 	if (vri == wil->bcast_vring) /* no BA for bcast */
1056 		return;
1057 	if (agg_wsize >= 0)
1058 		wil_addba_tx_request(wil, vri, agg_wsize);
1059 }
1060 
1061 static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
1062 			      int len)
1063 {
1064 	struct wmi_ba_status_event *evt = d;
1065 	struct vring_tx_data *txdata;
1066 
1067 	wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
1068 		    evt->ringid,
1069 		    evt->status == WMI_BA_AGREED ? "OK" : "N/A",
1070 		    evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
1071 		    evt->amsdu ? "+" : "-");
1072 
1073 	if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
1074 		wil_err(wil, "invalid ring id %d\n", evt->ringid);
1075 		return;
1076 	}
1077 
1078 	if (evt->status != WMI_BA_AGREED) {
1079 		evt->ba_timeout = 0;
1080 		evt->agg_wsize = 0;
1081 		evt->amsdu = 0;
1082 	}
1083 
1084 	txdata = &wil->vring_tx_data[evt->ringid];
1085 
1086 	txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
1087 	txdata->agg_wsize = evt->agg_wsize;
1088 	txdata->agg_amsdu = evt->amsdu;
1089 	txdata->addba_in_progress = false;
1090 }
1091 
1092 static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
1093 				 int len)
1094 {
1095 	struct wmi_rcp_addba_req_event *evt = d;
1096 
1097 	wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
1098 			     evt->ba_param_set, evt->ba_timeout,
1099 			     evt->ba_seq_ctrl);
1100 }
1101 
1102 static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
1103 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
1104 {
1105 	struct wmi_delba_event *evt = d;
1106 	u8 cid, tid;
1107 	u16 reason = __le16_to_cpu(evt->reason);
1108 	struct wil_sta_info *sta;
1109 	struct wil_tid_ampdu_rx *r;
1110 
1111 	might_sleep();
1112 	parse_cidxtid(evt->cidxtid, &cid, &tid);
1113 	wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
1114 		    cid, tid,
1115 		    evt->from_initiator ? "originator" : "recipient",
1116 		    reason);
1117 	if (!evt->from_initiator) {
1118 		int i;
1119 		/* find Tx vring it belongs to */
1120 		for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
1121 			if ((wil->vring2cid_tid[i][0] == cid) &&
1122 			    (wil->vring2cid_tid[i][1] == tid)) {
1123 				struct vring_tx_data *txdata =
1124 					&wil->vring_tx_data[i];
1125 
1126 				wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
1127 				txdata->agg_timeout = 0;
1128 				txdata->agg_wsize = 0;
1129 				txdata->addba_in_progress = false;
1130 
1131 				break; /* max. 1 matching ring */
1132 			}
1133 		}
1134 		if (i >= ARRAY_SIZE(wil->vring2cid_tid))
1135 			wil_err(wil, "DELBA: unable to find Tx vring\n");
1136 		return;
1137 	}
1138 
1139 	sta = &wil->sta[cid];
1140 
1141 	spin_lock_bh(&sta->tid_rx_lock);
1142 
1143 	r = sta->tid_rx[tid];
1144 	sta->tid_rx[tid] = NULL;
1145 	wil_tid_ampdu_rx_free(wil, r);
1146 
1147 	spin_unlock_bh(&sta->tid_rx_lock);
1148 }
1149 
1150 static void
1151 wmi_evt_sched_scan_result(struct wil6210_priv *wil, int id, void *d, int len)
1152 {
1153 	struct wmi_sched_scan_result_event *data = d;
1154 	struct wiphy *wiphy = wil_to_wiphy(wil);
1155 	struct ieee80211_mgmt *rx_mgmt_frame =
1156 		(struct ieee80211_mgmt *)data->payload;
1157 	int flen = len - offsetof(struct wmi_sched_scan_result_event, payload);
1158 	int ch_no;
1159 	u32 freq;
1160 	struct ieee80211_channel *channel;
1161 	s32 signal;
1162 	__le16 fc;
1163 	u32 d_len;
1164 	struct cfg80211_bss *bss;
1165 
1166 	if (flen < 0) {
1167 		wil_err(wil, "sched scan result event too short, len %d\n",
1168 			len);
1169 		return;
1170 	}
1171 
1172 	d_len = le32_to_cpu(data->info.len);
1173 	if (d_len != flen) {
1174 		wil_err(wil,
1175 			"sched scan result length mismatch, d_len %d should be %d\n",
1176 			d_len, flen);
1177 		return;
1178 	}
1179 
1180 	fc = rx_mgmt_frame->frame_control;
1181 	if (!ieee80211_is_probe_resp(fc)) {
1182 		wil_err(wil, "sched scan result invalid frame, fc 0x%04x\n",
1183 			fc);
1184 		return;
1185 	}
1186 
1187 	ch_no = data->info.channel + 1;
1188 	freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ);
1189 	channel = ieee80211_get_channel(wiphy, freq);
1190 	if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities))
1191 		signal = 100 * data->info.rssi;
1192 	else
1193 		signal = data->info.sqi;
1194 
1195 	wil_dbg_wmi(wil, "sched scan result: channel %d MCS %d RSSI %d\n",
1196 		    data->info.channel, data->info.mcs, data->info.rssi);
1197 	wil_dbg_wmi(wil, "len %d qid %d mid %d cid %d\n",
1198 		    d_len, data->info.qid, data->info.mid, data->info.cid);
1199 	wil_hex_dump_wmi("PROBE ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
1200 			 d_len, true);
1201 
1202 	if (!channel) {
1203 		wil_err(wil, "Frame on unsupported channel\n");
1204 		return;
1205 	}
1206 
1207 	bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
1208 					d_len, signal, GFP_KERNEL);
1209 	if (bss) {
1210 		wil_dbg_wmi(wil, "Added BSS %pM\n", rx_mgmt_frame->bssid);
1211 		cfg80211_put_bss(wiphy, bss);
1212 	} else {
1213 		wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
1214 	}
1215 
1216 	cfg80211_sched_scan_results(wiphy, 0);
1217 }
1218 
1219 /**
1220  * Some events are ignored for purpose; and need not be interpreted as
1221  * "unhandled events"
1222  */
1223 static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
1224 {
1225 	wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
1226 }
1227 
1228 static const struct {
1229 	int eventid;
1230 	void (*handler)(struct wil6210_priv *wil, int eventid,
1231 			void *data, int data_len);
1232 } wmi_evt_handlers[] = {
1233 	{WMI_READY_EVENTID,		wmi_evt_ready},
1234 	{WMI_FW_READY_EVENTID,			wmi_evt_ignore},
1235 	{WMI_RX_MGMT_PACKET_EVENTID,	wmi_evt_rx_mgmt},
1236 	{WMI_TX_MGMT_PACKET_EVENTID,		wmi_evt_tx_mgmt},
1237 	{WMI_SCAN_COMPLETE_EVENTID,	wmi_evt_scan_complete},
1238 	{WMI_CONNECT_EVENTID,		wmi_evt_connect},
1239 	{WMI_DISCONNECT_EVENTID,	wmi_evt_disconnect},
1240 	{WMI_EAPOL_RX_EVENTID,		wmi_evt_eapol_rx},
1241 	{WMI_BA_STATUS_EVENTID,		wmi_evt_ba_status},
1242 	{WMI_RCP_ADDBA_REQ_EVENTID,	wmi_evt_addba_rx_req},
1243 	{WMI_DELBA_EVENTID,		wmi_evt_delba},
1244 	{WMI_VRING_EN_EVENTID,		wmi_evt_vring_en},
1245 	{WMI_DATA_PORT_OPEN_EVENTID,		wmi_evt_ignore},
1246 	{WMI_SCHED_SCAN_RESULT_EVENTID,		wmi_evt_sched_scan_result},
1247 };
1248 
1249 /*
1250  * Run in IRQ context
1251  * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
1252  * that will be eventually handled by the @wmi_event_worker in the thread
1253  * context of thread "wil6210_wmi"
1254  */
1255 void wmi_recv_cmd(struct wil6210_priv *wil)
1256 {
1257 	struct wil6210_mbox_ring_desc d_tail;
1258 	struct wil6210_mbox_hdr hdr;
1259 	struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
1260 	struct pending_wmi_event *evt;
1261 	u8 *cmd;
1262 	void __iomem *src;
1263 	ulong flags;
1264 	unsigned n;
1265 	unsigned int num_immed_reply = 0;
1266 
1267 	if (!test_bit(wil_status_mbox_ready, wil->status)) {
1268 		wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
1269 		return;
1270 	}
1271 
1272 	if (test_bit(wil_status_suspended, wil->status)) {
1273 		wil_err(wil, "suspended. cannot handle WMI event\n");
1274 		return;
1275 	}
1276 
1277 	for (n = 0;; n++) {
1278 		u16 len;
1279 		bool q;
1280 		bool immed_reply = false;
1281 
1282 		r->head = wil_r(wil, RGF_MBOX +
1283 				offsetof(struct wil6210_mbox_ctl, rx.head));
1284 		if (r->tail == r->head)
1285 			break;
1286 
1287 		wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
1288 			    r->head, r->tail);
1289 		/* read cmd descriptor from tail */
1290 		wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
1291 				     sizeof(struct wil6210_mbox_ring_desc));
1292 		if (d_tail.sync == 0) {
1293 			wil_err(wil, "Mbox evt not owned by FW?\n");
1294 			break;
1295 		}
1296 
1297 		/* read cmd header from descriptor */
1298 		if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
1299 			wil_err(wil, "Mbox evt at 0x%08x?\n",
1300 				le32_to_cpu(d_tail.addr));
1301 			break;
1302 		}
1303 		len = le16_to_cpu(hdr.len);
1304 		wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
1305 			    le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
1306 			    hdr.flags);
1307 
1308 		/* read cmd buffer from descriptor */
1309 		src = wmi_buffer(wil, d_tail.addr) +
1310 		      sizeof(struct wil6210_mbox_hdr);
1311 		evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
1312 					     event.wmi) + len, 4),
1313 			      GFP_KERNEL);
1314 		if (!evt)
1315 			break;
1316 
1317 		evt->event.hdr = hdr;
1318 		cmd = (void *)&evt->event.wmi;
1319 		wil_memcpy_fromio_32(cmd, src, len);
1320 		/* mark entry as empty */
1321 		wil_w(wil, r->tail +
1322 		      offsetof(struct wil6210_mbox_ring_desc, sync), 0);
1323 		/* indicate */
1324 		if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
1325 		    (len >= sizeof(struct wmi_cmd_hdr))) {
1326 			struct wmi_cmd_hdr *wmi = &evt->event.wmi;
1327 			u16 id = le16_to_cpu(wmi->command_id);
1328 			u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
1329 			if (test_bit(wil_status_resuming, wil->status)) {
1330 				if (id == WMI_TRAFFIC_RESUME_EVENTID)
1331 					clear_bit(wil_status_resuming,
1332 						  wil->status);
1333 				else
1334 					wil_err(wil,
1335 						"WMI evt %d while resuming\n",
1336 						id);
1337 			}
1338 			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1339 			if (wil->reply_id && wil->reply_id == id) {
1340 				if (wil->reply_buf) {
1341 					memcpy(wil->reply_buf, wmi,
1342 					       min(len, wil->reply_size));
1343 					immed_reply = true;
1344 				}
1345 				if (id == WMI_TRAFFIC_SUSPEND_EVENTID) {
1346 					wil_dbg_wmi(wil,
1347 						    "set suspend_resp_rcvd\n");
1348 					wil->suspend_resp_rcvd = true;
1349 				}
1350 			}
1351 			spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
1352 
1353 			wil_dbg_wmi(wil, "recv %s (0x%04x) MID %d @%d msec\n",
1354 				    eventid2name(id), id, wmi->mid, tstamp);
1355 			trace_wil6210_wmi_event(wmi, &wmi[1],
1356 						len - sizeof(*wmi));
1357 		}
1358 		wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
1359 				 &evt->event.hdr, sizeof(hdr) + len, true);
1360 
1361 		/* advance tail */
1362 		r->tail = r->base + ((r->tail - r->base +
1363 			  sizeof(struct wil6210_mbox_ring_desc)) % r->size);
1364 		wil_w(wil, RGF_MBOX +
1365 		      offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail);
1366 
1367 		if (immed_reply) {
1368 			wil_dbg_wmi(wil, "recv_cmd: Complete WMI 0x%04x\n",
1369 				    wil->reply_id);
1370 			kfree(evt);
1371 			num_immed_reply++;
1372 			complete(&wil->wmi_call);
1373 		} else {
1374 			/* add to the pending list */
1375 			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1376 			list_add_tail(&evt->list, &wil->pending_wmi_ev);
1377 			spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
1378 			q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
1379 			wil_dbg_wmi(wil, "queue_work -> %d\n", q);
1380 		}
1381 	}
1382 	/* normally, 1 event per IRQ should be processed */
1383 	wil_dbg_wmi(wil, "recv_cmd: -> %d events queued, %d completed\n",
1384 		    n - num_immed_reply, num_immed_reply);
1385 }
1386 
1387 int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
1388 	     u16 reply_id, void *reply, u8 reply_size, int to_msec)
1389 {
1390 	int rc;
1391 	unsigned long remain;
1392 
1393 	mutex_lock(&wil->wmi_mutex);
1394 
1395 	spin_lock(&wil->wmi_ev_lock);
1396 	wil->reply_id = reply_id;
1397 	wil->reply_buf = reply;
1398 	wil->reply_size = reply_size;
1399 	reinit_completion(&wil->wmi_call);
1400 	spin_unlock(&wil->wmi_ev_lock);
1401 
1402 	rc = __wmi_send(wil, cmdid, buf, len);
1403 	if (rc)
1404 		goto out;
1405 
1406 	remain = wait_for_completion_timeout(&wil->wmi_call,
1407 					     msecs_to_jiffies(to_msec));
1408 	if (0 == remain) {
1409 		wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
1410 			cmdid, reply_id, to_msec);
1411 		rc = -ETIME;
1412 	} else {
1413 		wil_dbg_wmi(wil,
1414 			    "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
1415 			    cmdid, reply_id,
1416 			    to_msec - jiffies_to_msecs(remain));
1417 	}
1418 
1419 out:
1420 	spin_lock(&wil->wmi_ev_lock);
1421 	wil->reply_id = 0;
1422 	wil->reply_buf = NULL;
1423 	wil->reply_size = 0;
1424 	spin_unlock(&wil->wmi_ev_lock);
1425 
1426 	mutex_unlock(&wil->wmi_mutex);
1427 
1428 	return rc;
1429 }
1430 
1431 int wmi_echo(struct wil6210_priv *wil)
1432 {
1433 	struct wmi_echo_cmd cmd = {
1434 		.value = cpu_to_le32(0x12345678),
1435 	};
1436 
1437 	return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
1438 			WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
1439 }
1440 
1441 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
1442 {
1443 	struct wmi_set_mac_address_cmd cmd;
1444 
1445 	ether_addr_copy(cmd.mac, addr);
1446 
1447 	wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
1448 
1449 	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
1450 }
1451 
1452 int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
1453 {
1454 	int rc = 0;
1455 	struct wmi_led_cfg_cmd cmd = {
1456 		.led_mode = enable,
1457 		.id = led_id,
1458 		.slow_blink_cfg.blink_on =
1459 			cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].on_ms),
1460 		.slow_blink_cfg.blink_off =
1461 			cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].off_ms),
1462 		.medium_blink_cfg.blink_on =
1463 			cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].on_ms),
1464 		.medium_blink_cfg.blink_off =
1465 			cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].off_ms),
1466 		.fast_blink_cfg.blink_on =
1467 			cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].on_ms),
1468 		.fast_blink_cfg.blink_off =
1469 			cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].off_ms),
1470 		.led_polarity = led_polarity,
1471 	};
1472 	struct {
1473 		struct wmi_cmd_hdr wmi;
1474 		struct wmi_led_cfg_done_event evt;
1475 	} __packed reply;
1476 
1477 	if (led_id == WIL_LED_INVALID_ID)
1478 		goto out;
1479 
1480 	if (led_id > WIL_LED_MAX_ID) {
1481 		wil_err(wil, "Invalid led id %d\n", led_id);
1482 		rc = -EINVAL;
1483 		goto out;
1484 	}
1485 
1486 	wil_dbg_wmi(wil,
1487 		    "%s led %d\n",
1488 		    enable ? "enabling" : "disabling", led_id);
1489 
1490 	rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd),
1491 		      WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
1492 		      100);
1493 	if (rc)
1494 		goto out;
1495 
1496 	if (reply.evt.status) {
1497 		wil_err(wil, "led %d cfg failed with status %d\n",
1498 			led_id, le32_to_cpu(reply.evt.status));
1499 		rc = -EINVAL;
1500 	}
1501 
1502 out:
1503 	return rc;
1504 }
1505 
1506 int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
1507 		  u8 chan, u8 hidden_ssid, u8 is_go)
1508 {
1509 	int rc;
1510 
1511 	struct wmi_pcp_start_cmd cmd = {
1512 		.bcon_interval = cpu_to_le16(bi),
1513 		.network_type = wmi_nettype,
1514 		.disable_sec_offload = 1,
1515 		.channel = chan - 1,
1516 		.pcp_max_assoc_sta = max_assoc_sta,
1517 		.hidden_ssid = hidden_ssid,
1518 		.is_go = is_go,
1519 		.disable_ap_sme = disable_ap_sme,
1520 		.abft_len = wil->abft_len,
1521 	};
1522 	struct {
1523 		struct wmi_cmd_hdr wmi;
1524 		struct wmi_pcp_started_event evt;
1525 	} __packed reply;
1526 
1527 	if (!wil->privacy)
1528 		cmd.disable_sec = 1;
1529 
1530 	if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
1531 	    (cmd.pcp_max_assoc_sta <= 0)) {
1532 		wil_info(wil,
1533 			 "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
1534 			 max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
1535 		cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
1536 	}
1537 
1538 	if (disable_ap_sme &&
1539 	    !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME,
1540 		      wil->fw_capabilities)) {
1541 		wil_err(wil, "disable_ap_sme not supported by FW\n");
1542 		return -EOPNOTSUPP;
1543 	}
1544 
1545 	/*
1546 	 * Processing time may be huge, in case of secure AP it takes about
1547 	 * 3500ms for FW to start AP
1548 	 */
1549 	rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
1550 		      WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
1551 	if (rc)
1552 		return rc;
1553 
1554 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
1555 		rc = -EINVAL;
1556 
1557 	if (wmi_nettype != WMI_NETTYPE_P2P)
1558 		/* Don't fail due to error in the led configuration */
1559 		wmi_led_cfg(wil, true);
1560 
1561 	return rc;
1562 }
1563 
1564 int wmi_pcp_stop(struct wil6210_priv *wil)
1565 {
1566 	int rc;
1567 
1568 	rc = wmi_led_cfg(wil, false);
1569 	if (rc)
1570 		return rc;
1571 
1572 	return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
1573 			WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
1574 }
1575 
1576 int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
1577 {
1578 	struct wmi_set_ssid_cmd cmd = {
1579 		.ssid_len = cpu_to_le32(ssid_len),
1580 	};
1581 
1582 	if (ssid_len > sizeof(cmd.ssid))
1583 		return -EINVAL;
1584 
1585 	memcpy(cmd.ssid, ssid, ssid_len);
1586 
1587 	return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
1588 }
1589 
1590 int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
1591 {
1592 	int rc;
1593 	struct {
1594 		struct wmi_cmd_hdr wmi;
1595 		struct wmi_set_ssid_cmd cmd;
1596 	} __packed reply;
1597 	int len; /* reply.cmd.ssid_len in CPU order */
1598 
1599 	rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
1600 		      &reply, sizeof(reply), 20);
1601 	if (rc)
1602 		return rc;
1603 
1604 	len = le32_to_cpu(reply.cmd.ssid_len);
1605 	if (len > sizeof(reply.cmd.ssid))
1606 		return -EINVAL;
1607 
1608 	*ssid_len = len;
1609 	memcpy(ssid, reply.cmd.ssid, len);
1610 
1611 	return 0;
1612 }
1613 
1614 int wmi_set_channel(struct wil6210_priv *wil, int channel)
1615 {
1616 	struct wmi_set_pcp_channel_cmd cmd = {
1617 		.channel = channel - 1,
1618 	};
1619 
1620 	return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
1621 }
1622 
1623 int wmi_get_channel(struct wil6210_priv *wil, int *channel)
1624 {
1625 	int rc;
1626 	struct {
1627 		struct wmi_cmd_hdr wmi;
1628 		struct wmi_set_pcp_channel_cmd cmd;
1629 	} __packed reply;
1630 
1631 	rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
1632 		      WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
1633 	if (rc)
1634 		return rc;
1635 
1636 	if (reply.cmd.channel > 3)
1637 		return -EINVAL;
1638 
1639 	*channel = reply.cmd.channel + 1;
1640 
1641 	return 0;
1642 }
1643 
1644 int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
1645 {
1646 	int rc;
1647 	struct wmi_p2p_cfg_cmd cmd = {
1648 		.discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER,
1649 		.bcon_interval = cpu_to_le16(bi),
1650 		.channel = channel - 1,
1651 	};
1652 	struct {
1653 		struct wmi_cmd_hdr wmi;
1654 		struct wmi_p2p_cfg_done_event evt;
1655 	} __packed reply;
1656 
1657 	wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n");
1658 
1659 	rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd),
1660 		      WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300);
1661 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
1662 		wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status);
1663 		rc = -EINVAL;
1664 	}
1665 
1666 	return rc;
1667 }
1668 
1669 int wmi_start_listen(struct wil6210_priv *wil)
1670 {
1671 	int rc;
1672 	struct {
1673 		struct wmi_cmd_hdr wmi;
1674 		struct wmi_listen_started_event evt;
1675 	} __packed reply;
1676 
1677 	wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n");
1678 
1679 	rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
1680 		      WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300);
1681 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
1682 		wil_err(wil, "device failed to start listen. status %d\n",
1683 			reply.evt.status);
1684 		rc = -EINVAL;
1685 	}
1686 
1687 	return rc;
1688 }
1689 
1690 int wmi_start_search(struct wil6210_priv *wil)
1691 {
1692 	int rc;
1693 	struct {
1694 		struct wmi_cmd_hdr wmi;
1695 		struct wmi_search_started_event evt;
1696 	} __packed reply;
1697 
1698 	wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n");
1699 
1700 	rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0,
1701 		      WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300);
1702 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
1703 		wil_err(wil, "device failed to start search. status %d\n",
1704 			reply.evt.status);
1705 		rc = -EINVAL;
1706 	}
1707 
1708 	return rc;
1709 }
1710 
1711 int wmi_stop_discovery(struct wil6210_priv *wil)
1712 {
1713 	int rc;
1714 
1715 	wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
1716 
1717 	rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
1718 		      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
1719 
1720 	if (rc)
1721 		wil_err(wil, "Failed to stop discovery\n");
1722 
1723 	return rc;
1724 }
1725 
1726 int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
1727 		       const void *mac_addr, int key_usage)
1728 {
1729 	struct wmi_delete_cipher_key_cmd cmd = {
1730 		.key_index = key_index,
1731 	};
1732 
1733 	if (mac_addr)
1734 		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1735 
1736 	return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1737 }
1738 
1739 int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
1740 		       const void *mac_addr, int key_len, const void *key,
1741 		       int key_usage)
1742 {
1743 	struct wmi_add_cipher_key_cmd cmd = {
1744 		.key_index = key_index,
1745 		.key_usage = key_usage,
1746 		.key_len = key_len,
1747 	};
1748 
1749 	if (!key || (key_len > sizeof(cmd.key)))
1750 		return -EINVAL;
1751 
1752 	memcpy(cmd.key, key, key_len);
1753 	if (mac_addr)
1754 		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1755 
1756 	return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1757 }
1758 
1759 int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
1760 {
1761 	static const char *const names[] = {
1762 		[WMI_FRAME_BEACON]	= "BEACON",
1763 		[WMI_FRAME_PROBE_REQ]	= "PROBE_REQ",
1764 		[WMI_FRAME_PROBE_RESP]	= "WMI_FRAME_PROBE_RESP",
1765 		[WMI_FRAME_ASSOC_REQ]	= "WMI_FRAME_ASSOC_REQ",
1766 		[WMI_FRAME_ASSOC_RESP]	= "WMI_FRAME_ASSOC_RESP",
1767 	};
1768 	int rc;
1769 	u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
1770 	struct wmi_set_appie_cmd *cmd;
1771 
1772 	if (len < ie_len) {
1773 		rc = -EINVAL;
1774 		goto out;
1775 	}
1776 
1777 	cmd = kzalloc(len, GFP_KERNEL);
1778 	if (!cmd) {
1779 		rc = -ENOMEM;
1780 		goto out;
1781 	}
1782 	if (!ie)
1783 		ie_len = 0;
1784 
1785 	cmd->mgmt_frm_type = type;
1786 	/* BUG: FW API define ieLen as u8. Will fix FW */
1787 	cmd->ie_len = cpu_to_le16(ie_len);
1788 	memcpy(cmd->ie_info, ie, ie_len);
1789 	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
1790 	kfree(cmd);
1791 out:
1792 	if (rc) {
1793 		const char *name = type < ARRAY_SIZE(names) ?
1794 				   names[type] : "??";
1795 		wil_err(wil, "set_ie(%d %s) failed : %d\n", type, name, rc);
1796 	}
1797 
1798 	return rc;
1799 }
1800 
1801 /**
1802  * wmi_rxon - turn radio on/off
1803  * @on:		turn on if true, off otherwise
1804  *
1805  * Only switch radio. Channel should be set separately.
1806  * No timeout for rxon - radio turned on forever unless some other call
1807  * turns it off
1808  */
1809 int wmi_rxon(struct wil6210_priv *wil, bool on)
1810 {
1811 	int rc;
1812 	struct {
1813 		struct wmi_cmd_hdr wmi;
1814 		struct wmi_listen_started_event evt;
1815 	} __packed reply;
1816 
1817 	wil_info(wil, "(%s)\n", on ? "on" : "off");
1818 
1819 	if (on) {
1820 		rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
1821 			      WMI_LISTEN_STARTED_EVENTID,
1822 			      &reply, sizeof(reply), 100);
1823 		if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
1824 			rc = -EINVAL;
1825 	} else {
1826 		rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
1827 			      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
1828 	}
1829 
1830 	return rc;
1831 }
1832 
1833 int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
1834 {
1835 	struct wireless_dev *wdev = wil->wdev;
1836 	struct net_device *ndev = wil_to_ndev(wil);
1837 	struct wmi_cfg_rx_chain_cmd cmd = {
1838 		.action = WMI_RX_CHAIN_ADD,
1839 		.rx_sw_ring = {
1840 			.max_mpdu_size = cpu_to_le16(
1841 				wil_mtu2macbuf(wil->rx_buf_len)),
1842 			.ring_mem_base = cpu_to_le64(vring->pa),
1843 			.ring_size = cpu_to_le16(vring->size),
1844 		},
1845 		.mid = 0, /* TODO - what is it? */
1846 		.decap_trans_type = WMI_DECAP_TYPE_802_3,
1847 		.reorder_type = WMI_RX_SW_REORDER,
1848 		.host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
1849 	};
1850 	struct {
1851 		struct wmi_cmd_hdr wmi;
1852 		struct wmi_cfg_rx_chain_done_event evt;
1853 	} __packed evt;
1854 	int rc;
1855 
1856 	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
1857 		struct ieee80211_channel *ch = wil->monitor_chandef.chan;
1858 
1859 		cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
1860 		if (ch)
1861 			cmd.sniffer_cfg.channel = ch->hw_value - 1;
1862 		cmd.sniffer_cfg.phy_info_mode =
1863 			cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
1864 		cmd.sniffer_cfg.phy_support =
1865 			cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
1866 				    ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
1867 	} else {
1868 		/* Initialize offload (in non-sniffer mode).
1869 		 * Linux IP stack always calculates IP checksum
1870 		 * HW always calculate TCP/UDP checksum
1871 		 */
1872 		cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
1873 	}
1874 
1875 	if (rx_align_2)
1876 		cmd.l2_802_3_offload_ctrl |=
1877 				L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
1878 
1879 	/* typical time for secure PCP is 840ms */
1880 	rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
1881 		      WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
1882 	if (rc)
1883 		return rc;
1884 
1885 	vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
1886 
1887 	wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
1888 		     le32_to_cpu(evt.evt.status), vring->hwtail);
1889 
1890 	if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
1891 		rc = -EINVAL;
1892 
1893 	return rc;
1894 }
1895 
1896 int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
1897 {
1898 	int rc;
1899 	struct wmi_temp_sense_cmd cmd = {
1900 		.measure_baseband_en = cpu_to_le32(!!t_bb),
1901 		.measure_rf_en = cpu_to_le32(!!t_rf),
1902 		.measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
1903 	};
1904 	struct {
1905 		struct wmi_cmd_hdr wmi;
1906 		struct wmi_temp_sense_done_event evt;
1907 	} __packed reply;
1908 
1909 	rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
1910 		      WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
1911 	if (rc)
1912 		return rc;
1913 
1914 	if (t_bb)
1915 		*t_bb = le32_to_cpu(reply.evt.baseband_t1000);
1916 	if (t_rf)
1917 		*t_rf = le32_to_cpu(reply.evt.rf_t1000);
1918 
1919 	return 0;
1920 }
1921 
1922 int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
1923 		       u16 reason, bool full_disconnect, bool del_sta)
1924 {
1925 	int rc;
1926 	u16 reason_code;
1927 	struct wmi_disconnect_sta_cmd disc_sta_cmd = {
1928 		.disconnect_reason = cpu_to_le16(reason),
1929 	};
1930 	struct wmi_del_sta_cmd del_sta_cmd = {
1931 		.disconnect_reason = cpu_to_le16(reason),
1932 	};
1933 	struct {
1934 		struct wmi_cmd_hdr wmi;
1935 		struct wmi_disconnect_event evt;
1936 	} __packed reply;
1937 
1938 	wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
1939 
1940 	wil->locally_generated_disc = true;
1941 	if (del_sta) {
1942 		ether_addr_copy(del_sta_cmd.dst_mac, mac);
1943 		rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd,
1944 			      sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID,
1945 			      &reply, sizeof(reply), 1000);
1946 	} else {
1947 		ether_addr_copy(disc_sta_cmd.dst_mac, mac);
1948 		rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd,
1949 			      sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID,
1950 			      &reply, sizeof(reply), 1000);
1951 	}
1952 	/* failure to disconnect in reasonable time treated as FW error */
1953 	if (rc) {
1954 		wil_fw_error_recovery(wil);
1955 		return rc;
1956 	}
1957 
1958 	if (full_disconnect) {
1959 		/* call event handler manually after processing wmi_call,
1960 		 * to avoid deadlock - disconnect event handler acquires
1961 		 * wil->mutex while it is already held here
1962 		 */
1963 		reason_code = le16_to_cpu(reply.evt.protocol_reason_status);
1964 
1965 		wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
1966 			    reply.evt.bssid, reason_code,
1967 			    reply.evt.disconnect_reason);
1968 
1969 		wil->sinfo_gen++;
1970 		wil6210_disconnect(wil, reply.evt.bssid, reason_code, true);
1971 	}
1972 	return 0;
1973 }
1974 
1975 int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
1976 {
1977 	struct wmi_vring_ba_en_cmd cmd = {
1978 		.ringid = ringid,
1979 		.agg_max_wsize = size,
1980 		.ba_timeout = cpu_to_le16(timeout),
1981 		.amsdu = 0,
1982 	};
1983 
1984 	wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size,
1985 		    timeout);
1986 
1987 	return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
1988 }
1989 
1990 int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
1991 {
1992 	struct wmi_vring_ba_dis_cmd cmd = {
1993 		.ringid = ringid,
1994 		.reason = cpu_to_le16(reason),
1995 	};
1996 
1997 	wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason);
1998 
1999 	return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
2000 }
2001 
2002 int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
2003 {
2004 	struct wmi_rcp_delba_cmd cmd = {
2005 		.cidxtid = cidxtid,
2006 		.reason = cpu_to_le16(reason),
2007 	};
2008 
2009 	wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf,
2010 		    (cidxtid >> 4) & 0xf, reason);
2011 
2012 	return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
2013 }
2014 
2015 int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
2016 		      u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
2017 {
2018 	int rc;
2019 	struct wmi_rcp_addba_resp_cmd cmd = {
2020 		.cidxtid = mk_cidxtid(cid, tid),
2021 		.dialog_token = token,
2022 		.status_code = cpu_to_le16(status),
2023 		/* bit 0: A-MSDU supported
2024 		 * bit 1: policy (should be 0 for us)
2025 		 * bits 2..5: TID
2026 		 * bits 6..15: buffer size
2027 		 */
2028 		.ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
2029 					    (agg_wsize << 6)),
2030 		.ba_timeout = cpu_to_le16(timeout),
2031 	};
2032 	struct {
2033 		struct wmi_cmd_hdr wmi;
2034 		struct wmi_rcp_addba_resp_sent_event evt;
2035 	} __packed reply;
2036 
2037 	wil_dbg_wmi(wil,
2038 		    "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
2039 		    cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
2040 
2041 	rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
2042 		      WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
2043 		      100);
2044 	if (rc)
2045 		return rc;
2046 
2047 	if (reply.evt.status) {
2048 		wil_err(wil, "ADDBA response failed with status %d\n",
2049 			le16_to_cpu(reply.evt.status));
2050 		rc = -EINVAL;
2051 	}
2052 
2053 	return rc;
2054 }
2055 
2056 int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
2057 			   enum wmi_ps_profile_type ps_profile)
2058 {
2059 	int rc;
2060 	struct wmi_ps_dev_profile_cfg_cmd cmd = {
2061 		.ps_profile = ps_profile,
2062 	};
2063 	struct {
2064 		struct wmi_cmd_hdr wmi;
2065 		struct wmi_ps_dev_profile_cfg_event evt;
2066 	} __packed reply;
2067 	u32 status;
2068 
2069 	wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile);
2070 
2071 	reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR);
2072 
2073 	rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd),
2074 		      WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
2075 		      100);
2076 	if (rc)
2077 		return rc;
2078 
2079 	status = le32_to_cpu(reply.evt.status);
2080 
2081 	if (status != WMI_PS_CFG_CMD_STATUS_SUCCESS) {
2082 		wil_err(wil, "ps dev profile cfg failed with status %d\n",
2083 			status);
2084 		rc = -EINVAL;
2085 	}
2086 
2087 	return rc;
2088 }
2089 
2090 int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
2091 {
2092 	int rc;
2093 	struct wmi_set_mgmt_retry_limit_cmd cmd = {
2094 		.mgmt_retry_limit = retry_short,
2095 	};
2096 	struct {
2097 		struct wmi_cmd_hdr wmi;
2098 		struct wmi_set_mgmt_retry_limit_event evt;
2099 	} __packed reply;
2100 
2101 	wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short);
2102 
2103 	if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
2104 		return -ENOTSUPP;
2105 
2106 	reply.evt.status = WMI_FW_STATUS_FAILURE;
2107 
2108 	rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd),
2109 		      WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
2110 		      100);
2111 	if (rc)
2112 		return rc;
2113 
2114 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
2115 		wil_err(wil, "set mgmt retry limit failed with status %d\n",
2116 			reply.evt.status);
2117 		rc = -EINVAL;
2118 	}
2119 
2120 	return rc;
2121 }
2122 
2123 int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
2124 {
2125 	int rc;
2126 	struct {
2127 		struct wmi_cmd_hdr wmi;
2128 		struct wmi_get_mgmt_retry_limit_event evt;
2129 	} __packed reply;
2130 
2131 	wil_dbg_wmi(wil, "getting mgmt retry short\n");
2132 
2133 	if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
2134 		return -ENOTSUPP;
2135 
2136 	reply.evt.mgmt_retry_limit = 0;
2137 	rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0,
2138 		      WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
2139 		      100);
2140 	if (rc)
2141 		return rc;
2142 
2143 	if (retry_short)
2144 		*retry_short = reply.evt.mgmt_retry_limit;
2145 
2146 	return 0;
2147 }
2148 
2149 int wmi_abort_scan(struct wil6210_priv *wil)
2150 {
2151 	int rc;
2152 
2153 	wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n");
2154 
2155 	rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0);
2156 	if (rc)
2157 		wil_err(wil, "Failed to abort scan (%d)\n", rc);
2158 
2159 	return rc;
2160 }
2161 
2162 int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid)
2163 {
2164 	int rc;
2165 	struct wmi_new_sta_cmd cmd = {
2166 		.aid = aid,
2167 	};
2168 
2169 	wil_dbg_wmi(wil, "new sta %pM, aid %d\n", mac, aid);
2170 
2171 	ether_addr_copy(cmd.dst_mac, mac);
2172 
2173 	rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd));
2174 	if (rc)
2175 		wil_err(wil, "Failed to send new sta (%d)\n", rc);
2176 
2177 	return rc;
2178 }
2179 
2180 void wmi_event_flush(struct wil6210_priv *wil)
2181 {
2182 	ulong flags;
2183 	struct pending_wmi_event *evt, *t;
2184 
2185 	wil_dbg_wmi(wil, "event_flush\n");
2186 
2187 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
2188 
2189 	list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
2190 		list_del(&evt->list);
2191 		kfree(evt);
2192 	}
2193 
2194 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2195 }
2196 
2197 static const char *suspend_status2name(u8 status)
2198 {
2199 	switch (status) {
2200 	case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE:
2201 		return "LINK_NOT_IDLE";
2202 	default:
2203 		return "Untracked status";
2204 	}
2205 }
2206 
2207 int wmi_suspend(struct wil6210_priv *wil)
2208 {
2209 	int rc;
2210 	struct wmi_traffic_suspend_cmd cmd = {
2211 		.wakeup_trigger = wil->wakeup_trigger,
2212 	};
2213 	struct {
2214 		struct wmi_cmd_hdr wmi;
2215 		struct wmi_traffic_suspend_event evt;
2216 	} __packed reply;
2217 	u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP;
2218 
2219 	wil->suspend_resp_rcvd = false;
2220 	wil->suspend_resp_comp = false;
2221 
2222 	reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE;
2223 
2224 	rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd),
2225 		      WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
2226 		      suspend_to);
2227 	if (rc) {
2228 		wil_err(wil, "wmi_call for suspend req failed, rc=%d\n", rc);
2229 		if (rc == -ETIME)
2230 			/* wmi_call TO */
2231 			wil->suspend_stats.rejected_by_device++;
2232 		else
2233 			wil->suspend_stats.rejected_by_host++;
2234 		goto out;
2235 	}
2236 
2237 	wil_dbg_wmi(wil, "waiting for suspend_response_completed\n");
2238 
2239 	rc = wait_event_interruptible_timeout(wil->wq,
2240 					      wil->suspend_resp_comp,
2241 					      msecs_to_jiffies(suspend_to));
2242 	if (rc == 0) {
2243 		wil_err(wil, "TO waiting for suspend_response_completed\n");
2244 		if (wil->suspend_resp_rcvd)
2245 			/* Device responded but we TO due to another reason */
2246 			wil->suspend_stats.rejected_by_host++;
2247 		else
2248 			wil->suspend_stats.rejected_by_device++;
2249 		rc = -EBUSY;
2250 		goto out;
2251 	}
2252 
2253 	wil_dbg_wmi(wil, "suspend_response_completed rcvd\n");
2254 	if (reply.evt.status != WMI_TRAFFIC_SUSPEND_APPROVED) {
2255 		wil_dbg_pm(wil, "device rejected the suspend, %s\n",
2256 			   suspend_status2name(reply.evt.status));
2257 		wil->suspend_stats.rejected_by_device++;
2258 	}
2259 	rc = reply.evt.status;
2260 
2261 out:
2262 	wil->suspend_resp_rcvd = false;
2263 	wil->suspend_resp_comp = false;
2264 
2265 	return rc;
2266 }
2267 
2268 static void resume_triggers2string(u32 triggers, char *string, int str_size)
2269 {
2270 	string[0] = '\0';
2271 
2272 	if (!triggers) {
2273 		strlcat(string, " UNKNOWN", str_size);
2274 		return;
2275 	}
2276 
2277 	if (triggers & WMI_RESUME_TRIGGER_HOST)
2278 		strlcat(string, " HOST", str_size);
2279 
2280 	if (triggers & WMI_RESUME_TRIGGER_UCAST_RX)
2281 		strlcat(string, " UCAST_RX", str_size);
2282 
2283 	if (triggers & WMI_RESUME_TRIGGER_BCAST_RX)
2284 		strlcat(string, " BCAST_RX", str_size);
2285 
2286 	if (triggers & WMI_RESUME_TRIGGER_WMI_EVT)
2287 		strlcat(string, " WMI_EVT", str_size);
2288 }
2289 
2290 int wmi_resume(struct wil6210_priv *wil)
2291 {
2292 	int rc;
2293 	char string[100];
2294 	struct {
2295 		struct wmi_cmd_hdr wmi;
2296 		struct wmi_traffic_resume_event evt;
2297 	} __packed reply;
2298 
2299 	reply.evt.status = WMI_TRAFFIC_RESUME_FAILED;
2300 	reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN;
2301 
2302 	rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0,
2303 		      WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
2304 		      WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
2305 	if (rc)
2306 		return rc;
2307 	resume_triggers2string(le32_to_cpu(reply.evt.resume_triggers), string,
2308 			       sizeof(string));
2309 	wil_dbg_pm(wil, "device resume %s, resume triggers:%s (0x%x)\n",
2310 		   reply.evt.status ? "failed" : "passed", string,
2311 		   le32_to_cpu(reply.evt.resume_triggers));
2312 
2313 	return reply.evt.status;
2314 }
2315 
2316 static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
2317 				 void *d, int len)
2318 {
2319 	uint i;
2320 
2321 	for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
2322 		if (wmi_evt_handlers[i].eventid == id) {
2323 			wmi_evt_handlers[i].handler(wil, id, d, len);
2324 			return true;
2325 		}
2326 	}
2327 
2328 	return false;
2329 }
2330 
2331 static void wmi_event_handle(struct wil6210_priv *wil,
2332 			     struct wil6210_mbox_hdr *hdr)
2333 {
2334 	u16 len = le16_to_cpu(hdr->len);
2335 
2336 	if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
2337 	    (len >= sizeof(struct wmi_cmd_hdr))) {
2338 		struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
2339 		void *evt_data = (void *)(&wmi[1]);
2340 		u16 id = le16_to_cpu(wmi->command_id);
2341 
2342 		wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x)\n",
2343 			    eventid2name(id), id, wil->reply_id);
2344 		/* check if someone waits for this event */
2345 		if (wil->reply_id && wil->reply_id == id) {
2346 			WARN_ON(wil->reply_buf);
2347 			wmi_evt_call_handler(wil, id, evt_data,
2348 					     len - sizeof(*wmi));
2349 			wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n",
2350 				    id);
2351 			complete(&wil->wmi_call);
2352 			return;
2353 		}
2354 		/* unsolicited event */
2355 		/* search for handler */
2356 		if (!wmi_evt_call_handler(wil, id, evt_data,
2357 					  len - sizeof(*wmi))) {
2358 			wil_info(wil, "Unhandled event 0x%04x\n", id);
2359 		}
2360 	} else {
2361 		wil_err(wil, "Unknown event type\n");
2362 		print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
2363 			       hdr, sizeof(*hdr) + len, true);
2364 	}
2365 }
2366 
2367 /*
2368  * Retrieve next WMI event from the pending list
2369  */
2370 static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
2371 {
2372 	ulong flags;
2373 	struct list_head *ret = NULL;
2374 
2375 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
2376 
2377 	if (!list_empty(&wil->pending_wmi_ev)) {
2378 		ret = wil->pending_wmi_ev.next;
2379 		list_del(ret);
2380 	}
2381 
2382 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2383 
2384 	return ret;
2385 }
2386 
2387 /*
2388  * Handler for the WMI events
2389  */
2390 void wmi_event_worker(struct work_struct *work)
2391 {
2392 	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
2393 						 wmi_event_worker);
2394 	struct pending_wmi_event *evt;
2395 	struct list_head *lh;
2396 
2397 	wil_dbg_wmi(wil, "event_worker: Start\n");
2398 	while ((lh = next_wmi_ev(wil)) != NULL) {
2399 		evt = list_entry(lh, struct pending_wmi_event, list);
2400 		wmi_event_handle(wil, &evt->event.hdr);
2401 		kfree(evt);
2402 	}
2403 	wil_dbg_wmi(wil, "event_worker: Finished\n");
2404 }
2405 
2406 bool wil_is_wmi_idle(struct wil6210_priv *wil)
2407 {
2408 	ulong flags;
2409 	struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
2410 	bool rc = false;
2411 
2412 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
2413 
2414 	/* Check if there are pending WMI events in the events queue */
2415 	if (!list_empty(&wil->pending_wmi_ev)) {
2416 		wil_dbg_pm(wil, "Pending WMI events in queue\n");
2417 		goto out;
2418 	}
2419 
2420 	/* Check if there is a pending WMI call */
2421 	if (wil->reply_id) {
2422 		wil_dbg_pm(wil, "Pending WMI call\n");
2423 		goto out;
2424 	}
2425 
2426 	/* Check if there are pending RX events in mbox */
2427 	r->head = wil_r(wil, RGF_MBOX +
2428 			offsetof(struct wil6210_mbox_ctl, rx.head));
2429 	if (r->tail != r->head)
2430 		wil_dbg_pm(wil, "Pending WMI mbox events\n");
2431 	else
2432 		rc = true;
2433 
2434 out:
2435 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2436 	return rc;
2437 }
2438 
2439 static void
2440 wmi_sched_scan_set_ssids(struct wil6210_priv *wil,
2441 			 struct wmi_start_sched_scan_cmd *cmd,
2442 			 struct cfg80211_ssid *ssids, int n_ssids,
2443 			 struct cfg80211_match_set *match_sets,
2444 			 int n_match_sets)
2445 {
2446 	int i;
2447 
2448 	if (n_match_sets > WMI_MAX_PNO_SSID_NUM) {
2449 		wil_dbg_wmi(wil, "too many match sets (%d), use first %d\n",
2450 			    n_match_sets, WMI_MAX_PNO_SSID_NUM);
2451 		n_match_sets = WMI_MAX_PNO_SSID_NUM;
2452 	}
2453 	cmd->num_of_ssids = n_match_sets;
2454 
2455 	for (i = 0; i < n_match_sets; i++) {
2456 		struct wmi_sched_scan_ssid_match *wmi_match =
2457 			&cmd->ssid_for_match[i];
2458 		struct cfg80211_match_set *cfg_match = &match_sets[i];
2459 		int j;
2460 
2461 		wmi_match->ssid_len = cfg_match->ssid.ssid_len;
2462 		memcpy(wmi_match->ssid, cfg_match->ssid.ssid,
2463 		       min_t(u8, wmi_match->ssid_len, WMI_MAX_SSID_LEN));
2464 		wmi_match->rssi_threshold = S8_MIN;
2465 		if (cfg_match->rssi_thold >= S8_MIN &&
2466 		    cfg_match->rssi_thold <= S8_MAX)
2467 			wmi_match->rssi_threshold = cfg_match->rssi_thold;
2468 
2469 		for (j = 0; j < n_ssids; j++)
2470 			if (wmi_match->ssid_len == ssids[j].ssid_len &&
2471 			    memcmp(wmi_match->ssid, ssids[j].ssid,
2472 				   wmi_match->ssid_len) == 0)
2473 				wmi_match->add_ssid_to_probe = true;
2474 	}
2475 }
2476 
2477 static void
2478 wmi_sched_scan_set_channels(struct wil6210_priv *wil,
2479 			    struct wmi_start_sched_scan_cmd *cmd,
2480 			    u32 n_channels,
2481 			    struct ieee80211_channel **channels)
2482 {
2483 	int i;
2484 
2485 	if (n_channels > WMI_MAX_CHANNEL_NUM) {
2486 		wil_dbg_wmi(wil, "too many channels (%d), use first %d\n",
2487 			    n_channels, WMI_MAX_CHANNEL_NUM);
2488 		n_channels = WMI_MAX_CHANNEL_NUM;
2489 	}
2490 	cmd->num_of_channels = n_channels;
2491 
2492 	for (i = 0; i < n_channels; i++) {
2493 		struct ieee80211_channel *cfg_chan = channels[i];
2494 
2495 		cmd->channel_list[i] = cfg_chan->hw_value - 1;
2496 	}
2497 }
2498 
2499 static void
2500 wmi_sched_scan_set_plans(struct wil6210_priv *wil,
2501 			 struct wmi_start_sched_scan_cmd *cmd,
2502 			 struct cfg80211_sched_scan_plan *scan_plans,
2503 			 int n_scan_plans)
2504 {
2505 	int i;
2506 
2507 	if (n_scan_plans > WMI_MAX_PLANS_NUM) {
2508 		wil_dbg_wmi(wil, "too many plans (%d), use first %d\n",
2509 			    n_scan_plans, WMI_MAX_PLANS_NUM);
2510 		n_scan_plans = WMI_MAX_PLANS_NUM;
2511 	}
2512 
2513 	for (i = 0; i < n_scan_plans; i++) {
2514 		struct cfg80211_sched_scan_plan *cfg_plan = &scan_plans[i];
2515 
2516 		cmd->scan_plans[i].interval_sec =
2517 			cpu_to_le16(cfg_plan->interval);
2518 		cmd->scan_plans[i].num_of_iterations =
2519 			cpu_to_le16(cfg_plan->iterations);
2520 	}
2521 }
2522 
2523 int wmi_start_sched_scan(struct wil6210_priv *wil,
2524 			 struct cfg80211_sched_scan_request *request)
2525 {
2526 	int rc;
2527 	struct wmi_start_sched_scan_cmd cmd = {
2528 		.min_rssi_threshold = S8_MIN,
2529 		.initial_delay_sec = cpu_to_le16(request->delay),
2530 	};
2531 	struct {
2532 		struct wmi_cmd_hdr wmi;
2533 		struct wmi_start_sched_scan_event evt;
2534 	} __packed reply;
2535 
2536 	if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities))
2537 		return -ENOTSUPP;
2538 
2539 	if (request->min_rssi_thold >= S8_MIN &&
2540 	    request->min_rssi_thold <= S8_MAX)
2541 		cmd.min_rssi_threshold = request->min_rssi_thold;
2542 
2543 	wmi_sched_scan_set_ssids(wil, &cmd, request->ssids, request->n_ssids,
2544 				 request->match_sets, request->n_match_sets);
2545 	wmi_sched_scan_set_channels(wil, &cmd,
2546 				    request->n_channels, request->channels);
2547 	wmi_sched_scan_set_plans(wil, &cmd,
2548 				 request->scan_plans, request->n_scan_plans);
2549 
2550 	reply.evt.result = WMI_PNO_REJECT;
2551 
2552 	rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, &cmd, sizeof(cmd),
2553 		      WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply),
2554 		      WIL_WMI_CALL_GENERAL_TO_MS);
2555 	if (rc)
2556 		return rc;
2557 
2558 	if (reply.evt.result != WMI_PNO_SUCCESS) {
2559 		wil_err(wil, "start sched scan failed, result %d\n",
2560 			reply.evt.result);
2561 		return -EINVAL;
2562 	}
2563 
2564 	return 0;
2565 }
2566 
2567 int wmi_stop_sched_scan(struct wil6210_priv *wil)
2568 {
2569 	int rc;
2570 	struct {
2571 		struct wmi_cmd_hdr wmi;
2572 		struct wmi_stop_sched_scan_event evt;
2573 	} __packed reply;
2574 
2575 	if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities))
2576 		return -ENOTSUPP;
2577 
2578 	reply.evt.result = WMI_PNO_REJECT;
2579 
2580 	rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, NULL, 0,
2581 		      WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply),
2582 		      WIL_WMI_CALL_GENERAL_TO_MS);
2583 	if (rc)
2584 		return rc;
2585 
2586 	if (reply.evt.result != WMI_PNO_SUCCESS) {
2587 		wil_err(wil, "stop sched scan failed, result %d\n",
2588 			reply.evt.result);
2589 		return -EINVAL;
2590 	}
2591 
2592 	return 0;
2593 }
2594