1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
5  */
6 
7 #include <linux/moduleparam.h>
8 #include <linux/etherdevice.h>
9 #include <linux/if_arp.h>
10 
11 #include "wil6210.h"
12 #include "txrx.h"
13 #include "wmi.h"
14 #include "trace.h"
15 
16 /* set the default max assoc sta to max supported by driver */
17 uint max_assoc_sta = WIL6210_MAX_CID;
18 module_param(max_assoc_sta, uint, 0444);
19 MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
20 
21 int agg_wsize; /* = 0; */
22 module_param(agg_wsize, int, 0644);
23 MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
24 		 " 0 - use default; < 0 - don't auto-establish");
25 
26 u8 led_id = WIL_LED_INVALID_ID;
27 module_param(led_id, byte, 0444);
28 MODULE_PARM_DESC(led_id,
29 		 " 60G device led enablement. Set the led ID (0-2) to enable");
30 
31 #define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
32 #define WIL_WMI_PCP_STOP_TO_MS 5000
33 
34 /**
35  * WMI event receiving - theory of operations
36  *
37  * When firmware about to report WMI event, it fills memory area
38  * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
39  * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
40  *
41  * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
42  * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
43  * and handles events within the @wmi_event_worker. Every event get detached
44  * from list, processed and deleted.
45  *
46  * Purpose for this mechanism is to release IRQ thread; otherwise,
47  * if WMI event handling involves another WMI command flow, this 2-nd flow
48  * won't be completed because of blocked IRQ thread.
49  */
50 
51 /**
52  * Addressing - theory of operations
53  *
54  * There are several buses present on the WIL6210 card.
55  * Same memory areas are visible at different address on
56  * the different busses. There are 3 main bus masters:
57  *  - MAC CPU (ucode)
58  *  - User CPU (firmware)
59  *  - AHB (host)
60  *
61  * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
62  * AHB addresses starting from 0x880000
63  *
64  * Internally, firmware uses addresses that allow faster access but
65  * are invisible from the host. To read from these addresses, alternative
66  * AHB address must be used.
67  */
68 
69 /**
70  * @sparrow_fw_mapping provides memory remapping table for sparrow
71  *
72  * array size should be in sync with the declaration in the wil6210.h
73  *
74  * Sparrow memory mapping:
75  * Linker address         PCI/Host address
76  *                        0x880000 .. 0xa80000  2Mb BAR0
77  * 0x800000 .. 0x808000   0x900000 .. 0x908000  32k DCCM
78  * 0x840000 .. 0x860000   0x908000 .. 0x928000  128k PERIPH
79  */
80 const struct fw_map sparrow_fw_mapping[] = {
81 	/* FW code RAM 256k */
82 	{0x000000, 0x040000, 0x8c0000, "fw_code", true, true},
83 	/* FW data RAM 32k */
84 	{0x800000, 0x808000, 0x900000, "fw_data", true, true},
85 	/* periph data 128k */
86 	{0x840000, 0x860000, 0x908000, "fw_peri", true, true},
87 	/* various RGF 40k */
88 	{0x880000, 0x88a000, 0x880000, "rgf", true, true},
89 	/* AGC table   4k */
90 	{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
91 	/* Pcie_ext_rgf 4k */
92 	{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
93 	/* mac_ext_rgf 512b */
94 	{0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true, true},
95 	/* upper area 548k */
96 	{0x8c0000, 0x949000, 0x8c0000, "upper", true, true},
97 	/* UCODE areas - accessible by debugfs blobs but not by
98 	 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
99 	 */
100 	/* ucode code RAM 128k */
101 	{0x000000, 0x020000, 0x920000, "uc_code", false, false},
102 	/* ucode data RAM 16k */
103 	{0x800000, 0x804000, 0x940000, "uc_data", false, false},
104 };
105 
106 /**
107  * @sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
108  * it is a bit larger to support extra features
109  */
110 const struct fw_map sparrow_d0_mac_rgf_ext = {
111 	0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true
112 };
113 
114 /**
115  * @talyn_fw_mapping provides memory remapping table for Talyn
116  *
117  * array size should be in sync with the declaration in the wil6210.h
118  *
119  * Talyn memory mapping:
120  * Linker address         PCI/Host address
121  *                        0x880000 .. 0xc80000  4Mb BAR0
122  * 0x800000 .. 0x820000   0xa00000 .. 0xa20000  128k DCCM
123  * 0x840000 .. 0x858000   0xa20000 .. 0xa38000  96k PERIPH
124  */
125 const struct fw_map talyn_fw_mapping[] = {
126 	/* FW code RAM 1M */
127 	{0x000000, 0x100000, 0x900000, "fw_code", true, true},
128 	/* FW data RAM 128k */
129 	{0x800000, 0x820000, 0xa00000, "fw_data", true, true},
130 	/* periph. data RAM 96k */
131 	{0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
132 	/* various RGF 40k */
133 	{0x880000, 0x88a000, 0x880000, "rgf", true, true},
134 	/* AGC table 4k */
135 	{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
136 	/* Pcie_ext_rgf 4k */
137 	{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
138 	/* mac_ext_rgf 1344b */
139 	{0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true, true},
140 	/* ext USER RGF 4k */
141 	{0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
142 	/* OTP 4k */
143 	{0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
144 	/* DMA EXT RGF 64k */
145 	{0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
146 	/* upper area 1536k */
147 	{0x900000, 0xa80000, 0x900000, "upper", true, true},
148 	/* UCODE areas - accessible by debugfs blobs but not by
149 	 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
150 	 */
151 	/* ucode code RAM 256k */
152 	{0x000000, 0x040000, 0xa38000, "uc_code", false, false},
153 	/* ucode data RAM 32k */
154 	{0x800000, 0x808000, 0xa78000, "uc_data", false, false},
155 };
156 
157 /**
158  * @talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
159  *
160  * array size should be in sync with the declaration in the wil6210.h
161  *
162  * Talyn MB memory mapping:
163  * Linker address         PCI/Host address
164  *                        0x880000 .. 0xc80000  4Mb BAR0
165  * 0x800000 .. 0x820000   0xa00000 .. 0xa20000  128k DCCM
166  * 0x840000 .. 0x858000   0xa20000 .. 0xa38000  96k PERIPH
167  */
168 const struct fw_map talyn_mb_fw_mapping[] = {
169 	/* FW code RAM 768k */
170 	{0x000000, 0x0c0000, 0x900000, "fw_code", true, true},
171 	/* FW data RAM 128k */
172 	{0x800000, 0x820000, 0xa00000, "fw_data", true, true},
173 	/* periph. data RAM 96k */
174 	{0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
175 	/* various RGF 40k */
176 	{0x880000, 0x88a000, 0x880000, "rgf", true, true},
177 	/* AGC table 4k */
178 	{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
179 	/* Pcie_ext_rgf 4k */
180 	{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
181 	/* mac_ext_rgf 2256b */
182 	{0x88c000, 0x88c8d0, 0x88c000, "mac_rgf_ext", true, true},
183 	/* ext USER RGF 4k */
184 	{0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
185 	/* SEC PKA 16k */
186 	{0x890000, 0x894000, 0x890000, "sec_pka", true, true},
187 	/* SEC KDF RGF 3096b */
188 	{0x898000, 0x898c18, 0x898000, "sec_kdf_rgf", true, true},
189 	/* SEC MAIN 2124b */
190 	{0x89a000, 0x89a84c, 0x89a000, "sec_main", true, true},
191 	/* OTP 4k */
192 	{0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
193 	/* DMA EXT RGF 64k */
194 	{0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
195 	/* DUM USER RGF 528b */
196 	{0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true, true},
197 	/* DMA OFU 296b */
198 	{0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true, true},
199 	/* ucode debug 256b */
200 	{0x8c3000, 0x8c3100, 0x8c3000, "ucode_debug", true, true},
201 	/* upper area 1536k */
202 	{0x900000, 0xa80000, 0x900000, "upper", true, true},
203 	/* UCODE areas - accessible by debugfs blobs but not by
204 	 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
205 	 */
206 	/* ucode code RAM 256k */
207 	{0x000000, 0x040000, 0xa38000, "uc_code", false, false},
208 	/* ucode data RAM 32k */
209 	{0x800000, 0x808000, 0xa78000, "uc_data", false, false},
210 };
211 
212 struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
213 
214 struct blink_on_off_time led_blink_time[] = {
215 	{WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS},
216 	{WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS},
217 	{WIL_LED_BLINK_ON_FAST_MS, WIL_LED_BLINK_OFF_FAST_MS},
218 };
219 
220 struct auth_no_hdr {
221 	__le16 auth_alg;
222 	__le16 auth_transaction;
223 	__le16 status_code;
224 	/* possibly followed by Challenge text */
225 	u8 variable[0];
226 } __packed;
227 
228 u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
229 
230 /**
231  * return AHB address for given firmware internal (linker) address
232  * @x - internal address
233  * If address have no valid AHB mapping, return 0
234  */
235 static u32 wmi_addr_remap(u32 x)
236 {
237 	uint i;
238 
239 	for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
240 		if (fw_mapping[i].fw &&
241 		    ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)))
242 			return x + fw_mapping[i].host - fw_mapping[i].from;
243 	}
244 
245 	return 0;
246 }
247 
248 /**
249  * find fw_mapping entry by section name
250  * @section - section name
251  *
252  * Return pointer to section or NULL if not found
253  */
254 struct fw_map *wil_find_fw_mapping(const char *section)
255 {
256 	int i;
257 
258 	for (i = 0; i < ARRAY_SIZE(fw_mapping); i++)
259 		if (fw_mapping[i].name &&
260 		    !strcmp(section, fw_mapping[i].name))
261 			return &fw_mapping[i];
262 
263 	return NULL;
264 }
265 
266 /**
267  * Check address validity for WMI buffer; remap if needed
268  * @ptr - internal (linker) fw/ucode address
269  * @size - if non zero, validate the block does not
270  *  exceed the device memory (bar)
271  *
272  * Valid buffer should be DWORD aligned
273  *
274  * return address for accessing buffer from the host;
275  * if buffer is not valid, return NULL.
276  */
277 void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size)
278 {
279 	u32 off;
280 	u32 ptr = le32_to_cpu(ptr_);
281 
282 	if (ptr % 4)
283 		return NULL;
284 
285 	ptr = wmi_addr_remap(ptr);
286 	if (ptr < WIL6210_FW_HOST_OFF)
287 		return NULL;
288 
289 	off = HOSTADDR(ptr);
290 	if (off > wil->bar_size - 4)
291 		return NULL;
292 	if (size && ((off + size > wil->bar_size) || (off + size < off)))
293 		return NULL;
294 
295 	return wil->csr + off;
296 }
297 
298 void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
299 {
300 	return wmi_buffer_block(wil, ptr_, 0);
301 }
302 
303 /**
304  * Check address validity
305  */
306 void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
307 {
308 	u32 off;
309 
310 	if (ptr % 4)
311 		return NULL;
312 
313 	if (ptr < WIL6210_FW_HOST_OFF)
314 		return NULL;
315 
316 	off = HOSTADDR(ptr);
317 	if (off > wil->bar_size - 4)
318 		return NULL;
319 
320 	return wil->csr + off;
321 }
322 
323 int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
324 		 struct wil6210_mbox_hdr *hdr)
325 {
326 	void __iomem *src = wmi_buffer(wil, ptr);
327 
328 	if (!src)
329 		return -EINVAL;
330 
331 	wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
332 
333 	return 0;
334 }
335 
336 static const char *cmdid2name(u16 cmdid)
337 {
338 	switch (cmdid) {
339 	case WMI_NOTIFY_REQ_CMDID:
340 		return "WMI_NOTIFY_REQ_CMD";
341 	case WMI_START_SCAN_CMDID:
342 		return "WMI_START_SCAN_CMD";
343 	case WMI_CONNECT_CMDID:
344 		return "WMI_CONNECT_CMD";
345 	case WMI_DISCONNECT_CMDID:
346 		return "WMI_DISCONNECT_CMD";
347 	case WMI_SW_TX_REQ_CMDID:
348 		return "WMI_SW_TX_REQ_CMD";
349 	case WMI_GET_RF_SECTOR_PARAMS_CMDID:
350 		return "WMI_GET_RF_SECTOR_PARAMS_CMD";
351 	case WMI_SET_RF_SECTOR_PARAMS_CMDID:
352 		return "WMI_SET_RF_SECTOR_PARAMS_CMD";
353 	case WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID:
354 		return "WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD";
355 	case WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID:
356 		return "WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD";
357 	case WMI_BRP_SET_ANT_LIMIT_CMDID:
358 		return "WMI_BRP_SET_ANT_LIMIT_CMD";
359 	case WMI_TOF_SESSION_START_CMDID:
360 		return "WMI_TOF_SESSION_START_CMD";
361 	case WMI_AOA_MEAS_CMDID:
362 		return "WMI_AOA_MEAS_CMD";
363 	case WMI_PMC_CMDID:
364 		return "WMI_PMC_CMD";
365 	case WMI_TOF_GET_TX_RX_OFFSET_CMDID:
366 		return "WMI_TOF_GET_TX_RX_OFFSET_CMD";
367 	case WMI_TOF_SET_TX_RX_OFFSET_CMDID:
368 		return "WMI_TOF_SET_TX_RX_OFFSET_CMD";
369 	case WMI_VRING_CFG_CMDID:
370 		return "WMI_VRING_CFG_CMD";
371 	case WMI_BCAST_VRING_CFG_CMDID:
372 		return "WMI_BCAST_VRING_CFG_CMD";
373 	case WMI_TRAFFIC_SUSPEND_CMDID:
374 		return "WMI_TRAFFIC_SUSPEND_CMD";
375 	case WMI_TRAFFIC_RESUME_CMDID:
376 		return "WMI_TRAFFIC_RESUME_CMD";
377 	case WMI_ECHO_CMDID:
378 		return "WMI_ECHO_CMD";
379 	case WMI_SET_MAC_ADDRESS_CMDID:
380 		return "WMI_SET_MAC_ADDRESS_CMD";
381 	case WMI_LED_CFG_CMDID:
382 		return "WMI_LED_CFG_CMD";
383 	case WMI_PCP_START_CMDID:
384 		return "WMI_PCP_START_CMD";
385 	case WMI_PCP_STOP_CMDID:
386 		return "WMI_PCP_STOP_CMD";
387 	case WMI_SET_SSID_CMDID:
388 		return "WMI_SET_SSID_CMD";
389 	case WMI_GET_SSID_CMDID:
390 		return "WMI_GET_SSID_CMD";
391 	case WMI_SET_PCP_CHANNEL_CMDID:
392 		return "WMI_SET_PCP_CHANNEL_CMD";
393 	case WMI_GET_PCP_CHANNEL_CMDID:
394 		return "WMI_GET_PCP_CHANNEL_CMD";
395 	case WMI_P2P_CFG_CMDID:
396 		return "WMI_P2P_CFG_CMD";
397 	case WMI_PORT_ALLOCATE_CMDID:
398 		return "WMI_PORT_ALLOCATE_CMD";
399 	case WMI_PORT_DELETE_CMDID:
400 		return "WMI_PORT_DELETE_CMD";
401 	case WMI_START_LISTEN_CMDID:
402 		return "WMI_START_LISTEN_CMD";
403 	case WMI_START_SEARCH_CMDID:
404 		return "WMI_START_SEARCH_CMD";
405 	case WMI_DISCOVERY_STOP_CMDID:
406 		return "WMI_DISCOVERY_STOP_CMD";
407 	case WMI_DELETE_CIPHER_KEY_CMDID:
408 		return "WMI_DELETE_CIPHER_KEY_CMD";
409 	case WMI_ADD_CIPHER_KEY_CMDID:
410 		return "WMI_ADD_CIPHER_KEY_CMD";
411 	case WMI_SET_APPIE_CMDID:
412 		return "WMI_SET_APPIE_CMD";
413 	case WMI_CFG_RX_CHAIN_CMDID:
414 		return "WMI_CFG_RX_CHAIN_CMD";
415 	case WMI_TEMP_SENSE_CMDID:
416 		return "WMI_TEMP_SENSE_CMD";
417 	case WMI_DEL_STA_CMDID:
418 		return "WMI_DEL_STA_CMD";
419 	case WMI_DISCONNECT_STA_CMDID:
420 		return "WMI_DISCONNECT_STA_CMD";
421 	case WMI_RING_BA_EN_CMDID:
422 		return "WMI_RING_BA_EN_CMD";
423 	case WMI_RING_BA_DIS_CMDID:
424 		return "WMI_RING_BA_DIS_CMD";
425 	case WMI_RCP_DELBA_CMDID:
426 		return "WMI_RCP_DELBA_CMD";
427 	case WMI_RCP_ADDBA_RESP_CMDID:
428 		return "WMI_RCP_ADDBA_RESP_CMD";
429 	case WMI_RCP_ADDBA_RESP_EDMA_CMDID:
430 		return "WMI_RCP_ADDBA_RESP_EDMA_CMD";
431 	case WMI_PS_DEV_PROFILE_CFG_CMDID:
432 		return "WMI_PS_DEV_PROFILE_CFG_CMD";
433 	case WMI_SET_MGMT_RETRY_LIMIT_CMDID:
434 		return "WMI_SET_MGMT_RETRY_LIMIT_CMD";
435 	case WMI_GET_MGMT_RETRY_LIMIT_CMDID:
436 		return "WMI_GET_MGMT_RETRY_LIMIT_CMD";
437 	case WMI_ABORT_SCAN_CMDID:
438 		return "WMI_ABORT_SCAN_CMD";
439 	case WMI_NEW_STA_CMDID:
440 		return "WMI_NEW_STA_CMD";
441 	case WMI_SET_THERMAL_THROTTLING_CFG_CMDID:
442 		return "WMI_SET_THERMAL_THROTTLING_CFG_CMD";
443 	case WMI_GET_THERMAL_THROTTLING_CFG_CMDID:
444 		return "WMI_GET_THERMAL_THROTTLING_CFG_CMD";
445 	case WMI_LINK_MAINTAIN_CFG_WRITE_CMDID:
446 		return "WMI_LINK_MAINTAIN_CFG_WRITE_CMD";
447 	case WMI_LO_POWER_CALIB_FROM_OTP_CMDID:
448 		return "WMI_LO_POWER_CALIB_FROM_OTP_CMD";
449 	case WMI_START_SCHED_SCAN_CMDID:
450 		return "WMI_START_SCHED_SCAN_CMD";
451 	case WMI_STOP_SCHED_SCAN_CMDID:
452 		return "WMI_STOP_SCHED_SCAN_CMD";
453 	case WMI_TX_STATUS_RING_ADD_CMDID:
454 		return "WMI_TX_STATUS_RING_ADD_CMD";
455 	case WMI_RX_STATUS_RING_ADD_CMDID:
456 		return "WMI_RX_STATUS_RING_ADD_CMD";
457 	case WMI_TX_DESC_RING_ADD_CMDID:
458 		return "WMI_TX_DESC_RING_ADD_CMD";
459 	case WMI_RX_DESC_RING_ADD_CMDID:
460 		return "WMI_RX_DESC_RING_ADD_CMD";
461 	case WMI_BCAST_DESC_RING_ADD_CMDID:
462 		return "WMI_BCAST_DESC_RING_ADD_CMD";
463 	case WMI_CFG_DEF_RX_OFFLOAD_CMDID:
464 		return "WMI_CFG_DEF_RX_OFFLOAD_CMD";
465 	case WMI_LINK_STATS_CMDID:
466 		return "WMI_LINK_STATS_CMD";
467 	case WMI_SW_TX_REQ_EXT_CMDID:
468 		return "WMI_SW_TX_REQ_EXT_CMDID";
469 	case WMI_FT_AUTH_CMDID:
470 		return "WMI_FT_AUTH_CMD";
471 	case WMI_FT_REASSOC_CMDID:
472 		return "WMI_FT_REASSOC_CMD";
473 	case WMI_UPDATE_FT_IES_CMDID:
474 		return "WMI_UPDATE_FT_IES_CMD";
475 	case WMI_RBUFCAP_CFG_CMDID:
476 		return "WMI_RBUFCAP_CFG_CMD";
477 	case WMI_TEMP_SENSE_ALL_CMDID:
478 		return "WMI_TEMP_SENSE_ALL_CMDID";
479 	case WMI_SET_LINK_MONITOR_CMDID:
480 		return "WMI_SET_LINK_MONITOR_CMD";
481 	default:
482 		return "Untracked CMD";
483 	}
484 }
485 
486 static const char *eventid2name(u16 eventid)
487 {
488 	switch (eventid) {
489 	case WMI_NOTIFY_REQ_DONE_EVENTID:
490 		return "WMI_NOTIFY_REQ_DONE_EVENT";
491 	case WMI_DISCONNECT_EVENTID:
492 		return "WMI_DISCONNECT_EVENT";
493 	case WMI_SW_TX_COMPLETE_EVENTID:
494 		return "WMI_SW_TX_COMPLETE_EVENT";
495 	case WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID:
496 		return "WMI_GET_RF_SECTOR_PARAMS_DONE_EVENT";
497 	case WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID:
498 		return "WMI_SET_RF_SECTOR_PARAMS_DONE_EVENT";
499 	case WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID:
500 		return "WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
501 	case WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID:
502 		return "WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
503 	case WMI_BRP_SET_ANT_LIMIT_EVENTID:
504 		return "WMI_BRP_SET_ANT_LIMIT_EVENT";
505 	case WMI_FW_READY_EVENTID:
506 		return "WMI_FW_READY_EVENT";
507 	case WMI_TRAFFIC_RESUME_EVENTID:
508 		return "WMI_TRAFFIC_RESUME_EVENT";
509 	case WMI_TOF_GET_TX_RX_OFFSET_EVENTID:
510 		return "WMI_TOF_GET_TX_RX_OFFSET_EVENT";
511 	case WMI_TOF_SET_TX_RX_OFFSET_EVENTID:
512 		return "WMI_TOF_SET_TX_RX_OFFSET_EVENT";
513 	case WMI_VRING_CFG_DONE_EVENTID:
514 		return "WMI_VRING_CFG_DONE_EVENT";
515 	case WMI_READY_EVENTID:
516 		return "WMI_READY_EVENT";
517 	case WMI_RX_MGMT_PACKET_EVENTID:
518 		return "WMI_RX_MGMT_PACKET_EVENT";
519 	case WMI_TX_MGMT_PACKET_EVENTID:
520 		return "WMI_TX_MGMT_PACKET_EVENT";
521 	case WMI_SCAN_COMPLETE_EVENTID:
522 		return "WMI_SCAN_COMPLETE_EVENT";
523 	case WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID:
524 		return "WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT";
525 	case WMI_CONNECT_EVENTID:
526 		return "WMI_CONNECT_EVENT";
527 	case WMI_EAPOL_RX_EVENTID:
528 		return "WMI_EAPOL_RX_EVENT";
529 	case WMI_BA_STATUS_EVENTID:
530 		return "WMI_BA_STATUS_EVENT";
531 	case WMI_RCP_ADDBA_REQ_EVENTID:
532 		return "WMI_RCP_ADDBA_REQ_EVENT";
533 	case WMI_DELBA_EVENTID:
534 		return "WMI_DELBA_EVENT";
535 	case WMI_RING_EN_EVENTID:
536 		return "WMI_RING_EN_EVENT";
537 	case WMI_DATA_PORT_OPEN_EVENTID:
538 		return "WMI_DATA_PORT_OPEN_EVENT";
539 	case WMI_AOA_MEAS_EVENTID:
540 		return "WMI_AOA_MEAS_EVENT";
541 	case WMI_TOF_SESSION_END_EVENTID:
542 		return "WMI_TOF_SESSION_END_EVENT";
543 	case WMI_TOF_GET_CAPABILITIES_EVENTID:
544 		return "WMI_TOF_GET_CAPABILITIES_EVENT";
545 	case WMI_TOF_SET_LCR_EVENTID:
546 		return "WMI_TOF_SET_LCR_EVENT";
547 	case WMI_TOF_SET_LCI_EVENTID:
548 		return "WMI_TOF_SET_LCI_EVENT";
549 	case WMI_TOF_FTM_PER_DEST_RES_EVENTID:
550 		return "WMI_TOF_FTM_PER_DEST_RES_EVENT";
551 	case WMI_TOF_CHANNEL_INFO_EVENTID:
552 		return "WMI_TOF_CHANNEL_INFO_EVENT";
553 	case WMI_TRAFFIC_SUSPEND_EVENTID:
554 		return "WMI_TRAFFIC_SUSPEND_EVENT";
555 	case WMI_ECHO_RSP_EVENTID:
556 		return "WMI_ECHO_RSP_EVENT";
557 	case WMI_LED_CFG_DONE_EVENTID:
558 		return "WMI_LED_CFG_DONE_EVENT";
559 	case WMI_PCP_STARTED_EVENTID:
560 		return "WMI_PCP_STARTED_EVENT";
561 	case WMI_PCP_STOPPED_EVENTID:
562 		return "WMI_PCP_STOPPED_EVENT";
563 	case WMI_GET_SSID_EVENTID:
564 		return "WMI_GET_SSID_EVENT";
565 	case WMI_GET_PCP_CHANNEL_EVENTID:
566 		return "WMI_GET_PCP_CHANNEL_EVENT";
567 	case WMI_P2P_CFG_DONE_EVENTID:
568 		return "WMI_P2P_CFG_DONE_EVENT";
569 	case WMI_PORT_ALLOCATED_EVENTID:
570 		return "WMI_PORT_ALLOCATED_EVENT";
571 	case WMI_PORT_DELETED_EVENTID:
572 		return "WMI_PORT_DELETED_EVENT";
573 	case WMI_LISTEN_STARTED_EVENTID:
574 		return "WMI_LISTEN_STARTED_EVENT";
575 	case WMI_SEARCH_STARTED_EVENTID:
576 		return "WMI_SEARCH_STARTED_EVENT";
577 	case WMI_DISCOVERY_STOPPED_EVENTID:
578 		return "WMI_DISCOVERY_STOPPED_EVENT";
579 	case WMI_CFG_RX_CHAIN_DONE_EVENTID:
580 		return "WMI_CFG_RX_CHAIN_DONE_EVENT";
581 	case WMI_TEMP_SENSE_DONE_EVENTID:
582 		return "WMI_TEMP_SENSE_DONE_EVENT";
583 	case WMI_RCP_ADDBA_RESP_SENT_EVENTID:
584 		return "WMI_RCP_ADDBA_RESP_SENT_EVENT";
585 	case WMI_PS_DEV_PROFILE_CFG_EVENTID:
586 		return "WMI_PS_DEV_PROFILE_CFG_EVENT";
587 	case WMI_SET_MGMT_RETRY_LIMIT_EVENTID:
588 		return "WMI_SET_MGMT_RETRY_LIMIT_EVENT";
589 	case WMI_GET_MGMT_RETRY_LIMIT_EVENTID:
590 		return "WMI_GET_MGMT_RETRY_LIMIT_EVENT";
591 	case WMI_SET_THERMAL_THROTTLING_CFG_EVENTID:
592 		return "WMI_SET_THERMAL_THROTTLING_CFG_EVENT";
593 	case WMI_GET_THERMAL_THROTTLING_CFG_EVENTID:
594 		return "WMI_GET_THERMAL_THROTTLING_CFG_EVENT";
595 	case WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID:
596 		return "WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENT";
597 	case WMI_LO_POWER_CALIB_FROM_OTP_EVENTID:
598 		return "WMI_LO_POWER_CALIB_FROM_OTP_EVENT";
599 	case WMI_START_SCHED_SCAN_EVENTID:
600 		return "WMI_START_SCHED_SCAN_EVENT";
601 	case WMI_STOP_SCHED_SCAN_EVENTID:
602 		return "WMI_STOP_SCHED_SCAN_EVENT";
603 	case WMI_SCHED_SCAN_RESULT_EVENTID:
604 		return "WMI_SCHED_SCAN_RESULT_EVENT";
605 	case WMI_TX_STATUS_RING_CFG_DONE_EVENTID:
606 		return "WMI_TX_STATUS_RING_CFG_DONE_EVENT";
607 	case WMI_RX_STATUS_RING_CFG_DONE_EVENTID:
608 		return "WMI_RX_STATUS_RING_CFG_DONE_EVENT";
609 	case WMI_TX_DESC_RING_CFG_DONE_EVENTID:
610 		return "WMI_TX_DESC_RING_CFG_DONE_EVENT";
611 	case WMI_RX_DESC_RING_CFG_DONE_EVENTID:
612 		return "WMI_RX_DESC_RING_CFG_DONE_EVENT";
613 	case WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID:
614 		return "WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENT";
615 	case WMI_LINK_STATS_CONFIG_DONE_EVENTID:
616 		return "WMI_LINK_STATS_CONFIG_DONE_EVENT";
617 	case WMI_LINK_STATS_EVENTID:
618 		return "WMI_LINK_STATS_EVENT";
619 	case WMI_COMMAND_NOT_SUPPORTED_EVENTID:
620 		return "WMI_COMMAND_NOT_SUPPORTED_EVENT";
621 	case WMI_FT_AUTH_STATUS_EVENTID:
622 		return "WMI_FT_AUTH_STATUS_EVENT";
623 	case WMI_FT_REASSOC_STATUS_EVENTID:
624 		return "WMI_FT_REASSOC_STATUS_EVENT";
625 	case WMI_RBUFCAP_CFG_EVENTID:
626 		return "WMI_RBUFCAP_CFG_EVENT";
627 	case WMI_TEMP_SENSE_ALL_DONE_EVENTID:
628 		return "WMI_TEMP_SENSE_ALL_DONE_EVENTID";
629 	case WMI_SET_LINK_MONITOR_EVENTID:
630 		return "WMI_SET_LINK_MONITOR_EVENT";
631 	case WMI_LINK_MONITOR_EVENTID:
632 		return "WMI_LINK_MONITOR_EVENT";
633 	default:
634 		return "Untracked EVENT";
635 	}
636 }
637 
638 static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid,
639 		      void *buf, u16 len)
640 {
641 	struct {
642 		struct wil6210_mbox_hdr hdr;
643 		struct wmi_cmd_hdr wmi;
644 	} __packed cmd = {
645 		.hdr = {
646 			.type = WIL_MBOX_HDR_TYPE_WMI,
647 			.flags = 0,
648 			.len = cpu_to_le16(sizeof(cmd.wmi) + len),
649 		},
650 		.wmi = {
651 			.mid = mid,
652 			.command_id = cpu_to_le16(cmdid),
653 		},
654 	};
655 	struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
656 	struct wil6210_mbox_ring_desc d_head;
657 	u32 next_head;
658 	void __iomem *dst;
659 	void __iomem *head = wmi_addr(wil, r->head);
660 	uint retry;
661 	int rc = 0;
662 
663 	if (len > r->entry_size - sizeof(cmd)) {
664 		wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
665 			(int)(sizeof(cmd) + len), r->entry_size);
666 		return -ERANGE;
667 	}
668 
669 	might_sleep();
670 
671 	if (!test_bit(wil_status_fwready, wil->status)) {
672 		wil_err(wil, "WMI: cannot send command while FW not ready\n");
673 		return -EAGAIN;
674 	}
675 
676 	/* Allow sending only suspend / resume commands during susepnd flow */
677 	if ((test_bit(wil_status_suspending, wil->status) ||
678 	     test_bit(wil_status_suspended, wil->status) ||
679 	     test_bit(wil_status_resuming, wil->status)) &&
680 	     ((cmdid != WMI_TRAFFIC_SUSPEND_CMDID) &&
681 	      (cmdid != WMI_TRAFFIC_RESUME_CMDID))) {
682 		wil_err(wil, "WMI: reject send_command during suspend\n");
683 		return -EINVAL;
684 	}
685 
686 	if (!head) {
687 		wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
688 		return -EINVAL;
689 	}
690 
691 	wil_halp_vote(wil);
692 
693 	/* read Tx head till it is not busy */
694 	for (retry = 5; retry > 0; retry--) {
695 		wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
696 		if (d_head.sync == 0)
697 			break;
698 		msleep(20);
699 	}
700 	if (d_head.sync != 0) {
701 		wil_err(wil, "WMI head busy\n");
702 		rc = -EBUSY;
703 		goto out;
704 	}
705 	/* next head */
706 	next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
707 	wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
708 	/* wait till FW finish with previous command */
709 	for (retry = 5; retry > 0; retry--) {
710 		if (!test_bit(wil_status_fwready, wil->status)) {
711 			wil_err(wil, "WMI: cannot send command while FW not ready\n");
712 			rc = -EAGAIN;
713 			goto out;
714 		}
715 		r->tail = wil_r(wil, RGF_MBOX +
716 				offsetof(struct wil6210_mbox_ctl, tx.tail));
717 		if (next_head != r->tail)
718 			break;
719 		msleep(20);
720 	}
721 	if (next_head == r->tail) {
722 		wil_err(wil, "WMI ring full\n");
723 		rc = -EBUSY;
724 		goto out;
725 	}
726 	dst = wmi_buffer(wil, d_head.addr);
727 	if (!dst) {
728 		wil_err(wil, "invalid WMI buffer: 0x%08x\n",
729 			le32_to_cpu(d_head.addr));
730 		rc = -EAGAIN;
731 		goto out;
732 	}
733 	cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
734 	/* set command */
735 	wil_dbg_wmi(wil, "sending %s (0x%04x) [%d] mid %d\n",
736 		    cmdid2name(cmdid), cmdid, len, mid);
737 	wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
738 			 sizeof(cmd), true);
739 	wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
740 			 len, true);
741 	wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
742 	wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
743 	/* mark entry as full */
744 	wil_w(wil, r->head + offsetof(struct wil6210_mbox_ring_desc, sync), 1);
745 	/* advance next ptr */
746 	wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, tx.head),
747 	      r->head = next_head);
748 
749 	trace_wil6210_wmi_cmd(&cmd.wmi, buf, len);
750 
751 	/* interrupt to FW */
752 	wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS),
753 	      SW_INT_MBOX);
754 
755 out:
756 	wil_halp_unvote(wil);
757 	return rc;
758 }
759 
760 int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len)
761 {
762 	int rc;
763 
764 	mutex_lock(&wil->wmi_mutex);
765 	rc = __wmi_send(wil, cmdid, mid, buf, len);
766 	mutex_unlock(&wil->wmi_mutex);
767 
768 	return rc;
769 }
770 
771 /*=== Event handlers ===*/
772 static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
773 {
774 	struct wil6210_priv *wil = vif_to_wil(vif);
775 	struct wiphy *wiphy = wil_to_wiphy(wil);
776 	struct wmi_ready_event *evt = d;
777 	u8 fw_max_assoc_sta;
778 
779 	wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
780 		 wil->fw_version, le32_to_cpu(evt->sw_version),
781 		 evt->mac, evt->numof_additional_mids);
782 	if (evt->numof_additional_mids + 1 < wil->max_vifs) {
783 		wil_err(wil, "FW does not support enough MIDs (need %d)",
784 			wil->max_vifs - 1);
785 		return; /* FW load will fail after timeout */
786 	}
787 	/* ignore MAC address, we already have it from the boot loader */
788 	strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
789 
790 	if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) {
791 		wil_dbg_wmi(wil, "rfc calibration result %d\n",
792 			    evt->rfc_read_calib_result);
793 		wil->fw_calib_result = evt->rfc_read_calib_result;
794 	}
795 
796 	fw_max_assoc_sta = WIL6210_RX_DESC_MAX_CID;
797 	if (len > offsetof(struct wmi_ready_event, max_assoc_sta) &&
798 	    evt->max_assoc_sta > 0) {
799 		fw_max_assoc_sta = evt->max_assoc_sta;
800 		wil_dbg_wmi(wil, "fw reported max assoc sta %d\n",
801 			    fw_max_assoc_sta);
802 
803 		if (fw_max_assoc_sta > WIL6210_MAX_CID) {
804 			wil_dbg_wmi(wil,
805 				    "fw max assoc sta %d exceeds max driver supported %d\n",
806 				    fw_max_assoc_sta, WIL6210_MAX_CID);
807 			fw_max_assoc_sta = WIL6210_MAX_CID;
808 		}
809 	}
810 
811 	wil->max_assoc_sta = min_t(uint, max_assoc_sta, fw_max_assoc_sta);
812 	wil_dbg_wmi(wil, "setting max assoc sta to %d\n", wil->max_assoc_sta);
813 
814 	wil_set_recovery_state(wil, fw_recovery_idle);
815 	set_bit(wil_status_fwready, wil->status);
816 	/* let the reset sequence continue */
817 	complete(&wil->wmi_ready);
818 }
819 
820 static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
821 {
822 	struct wil6210_priv *wil = vif_to_wil(vif);
823 	struct wmi_rx_mgmt_packet_event *data = d;
824 	struct wiphy *wiphy = wil_to_wiphy(wil);
825 	struct ieee80211_mgmt *rx_mgmt_frame =
826 			(struct ieee80211_mgmt *)data->payload;
827 	int flen = len - offsetof(struct wmi_rx_mgmt_packet_event, payload);
828 	int ch_no;
829 	u32 freq;
830 	struct ieee80211_channel *channel;
831 	s32 signal;
832 	__le16 fc;
833 	u32 d_len;
834 	u16 d_status;
835 
836 	if (flen < 0) {
837 		wil_err(wil, "MGMT Rx: short event, len %d\n", len);
838 		return;
839 	}
840 
841 	d_len = le32_to_cpu(data->info.len);
842 	if (d_len != flen) {
843 		wil_err(wil,
844 			"MGMT Rx: length mismatch, d_len %d should be %d\n",
845 			d_len, flen);
846 		return;
847 	}
848 
849 	ch_no = data->info.channel + 1;
850 	freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ);
851 	channel = ieee80211_get_channel(wiphy, freq);
852 	if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities))
853 		signal = 100 * data->info.rssi;
854 	else
855 		signal = data->info.sqi;
856 	d_status = le16_to_cpu(data->info.status);
857 	fc = rx_mgmt_frame->frame_control;
858 
859 	wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n",
860 		    data->info.channel, data->info.mcs, data->info.rssi,
861 		    data->info.sqi);
862 	wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
863 		    le16_to_cpu(fc));
864 	wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
865 		    data->info.qid, data->info.mid, data->info.cid);
866 	wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
867 			 d_len, true);
868 
869 	if (!channel) {
870 		wil_err(wil, "Frame on unsupported channel\n");
871 		return;
872 	}
873 
874 	if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
875 		struct cfg80211_bss *bss;
876 		struct cfg80211_inform_bss bss_data = {
877 			.chan = channel,
878 			.scan_width = NL80211_BSS_CHAN_WIDTH_20,
879 			.signal = signal,
880 			.boottime_ns = ktime_to_ns(ktime_get_boottime()),
881 		};
882 		u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
883 		u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
884 		u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
885 		const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
886 		size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
887 						 u.beacon.variable);
888 		wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
889 		wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
890 		wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
891 		wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
892 				 ie_len, true);
893 
894 		wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
895 
896 		bss = cfg80211_inform_bss_frame_data(wiphy, &bss_data,
897 						     rx_mgmt_frame,
898 						     d_len, GFP_KERNEL);
899 		if (bss) {
900 			wil_dbg_wmi(wil, "Added BSS %pM\n",
901 				    rx_mgmt_frame->bssid);
902 			cfg80211_put_bss(wiphy, bss);
903 		} else {
904 			wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
905 		}
906 	} else {
907 		mutex_lock(&wil->vif_mutex);
908 		cfg80211_rx_mgmt(vif_to_radio_wdev(wil, vif), freq, signal,
909 				 (void *)rx_mgmt_frame, d_len, 0);
910 		mutex_unlock(&wil->vif_mutex);
911 	}
912 }
913 
914 static void wmi_evt_tx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
915 {
916 	struct wmi_tx_mgmt_packet_event *data = d;
917 	struct ieee80211_mgmt *mgmt_frame =
918 			(struct ieee80211_mgmt *)data->payload;
919 	int flen = len - offsetof(struct wmi_tx_mgmt_packet_event, payload);
920 
921 	wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET, 16, 1, mgmt_frame,
922 			 flen, true);
923 }
924 
925 static void wmi_evt_scan_complete(struct wil6210_vif *vif, int id,
926 				  void *d, int len)
927 {
928 	struct wil6210_priv *wil = vif_to_wil(vif);
929 
930 	mutex_lock(&wil->vif_mutex);
931 	if (vif->scan_request) {
932 		struct wmi_scan_complete_event *data = d;
933 		int status = le32_to_cpu(data->status);
934 		struct cfg80211_scan_info info = {
935 			.aborted = ((status != WMI_SCAN_SUCCESS) &&
936 				(status != WMI_SCAN_ABORT_REJECTED)),
937 		};
938 
939 		wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status);
940 		wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
941 			     vif->scan_request, info.aborted);
942 		del_timer_sync(&vif->scan_timer);
943 		cfg80211_scan_done(vif->scan_request, &info);
944 		if (vif->mid == 0)
945 			wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
946 		vif->scan_request = NULL;
947 		wake_up_interruptible(&wil->wq);
948 		if (vif->p2p.pending_listen_wdev) {
949 			wil_dbg_misc(wil, "Scheduling delayed listen\n");
950 			schedule_work(&vif->p2p.delayed_listen_work);
951 		}
952 	} else {
953 		wil_err(wil, "SCAN_COMPLETE while not scanning\n");
954 	}
955 	mutex_unlock(&wil->vif_mutex);
956 }
957 
958 static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
959 {
960 	struct wil6210_priv *wil = vif_to_wil(vif);
961 	struct net_device *ndev = vif_to_ndev(vif);
962 	struct wireless_dev *wdev = vif_to_wdev(vif);
963 	struct wmi_connect_event *evt = d;
964 	int ch; /* channel number */
965 	struct station_info *sinfo;
966 	u8 *assoc_req_ie, *assoc_resp_ie;
967 	size_t assoc_req_ielen, assoc_resp_ielen;
968 	/* capinfo(u16) + listen_interval(u16) + IEs */
969 	const size_t assoc_req_ie_offset = sizeof(u16) * 2;
970 	/* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
971 	const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
972 	int rc;
973 
974 	if (len < sizeof(*evt)) {
975 		wil_err(wil, "Connect event too short : %d bytes\n", len);
976 		return;
977 	}
978 	if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
979 		   evt->assoc_resp_len) {
980 		wil_err(wil,
981 			"Connect event corrupted : %d != %d + %d + %d + %d\n",
982 			len, (int)sizeof(*evt), evt->beacon_ie_len,
983 			evt->assoc_req_len, evt->assoc_resp_len);
984 		return;
985 	}
986 	if (evt->cid >= wil->max_assoc_sta) {
987 		wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
988 		return;
989 	}
990 
991 	ch = evt->channel + 1;
992 	wil_info(wil, "Connect %pM channel [%d] cid %d aid %d\n",
993 		 evt->bssid, ch, evt->cid, evt->aid);
994 	wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
995 			 evt->assoc_info, len - sizeof(*evt), true);
996 
997 	/* figure out IE's */
998 	assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
999 					assoc_req_ie_offset];
1000 	assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
1001 	if (evt->assoc_req_len <= assoc_req_ie_offset) {
1002 		assoc_req_ie = NULL;
1003 		assoc_req_ielen = 0;
1004 	}
1005 
1006 	assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
1007 					 evt->assoc_req_len +
1008 					 assoc_resp_ie_offset];
1009 	assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
1010 	if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
1011 		assoc_resp_ie = NULL;
1012 		assoc_resp_ielen = 0;
1013 	}
1014 
1015 	if (test_bit(wil_status_resetting, wil->status) ||
1016 	    !test_bit(wil_status_fwready, wil->status)) {
1017 		wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
1018 			evt->cid);
1019 		/* no need for cleanup, wil_reset will do that */
1020 		return;
1021 	}
1022 
1023 	mutex_lock(&wil->mutex);
1024 
1025 	if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
1026 	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
1027 		if (!test_bit(wil_vif_fwconnecting, vif->status)) {
1028 			wil_err(wil, "Not in connecting state\n");
1029 			mutex_unlock(&wil->mutex);
1030 			return;
1031 		}
1032 		del_timer_sync(&vif->connect_timer);
1033 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
1034 		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
1035 		if (wil->sta[evt->cid].status != wil_sta_unused) {
1036 			wil_err(wil, "AP: Invalid status %d for CID %d\n",
1037 				wil->sta[evt->cid].status, evt->cid);
1038 			mutex_unlock(&wil->mutex);
1039 			return;
1040 		}
1041 	}
1042 
1043 	ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
1044 	wil->sta[evt->cid].mid = vif->mid;
1045 	wil->sta[evt->cid].status = wil_sta_conn_pending;
1046 
1047 	rc = wil_ring_init_tx(vif, evt->cid);
1048 	if (rc) {
1049 		wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n",
1050 			evt->cid, rc);
1051 		wmi_disconnect_sta(vif, wil->sta[evt->cid].addr,
1052 				   WLAN_REASON_UNSPECIFIED, false);
1053 	} else {
1054 		wil_info(wil, "successful connection to CID %d\n", evt->cid);
1055 	}
1056 
1057 	if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
1058 	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
1059 		if (rc) {
1060 			netif_carrier_off(ndev);
1061 			wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
1062 			wil_err(wil, "cfg80211_connect_result with failure\n");
1063 			cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
1064 						NULL, 0,
1065 						WLAN_STATUS_UNSPECIFIED_FAILURE,
1066 						GFP_KERNEL);
1067 			goto out;
1068 		} else {
1069 			struct wiphy *wiphy = wil_to_wiphy(wil);
1070 
1071 			cfg80211_ref_bss(wiphy, vif->bss);
1072 			cfg80211_connect_bss(ndev, evt->bssid, vif->bss,
1073 					     assoc_req_ie, assoc_req_ielen,
1074 					     assoc_resp_ie, assoc_resp_ielen,
1075 					     WLAN_STATUS_SUCCESS, GFP_KERNEL,
1076 					     NL80211_TIMEOUT_UNSPECIFIED);
1077 		}
1078 		vif->bss = NULL;
1079 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
1080 		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
1081 
1082 		if (rc) {
1083 			if (disable_ap_sme)
1084 				/* notify new_sta has failed */
1085 				cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL);
1086 			goto out;
1087 		}
1088 
1089 		sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
1090 		if (!sinfo) {
1091 			rc = -ENOMEM;
1092 			goto out;
1093 		}
1094 
1095 		sinfo->generation = wil->sinfo_gen++;
1096 
1097 		if (assoc_req_ie) {
1098 			sinfo->assoc_req_ies = assoc_req_ie;
1099 			sinfo->assoc_req_ies_len = assoc_req_ielen;
1100 		}
1101 
1102 		cfg80211_new_sta(ndev, evt->bssid, sinfo, GFP_KERNEL);
1103 
1104 		kfree(sinfo);
1105 	} else {
1106 		wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype,
1107 			evt->cid);
1108 		goto out;
1109 	}
1110 
1111 	wil->sta[evt->cid].status = wil_sta_connected;
1112 	wil->sta[evt->cid].aid = evt->aid;
1113 	if (!test_and_set_bit(wil_vif_fwconnected, vif->status))
1114 		atomic_inc(&wil->connected_vifs);
1115 	wil_update_net_queues_bh(wil, vif, NULL, false);
1116 
1117 out:
1118 	if (rc) {
1119 		wil->sta[evt->cid].status = wil_sta_unused;
1120 		wil->sta[evt->cid].mid = U8_MAX;
1121 	}
1122 	clear_bit(wil_vif_fwconnecting, vif->status);
1123 	mutex_unlock(&wil->mutex);
1124 }
1125 
1126 static void wmi_evt_disconnect(struct wil6210_vif *vif, int id,
1127 			       void *d, int len)
1128 {
1129 	struct wil6210_priv *wil = vif_to_wil(vif);
1130 	struct wmi_disconnect_event *evt = d;
1131 	u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
1132 
1133 	wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
1134 		 evt->bssid, reason_code, evt->disconnect_reason);
1135 
1136 	wil->sinfo_gen++;
1137 
1138 	if (test_bit(wil_status_resetting, wil->status) ||
1139 	    !test_bit(wil_status_fwready, wil->status)) {
1140 		wil_err(wil, "status_resetting, cancel disconnect event\n");
1141 		/* no need for cleanup, wil_reset will do that */
1142 		return;
1143 	}
1144 
1145 	mutex_lock(&wil->mutex);
1146 	wil6210_disconnect_complete(vif, evt->bssid, reason_code);
1147 	if (disable_ap_sme) {
1148 		struct wireless_dev *wdev = vif_to_wdev(vif);
1149 		struct net_device *ndev = vif_to_ndev(vif);
1150 
1151 		/* disconnect event in disable_ap_sme mode means link loss */
1152 		switch (wdev->iftype) {
1153 		/* AP-like interface */
1154 		case NL80211_IFTYPE_AP:
1155 		case NL80211_IFTYPE_P2P_GO:
1156 			/* notify hostapd about link loss */
1157 			cfg80211_cqm_pktloss_notify(ndev, evt->bssid, 0,
1158 						    GFP_KERNEL);
1159 			break;
1160 		default:
1161 			break;
1162 		}
1163 	}
1164 	mutex_unlock(&wil->mutex);
1165 }
1166 
1167 /*
1168  * Firmware reports EAPOL frame using WME event.
1169  * Reconstruct Ethernet frame and deliver it via normal Rx
1170  */
1171 static void wmi_evt_eapol_rx(struct wil6210_vif *vif, int id, void *d, int len)
1172 {
1173 	struct wil6210_priv *wil = vif_to_wil(vif);
1174 	struct net_device *ndev = vif_to_ndev(vif);
1175 	struct wmi_eapol_rx_event *evt = d;
1176 	u16 eapol_len = le16_to_cpu(evt->eapol_len);
1177 	int sz = eapol_len + ETH_HLEN;
1178 	struct sk_buff *skb;
1179 	struct ethhdr *eth;
1180 	int cid;
1181 	struct wil_net_stats *stats = NULL;
1182 
1183 	wil_dbg_wmi(wil, "EAPOL len %d from %pM MID %d\n", eapol_len,
1184 		    evt->src_mac, vif->mid);
1185 
1186 	cid = wil_find_cid(wil, vif->mid, evt->src_mac);
1187 	if (cid >= 0)
1188 		stats = &wil->sta[cid].stats;
1189 
1190 	if (eapol_len > 196) { /* TODO: revisit size limit */
1191 		wil_err(wil, "EAPOL too large\n");
1192 		return;
1193 	}
1194 
1195 	skb = alloc_skb(sz, GFP_KERNEL);
1196 	if (!skb) {
1197 		wil_err(wil, "Failed to allocate skb\n");
1198 		return;
1199 	}
1200 
1201 	eth = skb_put(skb, ETH_HLEN);
1202 	ether_addr_copy(eth->h_dest, ndev->dev_addr);
1203 	ether_addr_copy(eth->h_source, evt->src_mac);
1204 	eth->h_proto = cpu_to_be16(ETH_P_PAE);
1205 	skb_put_data(skb, evt->eapol, eapol_len);
1206 	skb->protocol = eth_type_trans(skb, ndev);
1207 	if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
1208 		ndev->stats.rx_packets++;
1209 		ndev->stats.rx_bytes += sz;
1210 		if (stats) {
1211 			stats->rx_packets++;
1212 			stats->rx_bytes += sz;
1213 		}
1214 	} else {
1215 		ndev->stats.rx_dropped++;
1216 		if (stats)
1217 			stats->rx_dropped++;
1218 	}
1219 }
1220 
1221 static void wmi_evt_ring_en(struct wil6210_vif *vif, int id, void *d, int len)
1222 {
1223 	struct wil6210_priv *wil = vif_to_wil(vif);
1224 	struct wmi_ring_en_event *evt = d;
1225 	u8 vri = evt->ring_index;
1226 	struct wireless_dev *wdev = vif_to_wdev(vif);
1227 	struct wil_sta_info *sta;
1228 	u8 cid;
1229 	struct key_params params;
1230 
1231 	wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid);
1232 
1233 	if (vri >= ARRAY_SIZE(wil->ring_tx)) {
1234 		wil_err(wil, "Enable for invalid vring %d\n", vri);
1235 		return;
1236 	}
1237 
1238 	if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme ||
1239 	    test_bit(wil_vif_ft_roam, vif->status))
1240 		/* in AP mode with disable_ap_sme that is not FT,
1241 		 * this is done by wil_cfg80211_change_station()
1242 		 */
1243 		wil->ring_tx_data[vri].dot1x_open = true;
1244 	if (vri == vif->bcast_ring) /* no BA for bcast */
1245 		return;
1246 
1247 	cid = wil->ring2cid_tid[vri][0];
1248 	if (!wil_cid_valid(wil, cid)) {
1249 		wil_err(wil, "invalid cid %d for vring %d\n", cid, vri);
1250 		return;
1251 	}
1252 
1253 	/* In FT mode we get key but not store it as it is received
1254 	 * before WMI_CONNECT_EVENT received from FW.
1255 	 * wil_set_crypto_rx is called here to reset the security PN
1256 	 */
1257 	sta = &wil->sta[cid];
1258 	if (test_bit(wil_vif_ft_roam, vif->status)) {
1259 		memset(&params, 0, sizeof(params));
1260 		wil_set_crypto_rx(0, WMI_KEY_USE_PAIRWISE, sta, &params);
1261 		if (wdev->iftype != NL80211_IFTYPE_AP)
1262 			clear_bit(wil_vif_ft_roam, vif->status);
1263 	}
1264 
1265 	if (agg_wsize >= 0)
1266 		wil_addba_tx_request(wil, vri, agg_wsize);
1267 }
1268 
1269 static void wmi_evt_ba_status(struct wil6210_vif *vif, int id,
1270 			      void *d, int len)
1271 {
1272 	struct wil6210_priv *wil = vif_to_wil(vif);
1273 	struct wmi_ba_status_event *evt = d;
1274 	struct wil_ring_tx_data *txdata;
1275 
1276 	wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
1277 		    evt->ringid,
1278 		    evt->status == WMI_BA_AGREED ? "OK" : "N/A",
1279 		    evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
1280 		    evt->amsdu ? "+" : "-");
1281 
1282 	if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
1283 		wil_err(wil, "invalid ring id %d\n", evt->ringid);
1284 		return;
1285 	}
1286 
1287 	if (evt->status != WMI_BA_AGREED) {
1288 		evt->ba_timeout = 0;
1289 		evt->agg_wsize = 0;
1290 		evt->amsdu = 0;
1291 	}
1292 
1293 	txdata = &wil->ring_tx_data[evt->ringid];
1294 
1295 	txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
1296 	txdata->agg_wsize = evt->agg_wsize;
1297 	txdata->agg_amsdu = evt->amsdu;
1298 	txdata->addba_in_progress = false;
1299 }
1300 
1301 static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id,
1302 				 void *d, int len)
1303 {
1304 	struct wil6210_priv *wil = vif_to_wil(vif);
1305 	u8 cid, tid;
1306 	struct wmi_rcp_addba_req_event *evt = d;
1307 
1308 	if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
1309 		parse_cidxtid(evt->cidxtid, &cid, &tid);
1310 	} else {
1311 		cid = evt->cid;
1312 		tid = evt->tid;
1313 	}
1314 	wil_addba_rx_request(wil, vif->mid, cid, tid, evt->dialog_token,
1315 			     evt->ba_param_set, evt->ba_timeout,
1316 			     evt->ba_seq_ctrl);
1317 }
1318 
1319 static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len)
1320 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
1321 {
1322 	struct wil6210_priv *wil = vif_to_wil(vif);
1323 	struct wmi_delba_event *evt = d;
1324 	u8 cid, tid;
1325 	u16 reason = __le16_to_cpu(evt->reason);
1326 	struct wil_sta_info *sta;
1327 	struct wil_tid_ampdu_rx *r;
1328 
1329 	might_sleep();
1330 
1331 	if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
1332 		parse_cidxtid(evt->cidxtid, &cid, &tid);
1333 	} else {
1334 		cid = evt->cid;
1335 		tid = evt->tid;
1336 	}
1337 
1338 	if (!wil_cid_valid(wil, cid)) {
1339 		wil_err(wil, "DELBA: Invalid CID %d\n", cid);
1340 		return;
1341 	}
1342 
1343 	wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n",
1344 		    vif->mid, cid, tid,
1345 		    evt->from_initiator ? "originator" : "recipient",
1346 		    reason);
1347 	if (!evt->from_initiator) {
1348 		int i;
1349 		/* find Tx vring it belongs to */
1350 		for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++) {
1351 			if (wil->ring2cid_tid[i][0] == cid &&
1352 			    wil->ring2cid_tid[i][1] == tid) {
1353 				struct wil_ring_tx_data *txdata =
1354 					&wil->ring_tx_data[i];
1355 
1356 				wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
1357 				txdata->agg_timeout = 0;
1358 				txdata->agg_wsize = 0;
1359 				txdata->addba_in_progress = false;
1360 
1361 				break; /* max. 1 matching ring */
1362 			}
1363 		}
1364 		if (i >= ARRAY_SIZE(wil->ring2cid_tid))
1365 			wil_err(wil, "DELBA: unable to find Tx vring\n");
1366 		return;
1367 	}
1368 
1369 	sta = &wil->sta[cid];
1370 
1371 	spin_lock_bh(&sta->tid_rx_lock);
1372 
1373 	r = sta->tid_rx[tid];
1374 	sta->tid_rx[tid] = NULL;
1375 	wil_tid_ampdu_rx_free(wil, r);
1376 
1377 	spin_unlock_bh(&sta->tid_rx_lock);
1378 }
1379 
1380 static void
1381 wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len)
1382 {
1383 	struct wil6210_priv *wil = vif_to_wil(vif);
1384 	struct wmi_sched_scan_result_event *data = d;
1385 	struct wiphy *wiphy = wil_to_wiphy(wil);
1386 	struct ieee80211_mgmt *rx_mgmt_frame =
1387 		(struct ieee80211_mgmt *)data->payload;
1388 	int flen = len - offsetof(struct wmi_sched_scan_result_event, payload);
1389 	int ch_no;
1390 	u32 freq;
1391 	struct ieee80211_channel *channel;
1392 	s32 signal;
1393 	__le16 fc;
1394 	u32 d_len;
1395 	struct cfg80211_bss *bss;
1396 	struct cfg80211_inform_bss bss_data = {
1397 		.scan_width = NL80211_BSS_CHAN_WIDTH_20,
1398 		.boottime_ns = ktime_to_ns(ktime_get_boottime()),
1399 	};
1400 
1401 	if (flen < 0) {
1402 		wil_err(wil, "sched scan result event too short, len %d\n",
1403 			len);
1404 		return;
1405 	}
1406 
1407 	d_len = le32_to_cpu(data->info.len);
1408 	if (d_len != flen) {
1409 		wil_err(wil,
1410 			"sched scan result length mismatch, d_len %d should be %d\n",
1411 			d_len, flen);
1412 		return;
1413 	}
1414 
1415 	fc = rx_mgmt_frame->frame_control;
1416 	if (!ieee80211_is_probe_resp(fc)) {
1417 		wil_err(wil, "sched scan result invalid frame, fc 0x%04x\n",
1418 			fc);
1419 		return;
1420 	}
1421 
1422 	ch_no = data->info.channel + 1;
1423 	freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ);
1424 	channel = ieee80211_get_channel(wiphy, freq);
1425 	if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities))
1426 		signal = 100 * data->info.rssi;
1427 	else
1428 		signal = data->info.sqi;
1429 
1430 	wil_dbg_wmi(wil, "sched scan result: channel %d MCS %d RSSI %d\n",
1431 		    data->info.channel, data->info.mcs, data->info.rssi);
1432 	wil_dbg_wmi(wil, "len %d qid %d mid %d cid %d\n",
1433 		    d_len, data->info.qid, data->info.mid, data->info.cid);
1434 	wil_hex_dump_wmi("PROBE ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
1435 			 d_len, true);
1436 
1437 	if (!channel) {
1438 		wil_err(wil, "Frame on unsupported channel\n");
1439 		return;
1440 	}
1441 
1442 	bss_data.signal = signal;
1443 	bss_data.chan = channel;
1444 	bss = cfg80211_inform_bss_frame_data(wiphy, &bss_data, rx_mgmt_frame,
1445 					     d_len, GFP_KERNEL);
1446 	if (bss) {
1447 		wil_dbg_wmi(wil, "Added BSS %pM\n", rx_mgmt_frame->bssid);
1448 		cfg80211_put_bss(wiphy, bss);
1449 	} else {
1450 		wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
1451 	}
1452 
1453 	cfg80211_sched_scan_results(wiphy, 0);
1454 }
1455 
1456 static void wil_link_stats_store_basic(struct wil6210_vif *vif,
1457 				       struct wmi_link_stats_basic *basic)
1458 {
1459 	struct wil6210_priv *wil = vif_to_wil(vif);
1460 	u8 cid = basic->cid;
1461 	struct wil_sta_info *sta;
1462 
1463 	if (cid < 0 || cid >= wil->max_assoc_sta) {
1464 		wil_err(wil, "invalid cid %d\n", cid);
1465 		return;
1466 	}
1467 
1468 	sta = &wil->sta[cid];
1469 	sta->fw_stats_basic = *basic;
1470 }
1471 
1472 static void wil_link_stats_store_global(struct wil6210_vif *vif,
1473 					struct wmi_link_stats_global *global)
1474 {
1475 	struct wil6210_priv *wil = vif_to_wil(vif);
1476 
1477 	wil->fw_stats_global.stats = *global;
1478 }
1479 
1480 static void wmi_link_stats_parse(struct wil6210_vif *vif, u64 tsf,
1481 				 bool has_next, void *payload,
1482 				 size_t payload_size)
1483 {
1484 	struct wil6210_priv *wil = vif_to_wil(vif);
1485 	size_t hdr_size = sizeof(struct wmi_link_stats_record);
1486 	size_t stats_size, record_size, expected_size;
1487 	struct wmi_link_stats_record *hdr;
1488 
1489 	if (payload_size < hdr_size) {
1490 		wil_err(wil, "link stats wrong event size %zu\n", payload_size);
1491 		return;
1492 	}
1493 
1494 	while (payload_size >= hdr_size) {
1495 		hdr = payload;
1496 		stats_size = le16_to_cpu(hdr->record_size);
1497 		record_size = hdr_size + stats_size;
1498 
1499 		if (payload_size < record_size) {
1500 			wil_err(wil, "link stats payload ended unexpectedly, size %zu < %zu\n",
1501 				payload_size, record_size);
1502 			return;
1503 		}
1504 
1505 		switch (hdr->record_type_id) {
1506 		case WMI_LINK_STATS_TYPE_BASIC:
1507 			expected_size = sizeof(struct wmi_link_stats_basic);
1508 			if (stats_size < expected_size) {
1509 				wil_err(wil, "link stats invalid basic record size %zu < %zu\n",
1510 					stats_size, expected_size);
1511 				return;
1512 			}
1513 			if (vif->fw_stats_ready) {
1514 				/* clean old statistics */
1515 				vif->fw_stats_tsf = 0;
1516 				vif->fw_stats_ready = false;
1517 			}
1518 
1519 			wil_link_stats_store_basic(vif, payload + hdr_size);
1520 
1521 			if (!has_next) {
1522 				vif->fw_stats_tsf = tsf;
1523 				vif->fw_stats_ready = true;
1524 			}
1525 
1526 			break;
1527 		case WMI_LINK_STATS_TYPE_GLOBAL:
1528 			expected_size = sizeof(struct wmi_link_stats_global);
1529 			if (stats_size < sizeof(struct wmi_link_stats_global)) {
1530 				wil_err(wil, "link stats invalid global record size %zu < %zu\n",
1531 					stats_size, expected_size);
1532 				return;
1533 			}
1534 
1535 			if (wil->fw_stats_global.ready) {
1536 				/* clean old statistics */
1537 				wil->fw_stats_global.tsf = 0;
1538 				wil->fw_stats_global.ready = false;
1539 			}
1540 
1541 			wil_link_stats_store_global(vif, payload + hdr_size);
1542 
1543 			if (!has_next) {
1544 				wil->fw_stats_global.tsf = tsf;
1545 				wil->fw_stats_global.ready = true;
1546 			}
1547 
1548 			break;
1549 		default:
1550 			break;
1551 		}
1552 
1553 		/* skip to next record */
1554 		payload += record_size;
1555 		payload_size -= record_size;
1556 	}
1557 }
1558 
1559 static void
1560 wmi_evt_link_stats(struct wil6210_vif *vif, int id, void *d, int len)
1561 {
1562 	struct wil6210_priv *wil = vif_to_wil(vif);
1563 	struct wmi_link_stats_event *evt = d;
1564 	size_t payload_size;
1565 
1566 	if (len < offsetof(struct wmi_link_stats_event, payload)) {
1567 		wil_err(wil, "stats event way too short %d\n", len);
1568 		return;
1569 	}
1570 	payload_size = le16_to_cpu(evt->payload_size);
1571 	if (len < sizeof(struct wmi_link_stats_event) + payload_size) {
1572 		wil_err(wil, "stats event too short %d\n", len);
1573 		return;
1574 	}
1575 
1576 	wmi_link_stats_parse(vif, le64_to_cpu(evt->tsf), evt->has_next,
1577 			     evt->payload, payload_size);
1578 }
1579 
1580 /**
1581  * find cid and ringid for the station vif
1582  *
1583  * return error, if other interfaces are used or ring was not found
1584  */
1585 static int wil_find_cid_ringid_sta(struct wil6210_priv *wil,
1586 				   struct wil6210_vif *vif,
1587 				   int *cid,
1588 				   int *ringid)
1589 {
1590 	struct wil_ring *ring;
1591 	struct wil_ring_tx_data *txdata;
1592 	int min_ring_id = wil_get_min_tx_ring_id(wil);
1593 	int i;
1594 	u8 lcid;
1595 
1596 	if (!(vif->wdev.iftype == NL80211_IFTYPE_STATION ||
1597 	      vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) {
1598 		wil_err(wil, "invalid interface type %d\n", vif->wdev.iftype);
1599 		return -EINVAL;
1600 	}
1601 
1602 	/* In the STA mode, it is expected to have only one ring
1603 	 * for the AP we are connected to.
1604 	 * find it and return the cid associated with it.
1605 	 */
1606 	for (i = min_ring_id; i < WIL6210_MAX_TX_RINGS; i++) {
1607 		ring = &wil->ring_tx[i];
1608 		txdata = &wil->ring_tx_data[i];
1609 		if (!ring->va || !txdata->enabled || txdata->mid != vif->mid)
1610 			continue;
1611 
1612 		lcid = wil->ring2cid_tid[i][0];
1613 		if (lcid >= wil->max_assoc_sta) /* skip BCAST */
1614 			continue;
1615 
1616 		wil_dbg_wmi(wil, "find sta -> ringid %d cid %d\n", i, lcid);
1617 		*cid = lcid;
1618 		*ringid = i;
1619 		return 0;
1620 	}
1621 
1622 	wil_dbg_wmi(wil, "find sta cid while no rings active?\n");
1623 
1624 	return -ENOENT;
1625 }
1626 
1627 static void
1628 wmi_evt_auth_status(struct wil6210_vif *vif, int id, void *d, int len)
1629 {
1630 	struct wil6210_priv *wil = vif_to_wil(vif);
1631 	struct net_device *ndev = vif_to_ndev(vif);
1632 	struct wmi_ft_auth_status_event *data = d;
1633 	int ie_len = len - offsetof(struct wmi_ft_auth_status_event, ie_info);
1634 	int rc, cid = 0, ringid = 0;
1635 	struct cfg80211_ft_event_params ft;
1636 	u16 d_len;
1637 	/* auth_alg(u16) + auth_transaction(u16) + status_code(u16) */
1638 	const size_t auth_ie_offset = sizeof(u16) * 3;
1639 	struct auth_no_hdr *auth = (struct auth_no_hdr *)data->ie_info;
1640 
1641 	/* check the status */
1642 	if (ie_len >= 0 && data->status != WMI_FW_STATUS_SUCCESS) {
1643 		wil_err(wil, "FT: auth failed. status %d\n", data->status);
1644 		goto fail;
1645 	}
1646 
1647 	if (ie_len < auth_ie_offset) {
1648 		wil_err(wil, "FT: auth event too short, len %d\n", len);
1649 		goto fail;
1650 	}
1651 
1652 	d_len = le16_to_cpu(data->ie_len);
1653 	if (d_len != ie_len) {
1654 		wil_err(wil,
1655 			"FT: auth ie length mismatch, d_len %d should be %d\n",
1656 			d_len, ie_len);
1657 		goto fail;
1658 	}
1659 
1660 	if (!test_bit(wil_vif_ft_roam, wil->status)) {
1661 		wil_err(wil, "FT: Not in roaming state\n");
1662 		goto fail;
1663 	}
1664 
1665 	if (le16_to_cpu(auth->auth_transaction) != 2) {
1666 		wil_err(wil, "FT: auth error. auth_transaction %d\n",
1667 			le16_to_cpu(auth->auth_transaction));
1668 		goto fail;
1669 	}
1670 
1671 	if (le16_to_cpu(auth->auth_alg) != WLAN_AUTH_FT) {
1672 		wil_err(wil, "FT: auth error. auth_alg %d\n",
1673 			le16_to_cpu(auth->auth_alg));
1674 		goto fail;
1675 	}
1676 
1677 	wil_dbg_wmi(wil, "FT: Auth to %pM successfully\n", data->mac_addr);
1678 	wil_hex_dump_wmi("FT Auth ies : ", DUMP_PREFIX_OFFSET, 16, 1,
1679 			 data->ie_info, d_len, true);
1680 
1681 	/* find cid and ringid */
1682 	rc = wil_find_cid_ringid_sta(wil, vif, &cid, &ringid);
1683 	if (rc) {
1684 		wil_err(wil, "No valid cid found\n");
1685 		goto fail;
1686 	}
1687 
1688 	if (vif->privacy) {
1689 		/* For secure assoc, remove old keys */
1690 		rc = wmi_del_cipher_key(vif, 0, wil->sta[cid].addr,
1691 					WMI_KEY_USE_PAIRWISE);
1692 		if (rc) {
1693 			wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
1694 			goto fail;
1695 		}
1696 		rc = wmi_del_cipher_key(vif, 0, wil->sta[cid].addr,
1697 					WMI_KEY_USE_RX_GROUP);
1698 		if (rc) {
1699 			wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
1700 			goto fail;
1701 		}
1702 	}
1703 
1704 	memset(&ft, 0, sizeof(ft));
1705 	ft.ies = data->ie_info + auth_ie_offset;
1706 	ft.ies_len = d_len - auth_ie_offset;
1707 	ft.target_ap = data->mac_addr;
1708 	cfg80211_ft_event(ndev, &ft);
1709 
1710 	return;
1711 
1712 fail:
1713 	wil6210_disconnect(vif, NULL, WLAN_REASON_PREV_AUTH_NOT_VALID);
1714 }
1715 
1716 static void
1717 wmi_evt_reassoc_status(struct wil6210_vif *vif, int id, void *d, int len)
1718 {
1719 	struct wil6210_priv *wil = vif_to_wil(vif);
1720 	struct net_device *ndev = vif_to_ndev(vif);
1721 	struct wiphy *wiphy = wil_to_wiphy(wil);
1722 	struct wmi_ft_reassoc_status_event *data = d;
1723 	int ies_len = len - offsetof(struct wmi_ft_reassoc_status_event,
1724 				     ie_info);
1725 	int rc = -ENOENT, cid = 0, ringid = 0;
1726 	int ch; /* channel number (primary) */
1727 	size_t assoc_req_ie_len = 0, assoc_resp_ie_len = 0;
1728 	u8 *assoc_req_ie = NULL, *assoc_resp_ie = NULL;
1729 	/* capinfo(u16) + listen_interval(u16) + current_ap mac addr + IEs */
1730 	const size_t assoc_req_ie_offset = sizeof(u16) * 2 + ETH_ALEN;
1731 	/* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
1732 	const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
1733 	u16 d_len;
1734 	int freq;
1735 	struct cfg80211_roam_info info;
1736 
1737 	if (ies_len < 0) {
1738 		wil_err(wil, "ft reassoc event too short, len %d\n", len);
1739 		goto fail;
1740 	}
1741 
1742 	wil_dbg_wmi(wil, "Reasoc Status event: status=%d, aid=%d",
1743 		    data->status, data->aid);
1744 	wil_dbg_wmi(wil, "    mac_addr=%pM, beacon_ie_len=%d",
1745 		    data->mac_addr, data->beacon_ie_len);
1746 	wil_dbg_wmi(wil, "    reassoc_req_ie_len=%d, reassoc_resp_ie_len=%d",
1747 		    le16_to_cpu(data->reassoc_req_ie_len),
1748 		    le16_to_cpu(data->reassoc_resp_ie_len));
1749 
1750 	d_len = le16_to_cpu(data->beacon_ie_len) +
1751 		le16_to_cpu(data->reassoc_req_ie_len) +
1752 		le16_to_cpu(data->reassoc_resp_ie_len);
1753 	if (d_len != ies_len) {
1754 		wil_err(wil,
1755 			"ft reassoc ie length mismatch, d_len %d should be %d\n",
1756 			d_len, ies_len);
1757 		goto fail;
1758 	}
1759 
1760 	/* check the status */
1761 	if (data->status != WMI_FW_STATUS_SUCCESS) {
1762 		wil_err(wil, "ft reassoc failed. status %d\n", data->status);
1763 		goto fail;
1764 	}
1765 
1766 	/* find cid and ringid */
1767 	rc = wil_find_cid_ringid_sta(wil, vif, &cid, &ringid);
1768 	if (rc) {
1769 		wil_err(wil, "No valid cid found\n");
1770 		goto fail;
1771 	}
1772 
1773 	ch = data->channel + 1;
1774 	wil_info(wil, "FT: Roam %pM channel [%d] cid %d aid %d\n",
1775 		 data->mac_addr, ch, cid, data->aid);
1776 
1777 	wil_hex_dump_wmi("reassoc AI : ", DUMP_PREFIX_OFFSET, 16, 1,
1778 			 data->ie_info, len - sizeof(*data), true);
1779 
1780 	/* figure out IE's */
1781 	if (le16_to_cpu(data->reassoc_req_ie_len) > assoc_req_ie_offset) {
1782 		assoc_req_ie = &data->ie_info[assoc_req_ie_offset];
1783 		assoc_req_ie_len = le16_to_cpu(data->reassoc_req_ie_len) -
1784 			assoc_req_ie_offset;
1785 	}
1786 	if (le16_to_cpu(data->reassoc_resp_ie_len) <= assoc_resp_ie_offset) {
1787 		wil_err(wil, "FT: reassoc resp ie len is too short, len %d\n",
1788 			le16_to_cpu(data->reassoc_resp_ie_len));
1789 		goto fail;
1790 	}
1791 
1792 	assoc_resp_ie = &data->ie_info[le16_to_cpu(data->reassoc_req_ie_len) +
1793 		assoc_resp_ie_offset];
1794 	assoc_resp_ie_len = le16_to_cpu(data->reassoc_resp_ie_len) -
1795 		assoc_resp_ie_offset;
1796 
1797 	if (test_bit(wil_status_resetting, wil->status) ||
1798 	    !test_bit(wil_status_fwready, wil->status)) {
1799 		wil_err(wil, "FT: status_resetting, cancel reassoc event\n");
1800 		/* no need for cleanup, wil_reset will do that */
1801 		return;
1802 	}
1803 
1804 	mutex_lock(&wil->mutex);
1805 
1806 	/* ring modify to set the ring for the roamed AP settings */
1807 	wil_dbg_wmi(wil,
1808 		    "ft modify tx config for connection CID %d ring %d\n",
1809 		    cid, ringid);
1810 
1811 	rc = wil->txrx_ops.tx_ring_modify(vif, ringid, cid, 0);
1812 	if (rc) {
1813 		wil_err(wil, "modify TX for CID %d MID %d ring %d failed (%d)\n",
1814 			cid, vif->mid, ringid, rc);
1815 		mutex_unlock(&wil->mutex);
1816 		goto fail;
1817 	}
1818 
1819 	/* Update the driver STA members with the new bss */
1820 	wil->sta[cid].aid = data->aid;
1821 	wil->sta[cid].stats.ft_roams++;
1822 	ether_addr_copy(wil->sta[cid].addr, vif->bss->bssid);
1823 	mutex_unlock(&wil->mutex);
1824 	del_timer_sync(&vif->connect_timer);
1825 
1826 	cfg80211_ref_bss(wiphy, vif->bss);
1827 	freq = ieee80211_channel_to_frequency(ch, NL80211_BAND_60GHZ);
1828 
1829 	memset(&info, 0, sizeof(info));
1830 	info.channel = ieee80211_get_channel(wiphy, freq);
1831 	info.bss = vif->bss;
1832 	info.req_ie = assoc_req_ie;
1833 	info.req_ie_len = assoc_req_ie_len;
1834 	info.resp_ie = assoc_resp_ie;
1835 	info.resp_ie_len = assoc_resp_ie_len;
1836 	cfg80211_roamed(ndev, &info, GFP_KERNEL);
1837 	vif->bss = NULL;
1838 
1839 	return;
1840 
1841 fail:
1842 	wil6210_disconnect(vif, NULL, WLAN_REASON_PREV_AUTH_NOT_VALID);
1843 }
1844 
1845 static void
1846 wmi_evt_link_monitor(struct wil6210_vif *vif, int id, void *d, int len)
1847 {
1848 	struct wil6210_priv *wil = vif_to_wil(vif);
1849 	struct net_device *ndev = vif_to_ndev(vif);
1850 	struct wmi_link_monitor_event *evt = d;
1851 	enum nl80211_cqm_rssi_threshold_event event_type;
1852 
1853 	if (len < sizeof(*evt)) {
1854 		wil_err(wil, "link monitor event too short %d\n", len);
1855 		return;
1856 	}
1857 
1858 	wil_dbg_wmi(wil, "link monitor event, type %d rssi %d (stored %d)\n",
1859 		    evt->type, evt->rssi_level, wil->cqm_rssi_thold);
1860 
1861 	if (evt->type != WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT)
1862 		/* ignore */
1863 		return;
1864 
1865 	event_type = (evt->rssi_level > wil->cqm_rssi_thold ?
1866 		      NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH :
1867 		      NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW);
1868 	cfg80211_cqm_rssi_notify(ndev, event_type, evt->rssi_level, GFP_KERNEL);
1869 }
1870 
1871 /**
1872  * Some events are ignored for purpose; and need not be interpreted as
1873  * "unhandled events"
1874  */
1875 static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len)
1876 {
1877 	struct wil6210_priv *wil = vif_to_wil(vif);
1878 
1879 	wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
1880 }
1881 
1882 static const struct {
1883 	int eventid;
1884 	void (*handler)(struct wil6210_vif *vif,
1885 			int eventid, void *data, int data_len);
1886 } wmi_evt_handlers[] = {
1887 	{WMI_READY_EVENTID,		wmi_evt_ready},
1888 	{WMI_FW_READY_EVENTID,			wmi_evt_ignore},
1889 	{WMI_RX_MGMT_PACKET_EVENTID,	wmi_evt_rx_mgmt},
1890 	{WMI_TX_MGMT_PACKET_EVENTID,		wmi_evt_tx_mgmt},
1891 	{WMI_SCAN_COMPLETE_EVENTID,	wmi_evt_scan_complete},
1892 	{WMI_CONNECT_EVENTID,		wmi_evt_connect},
1893 	{WMI_DISCONNECT_EVENTID,	wmi_evt_disconnect},
1894 	{WMI_EAPOL_RX_EVENTID,		wmi_evt_eapol_rx},
1895 	{WMI_BA_STATUS_EVENTID,		wmi_evt_ba_status},
1896 	{WMI_RCP_ADDBA_REQ_EVENTID,	wmi_evt_addba_rx_req},
1897 	{WMI_DELBA_EVENTID,		wmi_evt_delba},
1898 	{WMI_RING_EN_EVENTID,		wmi_evt_ring_en},
1899 	{WMI_DATA_PORT_OPEN_EVENTID,		wmi_evt_ignore},
1900 	{WMI_SCHED_SCAN_RESULT_EVENTID,		wmi_evt_sched_scan_result},
1901 	{WMI_LINK_STATS_EVENTID,		wmi_evt_link_stats},
1902 	{WMI_FT_AUTH_STATUS_EVENTID,		wmi_evt_auth_status},
1903 	{WMI_FT_REASSOC_STATUS_EVENTID,		wmi_evt_reassoc_status},
1904 	{WMI_LINK_MONITOR_EVENTID,		wmi_evt_link_monitor},
1905 };
1906 
1907 /*
1908  * Run in IRQ context
1909  * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
1910  * that will be eventually handled by the @wmi_event_worker in the thread
1911  * context of thread "wil6210_wmi"
1912  */
1913 void wmi_recv_cmd(struct wil6210_priv *wil)
1914 {
1915 	struct wil6210_mbox_ring_desc d_tail;
1916 	struct wil6210_mbox_hdr hdr;
1917 	struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
1918 	struct pending_wmi_event *evt;
1919 	u8 *cmd;
1920 	void __iomem *src;
1921 	ulong flags;
1922 	unsigned n;
1923 	unsigned int num_immed_reply = 0;
1924 
1925 	if (!test_bit(wil_status_mbox_ready, wil->status)) {
1926 		wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
1927 		return;
1928 	}
1929 
1930 	if (test_bit(wil_status_suspended, wil->status)) {
1931 		wil_err(wil, "suspended. cannot handle WMI event\n");
1932 		return;
1933 	}
1934 
1935 	for (n = 0;; n++) {
1936 		u16 len;
1937 		bool q;
1938 		bool immed_reply = false;
1939 
1940 		r->head = wil_r(wil, RGF_MBOX +
1941 				offsetof(struct wil6210_mbox_ctl, rx.head));
1942 		if (r->tail == r->head)
1943 			break;
1944 
1945 		wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
1946 			    r->head, r->tail);
1947 		/* read cmd descriptor from tail */
1948 		wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
1949 				     sizeof(struct wil6210_mbox_ring_desc));
1950 		if (d_tail.sync == 0) {
1951 			wil_err(wil, "Mbox evt not owned by FW?\n");
1952 			break;
1953 		}
1954 
1955 		/* read cmd header from descriptor */
1956 		if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
1957 			wil_err(wil, "Mbox evt at 0x%08x?\n",
1958 				le32_to_cpu(d_tail.addr));
1959 			break;
1960 		}
1961 		len = le16_to_cpu(hdr.len);
1962 		wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
1963 			    le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
1964 			    hdr.flags);
1965 
1966 		/* read cmd buffer from descriptor */
1967 		src = wmi_buffer(wil, d_tail.addr) +
1968 		      sizeof(struct wil6210_mbox_hdr);
1969 		evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
1970 					     event.wmi) + len, 4),
1971 			      GFP_KERNEL);
1972 		if (!evt)
1973 			break;
1974 
1975 		evt->event.hdr = hdr;
1976 		cmd = (void *)&evt->event.wmi;
1977 		wil_memcpy_fromio_32(cmd, src, len);
1978 		/* mark entry as empty */
1979 		wil_w(wil, r->tail +
1980 		      offsetof(struct wil6210_mbox_ring_desc, sync), 0);
1981 		/* indicate */
1982 		if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
1983 		    (len >= sizeof(struct wmi_cmd_hdr))) {
1984 			struct wmi_cmd_hdr *wmi = &evt->event.wmi;
1985 			u16 id = le16_to_cpu(wmi->command_id);
1986 			u8 mid = wmi->mid;
1987 			u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
1988 			if (test_bit(wil_status_resuming, wil->status)) {
1989 				if (id == WMI_TRAFFIC_RESUME_EVENTID)
1990 					clear_bit(wil_status_resuming,
1991 						  wil->status);
1992 				else
1993 					wil_err(wil,
1994 						"WMI evt %d while resuming\n",
1995 						id);
1996 			}
1997 			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1998 			if (wil->reply_id && wil->reply_id == id &&
1999 			    wil->reply_mid == mid) {
2000 				if (wil->reply_buf) {
2001 					memcpy(wil->reply_buf, wmi,
2002 					       min(len, wil->reply_size));
2003 					immed_reply = true;
2004 				}
2005 				if (id == WMI_TRAFFIC_SUSPEND_EVENTID) {
2006 					wil_dbg_wmi(wil,
2007 						    "set suspend_resp_rcvd\n");
2008 					wil->suspend_resp_rcvd = true;
2009 				}
2010 			}
2011 			spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2012 
2013 			wil_dbg_wmi(wil, "recv %s (0x%04x) MID %d @%d msec\n",
2014 				    eventid2name(id), id, wmi->mid, tstamp);
2015 			trace_wil6210_wmi_event(wmi, &wmi[1],
2016 						len - sizeof(*wmi));
2017 		}
2018 		wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
2019 				 &evt->event.hdr, sizeof(hdr) + len, true);
2020 
2021 		/* advance tail */
2022 		r->tail = r->base + ((r->tail - r->base +
2023 			  sizeof(struct wil6210_mbox_ring_desc)) % r->size);
2024 		wil_w(wil, RGF_MBOX +
2025 		      offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail);
2026 
2027 		if (immed_reply) {
2028 			wil_dbg_wmi(wil, "recv_cmd: Complete WMI 0x%04x\n",
2029 				    wil->reply_id);
2030 			kfree(evt);
2031 			num_immed_reply++;
2032 			complete(&wil->wmi_call);
2033 		} else {
2034 			/* add to the pending list */
2035 			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
2036 			list_add_tail(&evt->list, &wil->pending_wmi_ev);
2037 			spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2038 			q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
2039 			wil_dbg_wmi(wil, "queue_work -> %d\n", q);
2040 		}
2041 	}
2042 	/* normally, 1 event per IRQ should be processed */
2043 	wil_dbg_wmi(wil, "recv_cmd: -> %d events queued, %d completed\n",
2044 		    n - num_immed_reply, num_immed_reply);
2045 }
2046 
2047 int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
2048 	     u16 reply_id, void *reply, u16 reply_size, int to_msec)
2049 {
2050 	int rc;
2051 	unsigned long remain;
2052 	ulong flags;
2053 
2054 	mutex_lock(&wil->wmi_mutex);
2055 
2056 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
2057 	wil->reply_id = reply_id;
2058 	wil->reply_mid = mid;
2059 	wil->reply_buf = reply;
2060 	wil->reply_size = reply_size;
2061 	reinit_completion(&wil->wmi_call);
2062 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2063 
2064 	rc = __wmi_send(wil, cmdid, mid, buf, len);
2065 	if (rc)
2066 		goto out;
2067 
2068 	remain = wait_for_completion_timeout(&wil->wmi_call,
2069 					     msecs_to_jiffies(to_msec));
2070 	if (0 == remain) {
2071 		wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
2072 			cmdid, reply_id, to_msec);
2073 		rc = -ETIME;
2074 	} else {
2075 		wil_dbg_wmi(wil,
2076 			    "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
2077 			    cmdid, reply_id,
2078 			    to_msec - jiffies_to_msecs(remain));
2079 	}
2080 
2081 out:
2082 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
2083 	wil->reply_id = 0;
2084 	wil->reply_mid = U8_MAX;
2085 	wil->reply_buf = NULL;
2086 	wil->reply_size = 0;
2087 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2088 
2089 	mutex_unlock(&wil->wmi_mutex);
2090 
2091 	return rc;
2092 }
2093 
2094 int wmi_echo(struct wil6210_priv *wil)
2095 {
2096 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2097 	struct wmi_echo_cmd cmd = {
2098 		.value = cpu_to_le32(0x12345678),
2099 	};
2100 
2101 	return wmi_call(wil, WMI_ECHO_CMDID, vif->mid, &cmd, sizeof(cmd),
2102 			WMI_ECHO_RSP_EVENTID, NULL, 0,
2103 			WIL_WMI_CALL_GENERAL_TO_MS);
2104 }
2105 
2106 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
2107 {
2108 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2109 	struct wmi_set_mac_address_cmd cmd;
2110 
2111 	ether_addr_copy(cmd.mac, addr);
2112 
2113 	wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
2114 
2115 	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, vif->mid,
2116 			&cmd, sizeof(cmd));
2117 }
2118 
2119 int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
2120 {
2121 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2122 	int rc = 0;
2123 	struct wmi_led_cfg_cmd cmd = {
2124 		.led_mode = enable,
2125 		.id = led_id,
2126 		.slow_blink_cfg.blink_on =
2127 			cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].on_ms),
2128 		.slow_blink_cfg.blink_off =
2129 			cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].off_ms),
2130 		.medium_blink_cfg.blink_on =
2131 			cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].on_ms),
2132 		.medium_blink_cfg.blink_off =
2133 			cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].off_ms),
2134 		.fast_blink_cfg.blink_on =
2135 			cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].on_ms),
2136 		.fast_blink_cfg.blink_off =
2137 			cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].off_ms),
2138 		.led_polarity = led_polarity,
2139 	};
2140 	struct {
2141 		struct wmi_cmd_hdr wmi;
2142 		struct wmi_led_cfg_done_event evt;
2143 	} __packed reply = {
2144 		.evt = {.status = cpu_to_le32(WMI_FW_STATUS_FAILURE)},
2145 	};
2146 
2147 	if (led_id == WIL_LED_INVALID_ID)
2148 		goto out;
2149 
2150 	if (led_id > WIL_LED_MAX_ID) {
2151 		wil_err(wil, "Invalid led id %d\n", led_id);
2152 		rc = -EINVAL;
2153 		goto out;
2154 	}
2155 
2156 	wil_dbg_wmi(wil,
2157 		    "%s led %d\n",
2158 		    enable ? "enabling" : "disabling", led_id);
2159 
2160 	rc = wmi_call(wil, WMI_LED_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
2161 		      WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
2162 		      WIL_WMI_CALL_GENERAL_TO_MS);
2163 	if (rc)
2164 		goto out;
2165 
2166 	if (reply.evt.status) {
2167 		wil_err(wil, "led %d cfg failed with status %d\n",
2168 			led_id, le32_to_cpu(reply.evt.status));
2169 		rc = -EINVAL;
2170 	}
2171 
2172 out:
2173 	return rc;
2174 }
2175 
2176 int wmi_rbufcap_cfg(struct wil6210_priv *wil, bool enable, u16 threshold)
2177 {
2178 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2179 	int rc;
2180 
2181 	struct wmi_rbufcap_cfg_cmd cmd = {
2182 		.enable = enable,
2183 		.rx_desc_threshold = cpu_to_le16(threshold),
2184 	};
2185 	struct {
2186 		struct wmi_cmd_hdr wmi;
2187 		struct wmi_rbufcap_cfg_event evt;
2188 	} __packed reply = {
2189 		.evt = {.status = WMI_FW_STATUS_FAILURE},
2190 	};
2191 
2192 	rc = wmi_call(wil, WMI_RBUFCAP_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
2193 		      WMI_RBUFCAP_CFG_EVENTID, &reply, sizeof(reply),
2194 		      WIL_WMI_CALL_GENERAL_TO_MS);
2195 	if (rc)
2196 		return rc;
2197 
2198 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
2199 		wil_err(wil, "RBUFCAP_CFG failed. status %d\n",
2200 			reply.evt.status);
2201 		rc = -EINVAL;
2202 	}
2203 
2204 	return rc;
2205 }
2206 
2207 int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype,
2208 		  u8 chan, u8 wmi_edmg_chan, u8 hidden_ssid, u8 is_go)
2209 {
2210 	struct wil6210_priv *wil = vif_to_wil(vif);
2211 	int rc;
2212 
2213 	struct wmi_pcp_start_cmd cmd = {
2214 		.bcon_interval = cpu_to_le16(bi),
2215 		.network_type = wmi_nettype,
2216 		.disable_sec_offload = 1,
2217 		.channel = chan - 1,
2218 		.edmg_channel = wmi_edmg_chan,
2219 		.pcp_max_assoc_sta = wil->max_assoc_sta,
2220 		.hidden_ssid = hidden_ssid,
2221 		.is_go = is_go,
2222 		.ap_sme_offload_mode = disable_ap_sme ?
2223 				       WMI_AP_SME_OFFLOAD_PARTIAL :
2224 				       WMI_AP_SME_OFFLOAD_FULL,
2225 		.abft_len = wil->abft_len,
2226 	};
2227 	struct {
2228 		struct wmi_cmd_hdr wmi;
2229 		struct wmi_pcp_started_event evt;
2230 	} __packed reply = {
2231 		.evt = {.status = WMI_FW_STATUS_FAILURE},
2232 	};
2233 
2234 	if (!vif->privacy)
2235 		cmd.disable_sec = 1;
2236 
2237 	if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
2238 	    (cmd.pcp_max_assoc_sta <= 0)) {
2239 		wil_err(wil, "unexpected max_assoc_sta %d\n",
2240 			cmd.pcp_max_assoc_sta);
2241 		return -EOPNOTSUPP;
2242 	}
2243 
2244 	if (disable_ap_sme &&
2245 	    !test_bit(WMI_FW_CAPABILITY_AP_SME_OFFLOAD_PARTIAL,
2246 		      wil->fw_capabilities)) {
2247 		wil_err(wil, "disable_ap_sme not supported by FW\n");
2248 		return -EOPNOTSUPP;
2249 	}
2250 
2251 	/*
2252 	 * Processing time may be huge, in case of secure AP it takes about
2253 	 * 3500ms for FW to start AP
2254 	 */
2255 	rc = wmi_call(wil, WMI_PCP_START_CMDID, vif->mid, &cmd, sizeof(cmd),
2256 		      WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
2257 	if (rc)
2258 		return rc;
2259 
2260 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
2261 		rc = -EINVAL;
2262 
2263 	if (wmi_nettype != WMI_NETTYPE_P2P)
2264 		/* Don't fail due to error in the led configuration */
2265 		wmi_led_cfg(wil, true);
2266 
2267 	return rc;
2268 }
2269 
2270 int wmi_pcp_stop(struct wil6210_vif *vif)
2271 {
2272 	struct wil6210_priv *wil = vif_to_wil(vif);
2273 	int rc;
2274 
2275 	rc = wmi_led_cfg(wil, false);
2276 	if (rc)
2277 		return rc;
2278 
2279 	return wmi_call(wil, WMI_PCP_STOP_CMDID, vif->mid, NULL, 0,
2280 			WMI_PCP_STOPPED_EVENTID, NULL, 0,
2281 			WIL_WMI_PCP_STOP_TO_MS);
2282 }
2283 
2284 int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid)
2285 {
2286 	struct wil6210_priv *wil = vif_to_wil(vif);
2287 	struct wmi_set_ssid_cmd cmd = {
2288 		.ssid_len = cpu_to_le32(ssid_len),
2289 	};
2290 
2291 	if (ssid_len > sizeof(cmd.ssid))
2292 		return -EINVAL;
2293 
2294 	memcpy(cmd.ssid, ssid, ssid_len);
2295 
2296 	return wmi_send(wil, WMI_SET_SSID_CMDID, vif->mid, &cmd, sizeof(cmd));
2297 }
2298 
2299 int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid)
2300 {
2301 	struct wil6210_priv *wil = vif_to_wil(vif);
2302 	int rc;
2303 	struct {
2304 		struct wmi_cmd_hdr wmi;
2305 		struct wmi_set_ssid_cmd cmd;
2306 	} __packed reply;
2307 	int len; /* reply.cmd.ssid_len in CPU order */
2308 
2309 	memset(&reply, 0, sizeof(reply));
2310 
2311 	rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0,
2312 		      WMI_GET_SSID_EVENTID, &reply, sizeof(reply),
2313 		      WIL_WMI_CALL_GENERAL_TO_MS);
2314 	if (rc)
2315 		return rc;
2316 
2317 	len = le32_to_cpu(reply.cmd.ssid_len);
2318 	if (len > sizeof(reply.cmd.ssid))
2319 		return -EINVAL;
2320 
2321 	*ssid_len = len;
2322 	memcpy(ssid, reply.cmd.ssid, len);
2323 
2324 	return 0;
2325 }
2326 
2327 int wmi_set_channel(struct wil6210_priv *wil, int channel)
2328 {
2329 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2330 	struct wmi_set_pcp_channel_cmd cmd = {
2331 		.channel = channel - 1,
2332 	};
2333 
2334 	return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, vif->mid,
2335 			&cmd, sizeof(cmd));
2336 }
2337 
2338 int wmi_get_channel(struct wil6210_priv *wil, int *channel)
2339 {
2340 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2341 	int rc;
2342 	struct {
2343 		struct wmi_cmd_hdr wmi;
2344 		struct wmi_set_pcp_channel_cmd cmd;
2345 	} __packed reply;
2346 
2347 	memset(&reply, 0, sizeof(reply));
2348 
2349 	rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0,
2350 		      WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply),
2351 		      WIL_WMI_CALL_GENERAL_TO_MS);
2352 	if (rc)
2353 		return rc;
2354 
2355 	if (reply.cmd.channel > 3)
2356 		return -EINVAL;
2357 
2358 	*channel = reply.cmd.channel + 1;
2359 
2360 	return 0;
2361 }
2362 
2363 int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi)
2364 {
2365 	struct wil6210_priv *wil = vif_to_wil(vif);
2366 	int rc;
2367 	struct wmi_p2p_cfg_cmd cmd = {
2368 		.discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER,
2369 		.bcon_interval = cpu_to_le16(bi),
2370 		.channel = channel - 1,
2371 	};
2372 	struct {
2373 		struct wmi_cmd_hdr wmi;
2374 		struct wmi_p2p_cfg_done_event evt;
2375 	} __packed reply = {
2376 		.evt = {.status = WMI_FW_STATUS_FAILURE},
2377 	};
2378 
2379 	wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n");
2380 
2381 	rc = wmi_call(wil, WMI_P2P_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
2382 		      WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300);
2383 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
2384 		wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status);
2385 		rc = -EINVAL;
2386 	}
2387 
2388 	return rc;
2389 }
2390 
2391 int wmi_start_listen(struct wil6210_vif *vif)
2392 {
2393 	struct wil6210_priv *wil = vif_to_wil(vif);
2394 	int rc;
2395 	struct {
2396 		struct wmi_cmd_hdr wmi;
2397 		struct wmi_listen_started_event evt;
2398 	} __packed reply = {
2399 		.evt = {.status = WMI_FW_STATUS_FAILURE},
2400 	};
2401 
2402 	wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n");
2403 
2404 	rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0,
2405 		      WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300);
2406 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
2407 		wil_err(wil, "device failed to start listen. status %d\n",
2408 			reply.evt.status);
2409 		rc = -EINVAL;
2410 	}
2411 
2412 	return rc;
2413 }
2414 
2415 int wmi_start_search(struct wil6210_vif *vif)
2416 {
2417 	struct wil6210_priv *wil = vif_to_wil(vif);
2418 	int rc;
2419 	struct {
2420 		struct wmi_cmd_hdr wmi;
2421 		struct wmi_search_started_event evt;
2422 	} __packed reply = {
2423 		.evt = {.status = WMI_FW_STATUS_FAILURE},
2424 	};
2425 
2426 	wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n");
2427 
2428 	rc = wmi_call(wil, WMI_START_SEARCH_CMDID, vif->mid, NULL, 0,
2429 		      WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300);
2430 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
2431 		wil_err(wil, "device failed to start search. status %d\n",
2432 			reply.evt.status);
2433 		rc = -EINVAL;
2434 	}
2435 
2436 	return rc;
2437 }
2438 
2439 int wmi_stop_discovery(struct wil6210_vif *vif)
2440 {
2441 	struct wil6210_priv *wil = vif_to_wil(vif);
2442 	int rc;
2443 
2444 	wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
2445 
2446 	rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
2447 		      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0,
2448 		      WIL_WMI_CALL_GENERAL_TO_MS);
2449 
2450 	if (rc)
2451 		wil_err(wil, "Failed to stop discovery\n");
2452 
2453 	return rc;
2454 }
2455 
2456 int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index,
2457 		       const void *mac_addr, int key_usage)
2458 {
2459 	struct wil6210_priv *wil = vif_to_wil(vif);
2460 	struct wmi_delete_cipher_key_cmd cmd = {
2461 		.key_index = key_index,
2462 	};
2463 
2464 	if (mac_addr)
2465 		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
2466 
2467 	return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, vif->mid,
2468 			&cmd, sizeof(cmd));
2469 }
2470 
2471 int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index,
2472 		       const void *mac_addr, int key_len, const void *key,
2473 		       int key_usage)
2474 {
2475 	struct wil6210_priv *wil = vif_to_wil(vif);
2476 	struct wmi_add_cipher_key_cmd cmd = {
2477 		.key_index = key_index,
2478 		.key_usage = key_usage,
2479 		.key_len = key_len,
2480 	};
2481 
2482 	if (key_len > sizeof(cmd.key))
2483 		return -EINVAL;
2484 
2485 	/* key len = 0 is allowed only for usage of WMI_KEY_USE_APPLY */
2486 	if ((key_len == 0 || !key) &&
2487 	    key_usage != WMI_KEY_USE_APPLY_PTK)
2488 		return -EINVAL;
2489 
2490 	if (key)
2491 		memcpy(cmd.key, key, key_len);
2492 
2493 	if (mac_addr)
2494 		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
2495 
2496 	return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, vif->mid,
2497 			&cmd, sizeof(cmd));
2498 }
2499 
2500 int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie)
2501 {
2502 	struct wil6210_priv *wil = vif_to_wil(vif);
2503 	static const char *const names[] = {
2504 		[WMI_FRAME_BEACON]	= "BEACON",
2505 		[WMI_FRAME_PROBE_REQ]	= "PROBE_REQ",
2506 		[WMI_FRAME_PROBE_RESP]	= "WMI_FRAME_PROBE_RESP",
2507 		[WMI_FRAME_ASSOC_REQ]	= "WMI_FRAME_ASSOC_REQ",
2508 		[WMI_FRAME_ASSOC_RESP]	= "WMI_FRAME_ASSOC_RESP",
2509 	};
2510 	int rc;
2511 	u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
2512 	struct wmi_set_appie_cmd *cmd;
2513 
2514 	if (len < ie_len) {
2515 		rc = -EINVAL;
2516 		goto out;
2517 	}
2518 
2519 	cmd = kzalloc(len, GFP_KERNEL);
2520 	if (!cmd) {
2521 		rc = -ENOMEM;
2522 		goto out;
2523 	}
2524 	if (!ie)
2525 		ie_len = 0;
2526 
2527 	cmd->mgmt_frm_type = type;
2528 	/* BUG: FW API define ieLen as u8. Will fix FW */
2529 	cmd->ie_len = cpu_to_le16(ie_len);
2530 	if (ie_len)
2531 		memcpy(cmd->ie_info, ie, ie_len);
2532 	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len);
2533 	kfree(cmd);
2534 out:
2535 	if (rc) {
2536 		const char *name = type < ARRAY_SIZE(names) ?
2537 				   names[type] : "??";
2538 		wil_err(wil, "set_ie(%d %s) failed : %d\n", type, name, rc);
2539 	}
2540 
2541 	return rc;
2542 }
2543 
2544 int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie)
2545 {
2546 	struct wil6210_priv *wil = vif_to_wil(vif);
2547 	u16 len;
2548 	struct wmi_update_ft_ies_cmd *cmd;
2549 	int rc;
2550 
2551 	if (!ie)
2552 		ie_len = 0;
2553 
2554 	len = sizeof(struct wmi_update_ft_ies_cmd) + ie_len;
2555 	if (len < ie_len) {
2556 		wil_err(wil, "wraparound. ie len %d\n", ie_len);
2557 		return -EINVAL;
2558 	}
2559 
2560 	cmd = kzalloc(len, GFP_KERNEL);
2561 	if (!cmd) {
2562 		rc = -ENOMEM;
2563 		goto out;
2564 	}
2565 
2566 	cmd->ie_len = cpu_to_le16(ie_len);
2567 	if (ie_len)
2568 		memcpy(cmd->ie_info, ie, ie_len);
2569 	rc = wmi_send(wil, WMI_UPDATE_FT_IES_CMDID, vif->mid, cmd, len);
2570 	kfree(cmd);
2571 
2572 out:
2573 	if (rc)
2574 		wil_err(wil, "update ft ies failed : %d\n", rc);
2575 
2576 	return rc;
2577 }
2578 
2579 /**
2580  * wmi_rxon - turn radio on/off
2581  * @on:		turn on if true, off otherwise
2582  *
2583  * Only switch radio. Channel should be set separately.
2584  * No timeout for rxon - radio turned on forever unless some other call
2585  * turns it off
2586  */
2587 int wmi_rxon(struct wil6210_priv *wil, bool on)
2588 {
2589 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2590 	int rc;
2591 	struct {
2592 		struct wmi_cmd_hdr wmi;
2593 		struct wmi_listen_started_event evt;
2594 	} __packed reply = {
2595 		.evt = {.status = WMI_FW_STATUS_FAILURE},
2596 	};
2597 
2598 	wil_info(wil, "(%s)\n", on ? "on" : "off");
2599 
2600 	if (on) {
2601 		rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0,
2602 			      WMI_LISTEN_STARTED_EVENTID,
2603 			      &reply, sizeof(reply),
2604 			      WIL_WMI_CALL_GENERAL_TO_MS);
2605 		if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
2606 			rc = -EINVAL;
2607 	} else {
2608 		rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
2609 			      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0,
2610 			      WIL_WMI_CALL_GENERAL_TO_MS);
2611 	}
2612 
2613 	return rc;
2614 }
2615 
2616 int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring)
2617 {
2618 	struct net_device *ndev = wil->main_ndev;
2619 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
2620 	struct wil6210_vif *vif = ndev_to_vif(ndev);
2621 	struct wmi_cfg_rx_chain_cmd cmd = {
2622 		.action = WMI_RX_CHAIN_ADD,
2623 		.rx_sw_ring = {
2624 			.max_mpdu_size = cpu_to_le16(
2625 				wil_mtu2macbuf(wil->rx_buf_len)),
2626 			.ring_mem_base = cpu_to_le64(vring->pa),
2627 			.ring_size = cpu_to_le16(vring->size),
2628 		},
2629 		.mid = 0, /* TODO - what is it? */
2630 		.decap_trans_type = WMI_DECAP_TYPE_802_3,
2631 		.reorder_type = WMI_RX_SW_REORDER,
2632 		.host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
2633 	};
2634 	struct {
2635 		struct wmi_cmd_hdr wmi;
2636 		struct wmi_cfg_rx_chain_done_event evt;
2637 	} __packed evt;
2638 	int rc;
2639 
2640 	memset(&evt, 0, sizeof(evt));
2641 
2642 	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
2643 		struct ieee80211_channel *ch = wil->monitor_chandef.chan;
2644 
2645 		cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
2646 		if (ch)
2647 			cmd.sniffer_cfg.channel = ch->hw_value - 1;
2648 		cmd.sniffer_cfg.phy_info_mode =
2649 			cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED);
2650 		cmd.sniffer_cfg.phy_support =
2651 			cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
2652 				    ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
2653 	} else {
2654 		/* Initialize offload (in non-sniffer mode).
2655 		 * Linux IP stack always calculates IP checksum
2656 		 * HW always calculate TCP/UDP checksum
2657 		 */
2658 		cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
2659 	}
2660 
2661 	if (rx_align_2)
2662 		cmd.l2_802_3_offload_ctrl |=
2663 				L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
2664 
2665 	/* typical time for secure PCP is 840ms */
2666 	rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, vif->mid, &cmd, sizeof(cmd),
2667 		      WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
2668 	if (rc)
2669 		return rc;
2670 
2671 	if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
2672 		rc = -EINVAL;
2673 
2674 	vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
2675 
2676 	wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
2677 		     le32_to_cpu(evt.evt.status), vring->hwtail);
2678 
2679 	return rc;
2680 }
2681 
2682 int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
2683 {
2684 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2685 	int rc;
2686 	struct wmi_temp_sense_cmd cmd = {
2687 		.measure_baseband_en = cpu_to_le32(!!t_bb),
2688 		.measure_rf_en = cpu_to_le32(!!t_rf),
2689 		.measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
2690 	};
2691 	struct {
2692 		struct wmi_cmd_hdr wmi;
2693 		struct wmi_temp_sense_done_event evt;
2694 	} __packed reply;
2695 
2696 	memset(&reply, 0, sizeof(reply));
2697 
2698 	rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd),
2699 		      WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply),
2700 		      WIL_WMI_CALL_GENERAL_TO_MS);
2701 	if (rc)
2702 		return rc;
2703 
2704 	if (t_bb)
2705 		*t_bb = le32_to_cpu(reply.evt.baseband_t1000);
2706 	if (t_rf)
2707 		*t_rf = le32_to_cpu(reply.evt.rf_t1000);
2708 
2709 	return 0;
2710 }
2711 
2712 int wmi_get_all_temperatures(struct wil6210_priv *wil,
2713 			     struct wmi_temp_sense_all_done_event
2714 			     *sense_all_evt)
2715 {
2716 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2717 	int rc;
2718 	struct wmi_temp_sense_all_cmd cmd = {
2719 		.measure_baseband_en = true,
2720 		.measure_rf_en = true,
2721 		.measure_mode = TEMPERATURE_MEASURE_NOW,
2722 	};
2723 	struct {
2724 		struct wmi_cmd_hdr wmi;
2725 		struct wmi_temp_sense_all_done_event evt;
2726 	} __packed reply;
2727 
2728 	if (!sense_all_evt) {
2729 		wil_err(wil, "Invalid sense_all_evt value\n");
2730 		return -EINVAL;
2731 	}
2732 
2733 	memset(&reply, 0, sizeof(reply));
2734 	reply.evt.status = WMI_FW_STATUS_FAILURE;
2735 	rc = wmi_call(wil, WMI_TEMP_SENSE_ALL_CMDID, vif->mid, &cmd,
2736 		      sizeof(cmd), WMI_TEMP_SENSE_ALL_DONE_EVENTID,
2737 		      &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
2738 	if (rc)
2739 		return rc;
2740 
2741 	if (reply.evt.status == WMI_FW_STATUS_FAILURE) {
2742 		wil_err(wil, "Failed getting TEMP_SENSE_ALL\n");
2743 		return -EINVAL;
2744 	}
2745 
2746 	memcpy(sense_all_evt, &reply.evt, sizeof(reply.evt));
2747 	return 0;
2748 }
2749 
2750 int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason,
2751 		       bool del_sta)
2752 {
2753 	struct wil6210_priv *wil = vif_to_wil(vif);
2754 	int rc;
2755 	struct wmi_disconnect_sta_cmd disc_sta_cmd = {
2756 		.disconnect_reason = cpu_to_le16(reason),
2757 	};
2758 	struct wmi_del_sta_cmd del_sta_cmd = {
2759 		.disconnect_reason = cpu_to_le16(reason),
2760 	};
2761 	struct {
2762 		struct wmi_cmd_hdr wmi;
2763 		struct wmi_disconnect_event evt;
2764 	} __packed reply;
2765 
2766 	wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
2767 
2768 	memset(&reply, 0, sizeof(reply));
2769 	vif->locally_generated_disc = true;
2770 	if (del_sta) {
2771 		ether_addr_copy(del_sta_cmd.dst_mac, mac);
2772 		rc = wmi_call(wil, WMI_DEL_STA_CMDID, vif->mid, &del_sta_cmd,
2773 			      sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID,
2774 			      &reply, sizeof(reply), 1000);
2775 	} else {
2776 		ether_addr_copy(disc_sta_cmd.dst_mac, mac);
2777 		rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, vif->mid,
2778 			      &disc_sta_cmd, sizeof(disc_sta_cmd),
2779 			      WMI_DISCONNECT_EVENTID,
2780 			      &reply, sizeof(reply), 1000);
2781 	}
2782 	/* failure to disconnect in reasonable time treated as FW error */
2783 	if (rc) {
2784 		wil_fw_error_recovery(wil);
2785 		return rc;
2786 	}
2787 	wil->sinfo_gen++;
2788 
2789 	return 0;
2790 }
2791 
2792 int wmi_addba(struct wil6210_priv *wil, u8 mid,
2793 	      u8 ringid, u8 size, u16 timeout)
2794 {
2795 	u8 amsdu = wil->use_enhanced_dma_hw && wil->use_rx_hw_reordering &&
2796 		test_bit(WMI_FW_CAPABILITY_AMSDU, wil->fw_capabilities) &&
2797 		wil->amsdu_en;
2798 	struct wmi_ring_ba_en_cmd cmd = {
2799 		.ring_id = ringid,
2800 		.agg_max_wsize = size,
2801 		.ba_timeout = cpu_to_le16(timeout),
2802 		.amsdu = amsdu,
2803 	};
2804 
2805 	wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d amsdu %d)\n",
2806 		    ringid, size, timeout, amsdu);
2807 
2808 	return wmi_send(wil, WMI_RING_BA_EN_CMDID, mid, &cmd, sizeof(cmd));
2809 }
2810 
2811 int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason)
2812 {
2813 	struct wmi_ring_ba_dis_cmd cmd = {
2814 		.ring_id = ringid,
2815 		.reason = cpu_to_le16(reason),
2816 	};
2817 
2818 	wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason);
2819 
2820 	return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd));
2821 }
2822 
2823 int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason)
2824 {
2825 	struct wmi_rcp_delba_cmd cmd = {
2826 		.reason = cpu_to_le16(reason),
2827 	};
2828 
2829 	if (cid >= WIL6210_RX_DESC_MAX_CID) {
2830 		cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
2831 		cmd.cid = cid;
2832 		cmd.tid = tid;
2833 	} else {
2834 		cmd.cidxtid = mk_cidxtid(cid, tid);
2835 	}
2836 
2837 	wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cid,
2838 		    tid, reason);
2839 
2840 	return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd));
2841 }
2842 
2843 int wmi_addba_rx_resp(struct wil6210_priv *wil,
2844 		      u8 mid, u8 cid, u8 tid, u8 token,
2845 		      u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
2846 {
2847 	int rc;
2848 	struct wmi_rcp_addba_resp_cmd cmd = {
2849 		.dialog_token = token,
2850 		.status_code = cpu_to_le16(status),
2851 		/* bit 0: A-MSDU supported
2852 		 * bit 1: policy (controlled by FW)
2853 		 * bits 2..5: TID
2854 		 * bits 6..15: buffer size
2855 		 */
2856 		.ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
2857 					    (agg_wsize << 6)),
2858 		.ba_timeout = cpu_to_le16(timeout),
2859 	};
2860 	struct {
2861 		struct wmi_cmd_hdr wmi;
2862 		struct wmi_rcp_addba_resp_sent_event evt;
2863 	} __packed reply = {
2864 		.evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)},
2865 	};
2866 
2867 	if (cid >= WIL6210_RX_DESC_MAX_CID) {
2868 		cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
2869 		cmd.cid = cid;
2870 		cmd.tid = tid;
2871 	} else {
2872 		cmd.cidxtid = mk_cidxtid(cid, tid);
2873 	}
2874 
2875 	wil_dbg_wmi(wil,
2876 		    "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
2877 		    mid, cid, tid, agg_wsize,
2878 		    timeout, status, amsdu ? "+" : "-");
2879 
2880 	rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, mid, &cmd, sizeof(cmd),
2881 		      WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
2882 		      WIL_WMI_CALL_GENERAL_TO_MS);
2883 	if (rc)
2884 		return rc;
2885 
2886 	if (reply.evt.status) {
2887 		wil_err(wil, "ADDBA response failed with status %d\n",
2888 			le16_to_cpu(reply.evt.status));
2889 		rc = -EINVAL;
2890 	}
2891 
2892 	return rc;
2893 }
2894 
2895 int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
2896 			   u8 token, u16 status, bool amsdu, u16 agg_wsize,
2897 			   u16 timeout)
2898 {
2899 	int rc;
2900 	struct wmi_rcp_addba_resp_edma_cmd cmd = {
2901 		.cid = cid,
2902 		.tid = tid,
2903 		.dialog_token = token,
2904 		.status_code = cpu_to_le16(status),
2905 		/* bit 0: A-MSDU supported
2906 		 * bit 1: policy (controlled by FW)
2907 		 * bits 2..5: TID
2908 		 * bits 6..15: buffer size
2909 		 */
2910 		.ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
2911 					    (agg_wsize << 6)),
2912 		.ba_timeout = cpu_to_le16(timeout),
2913 		/* route all the connections to status ring 0 */
2914 		.status_ring_id = WIL_DEFAULT_RX_STATUS_RING_ID,
2915 	};
2916 	struct {
2917 		struct wmi_cmd_hdr wmi;
2918 		struct wmi_rcp_addba_resp_sent_event evt;
2919 	} __packed reply = {
2920 		.evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)},
2921 	};
2922 
2923 	wil_dbg_wmi(wil,
2924 		    "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s, sring_id %d\n",
2925 		    cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-",
2926 		    WIL_DEFAULT_RX_STATUS_RING_ID);
2927 
2928 	rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_EDMA_CMDID, mid, &cmd,
2929 		      sizeof(cmd), WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply,
2930 		      sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
2931 	if (rc)
2932 		return rc;
2933 
2934 	if (reply.evt.status) {
2935 		wil_err(wil, "ADDBA response failed with status %d\n",
2936 			le16_to_cpu(reply.evt.status));
2937 		rc = -EINVAL;
2938 	}
2939 
2940 	return rc;
2941 }
2942 
2943 int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
2944 			   enum wmi_ps_profile_type ps_profile)
2945 {
2946 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2947 	int rc;
2948 	struct wmi_ps_dev_profile_cfg_cmd cmd = {
2949 		.ps_profile = ps_profile,
2950 	};
2951 	struct {
2952 		struct wmi_cmd_hdr wmi;
2953 		struct wmi_ps_dev_profile_cfg_event evt;
2954 	} __packed reply = {
2955 		.evt = {.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR)},
2956 	};
2957 	u32 status;
2958 
2959 	wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile);
2960 
2961 	rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid,
2962 		      &cmd, sizeof(cmd),
2963 		      WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
2964 		      WIL_WMI_CALL_GENERAL_TO_MS);
2965 	if (rc)
2966 		return rc;
2967 
2968 	status = le32_to_cpu(reply.evt.status);
2969 
2970 	if (status != WMI_PS_CFG_CMD_STATUS_SUCCESS) {
2971 		wil_err(wil, "ps dev profile cfg failed with status %d\n",
2972 			status);
2973 		rc = -EINVAL;
2974 	}
2975 
2976 	return rc;
2977 }
2978 
2979 int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
2980 {
2981 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2982 	int rc;
2983 	struct wmi_set_mgmt_retry_limit_cmd cmd = {
2984 		.mgmt_retry_limit = retry_short,
2985 	};
2986 	struct {
2987 		struct wmi_cmd_hdr wmi;
2988 		struct wmi_set_mgmt_retry_limit_event evt;
2989 	} __packed reply = {
2990 		.evt = {.status = WMI_FW_STATUS_FAILURE},
2991 	};
2992 
2993 	wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short);
2994 
2995 	if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
2996 		return -ENOTSUPP;
2997 
2998 	rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid,
2999 		      &cmd, sizeof(cmd),
3000 		      WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
3001 		      WIL_WMI_CALL_GENERAL_TO_MS);
3002 	if (rc)
3003 		return rc;
3004 
3005 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3006 		wil_err(wil, "set mgmt retry limit failed with status %d\n",
3007 			reply.evt.status);
3008 		rc = -EINVAL;
3009 	}
3010 
3011 	return rc;
3012 }
3013 
3014 int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
3015 {
3016 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
3017 	int rc;
3018 	struct {
3019 		struct wmi_cmd_hdr wmi;
3020 		struct wmi_get_mgmt_retry_limit_event evt;
3021 	} __packed reply;
3022 
3023 	wil_dbg_wmi(wil, "getting mgmt retry short\n");
3024 
3025 	if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
3026 		return -ENOTSUPP;
3027 
3028 	memset(&reply, 0, sizeof(reply));
3029 	rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0,
3030 		      WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
3031 		      WIL_WMI_CALL_GENERAL_TO_MS);
3032 	if (rc)
3033 		return rc;
3034 
3035 	if (retry_short)
3036 		*retry_short = reply.evt.mgmt_retry_limit;
3037 
3038 	return 0;
3039 }
3040 
3041 int wmi_abort_scan(struct wil6210_vif *vif)
3042 {
3043 	struct wil6210_priv *wil = vif_to_wil(vif);
3044 	int rc;
3045 
3046 	wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n");
3047 
3048 	rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, vif->mid, NULL, 0);
3049 	if (rc)
3050 		wil_err(wil, "Failed to abort scan (%d)\n", rc);
3051 
3052 	return rc;
3053 }
3054 
3055 int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid)
3056 {
3057 	struct wil6210_priv *wil = vif_to_wil(vif);
3058 	int rc;
3059 	struct wmi_new_sta_cmd cmd = {
3060 		.aid = aid,
3061 	};
3062 
3063 	wil_dbg_wmi(wil, "new sta %pM, aid %d\n", mac, aid);
3064 
3065 	ether_addr_copy(cmd.dst_mac, mac);
3066 
3067 	rc = wmi_send(wil, WMI_NEW_STA_CMDID, vif->mid, &cmd, sizeof(cmd));
3068 	if (rc)
3069 		wil_err(wil, "Failed to send new sta (%d)\n", rc);
3070 
3071 	return rc;
3072 }
3073 
3074 void wmi_event_flush(struct wil6210_priv *wil)
3075 {
3076 	ulong flags;
3077 	struct pending_wmi_event *evt, *t;
3078 
3079 	wil_dbg_wmi(wil, "event_flush\n");
3080 
3081 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
3082 
3083 	list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
3084 		list_del(&evt->list);
3085 		kfree(evt);
3086 	}
3087 
3088 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
3089 }
3090 
3091 static const char *suspend_status2name(u8 status)
3092 {
3093 	switch (status) {
3094 	case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE:
3095 		return "LINK_NOT_IDLE";
3096 	case WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT:
3097 		return "DISCONNECT";
3098 	case WMI_TRAFFIC_SUSPEND_REJECTED_OTHER:
3099 		return "OTHER";
3100 	default:
3101 		return "Untracked status";
3102 	}
3103 }
3104 
3105 int wmi_suspend(struct wil6210_priv *wil)
3106 {
3107 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
3108 	int rc;
3109 	struct wmi_traffic_suspend_cmd cmd = {
3110 		.wakeup_trigger = wil->wakeup_trigger,
3111 	};
3112 	struct {
3113 		struct wmi_cmd_hdr wmi;
3114 		struct wmi_traffic_suspend_event evt;
3115 	} __packed reply = {
3116 		.evt = {.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE},
3117 	};
3118 
3119 	u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP;
3120 
3121 	wil->suspend_resp_rcvd = false;
3122 	wil->suspend_resp_comp = false;
3123 
3124 	rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, vif->mid,
3125 		      &cmd, sizeof(cmd),
3126 		      WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
3127 		      suspend_to);
3128 	if (rc) {
3129 		wil_err(wil, "wmi_call for suspend req failed, rc=%d\n", rc);
3130 		if (rc == -ETIME)
3131 			/* wmi_call TO */
3132 			wil->suspend_stats.rejected_by_device++;
3133 		else
3134 			wil->suspend_stats.rejected_by_host++;
3135 		goto out;
3136 	}
3137 
3138 	wil_dbg_wmi(wil, "waiting for suspend_response_completed\n");
3139 
3140 	rc = wait_event_interruptible_timeout(wil->wq,
3141 					      wil->suspend_resp_comp,
3142 					      msecs_to_jiffies(suspend_to));
3143 	if (rc == 0) {
3144 		wil_err(wil, "TO waiting for suspend_response_completed\n");
3145 		if (wil->suspend_resp_rcvd)
3146 			/* Device responded but we TO due to another reason */
3147 			wil->suspend_stats.rejected_by_host++;
3148 		else
3149 			wil->suspend_stats.rejected_by_device++;
3150 		rc = -EBUSY;
3151 		goto out;
3152 	}
3153 
3154 	wil_dbg_wmi(wil, "suspend_response_completed rcvd\n");
3155 	if (reply.evt.status != WMI_TRAFFIC_SUSPEND_APPROVED) {
3156 		wil_dbg_pm(wil, "device rejected the suspend, %s\n",
3157 			   suspend_status2name(reply.evt.status));
3158 		wil->suspend_stats.rejected_by_device++;
3159 	}
3160 	rc = reply.evt.status;
3161 
3162 out:
3163 	wil->suspend_resp_rcvd = false;
3164 	wil->suspend_resp_comp = false;
3165 
3166 	return rc;
3167 }
3168 
3169 static void resume_triggers2string(u32 triggers, char *string, int str_size)
3170 {
3171 	string[0] = '\0';
3172 
3173 	if (!triggers) {
3174 		strlcat(string, " UNKNOWN", str_size);
3175 		return;
3176 	}
3177 
3178 	if (triggers & WMI_RESUME_TRIGGER_HOST)
3179 		strlcat(string, " HOST", str_size);
3180 
3181 	if (triggers & WMI_RESUME_TRIGGER_UCAST_RX)
3182 		strlcat(string, " UCAST_RX", str_size);
3183 
3184 	if (triggers & WMI_RESUME_TRIGGER_BCAST_RX)
3185 		strlcat(string, " BCAST_RX", str_size);
3186 
3187 	if (triggers & WMI_RESUME_TRIGGER_WMI_EVT)
3188 		strlcat(string, " WMI_EVT", str_size);
3189 
3190 	if (triggers & WMI_RESUME_TRIGGER_DISCONNECT)
3191 		strlcat(string, " DISCONNECT", str_size);
3192 }
3193 
3194 int wmi_resume(struct wil6210_priv *wil)
3195 {
3196 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
3197 	int rc;
3198 	char string[100];
3199 	struct {
3200 		struct wmi_cmd_hdr wmi;
3201 		struct wmi_traffic_resume_event evt;
3202 	} __packed reply = {
3203 		.evt = {.status = WMI_TRAFFIC_RESUME_FAILED,
3204 			.resume_triggers =
3205 				cpu_to_le32(WMI_RESUME_TRIGGER_UNKNOWN)},
3206 	};
3207 
3208 	rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, vif->mid, NULL, 0,
3209 		      WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
3210 		      WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
3211 	if (rc)
3212 		return rc;
3213 	resume_triggers2string(le32_to_cpu(reply.evt.resume_triggers), string,
3214 			       sizeof(string));
3215 	wil_dbg_pm(wil, "device resume %s, resume triggers:%s (0x%x)\n",
3216 		   reply.evt.status ? "failed" : "passed", string,
3217 		   le32_to_cpu(reply.evt.resume_triggers));
3218 
3219 	return reply.evt.status;
3220 }
3221 
3222 int wmi_port_allocate(struct wil6210_priv *wil, u8 mid,
3223 		      const u8 *mac, enum nl80211_iftype iftype)
3224 {
3225 	int rc;
3226 	struct wmi_port_allocate_cmd cmd = {
3227 		.mid = mid,
3228 	};
3229 	struct {
3230 		struct wmi_cmd_hdr wmi;
3231 		struct wmi_port_allocated_event evt;
3232 	} __packed reply = {
3233 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3234 	};
3235 
3236 	wil_dbg_misc(wil, "port allocate, mid %d iftype %d, mac %pM\n",
3237 		     mid, iftype, mac);
3238 
3239 	ether_addr_copy(cmd.mac, mac);
3240 	switch (iftype) {
3241 	case NL80211_IFTYPE_STATION:
3242 		cmd.port_role = WMI_PORT_STA;
3243 		break;
3244 	case NL80211_IFTYPE_AP:
3245 		cmd.port_role = WMI_PORT_AP;
3246 		break;
3247 	case NL80211_IFTYPE_P2P_CLIENT:
3248 		cmd.port_role = WMI_PORT_P2P_CLIENT;
3249 		break;
3250 	case NL80211_IFTYPE_P2P_GO:
3251 		cmd.port_role = WMI_PORT_P2P_GO;
3252 		break;
3253 	/* what about monitor??? */
3254 	default:
3255 		wil_err(wil, "unsupported iftype: %d\n", iftype);
3256 		return -EINVAL;
3257 	}
3258 
3259 	rc = wmi_call(wil, WMI_PORT_ALLOCATE_CMDID, mid,
3260 		      &cmd, sizeof(cmd),
3261 		      WMI_PORT_ALLOCATED_EVENTID, &reply,
3262 		      sizeof(reply), 300);
3263 	if (rc) {
3264 		wil_err(wil, "failed to allocate port, status %d\n", rc);
3265 		return rc;
3266 	}
3267 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3268 		wil_err(wil, "WMI_PORT_ALLOCATE returned status %d\n",
3269 			reply.evt.status);
3270 		return -EINVAL;
3271 	}
3272 
3273 	return 0;
3274 }
3275 
3276 int wmi_port_delete(struct wil6210_priv *wil, u8 mid)
3277 {
3278 	int rc;
3279 	struct wmi_port_delete_cmd cmd = {
3280 		.mid = mid,
3281 	};
3282 	struct {
3283 		struct wmi_cmd_hdr wmi;
3284 		struct wmi_port_deleted_event evt;
3285 	} __packed reply = {
3286 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3287 	};
3288 
3289 	wil_dbg_misc(wil, "port delete, mid %d\n", mid);
3290 
3291 	rc = wmi_call(wil, WMI_PORT_DELETE_CMDID, mid,
3292 		      &cmd, sizeof(cmd),
3293 		      WMI_PORT_DELETED_EVENTID, &reply,
3294 		      sizeof(reply), 2000);
3295 	if (rc) {
3296 		wil_err(wil, "failed to delete port, status %d\n", rc);
3297 		return rc;
3298 	}
3299 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3300 		wil_err(wil, "WMI_PORT_DELETE returned status %d\n",
3301 			reply.evt.status);
3302 		return -EINVAL;
3303 	}
3304 
3305 	return 0;
3306 }
3307 
3308 static bool wmi_evt_call_handler(struct wil6210_vif *vif, int id,
3309 				 void *d, int len)
3310 {
3311 	uint i;
3312 
3313 	for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
3314 		if (wmi_evt_handlers[i].eventid == id) {
3315 			wmi_evt_handlers[i].handler(vif, id, d, len);
3316 			return true;
3317 		}
3318 	}
3319 
3320 	return false;
3321 }
3322 
3323 static void wmi_event_handle(struct wil6210_priv *wil,
3324 			     struct wil6210_mbox_hdr *hdr)
3325 {
3326 	u16 len = le16_to_cpu(hdr->len);
3327 	struct wil6210_vif *vif;
3328 
3329 	if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
3330 	    (len >= sizeof(struct wmi_cmd_hdr))) {
3331 		struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
3332 		void *evt_data = (void *)(&wmi[1]);
3333 		u16 id = le16_to_cpu(wmi->command_id);
3334 		u8 mid = wmi->mid;
3335 
3336 		wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x,%d)\n",
3337 			    eventid2name(id), id, wil->reply_id,
3338 			    wil->reply_mid);
3339 
3340 		if (mid == MID_BROADCAST)
3341 			mid = 0;
3342 		if (mid >= GET_MAX_VIFS(wil)) {
3343 			wil_dbg_wmi(wil, "invalid mid %d, event skipped\n",
3344 				    mid);
3345 			return;
3346 		}
3347 		vif = wil->vifs[mid];
3348 		if (!vif) {
3349 			wil_dbg_wmi(wil, "event for empty VIF(%d), skipped\n",
3350 				    mid);
3351 			return;
3352 		}
3353 
3354 		/* check if someone waits for this event */
3355 		if (wil->reply_id && wil->reply_id == id &&
3356 		    wil->reply_mid == mid) {
3357 			if (wil->reply_buf) {
3358 				/* event received while wmi_call is waiting
3359 				 * with a buffer. Such event should be handled
3360 				 * in wmi_recv_cmd function. Handling the event
3361 				 * here means a previous wmi_call was timeout.
3362 				 * Drop the event and do not handle it.
3363 				 */
3364 				wil_err(wil,
3365 					"Old event (%d, %s) while wmi_call is waiting. Drop it and Continue waiting\n",
3366 					id, eventid2name(id));
3367 				return;
3368 			}
3369 
3370 			wmi_evt_call_handler(vif, id, evt_data,
3371 					     len - sizeof(*wmi));
3372 			wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n",
3373 				    id);
3374 			complete(&wil->wmi_call);
3375 			return;
3376 		}
3377 		/* unsolicited event */
3378 		/* search for handler */
3379 		if (!wmi_evt_call_handler(vif, id, evt_data,
3380 					  len - sizeof(*wmi))) {
3381 			wil_info(wil, "Unhandled event 0x%04x\n", id);
3382 		}
3383 	} else {
3384 		wil_err(wil, "Unknown event type\n");
3385 		print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
3386 			       hdr, sizeof(*hdr) + len, true);
3387 	}
3388 }
3389 
3390 /*
3391  * Retrieve next WMI event from the pending list
3392  */
3393 static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
3394 {
3395 	ulong flags;
3396 	struct list_head *ret = NULL;
3397 
3398 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
3399 
3400 	if (!list_empty(&wil->pending_wmi_ev)) {
3401 		ret = wil->pending_wmi_ev.next;
3402 		list_del(ret);
3403 	}
3404 
3405 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
3406 
3407 	return ret;
3408 }
3409 
3410 /*
3411  * Handler for the WMI events
3412  */
3413 void wmi_event_worker(struct work_struct *work)
3414 {
3415 	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
3416 						 wmi_event_worker);
3417 	struct pending_wmi_event *evt;
3418 	struct list_head *lh;
3419 
3420 	wil_dbg_wmi(wil, "event_worker: Start\n");
3421 	while ((lh = next_wmi_ev(wil)) != NULL) {
3422 		evt = list_entry(lh, struct pending_wmi_event, list);
3423 		wmi_event_handle(wil, &evt->event.hdr);
3424 		kfree(evt);
3425 	}
3426 	wil_dbg_wmi(wil, "event_worker: Finished\n");
3427 }
3428 
3429 bool wil_is_wmi_idle(struct wil6210_priv *wil)
3430 {
3431 	ulong flags;
3432 	struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
3433 	bool rc = false;
3434 
3435 	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
3436 
3437 	/* Check if there are pending WMI events in the events queue */
3438 	if (!list_empty(&wil->pending_wmi_ev)) {
3439 		wil_dbg_pm(wil, "Pending WMI events in queue\n");
3440 		goto out;
3441 	}
3442 
3443 	/* Check if there is a pending WMI call */
3444 	if (wil->reply_id) {
3445 		wil_dbg_pm(wil, "Pending WMI call\n");
3446 		goto out;
3447 	}
3448 
3449 	/* Check if there are pending RX events in mbox */
3450 	r->head = wil_r(wil, RGF_MBOX +
3451 			offsetof(struct wil6210_mbox_ctl, rx.head));
3452 	if (r->tail != r->head)
3453 		wil_dbg_pm(wil, "Pending WMI mbox events\n");
3454 	else
3455 		rc = true;
3456 
3457 out:
3458 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
3459 	return rc;
3460 }
3461 
3462 static void
3463 wmi_sched_scan_set_ssids(struct wil6210_priv *wil,
3464 			 struct wmi_start_sched_scan_cmd *cmd,
3465 			 struct cfg80211_ssid *ssids, int n_ssids,
3466 			 struct cfg80211_match_set *match_sets,
3467 			 int n_match_sets)
3468 {
3469 	int i;
3470 
3471 	if (n_match_sets > WMI_MAX_PNO_SSID_NUM) {
3472 		wil_dbg_wmi(wil, "too many match sets (%d), use first %d\n",
3473 			    n_match_sets, WMI_MAX_PNO_SSID_NUM);
3474 		n_match_sets = WMI_MAX_PNO_SSID_NUM;
3475 	}
3476 	cmd->num_of_ssids = n_match_sets;
3477 
3478 	for (i = 0; i < n_match_sets; i++) {
3479 		struct wmi_sched_scan_ssid_match *wmi_match =
3480 			&cmd->ssid_for_match[i];
3481 		struct cfg80211_match_set *cfg_match = &match_sets[i];
3482 		int j;
3483 
3484 		wmi_match->ssid_len = cfg_match->ssid.ssid_len;
3485 		memcpy(wmi_match->ssid, cfg_match->ssid.ssid,
3486 		       min_t(u8, wmi_match->ssid_len, WMI_MAX_SSID_LEN));
3487 		wmi_match->rssi_threshold = S8_MIN;
3488 		if (cfg_match->rssi_thold >= S8_MIN &&
3489 		    cfg_match->rssi_thold <= S8_MAX)
3490 			wmi_match->rssi_threshold = cfg_match->rssi_thold;
3491 
3492 		for (j = 0; j < n_ssids; j++)
3493 			if (wmi_match->ssid_len == ssids[j].ssid_len &&
3494 			    memcmp(wmi_match->ssid, ssids[j].ssid,
3495 				   wmi_match->ssid_len) == 0)
3496 				wmi_match->add_ssid_to_probe = true;
3497 	}
3498 }
3499 
3500 static void
3501 wmi_sched_scan_set_channels(struct wil6210_priv *wil,
3502 			    struct wmi_start_sched_scan_cmd *cmd,
3503 			    u32 n_channels,
3504 			    struct ieee80211_channel **channels)
3505 {
3506 	int i;
3507 
3508 	if (n_channels > WMI_MAX_CHANNEL_NUM) {
3509 		wil_dbg_wmi(wil, "too many channels (%d), use first %d\n",
3510 			    n_channels, WMI_MAX_CHANNEL_NUM);
3511 		n_channels = WMI_MAX_CHANNEL_NUM;
3512 	}
3513 	cmd->num_of_channels = n_channels;
3514 
3515 	for (i = 0; i < n_channels; i++) {
3516 		struct ieee80211_channel *cfg_chan = channels[i];
3517 
3518 		cmd->channel_list[i] = cfg_chan->hw_value - 1;
3519 	}
3520 }
3521 
3522 static void
3523 wmi_sched_scan_set_plans(struct wil6210_priv *wil,
3524 			 struct wmi_start_sched_scan_cmd *cmd,
3525 			 struct cfg80211_sched_scan_plan *scan_plans,
3526 			 int n_scan_plans)
3527 {
3528 	int i;
3529 
3530 	if (n_scan_plans > WMI_MAX_PLANS_NUM) {
3531 		wil_dbg_wmi(wil, "too many plans (%d), use first %d\n",
3532 			    n_scan_plans, WMI_MAX_PLANS_NUM);
3533 		n_scan_plans = WMI_MAX_PLANS_NUM;
3534 	}
3535 
3536 	for (i = 0; i < n_scan_plans; i++) {
3537 		struct cfg80211_sched_scan_plan *cfg_plan = &scan_plans[i];
3538 
3539 		cmd->scan_plans[i].interval_sec =
3540 			cpu_to_le16(cfg_plan->interval);
3541 		cmd->scan_plans[i].num_of_iterations =
3542 			cpu_to_le16(cfg_plan->iterations);
3543 	}
3544 }
3545 
3546 int wmi_start_sched_scan(struct wil6210_priv *wil,
3547 			 struct cfg80211_sched_scan_request *request)
3548 {
3549 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
3550 	int rc;
3551 	struct wmi_start_sched_scan_cmd cmd = {
3552 		.min_rssi_threshold = S8_MIN,
3553 		.initial_delay_sec = cpu_to_le16(request->delay),
3554 	};
3555 	struct {
3556 		struct wmi_cmd_hdr wmi;
3557 		struct wmi_start_sched_scan_event evt;
3558 	} __packed reply = {
3559 		.evt = {.result = WMI_PNO_REJECT},
3560 	};
3561 
3562 	if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities))
3563 		return -ENOTSUPP;
3564 
3565 	if (request->min_rssi_thold >= S8_MIN &&
3566 	    request->min_rssi_thold <= S8_MAX)
3567 		cmd.min_rssi_threshold = request->min_rssi_thold;
3568 
3569 	wmi_sched_scan_set_ssids(wil, &cmd, request->ssids, request->n_ssids,
3570 				 request->match_sets, request->n_match_sets);
3571 	wmi_sched_scan_set_channels(wil, &cmd,
3572 				    request->n_channels, request->channels);
3573 	wmi_sched_scan_set_plans(wil, &cmd,
3574 				 request->scan_plans, request->n_scan_plans);
3575 
3576 	rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, vif->mid,
3577 		      &cmd, sizeof(cmd),
3578 		      WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply),
3579 		      WIL_WMI_CALL_GENERAL_TO_MS);
3580 	if (rc)
3581 		return rc;
3582 
3583 	if (reply.evt.result != WMI_PNO_SUCCESS) {
3584 		wil_err(wil, "start sched scan failed, result %d\n",
3585 			reply.evt.result);
3586 		return -EINVAL;
3587 	}
3588 
3589 	return 0;
3590 }
3591 
3592 int wmi_stop_sched_scan(struct wil6210_priv *wil)
3593 {
3594 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
3595 	int rc;
3596 	struct {
3597 		struct wmi_cmd_hdr wmi;
3598 		struct wmi_stop_sched_scan_event evt;
3599 	} __packed reply = {
3600 		.evt = {.result = WMI_PNO_REJECT},
3601 	};
3602 
3603 	if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities))
3604 		return -ENOTSUPP;
3605 
3606 	rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, vif->mid, NULL, 0,
3607 		      WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply),
3608 		      WIL_WMI_CALL_GENERAL_TO_MS);
3609 	if (rc)
3610 		return rc;
3611 
3612 	if (reply.evt.result != WMI_PNO_SUCCESS) {
3613 		wil_err(wil, "stop sched scan failed, result %d\n",
3614 			reply.evt.result);
3615 		return -EINVAL;
3616 	}
3617 
3618 	return 0;
3619 }
3620 
3621 int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len)
3622 {
3623 	size_t total;
3624 	struct wil6210_priv *wil = vif_to_wil(vif);
3625 	struct ieee80211_mgmt *mgmt_frame = (void *)buf;
3626 	struct wmi_sw_tx_req_cmd *cmd;
3627 	struct {
3628 		struct wmi_cmd_hdr wmi;
3629 		struct wmi_sw_tx_complete_event evt;
3630 	} __packed evt = {
3631 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3632 	};
3633 	int rc;
3634 
3635 	wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid);
3636 	wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
3637 			  len, true);
3638 
3639 	if (len < sizeof(struct ieee80211_hdr_3addr))
3640 		return -EINVAL;
3641 
3642 	total = sizeof(*cmd) + len;
3643 	if (total < len) {
3644 		wil_err(wil, "mgmt_tx invalid len %zu\n", len);
3645 		return -EINVAL;
3646 	}
3647 
3648 	cmd = kmalloc(total, GFP_KERNEL);
3649 	if (!cmd)
3650 		return -ENOMEM;
3651 
3652 	memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
3653 	cmd->len = cpu_to_le16(len);
3654 	memcpy(cmd->payload, buf, len);
3655 
3656 	rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total,
3657 		      WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
3658 	if (!rc && evt.evt.status != WMI_FW_STATUS_SUCCESS) {
3659 		wil_dbg_wmi(wil, "mgmt_tx failed with status %d\n",
3660 			    evt.evt.status);
3661 		rc = -EAGAIN;
3662 	}
3663 
3664 	kfree(cmd);
3665 
3666 	return rc;
3667 }
3668 
3669 int wmi_mgmt_tx_ext(struct wil6210_vif *vif, const u8 *buf, size_t len,
3670 		    u8 channel, u16 duration_ms)
3671 {
3672 	size_t total;
3673 	struct wil6210_priv *wil = vif_to_wil(vif);
3674 	struct ieee80211_mgmt *mgmt_frame = (void *)buf;
3675 	struct wmi_sw_tx_req_ext_cmd *cmd;
3676 	struct {
3677 		struct wmi_cmd_hdr wmi;
3678 		struct wmi_sw_tx_complete_event evt;
3679 	} __packed evt = {
3680 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3681 	};
3682 	int rc;
3683 
3684 	wil_dbg_wmi(wil, "mgmt_tx_ext mid %d channel %d duration %d\n",
3685 		    vif->mid, channel, duration_ms);
3686 	wil_hex_dump_wmi("mgmt_tx_ext frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
3687 			 len, true);
3688 
3689 	if (len < sizeof(struct ieee80211_hdr_3addr)) {
3690 		wil_err(wil, "short frame. len %zu\n", len);
3691 		return -EINVAL;
3692 	}
3693 
3694 	total = sizeof(*cmd) + len;
3695 	if (total < len) {
3696 		wil_err(wil, "mgmt_tx_ext invalid len %zu\n", len);
3697 		return -EINVAL;
3698 	}
3699 
3700 	cmd = kzalloc(total, GFP_KERNEL);
3701 	if (!cmd)
3702 		return -ENOMEM;
3703 
3704 	memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
3705 	cmd->len = cpu_to_le16(len);
3706 	memcpy(cmd->payload, buf, len);
3707 	cmd->channel = channel - 1;
3708 	cmd->duration_ms = cpu_to_le16(duration_ms);
3709 
3710 	rc = wmi_call(wil, WMI_SW_TX_REQ_EXT_CMDID, vif->mid, cmd, total,
3711 		      WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
3712 	if (!rc && evt.evt.status != WMI_FW_STATUS_SUCCESS) {
3713 		wil_dbg_wmi(wil, "mgmt_tx_ext failed with status %d\n",
3714 			    evt.evt.status);
3715 		rc = -EAGAIN;
3716 	}
3717 
3718 	kfree(cmd);
3719 
3720 	return rc;
3721 }
3722 
3723 int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id)
3724 {
3725 	int rc;
3726 	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
3727 	struct wil_status_ring *sring = &wil->srings[ring_id];
3728 	struct wmi_tx_status_ring_add_cmd cmd = {
3729 		.ring_cfg = {
3730 			.ring_size = cpu_to_le16(sring->size),
3731 		},
3732 		.irq_index = WIL_TX_STATUS_IRQ_IDX
3733 	};
3734 	struct {
3735 		struct wmi_cmd_hdr hdr;
3736 		struct wmi_tx_status_ring_cfg_done_event evt;
3737 	} __packed reply = {
3738 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3739 	};
3740 
3741 	cmd.ring_cfg.ring_id = ring_id;
3742 
3743 	cmd.ring_cfg.ring_mem_base = cpu_to_le64(sring->pa);
3744 	rc = wmi_call(wil, WMI_TX_STATUS_RING_ADD_CMDID, vif->mid, &cmd,
3745 		      sizeof(cmd), WMI_TX_STATUS_RING_CFG_DONE_EVENTID,
3746 		      &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
3747 	if (rc) {
3748 		wil_err(wil, "TX_STATUS_RING_ADD_CMD failed, rc %d\n", rc);
3749 		return rc;
3750 	}
3751 
3752 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3753 		wil_err(wil, "TX_STATUS_RING_ADD_CMD failed, status %d\n",
3754 			reply.evt.status);
3755 		return -EINVAL;
3756 	}
3757 
3758 	sring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
3759 
3760 	return 0;
3761 }
3762 
3763 int wil_wmi_cfg_def_rx_offload(struct wil6210_priv *wil, u16 max_rx_pl_per_desc)
3764 {
3765 	struct net_device *ndev = wil->main_ndev;
3766 	struct wil6210_vif *vif = ndev_to_vif(ndev);
3767 	int rc;
3768 	struct wmi_cfg_def_rx_offload_cmd cmd = {
3769 		.max_msdu_size = cpu_to_le16(wil_mtu2macbuf(WIL_MAX_ETH_MTU)),
3770 		.max_rx_pl_per_desc = cpu_to_le16(max_rx_pl_per_desc),
3771 		.decap_trans_type = WMI_DECAP_TYPE_802_3,
3772 		.l2_802_3_offload_ctrl = 0,
3773 		.l3_l4_ctrl = 1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS,
3774 	};
3775 	struct {
3776 		struct wmi_cmd_hdr hdr;
3777 		struct wmi_cfg_def_rx_offload_done_event evt;
3778 	} __packed reply = {
3779 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3780 	};
3781 
3782 	rc = wmi_call(wil, WMI_CFG_DEF_RX_OFFLOAD_CMDID, vif->mid, &cmd,
3783 		      sizeof(cmd), WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID, &reply,
3784 		      sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
3785 	if (rc) {
3786 		wil_err(wil, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, rc %d\n", rc);
3787 		return rc;
3788 	}
3789 
3790 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3791 		wil_err(wil, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, status %d\n",
3792 			reply.evt.status);
3793 		return -EINVAL;
3794 	}
3795 
3796 	return 0;
3797 }
3798 
3799 int wil_wmi_rx_sring_add(struct wil6210_priv *wil, u16 ring_id)
3800 {
3801 	struct net_device *ndev = wil->main_ndev;
3802 	struct wil6210_vif *vif = ndev_to_vif(ndev);
3803 	struct wil_status_ring *sring = &wil->srings[ring_id];
3804 	int rc;
3805 	struct wmi_rx_status_ring_add_cmd cmd = {
3806 		.ring_cfg = {
3807 			.ring_size = cpu_to_le16(sring->size),
3808 			.ring_id = ring_id,
3809 		},
3810 		.rx_msg_type = wil->use_compressed_rx_status ?
3811 			WMI_RX_MSG_TYPE_COMPRESSED :
3812 			WMI_RX_MSG_TYPE_EXTENDED,
3813 		.irq_index = WIL_RX_STATUS_IRQ_IDX,
3814 	};
3815 	struct {
3816 		struct wmi_cmd_hdr hdr;
3817 		struct wmi_rx_status_ring_cfg_done_event evt;
3818 	} __packed reply = {
3819 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3820 	};
3821 
3822 	cmd.ring_cfg.ring_mem_base = cpu_to_le64(sring->pa);
3823 	rc = wmi_call(wil, WMI_RX_STATUS_RING_ADD_CMDID, vif->mid, &cmd,
3824 		      sizeof(cmd), WMI_RX_STATUS_RING_CFG_DONE_EVENTID, &reply,
3825 		      sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
3826 	if (rc) {
3827 		wil_err(wil, "RX_STATUS_RING_ADD_CMD failed, rc %d\n", rc);
3828 		return rc;
3829 	}
3830 
3831 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3832 		wil_err(wil, "RX_STATUS_RING_ADD_CMD failed, status %d\n",
3833 			reply.evt.status);
3834 		return -EINVAL;
3835 	}
3836 
3837 	sring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
3838 
3839 	return 0;
3840 }
3841 
3842 int wil_wmi_rx_desc_ring_add(struct wil6210_priv *wil, int status_ring_id)
3843 {
3844 	struct net_device *ndev = wil->main_ndev;
3845 	struct wil6210_vif *vif = ndev_to_vif(ndev);
3846 	struct wil_ring *ring = &wil->ring_rx;
3847 	int rc;
3848 	struct wmi_rx_desc_ring_add_cmd cmd = {
3849 		.ring_cfg = {
3850 			.ring_size = cpu_to_le16(ring->size),
3851 			.ring_id = WIL_RX_DESC_RING_ID,
3852 		},
3853 		.status_ring_id = status_ring_id,
3854 		.irq_index = WIL_RX_STATUS_IRQ_IDX,
3855 	};
3856 	struct {
3857 		struct wmi_cmd_hdr hdr;
3858 		struct wmi_rx_desc_ring_cfg_done_event evt;
3859 	} __packed reply = {
3860 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3861 	};
3862 
3863 	cmd.ring_cfg.ring_mem_base = cpu_to_le64(ring->pa);
3864 	cmd.sw_tail_host_addr = cpu_to_le64(ring->edma_rx_swtail.pa);
3865 	rc = wmi_call(wil, WMI_RX_DESC_RING_ADD_CMDID, vif->mid, &cmd,
3866 		      sizeof(cmd), WMI_RX_DESC_RING_CFG_DONE_EVENTID, &reply,
3867 		      sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
3868 	if (rc) {
3869 		wil_err(wil, "WMI_RX_DESC_RING_ADD_CMD failed, rc %d\n", rc);
3870 		return rc;
3871 	}
3872 
3873 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3874 		wil_err(wil, "WMI_RX_DESC_RING_ADD_CMD failed, status %d\n",
3875 			reply.evt.status);
3876 		return -EINVAL;
3877 	}
3878 
3879 	ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
3880 
3881 	return 0;
3882 }
3883 
3884 int wil_wmi_tx_desc_ring_add(struct wil6210_vif *vif, int ring_id, int cid,
3885 			     int tid)
3886 {
3887 	struct wil6210_priv *wil = vif_to_wil(vif);
3888 	int sring_id = wil->tx_sring_idx; /* there is only one TX sring */
3889 	int rc;
3890 	struct wil_ring *ring = &wil->ring_tx[ring_id];
3891 	struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];
3892 	struct wmi_tx_desc_ring_add_cmd cmd = {
3893 		.ring_cfg = {
3894 			.ring_size = cpu_to_le16(ring->size),
3895 			.ring_id = ring_id,
3896 		},
3897 		.status_ring_id = sring_id,
3898 		.cid = cid,
3899 		.tid = tid,
3900 		.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
3901 		.max_msdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
3902 		.schd_params = {
3903 			.priority = cpu_to_le16(0),
3904 			.timeslot_us = cpu_to_le16(0xfff),
3905 		}
3906 	};
3907 	struct {
3908 		struct wmi_cmd_hdr hdr;
3909 		struct wmi_tx_desc_ring_cfg_done_event evt;
3910 	} __packed reply = {
3911 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3912 	};
3913 
3914 	cmd.ring_cfg.ring_mem_base = cpu_to_le64(ring->pa);
3915 	rc = wmi_call(wil, WMI_TX_DESC_RING_ADD_CMDID, vif->mid, &cmd,
3916 		      sizeof(cmd), WMI_TX_DESC_RING_CFG_DONE_EVENTID, &reply,
3917 		      sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
3918 	if (rc) {
3919 		wil_err(wil, "WMI_TX_DESC_RING_ADD_CMD failed, rc %d\n", rc);
3920 		return rc;
3921 	}
3922 
3923 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3924 		wil_err(wil, "WMI_TX_DESC_RING_ADD_CMD failed, status %d\n",
3925 			reply.evt.status);
3926 		return -EINVAL;
3927 	}
3928 
3929 	spin_lock_bh(&txdata->lock);
3930 	ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
3931 	txdata->mid = vif->mid;
3932 	txdata->enabled = 1;
3933 	spin_unlock_bh(&txdata->lock);
3934 
3935 	return 0;
3936 }
3937 
3938 int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id)
3939 {
3940 	struct wil6210_priv *wil = vif_to_wil(vif);
3941 	struct wil_ring *ring = &wil->ring_tx[ring_id];
3942 	int rc;
3943 	struct wmi_bcast_desc_ring_add_cmd cmd = {
3944 		.ring_cfg = {
3945 			.ring_size = cpu_to_le16(ring->size),
3946 			.ring_id = ring_id,
3947 		},
3948 		.max_msdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
3949 		.status_ring_id = wil->tx_sring_idx,
3950 		.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
3951 	};
3952 	struct {
3953 		struct wmi_cmd_hdr hdr;
3954 		struct wmi_rx_desc_ring_cfg_done_event evt;
3955 	} __packed reply = {
3956 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3957 	};
3958 	struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];
3959 
3960 	cmd.ring_cfg.ring_mem_base = cpu_to_le64(ring->pa);
3961 	rc = wmi_call(wil, WMI_BCAST_DESC_RING_ADD_CMDID, vif->mid, &cmd,
3962 		      sizeof(cmd), WMI_TX_DESC_RING_CFG_DONE_EVENTID, &reply,
3963 		      sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
3964 	if (rc) {
3965 		wil_err(wil, "WMI_BCAST_DESC_RING_ADD_CMD failed, rc %d\n", rc);
3966 		return rc;
3967 	}
3968 
3969 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3970 		wil_err(wil, "Broadcast Tx config failed, status %d\n",
3971 			reply.evt.status);
3972 		return -EINVAL;
3973 	}
3974 
3975 	spin_lock_bh(&txdata->lock);
3976 	ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
3977 	txdata->mid = vif->mid;
3978 	txdata->enabled = 1;
3979 	spin_unlock_bh(&txdata->lock);
3980 
3981 	return 0;
3982 }
3983 
3984 int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval)
3985 {
3986 	struct wil6210_priv *wil = vif_to_wil(vif);
3987 	struct wmi_link_stats_cmd cmd = {
3988 		.record_type_mask = cpu_to_le32(type),
3989 		.cid = cid,
3990 		.action = WMI_LINK_STATS_SNAPSHOT,
3991 		.interval_msec = cpu_to_le32(interval),
3992 	};
3993 	struct {
3994 		struct wmi_cmd_hdr wmi;
3995 		struct wmi_link_stats_config_done_event evt;
3996 	} __packed reply = {
3997 		.evt = {.status = WMI_FW_STATUS_FAILURE},
3998 	};
3999 	int rc;
4000 
4001 	rc = wmi_call(wil, WMI_LINK_STATS_CMDID, vif->mid, &cmd, sizeof(cmd),
4002 		      WMI_LINK_STATS_CONFIG_DONE_EVENTID, &reply,
4003 		      sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
4004 	if (rc) {
4005 		wil_err(wil, "WMI_LINK_STATS_CMDID failed, rc %d\n", rc);
4006 		return rc;
4007 	}
4008 
4009 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
4010 		wil_err(wil, "Link statistics config failed, status %d\n",
4011 			reply.evt.status);
4012 		return -EINVAL;
4013 	}
4014 
4015 	return 0;
4016 }
4017 
4018 int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
4019 			    s32 rssi_thold, u32 rssi_hyst)
4020 {
4021 	struct net_device *ndev = wil->main_ndev;
4022 	struct wil6210_vif *vif = ndev_to_vif(ndev);
4023 	int rc;
4024 	struct {
4025 		struct wmi_set_link_monitor_cmd cmd;
4026 		s8 rssi_thold;
4027 	} __packed cmd = {
4028 		.cmd = {
4029 			.rssi_hyst = rssi_hyst,
4030 			.rssi_thresholds_list_size = 1,
4031 		},
4032 		.rssi_thold = rssi_thold,
4033 	};
4034 	struct {
4035 		struct wmi_cmd_hdr hdr;
4036 		struct wmi_set_link_monitor_event evt;
4037 	} __packed reply = {
4038 		.evt = {.status = WMI_FW_STATUS_FAILURE},
4039 	};
4040 
4041 	if (rssi_thold > S8_MAX || rssi_thold < S8_MIN || rssi_hyst > U8_MAX)
4042 		return -EINVAL;
4043 
4044 	rc = wmi_call(wil, WMI_SET_LINK_MONITOR_CMDID, vif->mid, &cmd,
4045 		      sizeof(cmd), WMI_SET_LINK_MONITOR_EVENTID,
4046 		      &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
4047 	if (rc) {
4048 		wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, rc %d\n", rc);
4049 		return rc;
4050 	}
4051 
4052 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
4053 		wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, status %d\n",
4054 			reply.evt.status);
4055 		return -EINVAL;
4056 	}
4057 
4058 	return 0;
4059 }
4060