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