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