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