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