1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
4 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
7 #include <linux/moduleparam.h>
8 #include <linux/etherdevice.h>
9 #include <linux/if_arp.h>
16 /* set the default max assoc sta to max supported by driver */
17 uint max_assoc_sta
= WIL6210_MAX_CID
;
18 module_param(max_assoc_sta
, uint
, 0444);
19 MODULE_PARM_DESC(max_assoc_sta
, " Max number of stations associated to the AP");
21 int agg_wsize
; /* = 0; */
22 module_param(agg_wsize
, int, 0644);
23 MODULE_PARM_DESC(agg_wsize
, " Window size for Tx Block Ack after connect;"
24 " 0 - use default; < 0 - don't auto-establish");
26 u8 led_id
= WIL_LED_INVALID_ID
;
27 module_param(led_id
, byte
, 0444);
28 MODULE_PARM_DESC(led_id
,
29 " 60G device led enablement. Set the led ID (0-2) to enable");
31 #define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
32 #define WIL_WMI_PCP_STOP_TO_MS 5000
35 * WMI event receiving - theory of operations
37 * When firmware about to report WMI event, it fills memory area
38 * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
39 * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
41 * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the
42 * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
43 * and handles events within the @wmi_event_worker. Every event get detached
44 * from list, processed and deleted.
46 * Purpose for this mechanism is to release IRQ thread; otherwise,
47 * if WMI event handling involves another WMI command flow, this 2-nd flow
48 * won't be completed because of blocked IRQ thread.
52 * Addressing - theory of operations
54 * There are several buses present on the WIL6210 card.
55 * Same memory areas are visible at different address on
56 * the different busses. There are 3 main bus masters:
58 * - User CPU (firmware)
61 * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
62 * AHB addresses starting from 0x880000
64 * Internally, firmware uses addresses that allow faster access but
65 * are invisible from the host. To read from these addresses, alternative
66 * AHB address must be used.
70 * @sparrow_fw_mapping provides memory remapping table for sparrow
72 * array size should be in sync with the declaration in the wil6210.h
74 * Sparrow memory mapping:
75 * Linker address PCI/Host address
76 * 0x880000 .. 0xa80000 2Mb BAR0
77 * 0x800000 .. 0x808000 0x900000 .. 0x908000 32k DCCM
78 * 0x840000 .. 0x860000 0x908000 .. 0x928000 128k PERIPH
80 const struct fw_map sparrow_fw_mapping
[] = {
81 /* FW code RAM 256k */
82 {0x000000, 0x040000, 0x8c0000, "fw_code", true, true},
84 {0x800000, 0x808000, 0x900000, "fw_data", true, true},
85 /* periph data 128k */
86 {0x840000, 0x860000, 0x908000, "fw_peri", true, true},
88 {0x880000, 0x88a000, 0x880000, "rgf", true, true},
90 {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
92 {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
93 /* mac_ext_rgf 512b */
94 {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true, true},
96 {0x8c0000, 0x949000, 0x8c0000, "upper", true, true},
97 /* UCODE areas - accessible by debugfs blobs but not by
98 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
100 /* ucode code RAM 128k */
101 {0x000000, 0x020000, 0x920000, "uc_code", false, false},
102 /* ucode data RAM 16k */
103 {0x800000, 0x804000, 0x940000, "uc_data", false, false},
107 * @sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
108 * it is a bit larger to support extra features
110 const struct fw_map sparrow_d0_mac_rgf_ext
= {
111 0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true
115 * @talyn_fw_mapping provides memory remapping table for Talyn
117 * array size should be in sync with the declaration in the wil6210.h
119 * Talyn memory mapping:
120 * Linker address PCI/Host address
121 * 0x880000 .. 0xc80000 4Mb BAR0
122 * 0x800000 .. 0x820000 0xa00000 .. 0xa20000 128k DCCM
123 * 0x840000 .. 0x858000 0xa20000 .. 0xa38000 96k PERIPH
125 const struct fw_map talyn_fw_mapping
[] = {
127 {0x000000, 0x100000, 0x900000, "fw_code", true, true},
128 /* FW data RAM 128k */
129 {0x800000, 0x820000, 0xa00000, "fw_data", true, true},
130 /* periph. data RAM 96k */
131 {0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
132 /* various RGF 40k */
133 {0x880000, 0x88a000, 0x880000, "rgf", true, true},
135 {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
136 /* Pcie_ext_rgf 4k */
137 {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
138 /* mac_ext_rgf 1344b */
139 {0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true, true},
140 /* ext USER RGF 4k */
141 {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
143 {0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
144 /* DMA EXT RGF 64k */
145 {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
146 /* upper area 1536k */
147 {0x900000, 0xa80000, 0x900000, "upper", true, true},
148 /* UCODE areas - accessible by debugfs blobs but not by
149 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
151 /* ucode code RAM 256k */
152 {0x000000, 0x040000, 0xa38000, "uc_code", false, false},
153 /* ucode data RAM 32k */
154 {0x800000, 0x808000, 0xa78000, "uc_data", false, false},
158 * @talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
160 * array size should be in sync with the declaration in the wil6210.h
162 * Talyn MB memory mapping:
163 * Linker address PCI/Host address
164 * 0x880000 .. 0xc80000 4Mb BAR0
165 * 0x800000 .. 0x820000 0xa00000 .. 0xa20000 128k DCCM
166 * 0x840000 .. 0x858000 0xa20000 .. 0xa38000 96k PERIPH
168 const struct fw_map talyn_mb_fw_mapping
[] = {
169 /* FW code RAM 768k */
170 {0x000000, 0x0c0000, 0x900000, "fw_code", true, true},
171 /* FW data RAM 128k */
172 {0x800000, 0x820000, 0xa00000, "fw_data", true, true},
173 /* periph. data RAM 96k */
174 {0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
175 /* various RGF 40k */
176 {0x880000, 0x88a000, 0x880000, "rgf", true, true},
178 {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
179 /* Pcie_ext_rgf 4k */
180 {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
181 /* mac_ext_rgf 2256b */
182 {0x88c000, 0x88c8d0, 0x88c000, "mac_rgf_ext", true, true},
183 /* ext USER RGF 4k */
184 {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
186 {0x890000, 0x894000, 0x890000, "sec_pka", true, true},
187 /* SEC KDF RGF 3096b */
188 {0x898000, 0x898c18, 0x898000, "sec_kdf_rgf", true, true},
190 {0x89a000, 0x89a84c, 0x89a000, "sec_main", true, true},
192 {0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
193 /* DMA EXT RGF 64k */
194 {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
195 /* DUM USER RGF 528b */
196 {0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true, true},
198 {0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true, true},
199 /* ucode debug 256b */
200 {0x8c3000, 0x8c3100, 0x8c3000, "ucode_debug", true, true},
201 /* upper area 1536k */
202 {0x900000, 0xa80000, 0x900000, "upper", true, true},
203 /* UCODE areas - accessible by debugfs blobs but not by
204 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
206 /* ucode code RAM 256k */
207 {0x000000, 0x040000, 0xa38000, "uc_code", false, false},
208 /* ucode data RAM 32k */
209 {0x800000, 0x808000, 0xa78000, "uc_data", false, false},
212 struct fw_map fw_mapping
[MAX_FW_MAPPING_TABLE_SIZE
];
214 struct blink_on_off_time led_blink_time
[] = {
215 {WIL_LED_BLINK_ON_SLOW_MS
, WIL_LED_BLINK_OFF_SLOW_MS
},
216 {WIL_LED_BLINK_ON_MED_MS
, WIL_LED_BLINK_OFF_MED_MS
},
217 {WIL_LED_BLINK_ON_FAST_MS
, WIL_LED_BLINK_OFF_FAST_MS
},
222 __le16 auth_transaction
;
224 /* possibly followed by Challenge text */
228 u8 led_polarity
= LED_POLARITY_LOW_ACTIVE
;
231 * return AHB address for given firmware internal (linker) address
232 * @x - internal address
233 * If address have no valid AHB mapping, return 0
235 static u32
wmi_addr_remap(u32 x
)
239 for (i
= 0; i
< ARRAY_SIZE(fw_mapping
); i
++) {
240 if (fw_mapping
[i
].fw
&&
241 ((x
>= fw_mapping
[i
].from
) && (x
< fw_mapping
[i
].to
)))
242 return x
+ fw_mapping
[i
].host
- fw_mapping
[i
].from
;
249 * find fw_mapping entry by section name
250 * @section - section name
252 * Return pointer to section or NULL if not found
254 struct fw_map
*wil_find_fw_mapping(const char *section
)
258 for (i
= 0; i
< ARRAY_SIZE(fw_mapping
); i
++)
259 if (fw_mapping
[i
].name
&&
260 !strcmp(section
, fw_mapping
[i
].name
))
261 return &fw_mapping
[i
];
267 * Check address validity for WMI buffer; remap if needed
268 * @ptr - internal (linker) fw/ucode address
269 * @size - if non zero, validate the block does not
270 * exceed the device memory (bar)
272 * Valid buffer should be DWORD aligned
274 * return address for accessing buffer from the host;
275 * if buffer is not valid, return NULL.
277 void __iomem
*wmi_buffer_block(struct wil6210_priv
*wil
, __le32 ptr_
, u32 size
)
280 u32 ptr
= le32_to_cpu(ptr_
);
285 ptr
= wmi_addr_remap(ptr
);
286 if (ptr
< WIL6210_FW_HOST_OFF
)
290 if (off
> wil
->bar_size
- 4)
292 if (size
&& ((off
+ size
> wil
->bar_size
) || (off
+ size
< off
)))
295 return wil
->csr
+ off
;
298 void __iomem
*wmi_buffer(struct wil6210_priv
*wil
, __le32 ptr_
)
300 return wmi_buffer_block(wil
, ptr_
, 0);
304 * Check address validity
306 void __iomem
*wmi_addr(struct wil6210_priv
*wil
, u32 ptr
)
313 if (ptr
< WIL6210_FW_HOST_OFF
)
317 if (off
> wil
->bar_size
- 4)
320 return wil
->csr
+ off
;
323 int wmi_read_hdr(struct wil6210_priv
*wil
, __le32 ptr
,
324 struct wil6210_mbox_hdr
*hdr
)
326 void __iomem
*src
= wmi_buffer(wil
, ptr
);
331 wil_memcpy_fromio_32(hdr
, src
, sizeof(*hdr
));
336 static const char *cmdid2name(u16 cmdid
)
339 case WMI_NOTIFY_REQ_CMDID
:
340 return "WMI_NOTIFY_REQ_CMD";
341 case WMI_START_SCAN_CMDID
:
342 return "WMI_START_SCAN_CMD";
343 case WMI_CONNECT_CMDID
:
344 return "WMI_CONNECT_CMD";
345 case WMI_DISCONNECT_CMDID
:
346 return "WMI_DISCONNECT_CMD";
347 case WMI_SW_TX_REQ_CMDID
:
348 return "WMI_SW_TX_REQ_CMD";
349 case WMI_GET_RF_SECTOR_PARAMS_CMDID
:
350 return "WMI_GET_RF_SECTOR_PARAMS_CMD";
351 case WMI_SET_RF_SECTOR_PARAMS_CMDID
:
352 return "WMI_SET_RF_SECTOR_PARAMS_CMD";
353 case WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID
:
354 return "WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD";
355 case WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID
:
356 return "WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD";
357 case WMI_BRP_SET_ANT_LIMIT_CMDID
:
358 return "WMI_BRP_SET_ANT_LIMIT_CMD";
359 case WMI_TOF_SESSION_START_CMDID
:
360 return "WMI_TOF_SESSION_START_CMD";
361 case WMI_AOA_MEAS_CMDID
:
362 return "WMI_AOA_MEAS_CMD";
364 return "WMI_PMC_CMD";
365 case WMI_TOF_GET_TX_RX_OFFSET_CMDID
:
366 return "WMI_TOF_GET_TX_RX_OFFSET_CMD";
367 case WMI_TOF_SET_TX_RX_OFFSET_CMDID
:
368 return "WMI_TOF_SET_TX_RX_OFFSET_CMD";
369 case WMI_VRING_CFG_CMDID
:
370 return "WMI_VRING_CFG_CMD";
371 case WMI_BCAST_VRING_CFG_CMDID
:
372 return "WMI_BCAST_VRING_CFG_CMD";
373 case WMI_TRAFFIC_SUSPEND_CMDID
:
374 return "WMI_TRAFFIC_SUSPEND_CMD";
375 case WMI_TRAFFIC_RESUME_CMDID
:
376 return "WMI_TRAFFIC_RESUME_CMD";
378 return "WMI_ECHO_CMD";
379 case WMI_SET_MAC_ADDRESS_CMDID
:
380 return "WMI_SET_MAC_ADDRESS_CMD";
381 case WMI_LED_CFG_CMDID
:
382 return "WMI_LED_CFG_CMD";
383 case WMI_PCP_START_CMDID
:
384 return "WMI_PCP_START_CMD";
385 case WMI_PCP_STOP_CMDID
:
386 return "WMI_PCP_STOP_CMD";
387 case WMI_SET_SSID_CMDID
:
388 return "WMI_SET_SSID_CMD";
389 case WMI_GET_SSID_CMDID
:
390 return "WMI_GET_SSID_CMD";
391 case WMI_SET_PCP_CHANNEL_CMDID
:
392 return "WMI_SET_PCP_CHANNEL_CMD";
393 case WMI_GET_PCP_CHANNEL_CMDID
:
394 return "WMI_GET_PCP_CHANNEL_CMD";
395 case WMI_P2P_CFG_CMDID
:
396 return "WMI_P2P_CFG_CMD";
397 case WMI_PORT_ALLOCATE_CMDID
:
398 return "WMI_PORT_ALLOCATE_CMD";
399 case WMI_PORT_DELETE_CMDID
:
400 return "WMI_PORT_DELETE_CMD";
401 case WMI_START_LISTEN_CMDID
:
402 return "WMI_START_LISTEN_CMD";
403 case WMI_START_SEARCH_CMDID
:
404 return "WMI_START_SEARCH_CMD";
405 case WMI_DISCOVERY_STOP_CMDID
:
406 return "WMI_DISCOVERY_STOP_CMD";
407 case WMI_DELETE_CIPHER_KEY_CMDID
:
408 return "WMI_DELETE_CIPHER_KEY_CMD";
409 case WMI_ADD_CIPHER_KEY_CMDID
:
410 return "WMI_ADD_CIPHER_KEY_CMD";
411 case WMI_SET_APPIE_CMDID
:
412 return "WMI_SET_APPIE_CMD";
413 case WMI_CFG_RX_CHAIN_CMDID
:
414 return "WMI_CFG_RX_CHAIN_CMD";
415 case WMI_TEMP_SENSE_CMDID
:
416 return "WMI_TEMP_SENSE_CMD";
417 case WMI_DEL_STA_CMDID
:
418 return "WMI_DEL_STA_CMD";
419 case WMI_DISCONNECT_STA_CMDID
:
420 return "WMI_DISCONNECT_STA_CMD";
421 case WMI_RING_BA_EN_CMDID
:
422 return "WMI_RING_BA_EN_CMD";
423 case WMI_RING_BA_DIS_CMDID
:
424 return "WMI_RING_BA_DIS_CMD";
425 case WMI_RCP_DELBA_CMDID
:
426 return "WMI_RCP_DELBA_CMD";
427 case WMI_RCP_ADDBA_RESP_CMDID
:
428 return "WMI_RCP_ADDBA_RESP_CMD";
429 case WMI_RCP_ADDBA_RESP_EDMA_CMDID
:
430 return "WMI_RCP_ADDBA_RESP_EDMA_CMD";
431 case WMI_PS_DEV_PROFILE_CFG_CMDID
:
432 return "WMI_PS_DEV_PROFILE_CFG_CMD";
433 case WMI_SET_MGMT_RETRY_LIMIT_CMDID
:
434 return "WMI_SET_MGMT_RETRY_LIMIT_CMD";
435 case WMI_GET_MGMT_RETRY_LIMIT_CMDID
:
436 return "WMI_GET_MGMT_RETRY_LIMIT_CMD";
437 case WMI_ABORT_SCAN_CMDID
:
438 return "WMI_ABORT_SCAN_CMD";
439 case WMI_NEW_STA_CMDID
:
440 return "WMI_NEW_STA_CMD";
441 case WMI_SET_THERMAL_THROTTLING_CFG_CMDID
:
442 return "WMI_SET_THERMAL_THROTTLING_CFG_CMD";
443 case WMI_GET_THERMAL_THROTTLING_CFG_CMDID
:
444 return "WMI_GET_THERMAL_THROTTLING_CFG_CMD";
445 case WMI_LINK_MAINTAIN_CFG_WRITE_CMDID
:
446 return "WMI_LINK_MAINTAIN_CFG_WRITE_CMD";
447 case WMI_LO_POWER_CALIB_FROM_OTP_CMDID
:
448 return "WMI_LO_POWER_CALIB_FROM_OTP_CMD";
449 case WMI_START_SCHED_SCAN_CMDID
:
450 return "WMI_START_SCHED_SCAN_CMD";
451 case WMI_STOP_SCHED_SCAN_CMDID
:
452 return "WMI_STOP_SCHED_SCAN_CMD";
453 case WMI_TX_STATUS_RING_ADD_CMDID
:
454 return "WMI_TX_STATUS_RING_ADD_CMD";
455 case WMI_RX_STATUS_RING_ADD_CMDID
:
456 return "WMI_RX_STATUS_RING_ADD_CMD";
457 case WMI_TX_DESC_RING_ADD_CMDID
:
458 return "WMI_TX_DESC_RING_ADD_CMD";
459 case WMI_RX_DESC_RING_ADD_CMDID
:
460 return "WMI_RX_DESC_RING_ADD_CMD";
461 case WMI_BCAST_DESC_RING_ADD_CMDID
:
462 return "WMI_BCAST_DESC_RING_ADD_CMD";
463 case WMI_CFG_DEF_RX_OFFLOAD_CMDID
:
464 return "WMI_CFG_DEF_RX_OFFLOAD_CMD";
465 case WMI_LINK_STATS_CMDID
:
466 return "WMI_LINK_STATS_CMD";
467 case WMI_SW_TX_REQ_EXT_CMDID
:
468 return "WMI_SW_TX_REQ_EXT_CMDID";
469 case WMI_FT_AUTH_CMDID
:
470 return "WMI_FT_AUTH_CMD";
471 case WMI_FT_REASSOC_CMDID
:
472 return "WMI_FT_REASSOC_CMD";
473 case WMI_UPDATE_FT_IES_CMDID
:
474 return "WMI_UPDATE_FT_IES_CMD";
475 case WMI_RBUFCAP_CFG_CMDID
:
476 return "WMI_RBUFCAP_CFG_CMD";
477 case WMI_TEMP_SENSE_ALL_CMDID
:
478 return "WMI_TEMP_SENSE_ALL_CMDID";
479 case WMI_SET_LINK_MONITOR_CMDID
:
480 return "WMI_SET_LINK_MONITOR_CMD";
482 return "Untracked CMD";
486 static const char *eventid2name(u16 eventid
)
489 case WMI_NOTIFY_REQ_DONE_EVENTID
:
490 return "WMI_NOTIFY_REQ_DONE_EVENT";
491 case WMI_DISCONNECT_EVENTID
:
492 return "WMI_DISCONNECT_EVENT";
493 case WMI_SW_TX_COMPLETE_EVENTID
:
494 return "WMI_SW_TX_COMPLETE_EVENT";
495 case WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID
:
496 return "WMI_GET_RF_SECTOR_PARAMS_DONE_EVENT";
497 case WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID
:
498 return "WMI_SET_RF_SECTOR_PARAMS_DONE_EVENT";
499 case WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID
:
500 return "WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
501 case WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID
:
502 return "WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
503 case WMI_BRP_SET_ANT_LIMIT_EVENTID
:
504 return "WMI_BRP_SET_ANT_LIMIT_EVENT";
505 case WMI_FW_READY_EVENTID
:
506 return "WMI_FW_READY_EVENT";
507 case WMI_TRAFFIC_RESUME_EVENTID
:
508 return "WMI_TRAFFIC_RESUME_EVENT";
509 case WMI_TOF_GET_TX_RX_OFFSET_EVENTID
:
510 return "WMI_TOF_GET_TX_RX_OFFSET_EVENT";
511 case WMI_TOF_SET_TX_RX_OFFSET_EVENTID
:
512 return "WMI_TOF_SET_TX_RX_OFFSET_EVENT";
513 case WMI_VRING_CFG_DONE_EVENTID
:
514 return "WMI_VRING_CFG_DONE_EVENT";
515 case WMI_READY_EVENTID
:
516 return "WMI_READY_EVENT";
517 case WMI_RX_MGMT_PACKET_EVENTID
:
518 return "WMI_RX_MGMT_PACKET_EVENT";
519 case WMI_TX_MGMT_PACKET_EVENTID
:
520 return "WMI_TX_MGMT_PACKET_EVENT";
521 case WMI_SCAN_COMPLETE_EVENTID
:
522 return "WMI_SCAN_COMPLETE_EVENT";
523 case WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID
:
524 return "WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT";
525 case WMI_CONNECT_EVENTID
:
526 return "WMI_CONNECT_EVENT";
527 case WMI_EAPOL_RX_EVENTID
:
528 return "WMI_EAPOL_RX_EVENT";
529 case WMI_BA_STATUS_EVENTID
:
530 return "WMI_BA_STATUS_EVENT";
531 case WMI_RCP_ADDBA_REQ_EVENTID
:
532 return "WMI_RCP_ADDBA_REQ_EVENT";
533 case WMI_DELBA_EVENTID
:
534 return "WMI_DELBA_EVENT";
535 case WMI_RING_EN_EVENTID
:
536 return "WMI_RING_EN_EVENT";
537 case WMI_DATA_PORT_OPEN_EVENTID
:
538 return "WMI_DATA_PORT_OPEN_EVENT";
539 case WMI_AOA_MEAS_EVENTID
:
540 return "WMI_AOA_MEAS_EVENT";
541 case WMI_TOF_SESSION_END_EVENTID
:
542 return "WMI_TOF_SESSION_END_EVENT";
543 case WMI_TOF_GET_CAPABILITIES_EVENTID
:
544 return "WMI_TOF_GET_CAPABILITIES_EVENT";
545 case WMI_TOF_SET_LCR_EVENTID
:
546 return "WMI_TOF_SET_LCR_EVENT";
547 case WMI_TOF_SET_LCI_EVENTID
:
548 return "WMI_TOF_SET_LCI_EVENT";
549 case WMI_TOF_FTM_PER_DEST_RES_EVENTID
:
550 return "WMI_TOF_FTM_PER_DEST_RES_EVENT";
551 case WMI_TOF_CHANNEL_INFO_EVENTID
:
552 return "WMI_TOF_CHANNEL_INFO_EVENT";
553 case WMI_TRAFFIC_SUSPEND_EVENTID
:
554 return "WMI_TRAFFIC_SUSPEND_EVENT";
555 case WMI_ECHO_RSP_EVENTID
:
556 return "WMI_ECHO_RSP_EVENT";
557 case WMI_LED_CFG_DONE_EVENTID
:
558 return "WMI_LED_CFG_DONE_EVENT";
559 case WMI_PCP_STARTED_EVENTID
:
560 return "WMI_PCP_STARTED_EVENT";
561 case WMI_PCP_STOPPED_EVENTID
:
562 return "WMI_PCP_STOPPED_EVENT";
563 case WMI_GET_SSID_EVENTID
:
564 return "WMI_GET_SSID_EVENT";
565 case WMI_GET_PCP_CHANNEL_EVENTID
:
566 return "WMI_GET_PCP_CHANNEL_EVENT";
567 case WMI_P2P_CFG_DONE_EVENTID
:
568 return "WMI_P2P_CFG_DONE_EVENT";
569 case WMI_PORT_ALLOCATED_EVENTID
:
570 return "WMI_PORT_ALLOCATED_EVENT";
571 case WMI_PORT_DELETED_EVENTID
:
572 return "WMI_PORT_DELETED_EVENT";
573 case WMI_LISTEN_STARTED_EVENTID
:
574 return "WMI_LISTEN_STARTED_EVENT";
575 case WMI_SEARCH_STARTED_EVENTID
:
576 return "WMI_SEARCH_STARTED_EVENT";
577 case WMI_DISCOVERY_STOPPED_EVENTID
:
578 return "WMI_DISCOVERY_STOPPED_EVENT";
579 case WMI_CFG_RX_CHAIN_DONE_EVENTID
:
580 return "WMI_CFG_RX_CHAIN_DONE_EVENT";
581 case WMI_TEMP_SENSE_DONE_EVENTID
:
582 return "WMI_TEMP_SENSE_DONE_EVENT";
583 case WMI_RCP_ADDBA_RESP_SENT_EVENTID
:
584 return "WMI_RCP_ADDBA_RESP_SENT_EVENT";
585 case WMI_PS_DEV_PROFILE_CFG_EVENTID
:
586 return "WMI_PS_DEV_PROFILE_CFG_EVENT";
587 case WMI_SET_MGMT_RETRY_LIMIT_EVENTID
:
588 return "WMI_SET_MGMT_RETRY_LIMIT_EVENT";
589 case WMI_GET_MGMT_RETRY_LIMIT_EVENTID
:
590 return "WMI_GET_MGMT_RETRY_LIMIT_EVENT";
591 case WMI_SET_THERMAL_THROTTLING_CFG_EVENTID
:
592 return "WMI_SET_THERMAL_THROTTLING_CFG_EVENT";
593 case WMI_GET_THERMAL_THROTTLING_CFG_EVENTID
:
594 return "WMI_GET_THERMAL_THROTTLING_CFG_EVENT";
595 case WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID
:
596 return "WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENT";
597 case WMI_LO_POWER_CALIB_FROM_OTP_EVENTID
:
598 return "WMI_LO_POWER_CALIB_FROM_OTP_EVENT";
599 case WMI_START_SCHED_SCAN_EVENTID
:
600 return "WMI_START_SCHED_SCAN_EVENT";
601 case WMI_STOP_SCHED_SCAN_EVENTID
:
602 return "WMI_STOP_SCHED_SCAN_EVENT";
603 case WMI_SCHED_SCAN_RESULT_EVENTID
:
604 return "WMI_SCHED_SCAN_RESULT_EVENT";
605 case WMI_TX_STATUS_RING_CFG_DONE_EVENTID
:
606 return "WMI_TX_STATUS_RING_CFG_DONE_EVENT";
607 case WMI_RX_STATUS_RING_CFG_DONE_EVENTID
:
608 return "WMI_RX_STATUS_RING_CFG_DONE_EVENT";
609 case WMI_TX_DESC_RING_CFG_DONE_EVENTID
:
610 return "WMI_TX_DESC_RING_CFG_DONE_EVENT";
611 case WMI_RX_DESC_RING_CFG_DONE_EVENTID
:
612 return "WMI_RX_DESC_RING_CFG_DONE_EVENT";
613 case WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID
:
614 return "WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENT";
615 case WMI_LINK_STATS_CONFIG_DONE_EVENTID
:
616 return "WMI_LINK_STATS_CONFIG_DONE_EVENT";
617 case WMI_LINK_STATS_EVENTID
:
618 return "WMI_LINK_STATS_EVENT";
619 case WMI_COMMAND_NOT_SUPPORTED_EVENTID
:
620 return "WMI_COMMAND_NOT_SUPPORTED_EVENT";
621 case WMI_FT_AUTH_STATUS_EVENTID
:
622 return "WMI_FT_AUTH_STATUS_EVENT";
623 case WMI_FT_REASSOC_STATUS_EVENTID
:
624 return "WMI_FT_REASSOC_STATUS_EVENT";
625 case WMI_RBUFCAP_CFG_EVENTID
:
626 return "WMI_RBUFCAP_CFG_EVENT";
627 case WMI_TEMP_SENSE_ALL_DONE_EVENTID
:
628 return "WMI_TEMP_SENSE_ALL_DONE_EVENTID";
629 case WMI_SET_LINK_MONITOR_EVENTID
:
630 return "WMI_SET_LINK_MONITOR_EVENT";
631 case WMI_LINK_MONITOR_EVENTID
:
632 return "WMI_LINK_MONITOR_EVENT";
634 return "Untracked EVENT";
638 static int __wmi_send(struct wil6210_priv
*wil
, u16 cmdid
, u8 mid
,
642 struct wil6210_mbox_hdr hdr
;
643 struct wmi_cmd_hdr wmi
;
646 .type
= WIL_MBOX_HDR_TYPE_WMI
,
648 .len
= cpu_to_le16(sizeof(cmd
.wmi
) + len
),
652 .command_id
= cpu_to_le16(cmdid
),
655 struct wil6210_mbox_ring
*r
= &wil
->mbox_ctl
.tx
;
656 struct wil6210_mbox_ring_desc d_head
;
659 void __iomem
*head
= wmi_addr(wil
, r
->head
);
663 if (len
> r
->entry_size
- sizeof(cmd
)) {
664 wil_err(wil
, "WMI size too large: %d bytes, max is %d\n",
665 (int)(sizeof(cmd
) + len
), r
->entry_size
);
671 if (!test_bit(wil_status_fwready
, wil
->status
)) {
672 wil_err(wil
, "WMI: cannot send command while FW not ready\n");
676 /* Allow sending only suspend / resume commands during susepnd flow */
677 if ((test_bit(wil_status_suspending
, wil
->status
) ||
678 test_bit(wil_status_suspended
, wil
->status
) ||
679 test_bit(wil_status_resuming
, wil
->status
)) &&
680 ((cmdid
!= WMI_TRAFFIC_SUSPEND_CMDID
) &&
681 (cmdid
!= WMI_TRAFFIC_RESUME_CMDID
))) {
682 wil_err(wil
, "WMI: reject send_command during suspend\n");
687 wil_err(wil
, "WMI head is garbage: 0x%08x\n", r
->head
);
693 /* read Tx head till it is not busy */
694 for (retry
= 5; retry
> 0; retry
--) {
695 wil_memcpy_fromio_32(&d_head
, head
, sizeof(d_head
));
696 if (d_head
.sync
== 0)
700 if (d_head
.sync
!= 0) {
701 wil_err(wil
, "WMI head busy\n");
706 next_head
= r
->base
+ ((r
->head
- r
->base
+ sizeof(d_head
)) % r
->size
);
707 wil_dbg_wmi(wil
, "Head 0x%08x -> 0x%08x\n", r
->head
, next_head
);
708 /* wait till FW finish with previous command */
709 for (retry
= 5; retry
> 0; retry
--) {
710 if (!test_bit(wil_status_fwready
, wil
->status
)) {
711 wil_err(wil
, "WMI: cannot send command while FW not ready\n");
715 r
->tail
= wil_r(wil
, RGF_MBOX
+
716 offsetof(struct wil6210_mbox_ctl
, tx
.tail
));
717 if (next_head
!= r
->tail
)
721 if (next_head
== r
->tail
) {
722 wil_err(wil
, "WMI ring full\n");
726 dst
= wmi_buffer(wil
, d_head
.addr
);
728 wil_err(wil
, "invalid WMI buffer: 0x%08x\n",
729 le32_to_cpu(d_head
.addr
));
733 cmd
.hdr
.seq
= cpu_to_le16(++wil
->wmi_seq
);
735 wil_dbg_wmi(wil
, "sending %s (0x%04x) [%d] mid %d\n",
736 cmdid2name(cmdid
), cmdid
, len
, mid
);
737 wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET
, 16, 1, &cmd
,
739 wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET
, 16, 1, buf
,
741 wil_memcpy_toio_32(dst
, &cmd
, sizeof(cmd
));
742 wil_memcpy_toio_32(dst
+ sizeof(cmd
), buf
, len
);
743 /* mark entry as full */
744 wil_w(wil
, r
->head
+ offsetof(struct wil6210_mbox_ring_desc
, sync
), 1);
745 /* advance next ptr */
746 wil_w(wil
, RGF_MBOX
+ offsetof(struct wil6210_mbox_ctl
, tx
.head
),
747 r
->head
= next_head
);
749 trace_wil6210_wmi_cmd(&cmd
.wmi
, buf
, len
);
751 /* interrupt to FW */
752 wil_w(wil
, RGF_USER_USER_ICR
+ offsetof(struct RGF_ICR
, ICS
),
756 wil_halp_unvote(wil
);
760 int wmi_send(struct wil6210_priv
*wil
, u16 cmdid
, u8 mid
, void *buf
, u16 len
)
764 mutex_lock(&wil
->wmi_mutex
);
765 rc
= __wmi_send(wil
, cmdid
, mid
, buf
, len
);
766 mutex_unlock(&wil
->wmi_mutex
);
771 /*=== Event handlers ===*/
772 static void wmi_evt_ready(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
774 struct wil6210_priv
*wil
= vif_to_wil(vif
);
775 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
776 struct wmi_ready_event
*evt
= d
;
779 wil_info(wil
, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
780 wil
->fw_version
, le32_to_cpu(evt
->sw_version
),
781 evt
->mac
, evt
->numof_additional_mids
);
782 if (evt
->numof_additional_mids
+ 1 < wil
->max_vifs
) {
783 wil_err(wil
, "FW does not support enough MIDs (need %d)",
785 return; /* FW load will fail after timeout */
787 /* ignore MAC address, we already have it from the boot loader */
788 strlcpy(wiphy
->fw_version
, wil
->fw_version
, sizeof(wiphy
->fw_version
));
790 if (len
> offsetof(struct wmi_ready_event
, rfc_read_calib_result
)) {
791 wil_dbg_wmi(wil
, "rfc calibration result %d\n",
792 evt
->rfc_read_calib_result
);
793 wil
->fw_calib_result
= evt
->rfc_read_calib_result
;
796 fw_max_assoc_sta
= WIL6210_RX_DESC_MAX_CID
;
797 if (len
> offsetof(struct wmi_ready_event
, max_assoc_sta
) &&
798 evt
->max_assoc_sta
> 0) {
799 fw_max_assoc_sta
= evt
->max_assoc_sta
;
800 wil_dbg_wmi(wil
, "fw reported max assoc sta %d\n",
803 if (fw_max_assoc_sta
> WIL6210_MAX_CID
) {
805 "fw max assoc sta %d exceeds max driver supported %d\n",
806 fw_max_assoc_sta
, WIL6210_MAX_CID
);
807 fw_max_assoc_sta
= WIL6210_MAX_CID
;
811 wil
->max_assoc_sta
= min_t(uint
, max_assoc_sta
, fw_max_assoc_sta
);
812 wil_dbg_wmi(wil
, "setting max assoc sta to %d\n", wil
->max_assoc_sta
);
814 wil_set_recovery_state(wil
, fw_recovery_idle
);
815 set_bit(wil_status_fwready
, wil
->status
);
816 /* let the reset sequence continue */
817 complete(&wil
->wmi_ready
);
820 static void wmi_evt_rx_mgmt(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
822 struct wil6210_priv
*wil
= vif_to_wil(vif
);
823 struct wmi_rx_mgmt_packet_event
*data
= d
;
824 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
825 struct ieee80211_mgmt
*rx_mgmt_frame
=
826 (struct ieee80211_mgmt
*)data
->payload
;
827 int flen
= len
- offsetof(struct wmi_rx_mgmt_packet_event
, payload
);
830 struct ieee80211_channel
*channel
;
837 wil_err(wil
, "MGMT Rx: short event, len %d\n", len
);
841 d_len
= le32_to_cpu(data
->info
.len
);
844 "MGMT Rx: length mismatch, d_len %d should be %d\n",
849 ch_no
= data
->info
.channel
+ 1;
850 freq
= ieee80211_channel_to_frequency(ch_no
, NL80211_BAND_60GHZ
);
851 channel
= ieee80211_get_channel(wiphy
, freq
);
852 if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING
, wil
->fw_capabilities
))
853 signal
= 100 * data
->info
.rssi
;
855 signal
= data
->info
.sqi
;
856 d_status
= le16_to_cpu(data
->info
.status
);
857 fc
= rx_mgmt_frame
->frame_control
;
859 wil_dbg_wmi(wil
, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n",
860 data
->info
.channel
, data
->info
.mcs
, data
->info
.rssi
,
862 wil_dbg_wmi(wil
, "status 0x%04x len %d fc 0x%04x\n", d_status
, d_len
,
864 wil_dbg_wmi(wil
, "qid %d mid %d cid %d\n",
865 data
->info
.qid
, data
->info
.mid
, data
->info
.cid
);
866 wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET
, 16, 1, rx_mgmt_frame
,
870 wil_err(wil
, "Frame on unsupported channel\n");
874 if (ieee80211_is_beacon(fc
) || ieee80211_is_probe_resp(fc
)) {
875 struct cfg80211_bss
*bss
;
876 struct cfg80211_inform_bss bss_data
= {
878 .scan_width
= NL80211_BSS_CHAN_WIDTH_20
,
880 .boottime_ns
= ktime_to_ns(ktime_get_boottime()),
882 u64 tsf
= le64_to_cpu(rx_mgmt_frame
->u
.beacon
.timestamp
);
883 u16 cap
= le16_to_cpu(rx_mgmt_frame
->u
.beacon
.capab_info
);
884 u16 bi
= le16_to_cpu(rx_mgmt_frame
->u
.beacon
.beacon_int
);
885 const u8
*ie_buf
= rx_mgmt_frame
->u
.beacon
.variable
;
886 size_t ie_len
= d_len
- offsetof(struct ieee80211_mgmt
,
888 wil_dbg_wmi(wil
, "Capability info : 0x%04x\n", cap
);
889 wil_dbg_wmi(wil
, "TSF : 0x%016llx\n", tsf
);
890 wil_dbg_wmi(wil
, "Beacon interval : %d\n", bi
);
891 wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET
, 16, 1, ie_buf
,
894 wil_dbg_wmi(wil
, "Capability info : 0x%04x\n", cap
);
896 bss
= cfg80211_inform_bss_frame_data(wiphy
, &bss_data
,
900 wil_dbg_wmi(wil
, "Added BSS %pM\n",
901 rx_mgmt_frame
->bssid
);
902 cfg80211_put_bss(wiphy
, bss
);
904 wil_err(wil
, "cfg80211_inform_bss_frame() failed\n");
907 mutex_lock(&wil
->vif_mutex
);
908 cfg80211_rx_mgmt(vif_to_radio_wdev(wil
, vif
), freq
, signal
,
909 (void *)rx_mgmt_frame
, d_len
, 0);
910 mutex_unlock(&wil
->vif_mutex
);
914 static void wmi_evt_tx_mgmt(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
916 struct wmi_tx_mgmt_packet_event
*data
= d
;
917 struct ieee80211_mgmt
*mgmt_frame
=
918 (struct ieee80211_mgmt
*)data
->payload
;
919 int flen
= len
- offsetof(struct wmi_tx_mgmt_packet_event
, payload
);
921 wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET
, 16, 1, mgmt_frame
,
925 static void wmi_evt_scan_complete(struct wil6210_vif
*vif
, int id
,
928 struct wil6210_priv
*wil
= vif_to_wil(vif
);
930 mutex_lock(&wil
->vif_mutex
);
931 if (vif
->scan_request
) {
932 struct wmi_scan_complete_event
*data
= d
;
933 int status
= le32_to_cpu(data
->status
);
934 struct cfg80211_scan_info info
= {
935 .aborted
= ((status
!= WMI_SCAN_SUCCESS
) &&
936 (status
!= WMI_SCAN_ABORT_REJECTED
)),
939 wil_dbg_wmi(wil
, "SCAN_COMPLETE(0x%08x)\n", status
);
940 wil_dbg_misc(wil
, "Complete scan_request 0x%p aborted %d\n",
941 vif
->scan_request
, info
.aborted
);
942 del_timer_sync(&vif
->scan_timer
);
943 cfg80211_scan_done(vif
->scan_request
, &info
);
945 wil
->radio_wdev
= wil
->main_ndev
->ieee80211_ptr
;
946 vif
->scan_request
= NULL
;
947 wake_up_interruptible(&wil
->wq
);
948 if (vif
->p2p
.pending_listen_wdev
) {
949 wil_dbg_misc(wil
, "Scheduling delayed listen\n");
950 schedule_work(&vif
->p2p
.delayed_listen_work
);
953 wil_err(wil
, "SCAN_COMPLETE while not scanning\n");
955 mutex_unlock(&wil
->vif_mutex
);
958 static void wmi_evt_connect(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
960 struct wil6210_priv
*wil
= vif_to_wil(vif
);
961 struct net_device
*ndev
= vif_to_ndev(vif
);
962 struct wireless_dev
*wdev
= vif_to_wdev(vif
);
963 struct wmi_connect_event
*evt
= d
;
964 int ch
; /* channel number */
965 struct station_info
*sinfo
;
966 u8
*assoc_req_ie
, *assoc_resp_ie
;
967 size_t assoc_req_ielen
, assoc_resp_ielen
;
968 /* capinfo(u16) + listen_interval(u16) + IEs */
969 const size_t assoc_req_ie_offset
= sizeof(u16
) * 2;
970 /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
971 const size_t assoc_resp_ie_offset
= sizeof(u16
) * 3;
974 if (len
< sizeof(*evt
)) {
975 wil_err(wil
, "Connect event too short : %d bytes\n", len
);
978 if (len
!= sizeof(*evt
) + evt
->beacon_ie_len
+ evt
->assoc_req_len
+
979 evt
->assoc_resp_len
) {
981 "Connect event corrupted : %d != %d + %d + %d + %d\n",
982 len
, (int)sizeof(*evt
), evt
->beacon_ie_len
,
983 evt
->assoc_req_len
, evt
->assoc_resp_len
);
986 if (evt
->cid
>= wil
->max_assoc_sta
) {
987 wil_err(wil
, "Connect CID invalid : %d\n", evt
->cid
);
991 ch
= evt
->channel
+ 1;
992 wil_info(wil
, "Connect %pM channel [%d] cid %d aid %d\n",
993 evt
->bssid
, ch
, evt
->cid
, evt
->aid
);
994 wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET
, 16, 1,
995 evt
->assoc_info
, len
- sizeof(*evt
), true);
997 /* figure out IE's */
998 assoc_req_ie
= &evt
->assoc_info
[evt
->beacon_ie_len
+
999 assoc_req_ie_offset
];
1000 assoc_req_ielen
= evt
->assoc_req_len
- assoc_req_ie_offset
;
1001 if (evt
->assoc_req_len
<= assoc_req_ie_offset
) {
1002 assoc_req_ie
= NULL
;
1003 assoc_req_ielen
= 0;
1006 assoc_resp_ie
= &evt
->assoc_info
[evt
->beacon_ie_len
+
1007 evt
->assoc_req_len
+
1008 assoc_resp_ie_offset
];
1009 assoc_resp_ielen
= evt
->assoc_resp_len
- assoc_resp_ie_offset
;
1010 if (evt
->assoc_resp_len
<= assoc_resp_ie_offset
) {
1011 assoc_resp_ie
= NULL
;
1012 assoc_resp_ielen
= 0;
1015 if (test_bit(wil_status_resetting
, wil
->status
) ||
1016 !test_bit(wil_status_fwready
, wil
->status
)) {
1017 wil_err(wil
, "status_resetting, cancel connect event, CID %d\n",
1019 /* no need for cleanup, wil_reset will do that */
1023 mutex_lock(&wil
->mutex
);
1025 if ((wdev
->iftype
== NL80211_IFTYPE_STATION
) ||
1026 (wdev
->iftype
== NL80211_IFTYPE_P2P_CLIENT
)) {
1027 if (!test_bit(wil_vif_fwconnecting
, vif
->status
)) {
1028 wil_err(wil
, "Not in connecting state\n");
1029 mutex_unlock(&wil
->mutex
);
1032 del_timer_sync(&vif
->connect_timer
);
1033 } else if ((wdev
->iftype
== NL80211_IFTYPE_AP
) ||
1034 (wdev
->iftype
== NL80211_IFTYPE_P2P_GO
)) {
1035 if (wil
->sta
[evt
->cid
].status
!= wil_sta_unused
) {
1036 wil_err(wil
, "AP: Invalid status %d for CID %d\n",
1037 wil
->sta
[evt
->cid
].status
, evt
->cid
);
1038 mutex_unlock(&wil
->mutex
);
1043 ether_addr_copy(wil
->sta
[evt
->cid
].addr
, evt
->bssid
);
1044 wil
->sta
[evt
->cid
].mid
= vif
->mid
;
1045 wil
->sta
[evt
->cid
].status
= wil_sta_conn_pending
;
1047 rc
= wil_ring_init_tx(vif
, evt
->cid
);
1049 wil_err(wil
, "config tx vring failed for CID %d, rc (%d)\n",
1051 wmi_disconnect_sta(vif
, wil
->sta
[evt
->cid
].addr
,
1052 WLAN_REASON_UNSPECIFIED
, false);
1054 wil_info(wil
, "successful connection to CID %d\n", evt
->cid
);
1057 if ((wdev
->iftype
== NL80211_IFTYPE_STATION
) ||
1058 (wdev
->iftype
== NL80211_IFTYPE_P2P_CLIENT
)) {
1060 netif_carrier_off(ndev
);
1061 wil6210_bus_request(wil
, WIL_DEFAULT_BUS_REQUEST_KBPS
);
1062 wil_err(wil
, "cfg80211_connect_result with failure\n");
1063 cfg80211_connect_result(ndev
, evt
->bssid
, NULL
, 0,
1065 WLAN_STATUS_UNSPECIFIED_FAILURE
,
1069 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
1071 cfg80211_ref_bss(wiphy
, vif
->bss
);
1072 cfg80211_connect_bss(ndev
, evt
->bssid
, vif
->bss
,
1073 assoc_req_ie
, assoc_req_ielen
,
1074 assoc_resp_ie
, assoc_resp_ielen
,
1075 WLAN_STATUS_SUCCESS
, GFP_KERNEL
,
1076 NL80211_TIMEOUT_UNSPECIFIED
);
1079 } else if ((wdev
->iftype
== NL80211_IFTYPE_AP
) ||
1080 (wdev
->iftype
== NL80211_IFTYPE_P2P_GO
)) {
1084 /* notify new_sta has failed */
1085 cfg80211_del_sta(ndev
, evt
->bssid
, GFP_KERNEL
);
1089 sinfo
= kzalloc(sizeof(*sinfo
), GFP_KERNEL
);
1095 sinfo
->generation
= wil
->sinfo_gen
++;
1098 sinfo
->assoc_req_ies
= assoc_req_ie
;
1099 sinfo
->assoc_req_ies_len
= assoc_req_ielen
;
1102 cfg80211_new_sta(ndev
, evt
->bssid
, sinfo
, GFP_KERNEL
);
1106 wil_err(wil
, "unhandled iftype %d for CID %d\n", wdev
->iftype
,
1111 wil
->sta
[evt
->cid
].status
= wil_sta_connected
;
1112 wil
->sta
[evt
->cid
].aid
= evt
->aid
;
1113 if (!test_and_set_bit(wil_vif_fwconnected
, vif
->status
))
1114 atomic_inc(&wil
->connected_vifs
);
1115 wil_update_net_queues_bh(wil
, vif
, NULL
, false);
1119 wil
->sta
[evt
->cid
].status
= wil_sta_unused
;
1120 wil
->sta
[evt
->cid
].mid
= U8_MAX
;
1122 clear_bit(wil_vif_fwconnecting
, vif
->status
);
1123 mutex_unlock(&wil
->mutex
);
1126 static void wmi_evt_disconnect(struct wil6210_vif
*vif
, int id
,
1129 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1130 struct wmi_disconnect_event
*evt
= d
;
1131 u16 reason_code
= le16_to_cpu(evt
->protocol_reason_status
);
1133 wil_info(wil
, "Disconnect %pM reason [proto %d wmi %d]\n",
1134 evt
->bssid
, reason_code
, evt
->disconnect_reason
);
1138 if (test_bit(wil_status_resetting
, wil
->status
) ||
1139 !test_bit(wil_status_fwready
, wil
->status
)) {
1140 wil_err(wil
, "status_resetting, cancel disconnect event\n");
1141 /* no need for cleanup, wil_reset will do that */
1145 mutex_lock(&wil
->mutex
);
1146 wil6210_disconnect_complete(vif
, evt
->bssid
, reason_code
);
1147 if (disable_ap_sme
) {
1148 struct wireless_dev
*wdev
= vif_to_wdev(vif
);
1149 struct net_device
*ndev
= vif_to_ndev(vif
);
1151 /* disconnect event in disable_ap_sme mode means link loss */
1152 switch (wdev
->iftype
) {
1153 /* AP-like interface */
1154 case NL80211_IFTYPE_AP
:
1155 case NL80211_IFTYPE_P2P_GO
:
1156 /* notify hostapd about link loss */
1157 cfg80211_cqm_pktloss_notify(ndev
, evt
->bssid
, 0,
1164 mutex_unlock(&wil
->mutex
);
1168 * Firmware reports EAPOL frame using WME event.
1169 * Reconstruct Ethernet frame and deliver it via normal Rx
1171 static void wmi_evt_eapol_rx(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1173 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1174 struct net_device
*ndev
= vif_to_ndev(vif
);
1175 struct wmi_eapol_rx_event
*evt
= d
;
1176 u16 eapol_len
= le16_to_cpu(evt
->eapol_len
);
1177 int sz
= eapol_len
+ ETH_HLEN
;
1178 struct sk_buff
*skb
;
1181 struct wil_net_stats
*stats
= NULL
;
1183 wil_dbg_wmi(wil
, "EAPOL len %d from %pM MID %d\n", eapol_len
,
1184 evt
->src_mac
, vif
->mid
);
1186 cid
= wil_find_cid(wil
, vif
->mid
, evt
->src_mac
);
1188 stats
= &wil
->sta
[cid
].stats
;
1190 if (eapol_len
> 196) { /* TODO: revisit size limit */
1191 wil_err(wil
, "EAPOL too large\n");
1195 skb
= alloc_skb(sz
, GFP_KERNEL
);
1197 wil_err(wil
, "Failed to allocate skb\n");
1201 eth
= skb_put(skb
, ETH_HLEN
);
1202 ether_addr_copy(eth
->h_dest
, ndev
->dev_addr
);
1203 ether_addr_copy(eth
->h_source
, evt
->src_mac
);
1204 eth
->h_proto
= cpu_to_be16(ETH_P_PAE
);
1205 skb_put_data(skb
, evt
->eapol
, eapol_len
);
1206 skb
->protocol
= eth_type_trans(skb
, ndev
);
1207 if (likely(netif_rx_ni(skb
) == NET_RX_SUCCESS
)) {
1208 ndev
->stats
.rx_packets
++;
1209 ndev
->stats
.rx_bytes
+= sz
;
1211 stats
->rx_packets
++;
1212 stats
->rx_bytes
+= sz
;
1215 ndev
->stats
.rx_dropped
++;
1217 stats
->rx_dropped
++;
1221 static void wmi_evt_ring_en(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1223 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1224 struct wmi_ring_en_event
*evt
= d
;
1225 u8 vri
= evt
->ring_index
;
1226 struct wireless_dev
*wdev
= vif_to_wdev(vif
);
1227 struct wil_sta_info
*sta
;
1229 struct key_params params
;
1231 wil_dbg_wmi(wil
, "Enable vring %d MID %d\n", vri
, vif
->mid
);
1233 if (vri
>= ARRAY_SIZE(wil
->ring_tx
)) {
1234 wil_err(wil
, "Enable for invalid vring %d\n", vri
);
1238 if (wdev
->iftype
!= NL80211_IFTYPE_AP
|| !disable_ap_sme
||
1239 test_bit(wil_vif_ft_roam
, vif
->status
))
1240 /* in AP mode with disable_ap_sme that is not FT,
1241 * this is done by wil_cfg80211_change_station()
1243 wil
->ring_tx_data
[vri
].dot1x_open
= true;
1244 if (vri
== vif
->bcast_ring
) /* no BA for bcast */
1247 cid
= wil
->ring2cid_tid
[vri
][0];
1248 if (!wil_cid_valid(wil
, cid
)) {
1249 wil_err(wil
, "invalid cid %d for vring %d\n", cid
, vri
);
1253 /* In FT mode we get key but not store it as it is received
1254 * before WMI_CONNECT_EVENT received from FW.
1255 * wil_set_crypto_rx is called here to reset the security PN
1257 sta
= &wil
->sta
[cid
];
1258 if (test_bit(wil_vif_ft_roam
, vif
->status
)) {
1259 memset(¶ms
, 0, sizeof(params
));
1260 wil_set_crypto_rx(0, WMI_KEY_USE_PAIRWISE
, sta
, ¶ms
);
1261 if (wdev
->iftype
!= NL80211_IFTYPE_AP
)
1262 clear_bit(wil_vif_ft_roam
, vif
->status
);
1266 wil_addba_tx_request(wil
, vri
, agg_wsize
);
1269 static void wmi_evt_ba_status(struct wil6210_vif
*vif
, int id
,
1272 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1273 struct wmi_ba_status_event
*evt
= d
;
1274 struct wil_ring_tx_data
*txdata
;
1276 wil_dbg_wmi(wil
, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
1278 evt
->status
== WMI_BA_AGREED
? "OK" : "N/A",
1279 evt
->agg_wsize
, __le16_to_cpu(evt
->ba_timeout
),
1280 evt
->amsdu
? "+" : "-");
1282 if (evt
->ringid
>= WIL6210_MAX_TX_RINGS
) {
1283 wil_err(wil
, "invalid ring id %d\n", evt
->ringid
);
1287 if (evt
->status
!= WMI_BA_AGREED
) {
1288 evt
->ba_timeout
= 0;
1293 txdata
= &wil
->ring_tx_data
[evt
->ringid
];
1295 txdata
->agg_timeout
= le16_to_cpu(evt
->ba_timeout
);
1296 txdata
->agg_wsize
= evt
->agg_wsize
;
1297 txdata
->agg_amsdu
= evt
->amsdu
;
1298 txdata
->addba_in_progress
= false;
1301 static void wmi_evt_addba_rx_req(struct wil6210_vif
*vif
, int id
,
1304 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1306 struct wmi_rcp_addba_req_event
*evt
= d
;
1308 if (evt
->cidxtid
!= CIDXTID_EXTENDED_CID_TID
) {
1309 parse_cidxtid(evt
->cidxtid
, &cid
, &tid
);
1314 wil_addba_rx_request(wil
, vif
->mid
, cid
, tid
, evt
->dialog_token
,
1315 evt
->ba_param_set
, evt
->ba_timeout
,
1319 static void wmi_evt_delba(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1320 __acquires(&sta
->tid_rx_lock
) __releases(&sta
->tid_rx_lock
)
1322 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1323 struct wmi_delba_event
*evt
= d
;
1325 u16 reason
= __le16_to_cpu(evt
->reason
);
1326 struct wil_sta_info
*sta
;
1327 struct wil_tid_ampdu_rx
*r
;
1331 if (evt
->cidxtid
!= CIDXTID_EXTENDED_CID_TID
) {
1332 parse_cidxtid(evt
->cidxtid
, &cid
, &tid
);
1338 if (!wil_cid_valid(wil
, cid
)) {
1339 wil_err(wil
, "DELBA: Invalid CID %d\n", cid
);
1343 wil_dbg_wmi(wil
, "DELBA MID %d CID %d TID %d from %s reason %d\n",
1345 evt
->from_initiator
? "originator" : "recipient",
1347 if (!evt
->from_initiator
) {
1349 /* find Tx vring it belongs to */
1350 for (i
= 0; i
< ARRAY_SIZE(wil
->ring2cid_tid
); i
++) {
1351 if (wil
->ring2cid_tid
[i
][0] == cid
&&
1352 wil
->ring2cid_tid
[i
][1] == tid
) {
1353 struct wil_ring_tx_data
*txdata
=
1354 &wil
->ring_tx_data
[i
];
1356 wil_dbg_wmi(wil
, "DELBA Tx vring %d\n", i
);
1357 txdata
->agg_timeout
= 0;
1358 txdata
->agg_wsize
= 0;
1359 txdata
->addba_in_progress
= false;
1361 break; /* max. 1 matching ring */
1364 if (i
>= ARRAY_SIZE(wil
->ring2cid_tid
))
1365 wil_err(wil
, "DELBA: unable to find Tx vring\n");
1369 sta
= &wil
->sta
[cid
];
1371 spin_lock_bh(&sta
->tid_rx_lock
);
1373 r
= sta
->tid_rx
[tid
];
1374 sta
->tid_rx
[tid
] = NULL
;
1375 wil_tid_ampdu_rx_free(wil
, r
);
1377 spin_unlock_bh(&sta
->tid_rx_lock
);
1381 wmi_evt_sched_scan_result(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1383 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1384 struct wmi_sched_scan_result_event
*data
= d
;
1385 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
1386 struct ieee80211_mgmt
*rx_mgmt_frame
=
1387 (struct ieee80211_mgmt
*)data
->payload
;
1388 int flen
= len
- offsetof(struct wmi_sched_scan_result_event
, payload
);
1391 struct ieee80211_channel
*channel
;
1395 struct cfg80211_bss
*bss
;
1396 struct cfg80211_inform_bss bss_data
= {
1397 .scan_width
= NL80211_BSS_CHAN_WIDTH_20
,
1398 .boottime_ns
= ktime_to_ns(ktime_get_boottime()),
1402 wil_err(wil
, "sched scan result event too short, len %d\n",
1407 d_len
= le32_to_cpu(data
->info
.len
);
1408 if (d_len
!= flen
) {
1410 "sched scan result length mismatch, d_len %d should be %d\n",
1415 fc
= rx_mgmt_frame
->frame_control
;
1416 if (!ieee80211_is_probe_resp(fc
)) {
1417 wil_err(wil
, "sched scan result invalid frame, fc 0x%04x\n",
1422 ch_no
= data
->info
.channel
+ 1;
1423 freq
= ieee80211_channel_to_frequency(ch_no
, NL80211_BAND_60GHZ
);
1424 channel
= ieee80211_get_channel(wiphy
, freq
);
1425 if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING
, wil
->fw_capabilities
))
1426 signal
= 100 * data
->info
.rssi
;
1428 signal
= data
->info
.sqi
;
1430 wil_dbg_wmi(wil
, "sched scan result: channel %d MCS %d RSSI %d\n",
1431 data
->info
.channel
, data
->info
.mcs
, data
->info
.rssi
);
1432 wil_dbg_wmi(wil
, "len %d qid %d mid %d cid %d\n",
1433 d_len
, data
->info
.qid
, data
->info
.mid
, data
->info
.cid
);
1434 wil_hex_dump_wmi("PROBE ", DUMP_PREFIX_OFFSET
, 16, 1, rx_mgmt_frame
,
1438 wil_err(wil
, "Frame on unsupported channel\n");
1442 bss_data
.signal
= signal
;
1443 bss_data
.chan
= channel
;
1444 bss
= cfg80211_inform_bss_frame_data(wiphy
, &bss_data
, rx_mgmt_frame
,
1447 wil_dbg_wmi(wil
, "Added BSS %pM\n", rx_mgmt_frame
->bssid
);
1448 cfg80211_put_bss(wiphy
, bss
);
1450 wil_err(wil
, "cfg80211_inform_bss_frame() failed\n");
1453 cfg80211_sched_scan_results(wiphy
, 0);
1456 static void wil_link_stats_store_basic(struct wil6210_vif
*vif
,
1457 struct wmi_link_stats_basic
*basic
)
1459 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1460 u8 cid
= basic
->cid
;
1461 struct wil_sta_info
*sta
;
1463 if (cid
< 0 || cid
>= wil
->max_assoc_sta
) {
1464 wil_err(wil
, "invalid cid %d\n", cid
);
1468 sta
= &wil
->sta
[cid
];
1469 sta
->fw_stats_basic
= *basic
;
1472 static void wil_link_stats_store_global(struct wil6210_vif
*vif
,
1473 struct wmi_link_stats_global
*global
)
1475 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1477 wil
->fw_stats_global
.stats
= *global
;
1480 static void wmi_link_stats_parse(struct wil6210_vif
*vif
, u64 tsf
,
1481 bool has_next
, void *payload
,
1482 size_t payload_size
)
1484 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1485 size_t hdr_size
= sizeof(struct wmi_link_stats_record
);
1486 size_t stats_size
, record_size
, expected_size
;
1487 struct wmi_link_stats_record
*hdr
;
1489 if (payload_size
< hdr_size
) {
1490 wil_err(wil
, "link stats wrong event size %zu\n", payload_size
);
1494 while (payload_size
>= hdr_size
) {
1496 stats_size
= le16_to_cpu(hdr
->record_size
);
1497 record_size
= hdr_size
+ stats_size
;
1499 if (payload_size
< record_size
) {
1500 wil_err(wil
, "link stats payload ended unexpectedly, size %zu < %zu\n",
1501 payload_size
, record_size
);
1505 switch (hdr
->record_type_id
) {
1506 case WMI_LINK_STATS_TYPE_BASIC
:
1507 expected_size
= sizeof(struct wmi_link_stats_basic
);
1508 if (stats_size
< expected_size
) {
1509 wil_err(wil
, "link stats invalid basic record size %zu < %zu\n",
1510 stats_size
, expected_size
);
1513 if (vif
->fw_stats_ready
) {
1514 /* clean old statistics */
1515 vif
->fw_stats_tsf
= 0;
1516 vif
->fw_stats_ready
= false;
1519 wil_link_stats_store_basic(vif
, payload
+ hdr_size
);
1522 vif
->fw_stats_tsf
= tsf
;
1523 vif
->fw_stats_ready
= true;
1527 case WMI_LINK_STATS_TYPE_GLOBAL
:
1528 expected_size
= sizeof(struct wmi_link_stats_global
);
1529 if (stats_size
< sizeof(struct wmi_link_stats_global
)) {
1530 wil_err(wil
, "link stats invalid global record size %zu < %zu\n",
1531 stats_size
, expected_size
);
1535 if (wil
->fw_stats_global
.ready
) {
1536 /* clean old statistics */
1537 wil
->fw_stats_global
.tsf
= 0;
1538 wil
->fw_stats_global
.ready
= false;
1541 wil_link_stats_store_global(vif
, payload
+ hdr_size
);
1544 wil
->fw_stats_global
.tsf
= tsf
;
1545 wil
->fw_stats_global
.ready
= true;
1553 /* skip to next record */
1554 payload
+= record_size
;
1555 payload_size
-= record_size
;
1560 wmi_evt_link_stats(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1562 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1563 struct wmi_link_stats_event
*evt
= d
;
1564 size_t payload_size
;
1566 if (len
< offsetof(struct wmi_link_stats_event
, payload
)) {
1567 wil_err(wil
, "stats event way too short %d\n", len
);
1570 payload_size
= le16_to_cpu(evt
->payload_size
);
1571 if (len
< sizeof(struct wmi_link_stats_event
) + payload_size
) {
1572 wil_err(wil
, "stats event too short %d\n", len
);
1576 wmi_link_stats_parse(vif
, le64_to_cpu(evt
->tsf
), evt
->has_next
,
1577 evt
->payload
, payload_size
);
1581 * find cid and ringid for the station vif
1583 * return error, if other interfaces are used or ring was not found
1585 static int wil_find_cid_ringid_sta(struct wil6210_priv
*wil
,
1586 struct wil6210_vif
*vif
,
1590 struct wil_ring
*ring
;
1591 struct wil_ring_tx_data
*txdata
;
1592 int min_ring_id
= wil_get_min_tx_ring_id(wil
);
1596 if (!(vif
->wdev
.iftype
== NL80211_IFTYPE_STATION
||
1597 vif
->wdev
.iftype
== NL80211_IFTYPE_P2P_CLIENT
)) {
1598 wil_err(wil
, "invalid interface type %d\n", vif
->wdev
.iftype
);
1602 /* In the STA mode, it is expected to have only one ring
1603 * for the AP we are connected to.
1604 * find it and return the cid associated with it.
1606 for (i
= min_ring_id
; i
< WIL6210_MAX_TX_RINGS
; i
++) {
1607 ring
= &wil
->ring_tx
[i
];
1608 txdata
= &wil
->ring_tx_data
[i
];
1609 if (!ring
->va
|| !txdata
->enabled
|| txdata
->mid
!= vif
->mid
)
1612 lcid
= wil
->ring2cid_tid
[i
][0];
1613 if (lcid
>= wil
->max_assoc_sta
) /* skip BCAST */
1616 wil_dbg_wmi(wil
, "find sta -> ringid %d cid %d\n", i
, lcid
);
1622 wil_dbg_wmi(wil
, "find sta cid while no rings active?\n");
1628 wmi_evt_auth_status(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1630 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1631 struct net_device
*ndev
= vif_to_ndev(vif
);
1632 struct wmi_ft_auth_status_event
*data
= d
;
1633 int ie_len
= len
- offsetof(struct wmi_ft_auth_status_event
, ie_info
);
1634 int rc
, cid
= 0, ringid
= 0;
1635 struct cfg80211_ft_event_params ft
;
1637 /* auth_alg(u16) + auth_transaction(u16) + status_code(u16) */
1638 const size_t auth_ie_offset
= sizeof(u16
) * 3;
1639 struct auth_no_hdr
*auth
= (struct auth_no_hdr
*)data
->ie_info
;
1641 /* check the status */
1642 if (ie_len
>= 0 && data
->status
!= WMI_FW_STATUS_SUCCESS
) {
1643 wil_err(wil
, "FT: auth failed. status %d\n", data
->status
);
1647 if (ie_len
< auth_ie_offset
) {
1648 wil_err(wil
, "FT: auth event too short, len %d\n", len
);
1652 d_len
= le16_to_cpu(data
->ie_len
);
1653 if (d_len
!= ie_len
) {
1655 "FT: auth ie length mismatch, d_len %d should be %d\n",
1660 if (!test_bit(wil_vif_ft_roam
, wil
->status
)) {
1661 wil_err(wil
, "FT: Not in roaming state\n");
1665 if (le16_to_cpu(auth
->auth_transaction
) != 2) {
1666 wil_err(wil
, "FT: auth error. auth_transaction %d\n",
1667 le16_to_cpu(auth
->auth_transaction
));
1671 if (le16_to_cpu(auth
->auth_alg
) != WLAN_AUTH_FT
) {
1672 wil_err(wil
, "FT: auth error. auth_alg %d\n",
1673 le16_to_cpu(auth
->auth_alg
));
1677 wil_dbg_wmi(wil
, "FT: Auth to %pM successfully\n", data
->mac_addr
);
1678 wil_hex_dump_wmi("FT Auth ies : ", DUMP_PREFIX_OFFSET
, 16, 1,
1679 data
->ie_info
, d_len
, true);
1681 /* find cid and ringid */
1682 rc
= wil_find_cid_ringid_sta(wil
, vif
, &cid
, &ringid
);
1684 wil_err(wil
, "No valid cid found\n");
1689 /* For secure assoc, remove old keys */
1690 rc
= wmi_del_cipher_key(vif
, 0, wil
->sta
[cid
].addr
,
1691 WMI_KEY_USE_PAIRWISE
);
1693 wil_err(wil
, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
1696 rc
= wmi_del_cipher_key(vif
, 0, wil
->sta
[cid
].addr
,
1697 WMI_KEY_USE_RX_GROUP
);
1699 wil_err(wil
, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
1704 memset(&ft
, 0, sizeof(ft
));
1705 ft
.ies
= data
->ie_info
+ auth_ie_offset
;
1706 ft
.ies_len
= d_len
- auth_ie_offset
;
1707 ft
.target_ap
= data
->mac_addr
;
1708 cfg80211_ft_event(ndev
, &ft
);
1713 wil6210_disconnect(vif
, NULL
, WLAN_REASON_PREV_AUTH_NOT_VALID
);
1717 wmi_evt_reassoc_status(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1719 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1720 struct net_device
*ndev
= vif_to_ndev(vif
);
1721 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
1722 struct wmi_ft_reassoc_status_event
*data
= d
;
1723 int ies_len
= len
- offsetof(struct wmi_ft_reassoc_status_event
,
1725 int rc
= -ENOENT
, cid
= 0, ringid
= 0;
1726 int ch
; /* channel number (primary) */
1727 size_t assoc_req_ie_len
= 0, assoc_resp_ie_len
= 0;
1728 u8
*assoc_req_ie
= NULL
, *assoc_resp_ie
= NULL
;
1729 /* capinfo(u16) + listen_interval(u16) + current_ap mac addr + IEs */
1730 const size_t assoc_req_ie_offset
= sizeof(u16
) * 2 + ETH_ALEN
;
1731 /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
1732 const size_t assoc_resp_ie_offset
= sizeof(u16
) * 3;
1735 struct cfg80211_roam_info info
;
1738 wil_err(wil
, "ft reassoc event too short, len %d\n", len
);
1742 wil_dbg_wmi(wil
, "Reasoc Status event: status=%d, aid=%d",
1743 data
->status
, data
->aid
);
1744 wil_dbg_wmi(wil
, " mac_addr=%pM, beacon_ie_len=%d",
1745 data
->mac_addr
, data
->beacon_ie_len
);
1746 wil_dbg_wmi(wil
, " reassoc_req_ie_len=%d, reassoc_resp_ie_len=%d",
1747 le16_to_cpu(data
->reassoc_req_ie_len
),
1748 le16_to_cpu(data
->reassoc_resp_ie_len
));
1750 d_len
= le16_to_cpu(data
->beacon_ie_len
) +
1751 le16_to_cpu(data
->reassoc_req_ie_len
) +
1752 le16_to_cpu(data
->reassoc_resp_ie_len
);
1753 if (d_len
!= ies_len
) {
1755 "ft reassoc ie length mismatch, d_len %d should be %d\n",
1760 /* check the status */
1761 if (data
->status
!= WMI_FW_STATUS_SUCCESS
) {
1762 wil_err(wil
, "ft reassoc failed. status %d\n", data
->status
);
1766 /* find cid and ringid */
1767 rc
= wil_find_cid_ringid_sta(wil
, vif
, &cid
, &ringid
);
1769 wil_err(wil
, "No valid cid found\n");
1773 ch
= data
->channel
+ 1;
1774 wil_info(wil
, "FT: Roam %pM channel [%d] cid %d aid %d\n",
1775 data
->mac_addr
, ch
, cid
, data
->aid
);
1777 wil_hex_dump_wmi("reassoc AI : ", DUMP_PREFIX_OFFSET
, 16, 1,
1778 data
->ie_info
, len
- sizeof(*data
), true);
1780 /* figure out IE's */
1781 if (le16_to_cpu(data
->reassoc_req_ie_len
) > assoc_req_ie_offset
) {
1782 assoc_req_ie
= &data
->ie_info
[assoc_req_ie_offset
];
1783 assoc_req_ie_len
= le16_to_cpu(data
->reassoc_req_ie_len
) -
1784 assoc_req_ie_offset
;
1786 if (le16_to_cpu(data
->reassoc_resp_ie_len
) <= assoc_resp_ie_offset
) {
1787 wil_err(wil
, "FT: reassoc resp ie len is too short, len %d\n",
1788 le16_to_cpu(data
->reassoc_resp_ie_len
));
1792 assoc_resp_ie
= &data
->ie_info
[le16_to_cpu(data
->reassoc_req_ie_len
) +
1793 assoc_resp_ie_offset
];
1794 assoc_resp_ie_len
= le16_to_cpu(data
->reassoc_resp_ie_len
) -
1795 assoc_resp_ie_offset
;
1797 if (test_bit(wil_status_resetting
, wil
->status
) ||
1798 !test_bit(wil_status_fwready
, wil
->status
)) {
1799 wil_err(wil
, "FT: status_resetting, cancel reassoc event\n");
1800 /* no need for cleanup, wil_reset will do that */
1804 mutex_lock(&wil
->mutex
);
1806 /* ring modify to set the ring for the roamed AP settings */
1808 "ft modify tx config for connection CID %d ring %d\n",
1811 rc
= wil
->txrx_ops
.tx_ring_modify(vif
, ringid
, cid
, 0);
1813 wil_err(wil
, "modify TX for CID %d MID %d ring %d failed (%d)\n",
1814 cid
, vif
->mid
, ringid
, rc
);
1815 mutex_unlock(&wil
->mutex
);
1819 /* Update the driver STA members with the new bss */
1820 wil
->sta
[cid
].aid
= data
->aid
;
1821 wil
->sta
[cid
].stats
.ft_roams
++;
1822 ether_addr_copy(wil
->sta
[cid
].addr
, vif
->bss
->bssid
);
1823 mutex_unlock(&wil
->mutex
);
1824 del_timer_sync(&vif
->connect_timer
);
1826 cfg80211_ref_bss(wiphy
, vif
->bss
);
1827 freq
= ieee80211_channel_to_frequency(ch
, NL80211_BAND_60GHZ
);
1829 memset(&info
, 0, sizeof(info
));
1830 info
.channel
= ieee80211_get_channel(wiphy
, freq
);
1831 info
.bss
= vif
->bss
;
1832 info
.req_ie
= assoc_req_ie
;
1833 info
.req_ie_len
= assoc_req_ie_len
;
1834 info
.resp_ie
= assoc_resp_ie
;
1835 info
.resp_ie_len
= assoc_resp_ie_len
;
1836 cfg80211_roamed(ndev
, &info
, GFP_KERNEL
);
1842 wil6210_disconnect(vif
, NULL
, WLAN_REASON_PREV_AUTH_NOT_VALID
);
1846 wmi_evt_link_monitor(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1848 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1849 struct net_device
*ndev
= vif_to_ndev(vif
);
1850 struct wmi_link_monitor_event
*evt
= d
;
1851 enum nl80211_cqm_rssi_threshold_event event_type
;
1853 if (len
< sizeof(*evt
)) {
1854 wil_err(wil
, "link monitor event too short %d\n", len
);
1858 wil_dbg_wmi(wil
, "link monitor event, type %d rssi %d (stored %d)\n",
1859 evt
->type
, evt
->rssi_level
, wil
->cqm_rssi_thold
);
1861 if (evt
->type
!= WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT
)
1865 event_type
= (evt
->rssi_level
> wil
->cqm_rssi_thold
?
1866 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
:
1867 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
);
1868 cfg80211_cqm_rssi_notify(ndev
, event_type
, evt
->rssi_level
, GFP_KERNEL
);
1872 * Some events are ignored for purpose; and need not be interpreted as
1873 * "unhandled events"
1875 static void wmi_evt_ignore(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1877 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1879 wil_dbg_wmi(wil
, "Ignore event 0x%04x len %d\n", id
, len
);
1882 static const struct {
1884 void (*handler
)(struct wil6210_vif
*vif
,
1885 int eventid
, void *data
, int data_len
);
1886 } wmi_evt_handlers
[] = {
1887 {WMI_READY_EVENTID
, wmi_evt_ready
},
1888 {WMI_FW_READY_EVENTID
, wmi_evt_ignore
},
1889 {WMI_RX_MGMT_PACKET_EVENTID
, wmi_evt_rx_mgmt
},
1890 {WMI_TX_MGMT_PACKET_EVENTID
, wmi_evt_tx_mgmt
},
1891 {WMI_SCAN_COMPLETE_EVENTID
, wmi_evt_scan_complete
},
1892 {WMI_CONNECT_EVENTID
, wmi_evt_connect
},
1893 {WMI_DISCONNECT_EVENTID
, wmi_evt_disconnect
},
1894 {WMI_EAPOL_RX_EVENTID
, wmi_evt_eapol_rx
},
1895 {WMI_BA_STATUS_EVENTID
, wmi_evt_ba_status
},
1896 {WMI_RCP_ADDBA_REQ_EVENTID
, wmi_evt_addba_rx_req
},
1897 {WMI_DELBA_EVENTID
, wmi_evt_delba
},
1898 {WMI_RING_EN_EVENTID
, wmi_evt_ring_en
},
1899 {WMI_DATA_PORT_OPEN_EVENTID
, wmi_evt_ignore
},
1900 {WMI_SCHED_SCAN_RESULT_EVENTID
, wmi_evt_sched_scan_result
},
1901 {WMI_LINK_STATS_EVENTID
, wmi_evt_link_stats
},
1902 {WMI_FT_AUTH_STATUS_EVENTID
, wmi_evt_auth_status
},
1903 {WMI_FT_REASSOC_STATUS_EVENTID
, wmi_evt_reassoc_status
},
1904 {WMI_LINK_MONITOR_EVENTID
, wmi_evt_link_monitor
},
1908 * Run in IRQ context
1909 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
1910 * that will be eventually handled by the @wmi_event_worker in the thread
1911 * context of thread "wil6210_wmi"
1913 void wmi_recv_cmd(struct wil6210_priv
*wil
)
1915 struct wil6210_mbox_ring_desc d_tail
;
1916 struct wil6210_mbox_hdr hdr
;
1917 struct wil6210_mbox_ring
*r
= &wil
->mbox_ctl
.rx
;
1918 struct pending_wmi_event
*evt
;
1923 unsigned int num_immed_reply
= 0;
1925 if (!test_bit(wil_status_mbox_ready
, wil
->status
)) {
1926 wil_err(wil
, "Reset in progress. Cannot handle WMI event\n");
1930 if (test_bit(wil_status_suspended
, wil
->status
)) {
1931 wil_err(wil
, "suspended. cannot handle WMI event\n");
1938 bool immed_reply
= false;
1940 r
->head
= wil_r(wil
, RGF_MBOX
+
1941 offsetof(struct wil6210_mbox_ctl
, rx
.head
));
1942 if (r
->tail
== r
->head
)
1945 wil_dbg_wmi(wil
, "Mbox head %08x tail %08x\n",
1947 /* read cmd descriptor from tail */
1948 wil_memcpy_fromio_32(&d_tail
, wil
->csr
+ HOSTADDR(r
->tail
),
1949 sizeof(struct wil6210_mbox_ring_desc
));
1950 if (d_tail
.sync
== 0) {
1951 wil_err(wil
, "Mbox evt not owned by FW?\n");
1955 /* read cmd header from descriptor */
1956 if (0 != wmi_read_hdr(wil
, d_tail
.addr
, &hdr
)) {
1957 wil_err(wil
, "Mbox evt at 0x%08x?\n",
1958 le32_to_cpu(d_tail
.addr
));
1961 len
= le16_to_cpu(hdr
.len
);
1962 wil_dbg_wmi(wil
, "Mbox evt %04x %04x %04x %02x\n",
1963 le16_to_cpu(hdr
.seq
), len
, le16_to_cpu(hdr
.type
),
1966 /* read cmd buffer from descriptor */
1967 src
= wmi_buffer(wil
, d_tail
.addr
) +
1968 sizeof(struct wil6210_mbox_hdr
);
1969 evt
= kmalloc(ALIGN(offsetof(struct pending_wmi_event
,
1970 event
.wmi
) + len
, 4),
1975 evt
->event
.hdr
= hdr
;
1976 cmd
= (void *)&evt
->event
.wmi
;
1977 wil_memcpy_fromio_32(cmd
, src
, len
);
1978 /* mark entry as empty */
1979 wil_w(wil
, r
->tail
+
1980 offsetof(struct wil6210_mbox_ring_desc
, sync
), 0);
1982 if ((hdr
.type
== WIL_MBOX_HDR_TYPE_WMI
) &&
1983 (len
>= sizeof(struct wmi_cmd_hdr
))) {
1984 struct wmi_cmd_hdr
*wmi
= &evt
->event
.wmi
;
1985 u16 id
= le16_to_cpu(wmi
->command_id
);
1987 u32 tstamp
= le32_to_cpu(wmi
->fw_timestamp
);
1988 if (test_bit(wil_status_resuming
, wil
->status
)) {
1989 if (id
== WMI_TRAFFIC_RESUME_EVENTID
)
1990 clear_bit(wil_status_resuming
,
1994 "WMI evt %d while resuming\n",
1997 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
1998 if (wil
->reply_id
&& wil
->reply_id
== id
&&
1999 wil
->reply_mid
== mid
) {
2000 if (wil
->reply_buf
) {
2001 memcpy(wil
->reply_buf
, wmi
,
2002 min(len
, wil
->reply_size
));
2005 if (id
== WMI_TRAFFIC_SUSPEND_EVENTID
) {
2007 "set suspend_resp_rcvd\n");
2008 wil
->suspend_resp_rcvd
= true;
2011 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2013 wil_dbg_wmi(wil
, "recv %s (0x%04x) MID %d @%d msec\n",
2014 eventid2name(id
), id
, wmi
->mid
, tstamp
);
2015 trace_wil6210_wmi_event(wmi
, &wmi
[1],
2016 len
- sizeof(*wmi
));
2018 wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET
, 16, 1,
2019 &evt
->event
.hdr
, sizeof(hdr
) + len
, true);
2022 r
->tail
= r
->base
+ ((r
->tail
- r
->base
+
2023 sizeof(struct wil6210_mbox_ring_desc
)) % r
->size
);
2024 wil_w(wil
, RGF_MBOX
+
2025 offsetof(struct wil6210_mbox_ctl
, rx
.tail
), r
->tail
);
2028 wil_dbg_wmi(wil
, "recv_cmd: Complete WMI 0x%04x\n",
2032 complete(&wil
->wmi_call
);
2034 /* add to the pending list */
2035 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
2036 list_add_tail(&evt
->list
, &wil
->pending_wmi_ev
);
2037 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2038 q
= queue_work(wil
->wmi_wq
, &wil
->wmi_event_worker
);
2039 wil_dbg_wmi(wil
, "queue_work -> %d\n", q
);
2042 /* normally, 1 event per IRQ should be processed */
2043 wil_dbg_wmi(wil
, "recv_cmd: -> %d events queued, %d completed\n",
2044 n
- num_immed_reply
, num_immed_reply
);
2047 int wmi_call(struct wil6210_priv
*wil
, u16 cmdid
, u8 mid
, void *buf
, u16 len
,
2048 u16 reply_id
, void *reply
, u16 reply_size
, int to_msec
)
2051 unsigned long remain
;
2054 mutex_lock(&wil
->wmi_mutex
);
2056 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
2057 wil
->reply_id
= reply_id
;
2058 wil
->reply_mid
= mid
;
2059 wil
->reply_buf
= reply
;
2060 wil
->reply_size
= reply_size
;
2061 reinit_completion(&wil
->wmi_call
);
2062 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2064 rc
= __wmi_send(wil
, cmdid
, mid
, buf
, len
);
2068 remain
= wait_for_completion_timeout(&wil
->wmi_call
,
2069 msecs_to_jiffies(to_msec
));
2071 wil_err(wil
, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
2072 cmdid
, reply_id
, to_msec
);
2076 "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
2078 to_msec
- jiffies_to_msecs(remain
));
2082 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
2084 wil
->reply_mid
= U8_MAX
;
2085 wil
->reply_buf
= NULL
;
2086 wil
->reply_size
= 0;
2087 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2089 mutex_unlock(&wil
->wmi_mutex
);
2094 int wmi_echo(struct wil6210_priv
*wil
)
2096 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2097 struct wmi_echo_cmd cmd
= {
2098 .value
= cpu_to_le32(0x12345678),
2101 return wmi_call(wil
, WMI_ECHO_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2102 WMI_ECHO_RSP_EVENTID
, NULL
, 0,
2103 WIL_WMI_CALL_GENERAL_TO_MS
);
2106 int wmi_set_mac_address(struct wil6210_priv
*wil
, void *addr
)
2108 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2109 struct wmi_set_mac_address_cmd cmd
;
2111 ether_addr_copy(cmd
.mac
, addr
);
2113 wil_dbg_wmi(wil
, "Set MAC %pM\n", addr
);
2115 return wmi_send(wil
, WMI_SET_MAC_ADDRESS_CMDID
, vif
->mid
,
2119 int wmi_led_cfg(struct wil6210_priv
*wil
, bool enable
)
2121 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2123 struct wmi_led_cfg_cmd cmd
= {
2126 .slow_blink_cfg
.blink_on
=
2127 cpu_to_le32(led_blink_time
[WIL_LED_TIME_SLOW
].on_ms
),
2128 .slow_blink_cfg
.blink_off
=
2129 cpu_to_le32(led_blink_time
[WIL_LED_TIME_SLOW
].off_ms
),
2130 .medium_blink_cfg
.blink_on
=
2131 cpu_to_le32(led_blink_time
[WIL_LED_TIME_MED
].on_ms
),
2132 .medium_blink_cfg
.blink_off
=
2133 cpu_to_le32(led_blink_time
[WIL_LED_TIME_MED
].off_ms
),
2134 .fast_blink_cfg
.blink_on
=
2135 cpu_to_le32(led_blink_time
[WIL_LED_TIME_FAST
].on_ms
),
2136 .fast_blink_cfg
.blink_off
=
2137 cpu_to_le32(led_blink_time
[WIL_LED_TIME_FAST
].off_ms
),
2138 .led_polarity
= led_polarity
,
2141 struct wmi_cmd_hdr wmi
;
2142 struct wmi_led_cfg_done_event evt
;
2143 } __packed reply
= {
2144 .evt
= {.status
= cpu_to_le32(WMI_FW_STATUS_FAILURE
)},
2147 if (led_id
== WIL_LED_INVALID_ID
)
2150 if (led_id
> WIL_LED_MAX_ID
) {
2151 wil_err(wil
, "Invalid led id %d\n", led_id
);
2158 enable
? "enabling" : "disabling", led_id
);
2160 rc
= wmi_call(wil
, WMI_LED_CFG_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2161 WMI_LED_CFG_DONE_EVENTID
, &reply
, sizeof(reply
),
2162 WIL_WMI_CALL_GENERAL_TO_MS
);
2166 if (reply
.evt
.status
) {
2167 wil_err(wil
, "led %d cfg failed with status %d\n",
2168 led_id
, le32_to_cpu(reply
.evt
.status
));
2176 int wmi_rbufcap_cfg(struct wil6210_priv
*wil
, bool enable
, u16 threshold
)
2178 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2181 struct wmi_rbufcap_cfg_cmd cmd
= {
2183 .rx_desc_threshold
= cpu_to_le16(threshold
),
2186 struct wmi_cmd_hdr wmi
;
2187 struct wmi_rbufcap_cfg_event evt
;
2188 } __packed reply
= {
2189 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2192 rc
= wmi_call(wil
, WMI_RBUFCAP_CFG_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2193 WMI_RBUFCAP_CFG_EVENTID
, &reply
, sizeof(reply
),
2194 WIL_WMI_CALL_GENERAL_TO_MS
);
2198 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2199 wil_err(wil
, "RBUFCAP_CFG failed. status %d\n",
2207 int wmi_pcp_start(struct wil6210_vif
*vif
, int bi
, u8 wmi_nettype
,
2208 u8 chan
, u8 wmi_edmg_chan
, u8 hidden_ssid
, u8 is_go
)
2210 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2213 struct wmi_pcp_start_cmd cmd
= {
2214 .bcon_interval
= cpu_to_le16(bi
),
2215 .network_type
= wmi_nettype
,
2216 .disable_sec_offload
= 1,
2217 .channel
= chan
- 1,
2218 .edmg_channel
= wmi_edmg_chan
,
2219 .pcp_max_assoc_sta
= wil
->max_assoc_sta
,
2220 .hidden_ssid
= hidden_ssid
,
2222 .ap_sme_offload_mode
= disable_ap_sme
?
2223 WMI_AP_SME_OFFLOAD_PARTIAL
:
2224 WMI_AP_SME_OFFLOAD_FULL
,
2225 .abft_len
= wil
->abft_len
,
2228 struct wmi_cmd_hdr wmi
;
2229 struct wmi_pcp_started_event evt
;
2230 } __packed reply
= {
2231 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2235 cmd
.disable_sec
= 1;
2237 if ((cmd
.pcp_max_assoc_sta
> WIL6210_MAX_CID
) ||
2238 (cmd
.pcp_max_assoc_sta
<= 0)) {
2239 wil_err(wil
, "unexpected max_assoc_sta %d\n",
2240 cmd
.pcp_max_assoc_sta
);
2244 if (disable_ap_sme
&&
2245 !test_bit(WMI_FW_CAPABILITY_AP_SME_OFFLOAD_PARTIAL
,
2246 wil
->fw_capabilities
)) {
2247 wil_err(wil
, "disable_ap_sme not supported by FW\n");
2252 * Processing time may be huge, in case of secure AP it takes about
2253 * 3500ms for FW to start AP
2255 rc
= wmi_call(wil
, WMI_PCP_START_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2256 WMI_PCP_STARTED_EVENTID
, &reply
, sizeof(reply
), 5000);
2260 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
)
2263 if (wmi_nettype
!= WMI_NETTYPE_P2P
)
2264 /* Don't fail due to error in the led configuration */
2265 wmi_led_cfg(wil
, true);
2270 int wmi_pcp_stop(struct wil6210_vif
*vif
)
2272 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2275 rc
= wmi_led_cfg(wil
, false);
2279 return wmi_call(wil
, WMI_PCP_STOP_CMDID
, vif
->mid
, NULL
, 0,
2280 WMI_PCP_STOPPED_EVENTID
, NULL
, 0,
2281 WIL_WMI_PCP_STOP_TO_MS
);
2284 int wmi_set_ssid(struct wil6210_vif
*vif
, u8 ssid_len
, const void *ssid
)
2286 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2287 struct wmi_set_ssid_cmd cmd
= {
2288 .ssid_len
= cpu_to_le32(ssid_len
),
2291 if (ssid_len
> sizeof(cmd
.ssid
))
2294 memcpy(cmd
.ssid
, ssid
, ssid_len
);
2296 return wmi_send(wil
, WMI_SET_SSID_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
));
2299 int wmi_get_ssid(struct wil6210_vif
*vif
, u8
*ssid_len
, void *ssid
)
2301 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2304 struct wmi_cmd_hdr wmi
;
2305 struct wmi_set_ssid_cmd cmd
;
2307 int len
; /* reply.cmd.ssid_len in CPU order */
2309 memset(&reply
, 0, sizeof(reply
));
2311 rc
= wmi_call(wil
, WMI_GET_SSID_CMDID
, vif
->mid
, NULL
, 0,
2312 WMI_GET_SSID_EVENTID
, &reply
, sizeof(reply
),
2313 WIL_WMI_CALL_GENERAL_TO_MS
);
2317 len
= le32_to_cpu(reply
.cmd
.ssid_len
);
2318 if (len
> sizeof(reply
.cmd
.ssid
))
2322 memcpy(ssid
, reply
.cmd
.ssid
, len
);
2327 int wmi_set_channel(struct wil6210_priv
*wil
, int channel
)
2329 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2330 struct wmi_set_pcp_channel_cmd cmd
= {
2331 .channel
= channel
- 1,
2334 return wmi_send(wil
, WMI_SET_PCP_CHANNEL_CMDID
, vif
->mid
,
2338 int wmi_get_channel(struct wil6210_priv
*wil
, int *channel
)
2340 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2343 struct wmi_cmd_hdr wmi
;
2344 struct wmi_set_pcp_channel_cmd cmd
;
2347 memset(&reply
, 0, sizeof(reply
));
2349 rc
= wmi_call(wil
, WMI_GET_PCP_CHANNEL_CMDID
, vif
->mid
, NULL
, 0,
2350 WMI_GET_PCP_CHANNEL_EVENTID
, &reply
, sizeof(reply
),
2351 WIL_WMI_CALL_GENERAL_TO_MS
);
2355 if (reply
.cmd
.channel
> 3)
2358 *channel
= reply
.cmd
.channel
+ 1;
2363 int wmi_p2p_cfg(struct wil6210_vif
*vif
, int channel
, int bi
)
2365 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2367 struct wmi_p2p_cfg_cmd cmd
= {
2368 .discovery_mode
= WMI_DISCOVERY_MODE_PEER2PEER
,
2369 .bcon_interval
= cpu_to_le16(bi
),
2370 .channel
= channel
- 1,
2373 struct wmi_cmd_hdr wmi
;
2374 struct wmi_p2p_cfg_done_event evt
;
2375 } __packed reply
= {
2376 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2379 wil_dbg_wmi(wil
, "sending WMI_P2P_CFG_CMDID\n");
2381 rc
= wmi_call(wil
, WMI_P2P_CFG_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2382 WMI_P2P_CFG_DONE_EVENTID
, &reply
, sizeof(reply
), 300);
2383 if (!rc
&& reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2384 wil_err(wil
, "P2P_CFG failed. status %d\n", reply
.evt
.status
);
2391 int wmi_start_listen(struct wil6210_vif
*vif
)
2393 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2396 struct wmi_cmd_hdr wmi
;
2397 struct wmi_listen_started_event evt
;
2398 } __packed reply
= {
2399 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2402 wil_dbg_wmi(wil
, "sending WMI_START_LISTEN_CMDID\n");
2404 rc
= wmi_call(wil
, WMI_START_LISTEN_CMDID
, vif
->mid
, NULL
, 0,
2405 WMI_LISTEN_STARTED_EVENTID
, &reply
, sizeof(reply
), 300);
2406 if (!rc
&& reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2407 wil_err(wil
, "device failed to start listen. status %d\n",
2415 int wmi_start_search(struct wil6210_vif
*vif
)
2417 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2420 struct wmi_cmd_hdr wmi
;
2421 struct wmi_search_started_event evt
;
2422 } __packed reply
= {
2423 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2426 wil_dbg_wmi(wil
, "sending WMI_START_SEARCH_CMDID\n");
2428 rc
= wmi_call(wil
, WMI_START_SEARCH_CMDID
, vif
->mid
, NULL
, 0,
2429 WMI_SEARCH_STARTED_EVENTID
, &reply
, sizeof(reply
), 300);
2430 if (!rc
&& reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2431 wil_err(wil
, "device failed to start search. status %d\n",
2439 int wmi_stop_discovery(struct wil6210_vif
*vif
)
2441 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2444 wil_dbg_wmi(wil
, "sending WMI_DISCOVERY_STOP_CMDID\n");
2446 rc
= wmi_call(wil
, WMI_DISCOVERY_STOP_CMDID
, vif
->mid
, NULL
, 0,
2447 WMI_DISCOVERY_STOPPED_EVENTID
, NULL
, 0,
2448 WIL_WMI_CALL_GENERAL_TO_MS
);
2451 wil_err(wil
, "Failed to stop discovery\n");
2456 int wmi_del_cipher_key(struct wil6210_vif
*vif
, u8 key_index
,
2457 const void *mac_addr
, int key_usage
)
2459 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2460 struct wmi_delete_cipher_key_cmd cmd
= {
2461 .key_index
= key_index
,
2465 memcpy(cmd
.mac
, mac_addr
, WMI_MAC_LEN
);
2467 return wmi_send(wil
, WMI_DELETE_CIPHER_KEY_CMDID
, vif
->mid
,
2471 int wmi_add_cipher_key(struct wil6210_vif
*vif
, u8 key_index
,
2472 const void *mac_addr
, int key_len
, const void *key
,
2475 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2476 struct wmi_add_cipher_key_cmd cmd
= {
2477 .key_index
= key_index
,
2478 .key_usage
= key_usage
,
2482 if (key_len
> sizeof(cmd
.key
))
2485 /* key len = 0 is allowed only for usage of WMI_KEY_USE_APPLY */
2486 if ((key_len
== 0 || !key
) &&
2487 key_usage
!= WMI_KEY_USE_APPLY_PTK
)
2491 memcpy(cmd
.key
, key
, key_len
);
2494 memcpy(cmd
.mac
, mac_addr
, WMI_MAC_LEN
);
2496 return wmi_send(wil
, WMI_ADD_CIPHER_KEY_CMDID
, vif
->mid
,
2500 int wmi_set_ie(struct wil6210_vif
*vif
, u8 type
, u16 ie_len
, const void *ie
)
2502 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2503 static const char *const names
[] = {
2504 [WMI_FRAME_BEACON
] = "BEACON",
2505 [WMI_FRAME_PROBE_REQ
] = "PROBE_REQ",
2506 [WMI_FRAME_PROBE_RESP
] = "WMI_FRAME_PROBE_RESP",
2507 [WMI_FRAME_ASSOC_REQ
] = "WMI_FRAME_ASSOC_REQ",
2508 [WMI_FRAME_ASSOC_RESP
] = "WMI_FRAME_ASSOC_RESP",
2511 u16 len
= sizeof(struct wmi_set_appie_cmd
) + ie_len
;
2512 struct wmi_set_appie_cmd
*cmd
;
2519 cmd
= kzalloc(len
, GFP_KERNEL
);
2527 cmd
->mgmt_frm_type
= type
;
2528 /* BUG: FW API define ieLen as u8. Will fix FW */
2529 cmd
->ie_len
= cpu_to_le16(ie_len
);
2531 memcpy(cmd
->ie_info
, ie
, ie_len
);
2532 rc
= wmi_send(wil
, WMI_SET_APPIE_CMDID
, vif
->mid
, cmd
, len
);
2536 const char *name
= type
< ARRAY_SIZE(names
) ?
2538 wil_err(wil
, "set_ie(%d %s) failed : %d\n", type
, name
, rc
);
2544 int wmi_update_ft_ies(struct wil6210_vif
*vif
, u16 ie_len
, const void *ie
)
2546 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2548 struct wmi_update_ft_ies_cmd
*cmd
;
2554 len
= sizeof(struct wmi_update_ft_ies_cmd
) + ie_len
;
2556 wil_err(wil
, "wraparound. ie len %d\n", ie_len
);
2560 cmd
= kzalloc(len
, GFP_KERNEL
);
2566 cmd
->ie_len
= cpu_to_le16(ie_len
);
2568 memcpy(cmd
->ie_info
, ie
, ie_len
);
2569 rc
= wmi_send(wil
, WMI_UPDATE_FT_IES_CMDID
, vif
->mid
, cmd
, len
);
2574 wil_err(wil
, "update ft ies failed : %d\n", rc
);
2580 * wmi_rxon - turn radio on/off
2581 * @on: turn on if true, off otherwise
2583 * Only switch radio. Channel should be set separately.
2584 * No timeout for rxon - radio turned on forever unless some other call
2587 int wmi_rxon(struct wil6210_priv
*wil
, bool on
)
2589 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2592 struct wmi_cmd_hdr wmi
;
2593 struct wmi_listen_started_event evt
;
2594 } __packed reply
= {
2595 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2598 wil_info(wil
, "(%s)\n", on
? "on" : "off");
2601 rc
= wmi_call(wil
, WMI_START_LISTEN_CMDID
, vif
->mid
, NULL
, 0,
2602 WMI_LISTEN_STARTED_EVENTID
,
2603 &reply
, sizeof(reply
),
2604 WIL_WMI_CALL_GENERAL_TO_MS
);
2605 if ((rc
== 0) && (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
))
2608 rc
= wmi_call(wil
, WMI_DISCOVERY_STOP_CMDID
, vif
->mid
, NULL
, 0,
2609 WMI_DISCOVERY_STOPPED_EVENTID
, NULL
, 0,
2610 WIL_WMI_CALL_GENERAL_TO_MS
);
2616 int wmi_rx_chain_add(struct wil6210_priv
*wil
, struct wil_ring
*vring
)
2618 struct net_device
*ndev
= wil
->main_ndev
;
2619 struct wireless_dev
*wdev
= ndev
->ieee80211_ptr
;
2620 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
2621 struct wmi_cfg_rx_chain_cmd cmd
= {
2622 .action
= WMI_RX_CHAIN_ADD
,
2624 .max_mpdu_size
= cpu_to_le16(
2625 wil_mtu2macbuf(wil
->rx_buf_len
)),
2626 .ring_mem_base
= cpu_to_le64(vring
->pa
),
2627 .ring_size
= cpu_to_le16(vring
->size
),
2629 .mid
= 0, /* TODO - what is it? */
2630 .decap_trans_type
= WMI_DECAP_TYPE_802_3
,
2631 .reorder_type
= WMI_RX_SW_REORDER
,
2632 .host_thrsh
= cpu_to_le16(rx_ring_overflow_thrsh
),
2635 struct wmi_cmd_hdr wmi
;
2636 struct wmi_cfg_rx_chain_done_event evt
;
2640 memset(&evt
, 0, sizeof(evt
));
2642 if (wdev
->iftype
== NL80211_IFTYPE_MONITOR
) {
2643 struct ieee80211_channel
*ch
= wil
->monitor_chandef
.chan
;
2645 cmd
.sniffer_cfg
.mode
= cpu_to_le32(WMI_SNIFFER_ON
);
2647 cmd
.sniffer_cfg
.channel
= ch
->hw_value
- 1;
2648 cmd
.sniffer_cfg
.phy_info_mode
=
2649 cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED
);
2650 cmd
.sniffer_cfg
.phy_support
=
2651 cpu_to_le32((wil
->monitor_flags
& MONITOR_FLAG_CONTROL
)
2652 ? WMI_SNIFFER_CP
: WMI_SNIFFER_BOTH_PHYS
);
2654 /* Initialize offload (in non-sniffer mode).
2655 * Linux IP stack always calculates IP checksum
2656 * HW always calculate TCP/UDP checksum
2658 cmd
.l3_l4_ctrl
|= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS
);
2662 cmd
.l2_802_3_offload_ctrl
|=
2663 L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK
;
2665 /* typical time for secure PCP is 840ms */
2666 rc
= wmi_call(wil
, WMI_CFG_RX_CHAIN_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2667 WMI_CFG_RX_CHAIN_DONE_EVENTID
, &evt
, sizeof(evt
), 2000);
2671 if (le32_to_cpu(evt
.evt
.status
) != WMI_CFG_RX_CHAIN_SUCCESS
)
2674 vring
->hwtail
= le32_to_cpu(evt
.evt
.rx_ring_tail_ptr
);
2676 wil_dbg_misc(wil
, "Rx init: status %d tail 0x%08x\n",
2677 le32_to_cpu(evt
.evt
.status
), vring
->hwtail
);
2682 int wmi_get_temperature(struct wil6210_priv
*wil
, u32
*t_bb
, u32
*t_rf
)
2684 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2686 struct wmi_temp_sense_cmd cmd
= {
2687 .measure_baseband_en
= cpu_to_le32(!!t_bb
),
2688 .measure_rf_en
= cpu_to_le32(!!t_rf
),
2689 .measure_mode
= cpu_to_le32(TEMPERATURE_MEASURE_NOW
),
2692 struct wmi_cmd_hdr wmi
;
2693 struct wmi_temp_sense_done_event evt
;
2696 memset(&reply
, 0, sizeof(reply
));
2698 rc
= wmi_call(wil
, WMI_TEMP_SENSE_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2699 WMI_TEMP_SENSE_DONE_EVENTID
, &reply
, sizeof(reply
),
2700 WIL_WMI_CALL_GENERAL_TO_MS
);
2705 *t_bb
= le32_to_cpu(reply
.evt
.baseband_t1000
);
2707 *t_rf
= le32_to_cpu(reply
.evt
.rf_t1000
);
2712 int wmi_get_all_temperatures(struct wil6210_priv
*wil
,
2713 struct wmi_temp_sense_all_done_event
2716 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2718 struct wmi_temp_sense_all_cmd cmd
= {
2719 .measure_baseband_en
= true,
2720 .measure_rf_en
= true,
2721 .measure_mode
= TEMPERATURE_MEASURE_NOW
,
2724 struct wmi_cmd_hdr wmi
;
2725 struct wmi_temp_sense_all_done_event evt
;
2728 if (!sense_all_evt
) {
2729 wil_err(wil
, "Invalid sense_all_evt value\n");
2733 memset(&reply
, 0, sizeof(reply
));
2734 reply
.evt
.status
= WMI_FW_STATUS_FAILURE
;
2735 rc
= wmi_call(wil
, WMI_TEMP_SENSE_ALL_CMDID
, vif
->mid
, &cmd
,
2736 sizeof(cmd
), WMI_TEMP_SENSE_ALL_DONE_EVENTID
,
2737 &reply
, sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
2741 if (reply
.evt
.status
== WMI_FW_STATUS_FAILURE
) {
2742 wil_err(wil
, "Failed getting TEMP_SENSE_ALL\n");
2746 memcpy(sense_all_evt
, &reply
.evt
, sizeof(reply
.evt
));
2750 int wmi_disconnect_sta(struct wil6210_vif
*vif
, const u8
*mac
, u16 reason
,
2753 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2755 struct wmi_disconnect_sta_cmd disc_sta_cmd
= {
2756 .disconnect_reason
= cpu_to_le16(reason
),
2758 struct wmi_del_sta_cmd del_sta_cmd
= {
2759 .disconnect_reason
= cpu_to_le16(reason
),
2762 struct wmi_cmd_hdr wmi
;
2763 struct wmi_disconnect_event evt
;
2766 wil_dbg_wmi(wil
, "disconnect_sta: (%pM, reason %d)\n", mac
, reason
);
2768 memset(&reply
, 0, sizeof(reply
));
2769 vif
->locally_generated_disc
= true;
2771 ether_addr_copy(del_sta_cmd
.dst_mac
, mac
);
2772 rc
= wmi_call(wil
, WMI_DEL_STA_CMDID
, vif
->mid
, &del_sta_cmd
,
2773 sizeof(del_sta_cmd
), WMI_DISCONNECT_EVENTID
,
2774 &reply
, sizeof(reply
), 1000);
2776 ether_addr_copy(disc_sta_cmd
.dst_mac
, mac
);
2777 rc
= wmi_call(wil
, WMI_DISCONNECT_STA_CMDID
, vif
->mid
,
2778 &disc_sta_cmd
, sizeof(disc_sta_cmd
),
2779 WMI_DISCONNECT_EVENTID
,
2780 &reply
, sizeof(reply
), 1000);
2782 /* failure to disconnect in reasonable time treated as FW error */
2784 wil_fw_error_recovery(wil
);
2792 int wmi_addba(struct wil6210_priv
*wil
, u8 mid
,
2793 u8 ringid
, u8 size
, u16 timeout
)
2795 u8 amsdu
= wil
->use_enhanced_dma_hw
&& wil
->use_rx_hw_reordering
&&
2796 test_bit(WMI_FW_CAPABILITY_AMSDU
, wil
->fw_capabilities
) &&
2798 struct wmi_ring_ba_en_cmd cmd
= {
2800 .agg_max_wsize
= size
,
2801 .ba_timeout
= cpu_to_le16(timeout
),
2805 wil_dbg_wmi(wil
, "addba: (ring %d size %d timeout %d amsdu %d)\n",
2806 ringid
, size
, timeout
, amsdu
);
2808 return wmi_send(wil
, WMI_RING_BA_EN_CMDID
, mid
, &cmd
, sizeof(cmd
));
2811 int wmi_delba_tx(struct wil6210_priv
*wil
, u8 mid
, u8 ringid
, u16 reason
)
2813 struct wmi_ring_ba_dis_cmd cmd
= {
2815 .reason
= cpu_to_le16(reason
),
2818 wil_dbg_wmi(wil
, "delba_tx: (ring %d reason %d)\n", ringid
, reason
);
2820 return wmi_send(wil
, WMI_RING_BA_DIS_CMDID
, mid
, &cmd
, sizeof(cmd
));
2823 int wmi_delba_rx(struct wil6210_priv
*wil
, u8 mid
, u8 cid
, u8 tid
, u16 reason
)
2825 struct wmi_rcp_delba_cmd cmd
= {
2826 .reason
= cpu_to_le16(reason
),
2829 if (cid
>= WIL6210_RX_DESC_MAX_CID
) {
2830 cmd
.cidxtid
= CIDXTID_EXTENDED_CID_TID
;
2834 cmd
.cidxtid
= mk_cidxtid(cid
, tid
);
2837 wil_dbg_wmi(wil
, "delba_rx: (CID %d TID %d reason %d)\n", cid
,
2840 return wmi_send(wil
, WMI_RCP_DELBA_CMDID
, mid
, &cmd
, sizeof(cmd
));
2843 int wmi_addba_rx_resp(struct wil6210_priv
*wil
,
2844 u8 mid
, u8 cid
, u8 tid
, u8 token
,
2845 u16 status
, bool amsdu
, u16 agg_wsize
, u16 timeout
)
2848 struct wmi_rcp_addba_resp_cmd cmd
= {
2849 .dialog_token
= token
,
2850 .status_code
= cpu_to_le16(status
),
2851 /* bit 0: A-MSDU supported
2852 * bit 1: policy (controlled by FW)
2854 * bits 6..15: buffer size
2856 .ba_param_set
= cpu_to_le16((amsdu
? 1 : 0) | (tid
<< 2) |
2858 .ba_timeout
= cpu_to_le16(timeout
),
2861 struct wmi_cmd_hdr wmi
;
2862 struct wmi_rcp_addba_resp_sent_event evt
;
2863 } __packed reply
= {
2864 .evt
= {.status
= cpu_to_le16(WMI_FW_STATUS_FAILURE
)},
2867 if (cid
>= WIL6210_RX_DESC_MAX_CID
) {
2868 cmd
.cidxtid
= CIDXTID_EXTENDED_CID_TID
;
2872 cmd
.cidxtid
= mk_cidxtid(cid
, tid
);
2876 "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
2877 mid
, cid
, tid
, agg_wsize
,
2878 timeout
, status
, amsdu
? "+" : "-");
2880 rc
= wmi_call(wil
, WMI_RCP_ADDBA_RESP_CMDID
, mid
, &cmd
, sizeof(cmd
),
2881 WMI_RCP_ADDBA_RESP_SENT_EVENTID
, &reply
, sizeof(reply
),
2882 WIL_WMI_CALL_GENERAL_TO_MS
);
2886 if (reply
.evt
.status
) {
2887 wil_err(wil
, "ADDBA response failed with status %d\n",
2888 le16_to_cpu(reply
.evt
.status
));
2895 int wmi_addba_rx_resp_edma(struct wil6210_priv
*wil
, u8 mid
, u8 cid
, u8 tid
,
2896 u8 token
, u16 status
, bool amsdu
, u16 agg_wsize
,
2900 struct wmi_rcp_addba_resp_edma_cmd cmd
= {
2903 .dialog_token
= token
,
2904 .status_code
= cpu_to_le16(status
),
2905 /* bit 0: A-MSDU supported
2906 * bit 1: policy (controlled by FW)
2908 * bits 6..15: buffer size
2910 .ba_param_set
= cpu_to_le16((amsdu
? 1 : 0) | (tid
<< 2) |
2912 .ba_timeout
= cpu_to_le16(timeout
),
2913 /* route all the connections to status ring 0 */
2914 .status_ring_id
= WIL_DEFAULT_RX_STATUS_RING_ID
,
2917 struct wmi_cmd_hdr wmi
;
2918 struct wmi_rcp_addba_resp_sent_event evt
;
2919 } __packed reply
= {
2920 .evt
= {.status
= cpu_to_le16(WMI_FW_STATUS_FAILURE
)},
2924 "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s, sring_id %d\n",
2925 cid
, tid
, agg_wsize
, timeout
, status
, amsdu
? "+" : "-",
2926 WIL_DEFAULT_RX_STATUS_RING_ID
);
2928 rc
= wmi_call(wil
, WMI_RCP_ADDBA_RESP_EDMA_CMDID
, mid
, &cmd
,
2929 sizeof(cmd
), WMI_RCP_ADDBA_RESP_SENT_EVENTID
, &reply
,
2930 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
2934 if (reply
.evt
.status
) {
2935 wil_err(wil
, "ADDBA response failed with status %d\n",
2936 le16_to_cpu(reply
.evt
.status
));
2943 int wmi_ps_dev_profile_cfg(struct wil6210_priv
*wil
,
2944 enum wmi_ps_profile_type ps_profile
)
2946 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2948 struct wmi_ps_dev_profile_cfg_cmd cmd
= {
2949 .ps_profile
= ps_profile
,
2952 struct wmi_cmd_hdr wmi
;
2953 struct wmi_ps_dev_profile_cfg_event evt
;
2954 } __packed reply
= {
2955 .evt
= {.status
= cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR
)},
2959 wil_dbg_wmi(wil
, "Setting ps dev profile %d\n", ps_profile
);
2961 rc
= wmi_call(wil
, WMI_PS_DEV_PROFILE_CFG_CMDID
, vif
->mid
,
2963 WMI_PS_DEV_PROFILE_CFG_EVENTID
, &reply
, sizeof(reply
),
2964 WIL_WMI_CALL_GENERAL_TO_MS
);
2968 status
= le32_to_cpu(reply
.evt
.status
);
2970 if (status
!= WMI_PS_CFG_CMD_STATUS_SUCCESS
) {
2971 wil_err(wil
, "ps dev profile cfg failed with status %d\n",
2979 int wmi_set_mgmt_retry(struct wil6210_priv
*wil
, u8 retry_short
)
2981 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2983 struct wmi_set_mgmt_retry_limit_cmd cmd
= {
2984 .mgmt_retry_limit
= retry_short
,
2987 struct wmi_cmd_hdr wmi
;
2988 struct wmi_set_mgmt_retry_limit_event evt
;
2989 } __packed reply
= {
2990 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2993 wil_dbg_wmi(wil
, "Setting mgmt retry short %d\n", retry_short
);
2995 if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT
, wil
->fw_capabilities
))
2998 rc
= wmi_call(wil
, WMI_SET_MGMT_RETRY_LIMIT_CMDID
, vif
->mid
,
3000 WMI_SET_MGMT_RETRY_LIMIT_EVENTID
, &reply
, sizeof(reply
),
3001 WIL_WMI_CALL_GENERAL_TO_MS
);
3005 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3006 wil_err(wil
, "set mgmt retry limit failed with status %d\n",
3014 int wmi_get_mgmt_retry(struct wil6210_priv
*wil
, u8
*retry_short
)
3016 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3019 struct wmi_cmd_hdr wmi
;
3020 struct wmi_get_mgmt_retry_limit_event evt
;
3023 wil_dbg_wmi(wil
, "getting mgmt retry short\n");
3025 if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT
, wil
->fw_capabilities
))
3028 memset(&reply
, 0, sizeof(reply
));
3029 rc
= wmi_call(wil
, WMI_GET_MGMT_RETRY_LIMIT_CMDID
, vif
->mid
, NULL
, 0,
3030 WMI_GET_MGMT_RETRY_LIMIT_EVENTID
, &reply
, sizeof(reply
),
3031 WIL_WMI_CALL_GENERAL_TO_MS
);
3036 *retry_short
= reply
.evt
.mgmt_retry_limit
;
3041 int wmi_abort_scan(struct wil6210_vif
*vif
)
3043 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3046 wil_dbg_wmi(wil
, "sending WMI_ABORT_SCAN_CMDID\n");
3048 rc
= wmi_send(wil
, WMI_ABORT_SCAN_CMDID
, vif
->mid
, NULL
, 0);
3050 wil_err(wil
, "Failed to abort scan (%d)\n", rc
);
3055 int wmi_new_sta(struct wil6210_vif
*vif
, const u8
*mac
, u8 aid
)
3057 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3059 struct wmi_new_sta_cmd cmd
= {
3063 wil_dbg_wmi(wil
, "new sta %pM, aid %d\n", mac
, aid
);
3065 ether_addr_copy(cmd
.dst_mac
, mac
);
3067 rc
= wmi_send(wil
, WMI_NEW_STA_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
));
3069 wil_err(wil
, "Failed to send new sta (%d)\n", rc
);
3074 void wmi_event_flush(struct wil6210_priv
*wil
)
3077 struct pending_wmi_event
*evt
, *t
;
3079 wil_dbg_wmi(wil
, "event_flush\n");
3081 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
3083 list_for_each_entry_safe(evt
, t
, &wil
->pending_wmi_ev
, list
) {
3084 list_del(&evt
->list
);
3088 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
3091 static const char *suspend_status2name(u8 status
)
3094 case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE
:
3095 return "LINK_NOT_IDLE";
3096 case WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT
:
3097 return "DISCONNECT";
3098 case WMI_TRAFFIC_SUSPEND_REJECTED_OTHER
:
3101 return "Untracked status";
3105 int wmi_suspend(struct wil6210_priv
*wil
)
3107 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3109 struct wmi_traffic_suspend_cmd cmd
= {
3110 .wakeup_trigger
= wil
->wakeup_trigger
,
3113 struct wmi_cmd_hdr wmi
;
3114 struct wmi_traffic_suspend_event evt
;
3115 } __packed reply
= {
3116 .evt
= {.status
= WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE
},
3119 u32 suspend_to
= WIL_WAIT_FOR_SUSPEND_RESUME_COMP
;
3121 wil
->suspend_resp_rcvd
= false;
3122 wil
->suspend_resp_comp
= false;
3124 rc
= wmi_call(wil
, WMI_TRAFFIC_SUSPEND_CMDID
, vif
->mid
,
3126 WMI_TRAFFIC_SUSPEND_EVENTID
, &reply
, sizeof(reply
),
3129 wil_err(wil
, "wmi_call for suspend req failed, rc=%d\n", rc
);
3132 wil
->suspend_stats
.rejected_by_device
++;
3134 wil
->suspend_stats
.rejected_by_host
++;
3138 wil_dbg_wmi(wil
, "waiting for suspend_response_completed\n");
3140 rc
= wait_event_interruptible_timeout(wil
->wq
,
3141 wil
->suspend_resp_comp
,
3142 msecs_to_jiffies(suspend_to
));
3144 wil_err(wil
, "TO waiting for suspend_response_completed\n");
3145 if (wil
->suspend_resp_rcvd
)
3146 /* Device responded but we TO due to another reason */
3147 wil
->suspend_stats
.rejected_by_host
++;
3149 wil
->suspend_stats
.rejected_by_device
++;
3154 wil_dbg_wmi(wil
, "suspend_response_completed rcvd\n");
3155 if (reply
.evt
.status
!= WMI_TRAFFIC_SUSPEND_APPROVED
) {
3156 wil_dbg_pm(wil
, "device rejected the suspend, %s\n",
3157 suspend_status2name(reply
.evt
.status
));
3158 wil
->suspend_stats
.rejected_by_device
++;
3160 rc
= reply
.evt
.status
;
3163 wil
->suspend_resp_rcvd
= false;
3164 wil
->suspend_resp_comp
= false;
3169 static void resume_triggers2string(u32 triggers
, char *string
, int str_size
)
3174 strlcat(string
, " UNKNOWN", str_size
);
3178 if (triggers
& WMI_RESUME_TRIGGER_HOST
)
3179 strlcat(string
, " HOST", str_size
);
3181 if (triggers
& WMI_RESUME_TRIGGER_UCAST_RX
)
3182 strlcat(string
, " UCAST_RX", str_size
);
3184 if (triggers
& WMI_RESUME_TRIGGER_BCAST_RX
)
3185 strlcat(string
, " BCAST_RX", str_size
);
3187 if (triggers
& WMI_RESUME_TRIGGER_WMI_EVT
)
3188 strlcat(string
, " WMI_EVT", str_size
);
3190 if (triggers
& WMI_RESUME_TRIGGER_DISCONNECT
)
3191 strlcat(string
, " DISCONNECT", str_size
);
3194 int wmi_resume(struct wil6210_priv
*wil
)
3196 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3200 struct wmi_cmd_hdr wmi
;
3201 struct wmi_traffic_resume_event evt
;
3202 } __packed reply
= {
3203 .evt
= {.status
= WMI_TRAFFIC_RESUME_FAILED
,
3205 cpu_to_le32(WMI_RESUME_TRIGGER_UNKNOWN
)},
3208 rc
= wmi_call(wil
, WMI_TRAFFIC_RESUME_CMDID
, vif
->mid
, NULL
, 0,
3209 WMI_TRAFFIC_RESUME_EVENTID
, &reply
, sizeof(reply
),
3210 WIL_WAIT_FOR_SUSPEND_RESUME_COMP
);
3213 resume_triggers2string(le32_to_cpu(reply
.evt
.resume_triggers
), string
,
3215 wil_dbg_pm(wil
, "device resume %s, resume triggers:%s (0x%x)\n",
3216 reply
.evt
.status
? "failed" : "passed", string
,
3217 le32_to_cpu(reply
.evt
.resume_triggers
));
3219 return reply
.evt
.status
;
3222 int wmi_port_allocate(struct wil6210_priv
*wil
, u8 mid
,
3223 const u8
*mac
, enum nl80211_iftype iftype
)
3226 struct wmi_port_allocate_cmd cmd
= {
3230 struct wmi_cmd_hdr wmi
;
3231 struct wmi_port_allocated_event evt
;
3232 } __packed reply
= {
3233 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3236 wil_dbg_misc(wil
, "port allocate, mid %d iftype %d, mac %pM\n",
3239 ether_addr_copy(cmd
.mac
, mac
);
3241 case NL80211_IFTYPE_STATION
:
3242 cmd
.port_role
= WMI_PORT_STA
;
3244 case NL80211_IFTYPE_AP
:
3245 cmd
.port_role
= WMI_PORT_AP
;
3247 case NL80211_IFTYPE_P2P_CLIENT
:
3248 cmd
.port_role
= WMI_PORT_P2P_CLIENT
;
3250 case NL80211_IFTYPE_P2P_GO
:
3251 cmd
.port_role
= WMI_PORT_P2P_GO
;
3253 /* what about monitor??? */
3255 wil_err(wil
, "unsupported iftype: %d\n", iftype
);
3259 rc
= wmi_call(wil
, WMI_PORT_ALLOCATE_CMDID
, mid
,
3261 WMI_PORT_ALLOCATED_EVENTID
, &reply
,
3262 sizeof(reply
), 300);
3264 wil_err(wil
, "failed to allocate port, status %d\n", rc
);
3267 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3268 wil_err(wil
, "WMI_PORT_ALLOCATE returned status %d\n",
3276 int wmi_port_delete(struct wil6210_priv
*wil
, u8 mid
)
3279 struct wmi_port_delete_cmd cmd
= {
3283 struct wmi_cmd_hdr wmi
;
3284 struct wmi_port_deleted_event evt
;
3285 } __packed reply
= {
3286 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3289 wil_dbg_misc(wil
, "port delete, mid %d\n", mid
);
3291 rc
= wmi_call(wil
, WMI_PORT_DELETE_CMDID
, mid
,
3293 WMI_PORT_DELETED_EVENTID
, &reply
,
3294 sizeof(reply
), 2000);
3296 wil_err(wil
, "failed to delete port, status %d\n", rc
);
3299 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3300 wil_err(wil
, "WMI_PORT_DELETE returned status %d\n",
3308 static bool wmi_evt_call_handler(struct wil6210_vif
*vif
, int id
,
3313 for (i
= 0; i
< ARRAY_SIZE(wmi_evt_handlers
); i
++) {
3314 if (wmi_evt_handlers
[i
].eventid
== id
) {
3315 wmi_evt_handlers
[i
].handler(vif
, id
, d
, len
);
3323 static void wmi_event_handle(struct wil6210_priv
*wil
,
3324 struct wil6210_mbox_hdr
*hdr
)
3326 u16 len
= le16_to_cpu(hdr
->len
);
3327 struct wil6210_vif
*vif
;
3329 if ((hdr
->type
== WIL_MBOX_HDR_TYPE_WMI
) &&
3330 (len
>= sizeof(struct wmi_cmd_hdr
))) {
3331 struct wmi_cmd_hdr
*wmi
= (void *)(&hdr
[1]);
3332 void *evt_data
= (void *)(&wmi
[1]);
3333 u16 id
= le16_to_cpu(wmi
->command_id
);
3336 wil_dbg_wmi(wil
, "Handle %s (0x%04x) (reply_id 0x%04x,%d)\n",
3337 eventid2name(id
), id
, wil
->reply_id
,
3340 if (mid
== MID_BROADCAST
)
3342 if (mid
>= GET_MAX_VIFS(wil
)) {
3343 wil_dbg_wmi(wil
, "invalid mid %d, event skipped\n",
3347 vif
= wil
->vifs
[mid
];
3349 wil_dbg_wmi(wil
, "event for empty VIF(%d), skipped\n",
3354 /* check if someone waits for this event */
3355 if (wil
->reply_id
&& wil
->reply_id
== id
&&
3356 wil
->reply_mid
== mid
) {
3357 if (wil
->reply_buf
) {
3358 /* event received while wmi_call is waiting
3359 * with a buffer. Such event should be handled
3360 * in wmi_recv_cmd function. Handling the event
3361 * here means a previous wmi_call was timeout.
3362 * Drop the event and do not handle it.
3365 "Old event (%d, %s) while wmi_call is waiting. Drop it and Continue waiting\n",
3366 id
, eventid2name(id
));
3370 wmi_evt_call_handler(vif
, id
, evt_data
,
3371 len
- sizeof(*wmi
));
3372 wil_dbg_wmi(wil
, "event_handle: Complete WMI 0x%04x\n",
3374 complete(&wil
->wmi_call
);
3377 /* unsolicited event */
3378 /* search for handler */
3379 if (!wmi_evt_call_handler(vif
, id
, evt_data
,
3380 len
- sizeof(*wmi
))) {
3381 wil_info(wil
, "Unhandled event 0x%04x\n", id
);
3384 wil_err(wil
, "Unknown event type\n");
3385 print_hex_dump(KERN_ERR
, "evt?? ", DUMP_PREFIX_OFFSET
, 16, 1,
3386 hdr
, sizeof(*hdr
) + len
, true);
3391 * Retrieve next WMI event from the pending list
3393 static struct list_head
*next_wmi_ev(struct wil6210_priv
*wil
)
3396 struct list_head
*ret
= NULL
;
3398 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
3400 if (!list_empty(&wil
->pending_wmi_ev
)) {
3401 ret
= wil
->pending_wmi_ev
.next
;
3405 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
3411 * Handler for the WMI events
3413 void wmi_event_worker(struct work_struct
*work
)
3415 struct wil6210_priv
*wil
= container_of(work
, struct wil6210_priv
,
3417 struct pending_wmi_event
*evt
;
3418 struct list_head
*lh
;
3420 wil_dbg_wmi(wil
, "event_worker: Start\n");
3421 while ((lh
= next_wmi_ev(wil
)) != NULL
) {
3422 evt
= list_entry(lh
, struct pending_wmi_event
, list
);
3423 wmi_event_handle(wil
, &evt
->event
.hdr
);
3426 wil_dbg_wmi(wil
, "event_worker: Finished\n");
3429 bool wil_is_wmi_idle(struct wil6210_priv
*wil
)
3432 struct wil6210_mbox_ring
*r
= &wil
->mbox_ctl
.rx
;
3435 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
3437 /* Check if there are pending WMI events in the events queue */
3438 if (!list_empty(&wil
->pending_wmi_ev
)) {
3439 wil_dbg_pm(wil
, "Pending WMI events in queue\n");
3443 /* Check if there is a pending WMI call */
3444 if (wil
->reply_id
) {
3445 wil_dbg_pm(wil
, "Pending WMI call\n");
3449 /* Check if there are pending RX events in mbox */
3450 r
->head
= wil_r(wil
, RGF_MBOX
+
3451 offsetof(struct wil6210_mbox_ctl
, rx
.head
));
3452 if (r
->tail
!= r
->head
)
3453 wil_dbg_pm(wil
, "Pending WMI mbox events\n");
3458 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
3463 wmi_sched_scan_set_ssids(struct wil6210_priv
*wil
,
3464 struct wmi_start_sched_scan_cmd
*cmd
,
3465 struct cfg80211_ssid
*ssids
, int n_ssids
,
3466 struct cfg80211_match_set
*match_sets
,
3471 if (n_match_sets
> WMI_MAX_PNO_SSID_NUM
) {
3472 wil_dbg_wmi(wil
, "too many match sets (%d), use first %d\n",
3473 n_match_sets
, WMI_MAX_PNO_SSID_NUM
);
3474 n_match_sets
= WMI_MAX_PNO_SSID_NUM
;
3476 cmd
->num_of_ssids
= n_match_sets
;
3478 for (i
= 0; i
< n_match_sets
; i
++) {
3479 struct wmi_sched_scan_ssid_match
*wmi_match
=
3480 &cmd
->ssid_for_match
[i
];
3481 struct cfg80211_match_set
*cfg_match
= &match_sets
[i
];
3484 wmi_match
->ssid_len
= cfg_match
->ssid
.ssid_len
;
3485 memcpy(wmi_match
->ssid
, cfg_match
->ssid
.ssid
,
3486 min_t(u8
, wmi_match
->ssid_len
, WMI_MAX_SSID_LEN
));
3487 wmi_match
->rssi_threshold
= S8_MIN
;
3488 if (cfg_match
->rssi_thold
>= S8_MIN
&&
3489 cfg_match
->rssi_thold
<= S8_MAX
)
3490 wmi_match
->rssi_threshold
= cfg_match
->rssi_thold
;
3492 for (j
= 0; j
< n_ssids
; j
++)
3493 if (wmi_match
->ssid_len
== ssids
[j
].ssid_len
&&
3494 memcmp(wmi_match
->ssid
, ssids
[j
].ssid
,
3495 wmi_match
->ssid_len
) == 0)
3496 wmi_match
->add_ssid_to_probe
= true;
3501 wmi_sched_scan_set_channels(struct wil6210_priv
*wil
,
3502 struct wmi_start_sched_scan_cmd
*cmd
,
3504 struct ieee80211_channel
**channels
)
3508 if (n_channels
> WMI_MAX_CHANNEL_NUM
) {
3509 wil_dbg_wmi(wil
, "too many channels (%d), use first %d\n",
3510 n_channels
, WMI_MAX_CHANNEL_NUM
);
3511 n_channels
= WMI_MAX_CHANNEL_NUM
;
3513 cmd
->num_of_channels
= n_channels
;
3515 for (i
= 0; i
< n_channels
; i
++) {
3516 struct ieee80211_channel
*cfg_chan
= channels
[i
];
3518 cmd
->channel_list
[i
] = cfg_chan
->hw_value
- 1;
3523 wmi_sched_scan_set_plans(struct wil6210_priv
*wil
,
3524 struct wmi_start_sched_scan_cmd
*cmd
,
3525 struct cfg80211_sched_scan_plan
*scan_plans
,
3530 if (n_scan_plans
> WMI_MAX_PLANS_NUM
) {
3531 wil_dbg_wmi(wil
, "too many plans (%d), use first %d\n",
3532 n_scan_plans
, WMI_MAX_PLANS_NUM
);
3533 n_scan_plans
= WMI_MAX_PLANS_NUM
;
3536 for (i
= 0; i
< n_scan_plans
; i
++) {
3537 struct cfg80211_sched_scan_plan
*cfg_plan
= &scan_plans
[i
];
3539 cmd
->scan_plans
[i
].interval_sec
=
3540 cpu_to_le16(cfg_plan
->interval
);
3541 cmd
->scan_plans
[i
].num_of_iterations
=
3542 cpu_to_le16(cfg_plan
->iterations
);
3546 int wmi_start_sched_scan(struct wil6210_priv
*wil
,
3547 struct cfg80211_sched_scan_request
*request
)
3549 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3551 struct wmi_start_sched_scan_cmd cmd
= {
3552 .min_rssi_threshold
= S8_MIN
,
3553 .initial_delay_sec
= cpu_to_le16(request
->delay
),
3556 struct wmi_cmd_hdr wmi
;
3557 struct wmi_start_sched_scan_event evt
;
3558 } __packed reply
= {
3559 .evt
= {.result
= WMI_PNO_REJECT
},
3562 if (!test_bit(WMI_FW_CAPABILITY_PNO
, wil
->fw_capabilities
))
3565 if (request
->min_rssi_thold
>= S8_MIN
&&
3566 request
->min_rssi_thold
<= S8_MAX
)
3567 cmd
.min_rssi_threshold
= request
->min_rssi_thold
;
3569 wmi_sched_scan_set_ssids(wil
, &cmd
, request
->ssids
, request
->n_ssids
,
3570 request
->match_sets
, request
->n_match_sets
);
3571 wmi_sched_scan_set_channels(wil
, &cmd
,
3572 request
->n_channels
, request
->channels
);
3573 wmi_sched_scan_set_plans(wil
, &cmd
,
3574 request
->scan_plans
, request
->n_scan_plans
);
3576 rc
= wmi_call(wil
, WMI_START_SCHED_SCAN_CMDID
, vif
->mid
,
3578 WMI_START_SCHED_SCAN_EVENTID
, &reply
, sizeof(reply
),
3579 WIL_WMI_CALL_GENERAL_TO_MS
);
3583 if (reply
.evt
.result
!= WMI_PNO_SUCCESS
) {
3584 wil_err(wil
, "start sched scan failed, result %d\n",
3592 int wmi_stop_sched_scan(struct wil6210_priv
*wil
)
3594 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3597 struct wmi_cmd_hdr wmi
;
3598 struct wmi_stop_sched_scan_event evt
;
3599 } __packed reply
= {
3600 .evt
= {.result
= WMI_PNO_REJECT
},
3603 if (!test_bit(WMI_FW_CAPABILITY_PNO
, wil
->fw_capabilities
))
3606 rc
= wmi_call(wil
, WMI_STOP_SCHED_SCAN_CMDID
, vif
->mid
, NULL
, 0,
3607 WMI_STOP_SCHED_SCAN_EVENTID
, &reply
, sizeof(reply
),
3608 WIL_WMI_CALL_GENERAL_TO_MS
);
3612 if (reply
.evt
.result
!= WMI_PNO_SUCCESS
) {
3613 wil_err(wil
, "stop sched scan failed, result %d\n",
3621 int wmi_mgmt_tx(struct wil6210_vif
*vif
, const u8
*buf
, size_t len
)
3624 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3625 struct ieee80211_mgmt
*mgmt_frame
= (void *)buf
;
3626 struct wmi_sw_tx_req_cmd
*cmd
;
3628 struct wmi_cmd_hdr wmi
;
3629 struct wmi_sw_tx_complete_event evt
;
3631 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3635 wil_dbg_misc(wil
, "mgmt_tx mid %d\n", vif
->mid
);
3636 wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET
, 16, 1, buf
,
3639 if (len
< sizeof(struct ieee80211_hdr_3addr
))
3642 total
= sizeof(*cmd
) + len
;
3644 wil_err(wil
, "mgmt_tx invalid len %zu\n", len
);
3648 cmd
= kmalloc(total
, GFP_KERNEL
);
3652 memcpy(cmd
->dst_mac
, mgmt_frame
->da
, WMI_MAC_LEN
);
3653 cmd
->len
= cpu_to_le16(len
);
3654 memcpy(cmd
->payload
, buf
, len
);
3656 rc
= wmi_call(wil
, WMI_SW_TX_REQ_CMDID
, vif
->mid
, cmd
, total
,
3657 WMI_SW_TX_COMPLETE_EVENTID
, &evt
, sizeof(evt
), 2000);
3658 if (!rc
&& evt
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3659 wil_dbg_wmi(wil
, "mgmt_tx failed with status %d\n",
3669 int wmi_mgmt_tx_ext(struct wil6210_vif
*vif
, const u8
*buf
, size_t len
,
3670 u8 channel
, u16 duration_ms
)
3673 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3674 struct ieee80211_mgmt
*mgmt_frame
= (void *)buf
;
3675 struct wmi_sw_tx_req_ext_cmd
*cmd
;
3677 struct wmi_cmd_hdr wmi
;
3678 struct wmi_sw_tx_complete_event evt
;
3680 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3684 wil_dbg_wmi(wil
, "mgmt_tx_ext mid %d channel %d duration %d\n",
3685 vif
->mid
, channel
, duration_ms
);
3686 wil_hex_dump_wmi("mgmt_tx_ext frame ", DUMP_PREFIX_OFFSET
, 16, 1, buf
,
3689 if (len
< sizeof(struct ieee80211_hdr_3addr
)) {
3690 wil_err(wil
, "short frame. len %zu\n", len
);
3694 total
= sizeof(*cmd
) + len
;
3696 wil_err(wil
, "mgmt_tx_ext invalid len %zu\n", len
);
3700 cmd
= kzalloc(total
, GFP_KERNEL
);
3704 memcpy(cmd
->dst_mac
, mgmt_frame
->da
, WMI_MAC_LEN
);
3705 cmd
->len
= cpu_to_le16(len
);
3706 memcpy(cmd
->payload
, buf
, len
);
3707 cmd
->channel
= channel
- 1;
3708 cmd
->duration_ms
= cpu_to_le16(duration_ms
);
3710 rc
= wmi_call(wil
, WMI_SW_TX_REQ_EXT_CMDID
, vif
->mid
, cmd
, total
,
3711 WMI_SW_TX_COMPLETE_EVENTID
, &evt
, sizeof(evt
), 2000);
3712 if (!rc
&& evt
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3713 wil_dbg_wmi(wil
, "mgmt_tx_ext failed with status %d\n",
3723 int wil_wmi_tx_sring_cfg(struct wil6210_priv
*wil
, int ring_id
)
3726 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3727 struct wil_status_ring
*sring
= &wil
->srings
[ring_id
];
3728 struct wmi_tx_status_ring_add_cmd cmd
= {
3730 .ring_size
= cpu_to_le16(sring
->size
),
3732 .irq_index
= WIL_TX_STATUS_IRQ_IDX
3735 struct wmi_cmd_hdr hdr
;
3736 struct wmi_tx_status_ring_cfg_done_event evt
;
3737 } __packed reply
= {
3738 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3741 cmd
.ring_cfg
.ring_id
= ring_id
;
3743 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(sring
->pa
);
3744 rc
= wmi_call(wil
, WMI_TX_STATUS_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3745 sizeof(cmd
), WMI_TX_STATUS_RING_CFG_DONE_EVENTID
,
3746 &reply
, sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3748 wil_err(wil
, "TX_STATUS_RING_ADD_CMD failed, rc %d\n", rc
);
3752 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3753 wil_err(wil
, "TX_STATUS_RING_ADD_CMD failed, status %d\n",
3758 sring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3763 int wil_wmi_cfg_def_rx_offload(struct wil6210_priv
*wil
, u16 max_rx_pl_per_desc
)
3765 struct net_device
*ndev
= wil
->main_ndev
;
3766 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
3768 struct wmi_cfg_def_rx_offload_cmd cmd
= {
3769 .max_msdu_size
= cpu_to_le16(wil_mtu2macbuf(WIL_MAX_ETH_MTU
)),
3770 .max_rx_pl_per_desc
= cpu_to_le16(max_rx_pl_per_desc
),
3771 .decap_trans_type
= WMI_DECAP_TYPE_802_3
,
3772 .l2_802_3_offload_ctrl
= 0,
3773 .l3_l4_ctrl
= 1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS
,
3776 struct wmi_cmd_hdr hdr
;
3777 struct wmi_cfg_def_rx_offload_done_event evt
;
3778 } __packed reply
= {
3779 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3782 rc
= wmi_call(wil
, WMI_CFG_DEF_RX_OFFLOAD_CMDID
, vif
->mid
, &cmd
,
3783 sizeof(cmd
), WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID
, &reply
,
3784 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3786 wil_err(wil
, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, rc %d\n", rc
);
3790 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3791 wil_err(wil
, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, status %d\n",
3799 int wil_wmi_rx_sring_add(struct wil6210_priv
*wil
, u16 ring_id
)
3801 struct net_device
*ndev
= wil
->main_ndev
;
3802 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
3803 struct wil_status_ring
*sring
= &wil
->srings
[ring_id
];
3805 struct wmi_rx_status_ring_add_cmd cmd
= {
3807 .ring_size
= cpu_to_le16(sring
->size
),
3810 .rx_msg_type
= wil
->use_compressed_rx_status
?
3811 WMI_RX_MSG_TYPE_COMPRESSED
:
3812 WMI_RX_MSG_TYPE_EXTENDED
,
3813 .irq_index
= WIL_RX_STATUS_IRQ_IDX
,
3816 struct wmi_cmd_hdr hdr
;
3817 struct wmi_rx_status_ring_cfg_done_event evt
;
3818 } __packed reply
= {
3819 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3822 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(sring
->pa
);
3823 rc
= wmi_call(wil
, WMI_RX_STATUS_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3824 sizeof(cmd
), WMI_RX_STATUS_RING_CFG_DONE_EVENTID
, &reply
,
3825 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3827 wil_err(wil
, "RX_STATUS_RING_ADD_CMD failed, rc %d\n", rc
);
3831 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3832 wil_err(wil
, "RX_STATUS_RING_ADD_CMD failed, status %d\n",
3837 sring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3842 int wil_wmi_rx_desc_ring_add(struct wil6210_priv
*wil
, int status_ring_id
)
3844 struct net_device
*ndev
= wil
->main_ndev
;
3845 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
3846 struct wil_ring
*ring
= &wil
->ring_rx
;
3848 struct wmi_rx_desc_ring_add_cmd cmd
= {
3850 .ring_size
= cpu_to_le16(ring
->size
),
3851 .ring_id
= WIL_RX_DESC_RING_ID
,
3853 .status_ring_id
= status_ring_id
,
3854 .irq_index
= WIL_RX_STATUS_IRQ_IDX
,
3857 struct wmi_cmd_hdr hdr
;
3858 struct wmi_rx_desc_ring_cfg_done_event evt
;
3859 } __packed reply
= {
3860 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3863 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(ring
->pa
);
3864 cmd
.sw_tail_host_addr
= cpu_to_le64(ring
->edma_rx_swtail
.pa
);
3865 rc
= wmi_call(wil
, WMI_RX_DESC_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3866 sizeof(cmd
), WMI_RX_DESC_RING_CFG_DONE_EVENTID
, &reply
,
3867 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3869 wil_err(wil
, "WMI_RX_DESC_RING_ADD_CMD failed, rc %d\n", rc
);
3873 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3874 wil_err(wil
, "WMI_RX_DESC_RING_ADD_CMD failed, status %d\n",
3879 ring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3884 int wil_wmi_tx_desc_ring_add(struct wil6210_vif
*vif
, int ring_id
, int cid
,
3887 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3888 int sring_id
= wil
->tx_sring_idx
; /* there is only one TX sring */
3890 struct wil_ring
*ring
= &wil
->ring_tx
[ring_id
];
3891 struct wil_ring_tx_data
*txdata
= &wil
->ring_tx_data
[ring_id
];
3892 struct wmi_tx_desc_ring_add_cmd cmd
= {
3894 .ring_size
= cpu_to_le16(ring
->size
),
3897 .status_ring_id
= sring_id
,
3900 .encap_trans_type
= WMI_VRING_ENC_TYPE_802_3
,
3901 .max_msdu_size
= cpu_to_le16(wil_mtu2macbuf(mtu_max
)),
3903 .priority
= cpu_to_le16(0),
3904 .timeslot_us
= cpu_to_le16(0xfff),
3908 struct wmi_cmd_hdr hdr
;
3909 struct wmi_tx_desc_ring_cfg_done_event evt
;
3910 } __packed reply
= {
3911 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3914 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(ring
->pa
);
3915 rc
= wmi_call(wil
, WMI_TX_DESC_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3916 sizeof(cmd
), WMI_TX_DESC_RING_CFG_DONE_EVENTID
, &reply
,
3917 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3919 wil_err(wil
, "WMI_TX_DESC_RING_ADD_CMD failed, rc %d\n", rc
);
3923 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3924 wil_err(wil
, "WMI_TX_DESC_RING_ADD_CMD failed, status %d\n",
3929 spin_lock_bh(&txdata
->lock
);
3930 ring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3931 txdata
->mid
= vif
->mid
;
3932 txdata
->enabled
= 1;
3933 spin_unlock_bh(&txdata
->lock
);
3938 int wil_wmi_bcast_desc_ring_add(struct wil6210_vif
*vif
, int ring_id
)
3940 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3941 struct wil_ring
*ring
= &wil
->ring_tx
[ring_id
];
3943 struct wmi_bcast_desc_ring_add_cmd cmd
= {
3945 .ring_size
= cpu_to_le16(ring
->size
),
3948 .max_msdu_size
= cpu_to_le16(wil_mtu2macbuf(mtu_max
)),
3949 .status_ring_id
= wil
->tx_sring_idx
,
3950 .encap_trans_type
= WMI_VRING_ENC_TYPE_802_3
,
3953 struct wmi_cmd_hdr hdr
;
3954 struct wmi_rx_desc_ring_cfg_done_event evt
;
3955 } __packed reply
= {
3956 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3958 struct wil_ring_tx_data
*txdata
= &wil
->ring_tx_data
[ring_id
];
3960 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(ring
->pa
);
3961 rc
= wmi_call(wil
, WMI_BCAST_DESC_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3962 sizeof(cmd
), WMI_TX_DESC_RING_CFG_DONE_EVENTID
, &reply
,
3963 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3965 wil_err(wil
, "WMI_BCAST_DESC_RING_ADD_CMD failed, rc %d\n", rc
);
3969 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3970 wil_err(wil
, "Broadcast Tx config failed, status %d\n",
3975 spin_lock_bh(&txdata
->lock
);
3976 ring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3977 txdata
->mid
= vif
->mid
;
3978 txdata
->enabled
= 1;
3979 spin_unlock_bh(&txdata
->lock
);
3984 int wmi_link_stats_cfg(struct wil6210_vif
*vif
, u32 type
, u8 cid
, u32 interval
)
3986 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3987 struct wmi_link_stats_cmd cmd
= {
3988 .record_type_mask
= cpu_to_le32(type
),
3990 .action
= WMI_LINK_STATS_SNAPSHOT
,
3991 .interval_msec
= cpu_to_le32(interval
),
3994 struct wmi_cmd_hdr wmi
;
3995 struct wmi_link_stats_config_done_event evt
;
3996 } __packed reply
= {
3997 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
4001 rc
= wmi_call(wil
, WMI_LINK_STATS_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
4002 WMI_LINK_STATS_CONFIG_DONE_EVENTID
, &reply
,
4003 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
4005 wil_err(wil
, "WMI_LINK_STATS_CMDID failed, rc %d\n", rc
);
4009 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
4010 wil_err(wil
, "Link statistics config failed, status %d\n",
4018 int wmi_set_cqm_rssi_config(struct wil6210_priv
*wil
,
4019 s32 rssi_thold
, u32 rssi_hyst
)
4021 struct net_device
*ndev
= wil
->main_ndev
;
4022 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
4025 struct wmi_set_link_monitor_cmd cmd
;
4029 .rssi_hyst
= rssi_hyst
,
4030 .rssi_thresholds_list_size
= 1,
4032 .rssi_thold
= rssi_thold
,
4035 struct wmi_cmd_hdr hdr
;
4036 struct wmi_set_link_monitor_event evt
;
4037 } __packed reply
= {
4038 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
4041 if (rssi_thold
> S8_MAX
|| rssi_thold
< S8_MIN
|| rssi_hyst
> U8_MAX
)
4044 rc
= wmi_call(wil
, WMI_SET_LINK_MONITOR_CMDID
, vif
->mid
, &cmd
,
4045 sizeof(cmd
), WMI_SET_LINK_MONITOR_EVENTID
,
4046 &reply
, sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
4048 wil_err(wil
, "WMI_SET_LINK_MONITOR_CMDID failed, rc %d\n", rc
);
4052 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
4053 wil_err(wil
, "WMI_SET_LINK_MONITOR_CMDID failed, status %d\n",