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