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