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