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 * DOC: 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 * DOC: 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.
69 /* sparrow_fw_mapping provides memory remapping table for sparrow
71 * array size should be in sync with the declaration in the wil6210.h
73 * Sparrow memory mapping:
74 * Linker address PCI/Host address
75 * 0x880000 .. 0xa80000 2Mb BAR0
76 * 0x800000 .. 0x808000 0x900000 .. 0x908000 32k DCCM
77 * 0x840000 .. 0x860000 0x908000 .. 0x928000 128k PERIPH
79 const struct fw_map sparrow_fw_mapping
[] = {
80 /* FW code RAM 256k */
81 {0x000000, 0x040000, 0x8c0000, "fw_code", true, true},
83 {0x800000, 0x808000, 0x900000, "fw_data", true, true},
84 /* periph data 128k */
85 {0x840000, 0x860000, 0x908000, "fw_peri", true, true},
87 {0x880000, 0x88a000, 0x880000, "rgf", true, true},
89 {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
91 {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
92 /* mac_ext_rgf 512b */
93 {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true, true},
95 {0x8c0000, 0x949000, 0x8c0000, "upper", true, true},
96 /* UCODE areas - accessible by debugfs blobs but not by
97 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
99 /* ucode code RAM 128k */
100 {0x000000, 0x020000, 0x920000, "uc_code", false, false},
101 /* ucode data RAM 16k */
102 {0x800000, 0x804000, 0x940000, "uc_data", false, false},
105 /* sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
106 * it is a bit larger to support extra features
108 const struct fw_map sparrow_d0_mac_rgf_ext
= {
109 0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true
112 /* talyn_fw_mapping provides memory remapping table for Talyn
114 * array size should be in sync with the declaration in the wil6210.h
116 * Talyn memory mapping:
117 * Linker address PCI/Host address
118 * 0x880000 .. 0xc80000 4Mb BAR0
119 * 0x800000 .. 0x820000 0xa00000 .. 0xa20000 128k DCCM
120 * 0x840000 .. 0x858000 0xa20000 .. 0xa38000 96k PERIPH
122 const struct fw_map talyn_fw_mapping
[] = {
124 {0x000000, 0x100000, 0x900000, "fw_code", true, true},
125 /* FW data RAM 128k */
126 {0x800000, 0x820000, 0xa00000, "fw_data", true, true},
127 /* periph. data RAM 96k */
128 {0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
129 /* various RGF 40k */
130 {0x880000, 0x88a000, 0x880000, "rgf", true, true},
132 {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
133 /* Pcie_ext_rgf 4k */
134 {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
135 /* mac_ext_rgf 1344b */
136 {0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true, true},
137 /* ext USER RGF 4k */
138 {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
140 {0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
141 /* DMA EXT RGF 64k */
142 {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
143 /* upper area 1536k */
144 {0x900000, 0xa80000, 0x900000, "upper", true, true},
145 /* UCODE areas - accessible by debugfs blobs but not by
146 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
148 /* ucode code RAM 256k */
149 {0x000000, 0x040000, 0xa38000, "uc_code", false, false},
150 /* ucode data RAM 32k */
151 {0x800000, 0x808000, 0xa78000, "uc_data", false, false},
154 /* talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
156 * array size should be in sync with the declaration in the wil6210.h
158 * Talyn MB memory mapping:
159 * Linker address PCI/Host address
160 * 0x880000 .. 0xc80000 4Mb BAR0
161 * 0x800000 .. 0x820000 0xa00000 .. 0xa20000 128k DCCM
162 * 0x840000 .. 0x858000 0xa20000 .. 0xa38000 96k PERIPH
164 const struct fw_map talyn_mb_fw_mapping
[] = {
165 /* FW code RAM 768k */
166 {0x000000, 0x0c0000, 0x900000, "fw_code", true, true},
167 /* FW data RAM 128k */
168 {0x800000, 0x820000, 0xa00000, "fw_data", true, true},
169 /* periph. data RAM 96k */
170 {0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
171 /* various RGF 40k */
172 {0x880000, 0x88a000, 0x880000, "rgf", true, true},
174 {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
175 /* Pcie_ext_rgf 4k */
176 {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
177 /* mac_ext_rgf 2256b */
178 {0x88c000, 0x88c8d0, 0x88c000, "mac_rgf_ext", true, true},
179 /* ext USER RGF 4k */
180 {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
182 {0x890000, 0x894000, 0x890000, "sec_pka", true, true},
183 /* SEC KDF RGF 3096b */
184 {0x898000, 0x898c18, 0x898000, "sec_kdf_rgf", true, true},
186 {0x89a000, 0x89a84c, 0x89a000, "sec_main", true, true},
188 {0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
189 /* DMA EXT RGF 64k */
190 {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
191 /* DUM USER RGF 528b */
192 {0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true, true},
194 {0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true, true},
195 /* ucode debug 256b */
196 {0x8c3000, 0x8c3100, 0x8c3000, "ucode_debug", true, true},
197 /* upper area 1536k */
198 {0x900000, 0xa80000, 0x900000, "upper", true, true},
199 /* UCODE areas - accessible by debugfs blobs but not by
200 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
202 /* ucode code RAM 256k */
203 {0x000000, 0x040000, 0xa38000, "uc_code", false, false},
204 /* ucode data RAM 32k */
205 {0x800000, 0x808000, 0xa78000, "uc_data", false, false},
208 struct fw_map fw_mapping
[MAX_FW_MAPPING_TABLE_SIZE
];
210 struct blink_on_off_time led_blink_time
[] = {
211 {WIL_LED_BLINK_ON_SLOW_MS
, WIL_LED_BLINK_OFF_SLOW_MS
},
212 {WIL_LED_BLINK_ON_MED_MS
, WIL_LED_BLINK_OFF_MED_MS
},
213 {WIL_LED_BLINK_ON_FAST_MS
, WIL_LED_BLINK_OFF_FAST_MS
},
218 __le16 auth_transaction
;
220 /* possibly followed by Challenge text */
224 u8 led_polarity
= LED_POLARITY_LOW_ACTIVE
;
227 * wmi_addr_remap - return AHB address for given firmware internal (linker) address
228 * @x: internal address
229 * If address have no valid AHB mapping, return 0
231 static u32
wmi_addr_remap(u32 x
)
235 for (i
= 0; i
< ARRAY_SIZE(fw_mapping
); i
++) {
236 if (fw_mapping
[i
].fw
&&
237 ((x
>= fw_mapping
[i
].from
) && (x
< fw_mapping
[i
].to
)))
238 return x
+ fw_mapping
[i
].host
- fw_mapping
[i
].from
;
245 * wil_find_fw_mapping - find fw_mapping entry by section name
246 * @section: section name
248 * Return pointer to section or NULL if not found
250 struct fw_map
*wil_find_fw_mapping(const char *section
)
254 for (i
= 0; i
< ARRAY_SIZE(fw_mapping
); i
++)
255 if (fw_mapping
[i
].name
&&
256 !strcmp(section
, fw_mapping
[i
].name
))
257 return &fw_mapping
[i
];
263 * wmi_buffer_block - Check address validity for WMI buffer; remap if needed
265 * @ptr_: internal (linker) fw/ucode address
266 * @size: if non zero, validate the block does not
267 * exceed the device memory (bar)
269 * Valid buffer should be DWORD aligned
271 * return address for accessing buffer from the host;
272 * if buffer is not valid, return NULL.
274 void __iomem
*wmi_buffer_block(struct wil6210_priv
*wil
, __le32 ptr_
, u32 size
)
277 u32 ptr
= le32_to_cpu(ptr_
);
282 ptr
= wmi_addr_remap(ptr
);
283 if (ptr
< WIL6210_FW_HOST_OFF
)
287 if (off
> wil
->bar_size
- 4)
289 if (size
&& ((off
+ size
> wil
->bar_size
) || (off
+ size
< off
)))
292 return wil
->csr
+ off
;
295 void __iomem
*wmi_buffer(struct wil6210_priv
*wil
, __le32 ptr_
)
297 return wmi_buffer_block(wil
, ptr_
, 0);
300 /* Check address validity */
301 void __iomem
*wmi_addr(struct wil6210_priv
*wil
, u32 ptr
)
308 if (ptr
< WIL6210_FW_HOST_OFF
)
312 if (off
> wil
->bar_size
- 4)
315 return wil
->csr
+ off
;
318 int wmi_read_hdr(struct wil6210_priv
*wil
, __le32 ptr
,
319 struct wil6210_mbox_hdr
*hdr
)
321 void __iomem
*src
= wmi_buffer(wil
, ptr
);
326 wil_memcpy_fromio_32(hdr
, src
, sizeof(*hdr
));
331 static const char *cmdid2name(u16 cmdid
)
334 case WMI_NOTIFY_REQ_CMDID
:
335 return "WMI_NOTIFY_REQ_CMD";
336 case WMI_START_SCAN_CMDID
:
337 return "WMI_START_SCAN_CMD";
338 case WMI_CONNECT_CMDID
:
339 return "WMI_CONNECT_CMD";
340 case WMI_DISCONNECT_CMDID
:
341 return "WMI_DISCONNECT_CMD";
342 case WMI_SW_TX_REQ_CMDID
:
343 return "WMI_SW_TX_REQ_CMD";
344 case WMI_GET_RF_SECTOR_PARAMS_CMDID
:
345 return "WMI_GET_RF_SECTOR_PARAMS_CMD";
346 case WMI_SET_RF_SECTOR_PARAMS_CMDID
:
347 return "WMI_SET_RF_SECTOR_PARAMS_CMD";
348 case WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID
:
349 return "WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD";
350 case WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID
:
351 return "WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD";
352 case WMI_BRP_SET_ANT_LIMIT_CMDID
:
353 return "WMI_BRP_SET_ANT_LIMIT_CMD";
354 case WMI_TOF_SESSION_START_CMDID
:
355 return "WMI_TOF_SESSION_START_CMD";
356 case WMI_AOA_MEAS_CMDID
:
357 return "WMI_AOA_MEAS_CMD";
359 return "WMI_PMC_CMD";
360 case WMI_TOF_GET_TX_RX_OFFSET_CMDID
:
361 return "WMI_TOF_GET_TX_RX_OFFSET_CMD";
362 case WMI_TOF_SET_TX_RX_OFFSET_CMDID
:
363 return "WMI_TOF_SET_TX_RX_OFFSET_CMD";
364 case WMI_VRING_CFG_CMDID
:
365 return "WMI_VRING_CFG_CMD";
366 case WMI_BCAST_VRING_CFG_CMDID
:
367 return "WMI_BCAST_VRING_CFG_CMD";
368 case WMI_TRAFFIC_SUSPEND_CMDID
:
369 return "WMI_TRAFFIC_SUSPEND_CMD";
370 case WMI_TRAFFIC_RESUME_CMDID
:
371 return "WMI_TRAFFIC_RESUME_CMD";
373 return "WMI_ECHO_CMD";
374 case WMI_SET_MAC_ADDRESS_CMDID
:
375 return "WMI_SET_MAC_ADDRESS_CMD";
376 case WMI_LED_CFG_CMDID
:
377 return "WMI_LED_CFG_CMD";
378 case WMI_PCP_START_CMDID
:
379 return "WMI_PCP_START_CMD";
380 case WMI_PCP_STOP_CMDID
:
381 return "WMI_PCP_STOP_CMD";
382 case WMI_SET_SSID_CMDID
:
383 return "WMI_SET_SSID_CMD";
384 case WMI_GET_SSID_CMDID
:
385 return "WMI_GET_SSID_CMD";
386 case WMI_SET_PCP_CHANNEL_CMDID
:
387 return "WMI_SET_PCP_CHANNEL_CMD";
388 case WMI_GET_PCP_CHANNEL_CMDID
:
389 return "WMI_GET_PCP_CHANNEL_CMD";
390 case WMI_P2P_CFG_CMDID
:
391 return "WMI_P2P_CFG_CMD";
392 case WMI_PORT_ALLOCATE_CMDID
:
393 return "WMI_PORT_ALLOCATE_CMD";
394 case WMI_PORT_DELETE_CMDID
:
395 return "WMI_PORT_DELETE_CMD";
396 case WMI_START_LISTEN_CMDID
:
397 return "WMI_START_LISTEN_CMD";
398 case WMI_START_SEARCH_CMDID
:
399 return "WMI_START_SEARCH_CMD";
400 case WMI_DISCOVERY_STOP_CMDID
:
401 return "WMI_DISCOVERY_STOP_CMD";
402 case WMI_DELETE_CIPHER_KEY_CMDID
:
403 return "WMI_DELETE_CIPHER_KEY_CMD";
404 case WMI_ADD_CIPHER_KEY_CMDID
:
405 return "WMI_ADD_CIPHER_KEY_CMD";
406 case WMI_SET_APPIE_CMDID
:
407 return "WMI_SET_APPIE_CMD";
408 case WMI_CFG_RX_CHAIN_CMDID
:
409 return "WMI_CFG_RX_CHAIN_CMD";
410 case WMI_TEMP_SENSE_CMDID
:
411 return "WMI_TEMP_SENSE_CMD";
412 case WMI_DEL_STA_CMDID
:
413 return "WMI_DEL_STA_CMD";
414 case WMI_DISCONNECT_STA_CMDID
:
415 return "WMI_DISCONNECT_STA_CMD";
416 case WMI_RING_BA_EN_CMDID
:
417 return "WMI_RING_BA_EN_CMD";
418 case WMI_RING_BA_DIS_CMDID
:
419 return "WMI_RING_BA_DIS_CMD";
420 case WMI_RCP_DELBA_CMDID
:
421 return "WMI_RCP_DELBA_CMD";
422 case WMI_RCP_ADDBA_RESP_CMDID
:
423 return "WMI_RCP_ADDBA_RESP_CMD";
424 case WMI_RCP_ADDBA_RESP_EDMA_CMDID
:
425 return "WMI_RCP_ADDBA_RESP_EDMA_CMD";
426 case WMI_PS_DEV_PROFILE_CFG_CMDID
:
427 return "WMI_PS_DEV_PROFILE_CFG_CMD";
428 case WMI_SET_MGMT_RETRY_LIMIT_CMDID
:
429 return "WMI_SET_MGMT_RETRY_LIMIT_CMD";
430 case WMI_GET_MGMT_RETRY_LIMIT_CMDID
:
431 return "WMI_GET_MGMT_RETRY_LIMIT_CMD";
432 case WMI_ABORT_SCAN_CMDID
:
433 return "WMI_ABORT_SCAN_CMD";
434 case WMI_NEW_STA_CMDID
:
435 return "WMI_NEW_STA_CMD";
436 case WMI_SET_THERMAL_THROTTLING_CFG_CMDID
:
437 return "WMI_SET_THERMAL_THROTTLING_CFG_CMD";
438 case WMI_GET_THERMAL_THROTTLING_CFG_CMDID
:
439 return "WMI_GET_THERMAL_THROTTLING_CFG_CMD";
440 case WMI_LINK_MAINTAIN_CFG_WRITE_CMDID
:
441 return "WMI_LINK_MAINTAIN_CFG_WRITE_CMD";
442 case WMI_LO_POWER_CALIB_FROM_OTP_CMDID
:
443 return "WMI_LO_POWER_CALIB_FROM_OTP_CMD";
444 case WMI_START_SCHED_SCAN_CMDID
:
445 return "WMI_START_SCHED_SCAN_CMD";
446 case WMI_STOP_SCHED_SCAN_CMDID
:
447 return "WMI_STOP_SCHED_SCAN_CMD";
448 case WMI_TX_STATUS_RING_ADD_CMDID
:
449 return "WMI_TX_STATUS_RING_ADD_CMD";
450 case WMI_RX_STATUS_RING_ADD_CMDID
:
451 return "WMI_RX_STATUS_RING_ADD_CMD";
452 case WMI_TX_DESC_RING_ADD_CMDID
:
453 return "WMI_TX_DESC_RING_ADD_CMD";
454 case WMI_RX_DESC_RING_ADD_CMDID
:
455 return "WMI_RX_DESC_RING_ADD_CMD";
456 case WMI_BCAST_DESC_RING_ADD_CMDID
:
457 return "WMI_BCAST_DESC_RING_ADD_CMD";
458 case WMI_CFG_DEF_RX_OFFLOAD_CMDID
:
459 return "WMI_CFG_DEF_RX_OFFLOAD_CMD";
460 case WMI_LINK_STATS_CMDID
:
461 return "WMI_LINK_STATS_CMD";
462 case WMI_SW_TX_REQ_EXT_CMDID
:
463 return "WMI_SW_TX_REQ_EXT_CMDID";
464 case WMI_FT_AUTH_CMDID
:
465 return "WMI_FT_AUTH_CMD";
466 case WMI_FT_REASSOC_CMDID
:
467 return "WMI_FT_REASSOC_CMD";
468 case WMI_UPDATE_FT_IES_CMDID
:
469 return "WMI_UPDATE_FT_IES_CMD";
470 case WMI_RBUFCAP_CFG_CMDID
:
471 return "WMI_RBUFCAP_CFG_CMD";
472 case WMI_TEMP_SENSE_ALL_CMDID
:
473 return "WMI_TEMP_SENSE_ALL_CMDID";
474 case WMI_SET_LINK_MONITOR_CMDID
:
475 return "WMI_SET_LINK_MONITOR_CMD";
477 return "Untracked CMD";
481 static const char *eventid2name(u16 eventid
)
484 case WMI_NOTIFY_REQ_DONE_EVENTID
:
485 return "WMI_NOTIFY_REQ_DONE_EVENT";
486 case WMI_DISCONNECT_EVENTID
:
487 return "WMI_DISCONNECT_EVENT";
488 case WMI_SW_TX_COMPLETE_EVENTID
:
489 return "WMI_SW_TX_COMPLETE_EVENT";
490 case WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID
:
491 return "WMI_GET_RF_SECTOR_PARAMS_DONE_EVENT";
492 case WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID
:
493 return "WMI_SET_RF_SECTOR_PARAMS_DONE_EVENT";
494 case WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID
:
495 return "WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
496 case WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID
:
497 return "WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT";
498 case WMI_BRP_SET_ANT_LIMIT_EVENTID
:
499 return "WMI_BRP_SET_ANT_LIMIT_EVENT";
500 case WMI_FW_READY_EVENTID
:
501 return "WMI_FW_READY_EVENT";
502 case WMI_TRAFFIC_RESUME_EVENTID
:
503 return "WMI_TRAFFIC_RESUME_EVENT";
504 case WMI_TOF_GET_TX_RX_OFFSET_EVENTID
:
505 return "WMI_TOF_GET_TX_RX_OFFSET_EVENT";
506 case WMI_TOF_SET_TX_RX_OFFSET_EVENTID
:
507 return "WMI_TOF_SET_TX_RX_OFFSET_EVENT";
508 case WMI_VRING_CFG_DONE_EVENTID
:
509 return "WMI_VRING_CFG_DONE_EVENT";
510 case WMI_READY_EVENTID
:
511 return "WMI_READY_EVENT";
512 case WMI_RX_MGMT_PACKET_EVENTID
:
513 return "WMI_RX_MGMT_PACKET_EVENT";
514 case WMI_TX_MGMT_PACKET_EVENTID
:
515 return "WMI_TX_MGMT_PACKET_EVENT";
516 case WMI_SCAN_COMPLETE_EVENTID
:
517 return "WMI_SCAN_COMPLETE_EVENT";
518 case WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID
:
519 return "WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT";
520 case WMI_CONNECT_EVENTID
:
521 return "WMI_CONNECT_EVENT";
522 case WMI_EAPOL_RX_EVENTID
:
523 return "WMI_EAPOL_RX_EVENT";
524 case WMI_BA_STATUS_EVENTID
:
525 return "WMI_BA_STATUS_EVENT";
526 case WMI_RCP_ADDBA_REQ_EVENTID
:
527 return "WMI_RCP_ADDBA_REQ_EVENT";
528 case WMI_DELBA_EVENTID
:
529 return "WMI_DELBA_EVENT";
530 case WMI_RING_EN_EVENTID
:
531 return "WMI_RING_EN_EVENT";
532 case WMI_DATA_PORT_OPEN_EVENTID
:
533 return "WMI_DATA_PORT_OPEN_EVENT";
534 case WMI_AOA_MEAS_EVENTID
:
535 return "WMI_AOA_MEAS_EVENT";
536 case WMI_TOF_SESSION_END_EVENTID
:
537 return "WMI_TOF_SESSION_END_EVENT";
538 case WMI_TOF_GET_CAPABILITIES_EVENTID
:
539 return "WMI_TOF_GET_CAPABILITIES_EVENT";
540 case WMI_TOF_SET_LCR_EVENTID
:
541 return "WMI_TOF_SET_LCR_EVENT";
542 case WMI_TOF_SET_LCI_EVENTID
:
543 return "WMI_TOF_SET_LCI_EVENT";
544 case WMI_TOF_FTM_PER_DEST_RES_EVENTID
:
545 return "WMI_TOF_FTM_PER_DEST_RES_EVENT";
546 case WMI_TOF_CHANNEL_INFO_EVENTID
:
547 return "WMI_TOF_CHANNEL_INFO_EVENT";
548 case WMI_TRAFFIC_SUSPEND_EVENTID
:
549 return "WMI_TRAFFIC_SUSPEND_EVENT";
550 case WMI_ECHO_RSP_EVENTID
:
551 return "WMI_ECHO_RSP_EVENT";
552 case WMI_LED_CFG_DONE_EVENTID
:
553 return "WMI_LED_CFG_DONE_EVENT";
554 case WMI_PCP_STARTED_EVENTID
:
555 return "WMI_PCP_STARTED_EVENT";
556 case WMI_PCP_STOPPED_EVENTID
:
557 return "WMI_PCP_STOPPED_EVENT";
558 case WMI_GET_SSID_EVENTID
:
559 return "WMI_GET_SSID_EVENT";
560 case WMI_GET_PCP_CHANNEL_EVENTID
:
561 return "WMI_GET_PCP_CHANNEL_EVENT";
562 case WMI_P2P_CFG_DONE_EVENTID
:
563 return "WMI_P2P_CFG_DONE_EVENT";
564 case WMI_PORT_ALLOCATED_EVENTID
:
565 return "WMI_PORT_ALLOCATED_EVENT";
566 case WMI_PORT_DELETED_EVENTID
:
567 return "WMI_PORT_DELETED_EVENT";
568 case WMI_LISTEN_STARTED_EVENTID
:
569 return "WMI_LISTEN_STARTED_EVENT";
570 case WMI_SEARCH_STARTED_EVENTID
:
571 return "WMI_SEARCH_STARTED_EVENT";
572 case WMI_DISCOVERY_STOPPED_EVENTID
:
573 return "WMI_DISCOVERY_STOPPED_EVENT";
574 case WMI_CFG_RX_CHAIN_DONE_EVENTID
:
575 return "WMI_CFG_RX_CHAIN_DONE_EVENT";
576 case WMI_TEMP_SENSE_DONE_EVENTID
:
577 return "WMI_TEMP_SENSE_DONE_EVENT";
578 case WMI_RCP_ADDBA_RESP_SENT_EVENTID
:
579 return "WMI_RCP_ADDBA_RESP_SENT_EVENT";
580 case WMI_PS_DEV_PROFILE_CFG_EVENTID
:
581 return "WMI_PS_DEV_PROFILE_CFG_EVENT";
582 case WMI_SET_MGMT_RETRY_LIMIT_EVENTID
:
583 return "WMI_SET_MGMT_RETRY_LIMIT_EVENT";
584 case WMI_GET_MGMT_RETRY_LIMIT_EVENTID
:
585 return "WMI_GET_MGMT_RETRY_LIMIT_EVENT";
586 case WMI_SET_THERMAL_THROTTLING_CFG_EVENTID
:
587 return "WMI_SET_THERMAL_THROTTLING_CFG_EVENT";
588 case WMI_GET_THERMAL_THROTTLING_CFG_EVENTID
:
589 return "WMI_GET_THERMAL_THROTTLING_CFG_EVENT";
590 case WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID
:
591 return "WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENT";
592 case WMI_LO_POWER_CALIB_FROM_OTP_EVENTID
:
593 return "WMI_LO_POWER_CALIB_FROM_OTP_EVENT";
594 case WMI_START_SCHED_SCAN_EVENTID
:
595 return "WMI_START_SCHED_SCAN_EVENT";
596 case WMI_STOP_SCHED_SCAN_EVENTID
:
597 return "WMI_STOP_SCHED_SCAN_EVENT";
598 case WMI_SCHED_SCAN_RESULT_EVENTID
:
599 return "WMI_SCHED_SCAN_RESULT_EVENT";
600 case WMI_TX_STATUS_RING_CFG_DONE_EVENTID
:
601 return "WMI_TX_STATUS_RING_CFG_DONE_EVENT";
602 case WMI_RX_STATUS_RING_CFG_DONE_EVENTID
:
603 return "WMI_RX_STATUS_RING_CFG_DONE_EVENT";
604 case WMI_TX_DESC_RING_CFG_DONE_EVENTID
:
605 return "WMI_TX_DESC_RING_CFG_DONE_EVENT";
606 case WMI_RX_DESC_RING_CFG_DONE_EVENTID
:
607 return "WMI_RX_DESC_RING_CFG_DONE_EVENT";
608 case WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID
:
609 return "WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENT";
610 case WMI_LINK_STATS_CONFIG_DONE_EVENTID
:
611 return "WMI_LINK_STATS_CONFIG_DONE_EVENT";
612 case WMI_LINK_STATS_EVENTID
:
613 return "WMI_LINK_STATS_EVENT";
614 case WMI_COMMAND_NOT_SUPPORTED_EVENTID
:
615 return "WMI_COMMAND_NOT_SUPPORTED_EVENT";
616 case WMI_FT_AUTH_STATUS_EVENTID
:
617 return "WMI_FT_AUTH_STATUS_EVENT";
618 case WMI_FT_REASSOC_STATUS_EVENTID
:
619 return "WMI_FT_REASSOC_STATUS_EVENT";
620 case WMI_RBUFCAP_CFG_EVENTID
:
621 return "WMI_RBUFCAP_CFG_EVENT";
622 case WMI_TEMP_SENSE_ALL_DONE_EVENTID
:
623 return "WMI_TEMP_SENSE_ALL_DONE_EVENTID";
624 case WMI_SET_LINK_MONITOR_EVENTID
:
625 return "WMI_SET_LINK_MONITOR_EVENT";
626 case WMI_LINK_MONITOR_EVENTID
:
627 return "WMI_LINK_MONITOR_EVENT";
629 return "Untracked EVENT";
633 static int __wmi_send(struct wil6210_priv
*wil
, u16 cmdid
, u8 mid
,
637 struct wil6210_mbox_hdr hdr
;
638 struct wmi_cmd_hdr wmi
;
641 .type
= WIL_MBOX_HDR_TYPE_WMI
,
643 .len
= cpu_to_le16(sizeof(cmd
.wmi
) + len
),
647 .command_id
= cpu_to_le16(cmdid
),
650 struct wil6210_mbox_ring
*r
= &wil
->mbox_ctl
.tx
;
651 struct wil6210_mbox_ring_desc d_head
;
654 void __iomem
*head
= wmi_addr(wil
, r
->head
);
658 if (len
> r
->entry_size
- sizeof(cmd
)) {
659 wil_err(wil
, "WMI size too large: %d bytes, max is %d\n",
660 (int)(sizeof(cmd
) + len
), r
->entry_size
);
666 if (!test_bit(wil_status_fwready
, wil
->status
)) {
667 wil_err(wil
, "WMI: cannot send command while FW not ready\n");
671 /* Allow sending only suspend / resume commands during susepnd flow */
672 if ((test_bit(wil_status_suspending
, wil
->status
) ||
673 test_bit(wil_status_suspended
, wil
->status
) ||
674 test_bit(wil_status_resuming
, wil
->status
)) &&
675 ((cmdid
!= WMI_TRAFFIC_SUSPEND_CMDID
) &&
676 (cmdid
!= WMI_TRAFFIC_RESUME_CMDID
))) {
677 wil_err(wil
, "WMI: reject send_command during suspend\n");
682 wil_err(wil
, "WMI head is garbage: 0x%08x\n", r
->head
);
688 /* read Tx head till it is not busy */
689 for (retry
= 5; retry
> 0; retry
--) {
690 wil_memcpy_fromio_32(&d_head
, head
, sizeof(d_head
));
691 if (d_head
.sync
== 0)
695 if (d_head
.sync
!= 0) {
696 wil_err(wil
, "WMI head busy\n");
701 next_head
= r
->base
+ ((r
->head
- r
->base
+ sizeof(d_head
)) % r
->size
);
702 wil_dbg_wmi(wil
, "Head 0x%08x -> 0x%08x\n", r
->head
, next_head
);
703 /* wait till FW finish with previous command */
704 for (retry
= 5; retry
> 0; retry
--) {
705 if (!test_bit(wil_status_fwready
, wil
->status
)) {
706 wil_err(wil
, "WMI: cannot send command while FW not ready\n");
710 r
->tail
= wil_r(wil
, RGF_MBOX
+
711 offsetof(struct wil6210_mbox_ctl
, tx
.tail
));
712 if (next_head
!= r
->tail
)
716 if (next_head
== r
->tail
) {
717 wil_err(wil
, "WMI ring full\n");
721 dst
= wmi_buffer(wil
, d_head
.addr
);
723 wil_err(wil
, "invalid WMI buffer: 0x%08x\n",
724 le32_to_cpu(d_head
.addr
));
728 cmd
.hdr
.seq
= cpu_to_le16(++wil
->wmi_seq
);
730 wil_dbg_wmi(wil
, "sending %s (0x%04x) [%d] mid %d\n",
731 cmdid2name(cmdid
), cmdid
, len
, mid
);
732 wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET
, 16, 1, &cmd
,
734 wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET
, 16, 1, buf
,
736 wil_memcpy_toio_32(dst
, &cmd
, sizeof(cmd
));
737 wil_memcpy_toio_32(dst
+ sizeof(cmd
), buf
, len
);
738 /* mark entry as full */
739 wil_w(wil
, r
->head
+ offsetof(struct wil6210_mbox_ring_desc
, sync
), 1);
740 /* advance next ptr */
741 wil_w(wil
, RGF_MBOX
+ offsetof(struct wil6210_mbox_ctl
, tx
.head
),
742 r
->head
= next_head
);
744 trace_wil6210_wmi_cmd(&cmd
.wmi
, buf
, len
);
746 /* interrupt to FW */
747 wil_w(wil
, RGF_USER_USER_ICR
+ offsetof(struct RGF_ICR
, ICS
),
751 wil_halp_unvote(wil
);
755 int wmi_send(struct wil6210_priv
*wil
, u16 cmdid
, u8 mid
, void *buf
, u16 len
)
759 mutex_lock(&wil
->wmi_mutex
);
760 rc
= __wmi_send(wil
, cmdid
, mid
, buf
, len
);
761 mutex_unlock(&wil
->wmi_mutex
);
766 /*=== Event handlers ===*/
767 static void wmi_evt_ready(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
769 struct wil6210_priv
*wil
= vif_to_wil(vif
);
770 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
771 struct wmi_ready_event
*evt
= d
;
774 wil_info(wil
, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
775 wil
->fw_version
, le32_to_cpu(evt
->sw_version
),
776 evt
->mac
, evt
->numof_additional_mids
);
777 if (evt
->numof_additional_mids
+ 1 < wil
->max_vifs
) {
778 wil_err(wil
, "FW does not support enough MIDs (need %d)",
780 return; /* FW load will fail after timeout */
782 /* ignore MAC address, we already have it from the boot loader */
783 strscpy(wiphy
->fw_version
, wil
->fw_version
, sizeof(wiphy
->fw_version
));
785 if (len
> offsetof(struct wmi_ready_event
, rfc_read_calib_result
)) {
786 wil_dbg_wmi(wil
, "rfc calibration result %d\n",
787 evt
->rfc_read_calib_result
);
788 wil
->fw_calib_result
= evt
->rfc_read_calib_result
;
791 fw_max_assoc_sta
= WIL6210_RX_DESC_MAX_CID
;
792 if (len
> offsetof(struct wmi_ready_event
, max_assoc_sta
) &&
793 evt
->max_assoc_sta
> 0) {
794 fw_max_assoc_sta
= evt
->max_assoc_sta
;
795 wil_dbg_wmi(wil
, "fw reported max assoc sta %d\n",
798 if (fw_max_assoc_sta
> WIL6210_MAX_CID
) {
800 "fw max assoc sta %d exceeds max driver supported %d\n",
801 fw_max_assoc_sta
, WIL6210_MAX_CID
);
802 fw_max_assoc_sta
= WIL6210_MAX_CID
;
806 wil
->max_assoc_sta
= min_t(uint
, max_assoc_sta
, fw_max_assoc_sta
);
807 wil_dbg_wmi(wil
, "setting max assoc sta to %d\n", wil
->max_assoc_sta
);
809 wil_set_recovery_state(wil
, fw_recovery_idle
);
810 set_bit(wil_status_fwready
, wil
->status
);
811 /* let the reset sequence continue */
812 complete(&wil
->wmi_ready
);
815 static void wmi_evt_rx_mgmt(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
817 struct wil6210_priv
*wil
= vif_to_wil(vif
);
818 struct wmi_rx_mgmt_packet_event
*data
= d
;
819 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
820 struct ieee80211_mgmt
*rx_mgmt_frame
=
821 (struct ieee80211_mgmt
*)data
->payload
;
822 int flen
= len
- offsetof(struct wmi_rx_mgmt_packet_event
, payload
);
825 struct ieee80211_channel
*channel
;
832 wil_err(wil
, "MGMT Rx: short event, len %d\n", len
);
836 d_len
= le32_to_cpu(data
->info
.len
);
839 "MGMT Rx: length mismatch, d_len %d should be %d\n",
844 ch_no
= data
->info
.channel
+ 1;
845 freq
= ieee80211_channel_to_frequency(ch_no
, NL80211_BAND_60GHZ
);
846 channel
= ieee80211_get_channel(wiphy
, freq
);
847 if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING
, wil
->fw_capabilities
))
848 signal
= 100 * data
->info
.rssi
;
850 signal
= data
->info
.sqi
;
851 d_status
= le16_to_cpu(data
->info
.status
);
852 fc
= rx_mgmt_frame
->frame_control
;
854 wil_dbg_wmi(wil
, "MGMT Rx: channel %d MCS %s RSSI %d SQI %d%%\n",
855 data
->info
.channel
, WIL_EXTENDED_MCS_CHECK(data
->info
.mcs
),
856 data
->info
.rssi
, data
->info
.sqi
);
857 wil_dbg_wmi(wil
, "status 0x%04x len %d fc 0x%04x\n", d_status
, d_len
,
859 wil_dbg_wmi(wil
, "qid %d mid %d cid %d\n",
860 data
->info
.qid
, data
->info
.mid
, data
->info
.cid
);
861 wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET
, 16, 1, rx_mgmt_frame
,
865 wil_err(wil
, "Frame on unsupported channel\n");
869 if (ieee80211_is_beacon(fc
) || ieee80211_is_probe_resp(fc
)) {
870 struct cfg80211_bss
*bss
;
871 struct cfg80211_inform_bss bss_data
= {
874 .boottime_ns
= ktime_to_ns(ktime_get_boottime()),
876 u64 tsf
= le64_to_cpu(rx_mgmt_frame
->u
.beacon
.timestamp
);
877 u16 cap
= le16_to_cpu(rx_mgmt_frame
->u
.beacon
.capab_info
);
878 u16 bi
= le16_to_cpu(rx_mgmt_frame
->u
.beacon
.beacon_int
);
879 const u8
*ie_buf
= rx_mgmt_frame
->u
.beacon
.variable
;
880 size_t ie_len
= d_len
- offsetof(struct ieee80211_mgmt
,
882 wil_dbg_wmi(wil
, "Capability info : 0x%04x\n", cap
);
883 wil_dbg_wmi(wil
, "TSF : 0x%016llx\n", tsf
);
884 wil_dbg_wmi(wil
, "Beacon interval : %d\n", bi
);
885 wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET
, 16, 1, ie_buf
,
888 wil_dbg_wmi(wil
, "Capability info : 0x%04x\n", cap
);
890 bss
= cfg80211_inform_bss_frame_data(wiphy
, &bss_data
,
894 wil_dbg_wmi(wil
, "Added BSS %pM\n",
895 rx_mgmt_frame
->bssid
);
896 cfg80211_put_bss(wiphy
, bss
);
898 wil_err(wil
, "cfg80211_inform_bss_frame() failed\n");
901 mutex_lock(&wil
->vif_mutex
);
902 cfg80211_rx_mgmt(vif_to_radio_wdev(wil
, vif
), freq
, signal
,
903 (void *)rx_mgmt_frame
, d_len
, 0);
904 mutex_unlock(&wil
->vif_mutex
);
908 static void wmi_evt_tx_mgmt(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
910 struct wmi_tx_mgmt_packet_event
*data
= d
;
911 struct ieee80211_mgmt
*mgmt_frame
=
912 (struct ieee80211_mgmt
*)data
->payload
;
913 int flen
= len
- offsetof(struct wmi_tx_mgmt_packet_event
, payload
);
915 wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET
, 16, 1, mgmt_frame
,
919 static void wmi_evt_scan_complete(struct wil6210_vif
*vif
, int id
,
922 struct wil6210_priv
*wil
= vif_to_wil(vif
);
924 mutex_lock(&wil
->vif_mutex
);
925 if (vif
->scan_request
) {
926 struct wmi_scan_complete_event
*data
= d
;
927 int status
= le32_to_cpu(data
->status
);
928 struct cfg80211_scan_info info
= {
929 .aborted
= ((status
!= WMI_SCAN_SUCCESS
) &&
930 (status
!= WMI_SCAN_ABORT_REJECTED
)),
933 wil_dbg_wmi(wil
, "SCAN_COMPLETE(0x%08x)\n", status
);
934 wil_dbg_misc(wil
, "Complete scan_request 0x%p aborted %d\n",
935 vif
->scan_request
, info
.aborted
);
936 del_timer_sync(&vif
->scan_timer
);
937 cfg80211_scan_done(vif
->scan_request
, &info
);
939 wil
->radio_wdev
= wil
->main_ndev
->ieee80211_ptr
;
940 vif
->scan_request
= NULL
;
941 wake_up_interruptible(&wil
->wq
);
942 if (vif
->p2p
.pending_listen_wdev
) {
943 wil_dbg_misc(wil
, "Scheduling delayed listen\n");
944 schedule_work(&vif
->p2p
.delayed_listen_work
);
947 wil_err(wil
, "SCAN_COMPLETE while not scanning\n");
949 mutex_unlock(&wil
->vif_mutex
);
952 static void wmi_evt_connect(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
954 struct wil6210_priv
*wil
= vif_to_wil(vif
);
955 struct net_device
*ndev
= vif_to_ndev(vif
);
956 struct wireless_dev
*wdev
= vif_to_wdev(vif
);
957 struct wmi_connect_event
*evt
= d
;
958 int ch
; /* channel number */
959 struct station_info
*sinfo
;
960 u8
*assoc_req_ie
, *assoc_resp_ie
;
961 size_t assoc_req_ielen
, assoc_resp_ielen
;
962 /* capinfo(u16) + listen_interval(u16) + IEs */
963 const size_t assoc_req_ie_offset
= sizeof(u16
) * 2;
964 /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
965 const size_t assoc_resp_ie_offset
= sizeof(u16
) * 3;
968 if (len
< sizeof(*evt
)) {
969 wil_err(wil
, "Connect event too short : %d bytes\n", len
);
972 if (len
!= sizeof(*evt
) + evt
->beacon_ie_len
+ evt
->assoc_req_len
+
973 evt
->assoc_resp_len
) {
975 "Connect event corrupted : %d != %d + %d + %d + %d\n",
976 len
, (int)sizeof(*evt
), evt
->beacon_ie_len
,
977 evt
->assoc_req_len
, evt
->assoc_resp_len
);
980 if (evt
->cid
>= wil
->max_assoc_sta
) {
981 wil_err(wil
, "Connect CID invalid : %d\n", evt
->cid
);
985 ch
= evt
->channel
+ 1;
986 wil_info(wil
, "Connect %pM channel [%d] cid %d aid %d\n",
987 evt
->bssid
, ch
, evt
->cid
, evt
->aid
);
988 wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET
, 16, 1,
989 evt
->assoc_info
, len
- sizeof(*evt
), true);
991 /* figure out IE's */
992 assoc_req_ie
= &evt
->assoc_info
[evt
->beacon_ie_len
+
993 assoc_req_ie_offset
];
994 assoc_req_ielen
= evt
->assoc_req_len
- assoc_req_ie_offset
;
995 if (evt
->assoc_req_len
<= assoc_req_ie_offset
) {
1000 assoc_resp_ie
= &evt
->assoc_info
[evt
->beacon_ie_len
+
1001 evt
->assoc_req_len
+
1002 assoc_resp_ie_offset
];
1003 assoc_resp_ielen
= evt
->assoc_resp_len
- assoc_resp_ie_offset
;
1004 if (evt
->assoc_resp_len
<= assoc_resp_ie_offset
) {
1005 assoc_resp_ie
= NULL
;
1006 assoc_resp_ielen
= 0;
1009 if (test_bit(wil_status_resetting
, wil
->status
) ||
1010 !test_bit(wil_status_fwready
, wil
->status
)) {
1011 wil_err(wil
, "status_resetting, cancel connect event, CID %d\n",
1013 /* no need for cleanup, wil_reset will do that */
1017 mutex_lock(&wil
->mutex
);
1019 if ((wdev
->iftype
== NL80211_IFTYPE_STATION
) ||
1020 (wdev
->iftype
== NL80211_IFTYPE_P2P_CLIENT
)) {
1021 if (!test_bit(wil_vif_fwconnecting
, vif
->status
)) {
1022 wil_err(wil
, "Not in connecting state\n");
1023 mutex_unlock(&wil
->mutex
);
1026 del_timer_sync(&vif
->connect_timer
);
1027 } else if ((wdev
->iftype
== NL80211_IFTYPE_AP
) ||
1028 (wdev
->iftype
== NL80211_IFTYPE_P2P_GO
)) {
1029 if (wil
->sta
[evt
->cid
].status
!= wil_sta_unused
) {
1030 wil_err(wil
, "AP: Invalid status %d for CID %d\n",
1031 wil
->sta
[evt
->cid
].status
, evt
->cid
);
1032 mutex_unlock(&wil
->mutex
);
1037 ether_addr_copy(wil
->sta
[evt
->cid
].addr
, evt
->bssid
);
1038 wil
->sta
[evt
->cid
].mid
= vif
->mid
;
1039 wil
->sta
[evt
->cid
].status
= wil_sta_conn_pending
;
1041 rc
= wil_ring_init_tx(vif
, evt
->cid
);
1043 wil_err(wil
, "config tx vring failed for CID %d, rc (%d)\n",
1045 wmi_disconnect_sta(vif
, wil
->sta
[evt
->cid
].addr
,
1046 WLAN_REASON_UNSPECIFIED
, false);
1048 wil_info(wil
, "successful connection to CID %d\n", evt
->cid
);
1051 if ((wdev
->iftype
== NL80211_IFTYPE_STATION
) ||
1052 (wdev
->iftype
== NL80211_IFTYPE_P2P_CLIENT
)) {
1054 netif_carrier_off(ndev
);
1055 wil6210_bus_request(wil
, WIL_DEFAULT_BUS_REQUEST_KBPS
);
1056 wil_err(wil
, "cfg80211_connect_result with failure\n");
1057 cfg80211_connect_result(ndev
, evt
->bssid
, NULL
, 0,
1059 WLAN_STATUS_UNSPECIFIED_FAILURE
,
1063 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
1065 cfg80211_ref_bss(wiphy
, vif
->bss
);
1066 cfg80211_connect_bss(ndev
, evt
->bssid
, vif
->bss
,
1067 assoc_req_ie
, assoc_req_ielen
,
1068 assoc_resp_ie
, assoc_resp_ielen
,
1069 WLAN_STATUS_SUCCESS
, GFP_KERNEL
,
1070 NL80211_TIMEOUT_UNSPECIFIED
);
1073 } else if ((wdev
->iftype
== NL80211_IFTYPE_AP
) ||
1074 (wdev
->iftype
== NL80211_IFTYPE_P2P_GO
)) {
1078 /* notify new_sta has failed */
1079 cfg80211_del_sta(ndev
, evt
->bssid
, GFP_KERNEL
);
1083 sinfo
= kzalloc(sizeof(*sinfo
), GFP_KERNEL
);
1089 sinfo
->generation
= wil
->sinfo_gen
++;
1092 sinfo
->assoc_req_ies
= assoc_req_ie
;
1093 sinfo
->assoc_req_ies_len
= assoc_req_ielen
;
1096 cfg80211_new_sta(ndev
, evt
->bssid
, sinfo
, GFP_KERNEL
);
1100 wil_err(wil
, "unhandled iftype %d for CID %d\n", wdev
->iftype
,
1105 wil
->sta
[evt
->cid
].status
= wil_sta_connected
;
1106 wil
->sta
[evt
->cid
].aid
= evt
->aid
;
1107 if (!test_and_set_bit(wil_vif_fwconnected
, vif
->status
))
1108 atomic_inc(&wil
->connected_vifs
);
1109 wil_update_net_queues_bh(wil
, vif
, NULL
, false);
1113 wil
->sta
[evt
->cid
].status
= wil_sta_unused
;
1114 wil
->sta
[evt
->cid
].mid
= U8_MAX
;
1116 clear_bit(wil_vif_fwconnecting
, vif
->status
);
1117 mutex_unlock(&wil
->mutex
);
1120 static void wmi_evt_disconnect(struct wil6210_vif
*vif
, int id
,
1123 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1124 struct wmi_disconnect_event
*evt
= d
;
1125 u16 reason_code
= le16_to_cpu(evt
->protocol_reason_status
);
1127 wil_info(wil
, "Disconnect %pM reason [proto %d wmi %d]\n",
1128 evt
->bssid
, reason_code
, evt
->disconnect_reason
);
1132 if (test_bit(wil_status_resetting
, wil
->status
) ||
1133 !test_bit(wil_status_fwready
, wil
->status
)) {
1134 wil_err(wil
, "status_resetting, cancel disconnect event\n");
1135 /* no need for cleanup, wil_reset will do that */
1139 mutex_lock(&wil
->mutex
);
1140 wil6210_disconnect_complete(vif
, evt
->bssid
, reason_code
);
1141 if (disable_ap_sme
) {
1142 struct wireless_dev
*wdev
= vif_to_wdev(vif
);
1143 struct net_device
*ndev
= vif_to_ndev(vif
);
1145 /* disconnect event in disable_ap_sme mode means link loss */
1146 switch (wdev
->iftype
) {
1147 /* AP-like interface */
1148 case NL80211_IFTYPE_AP
:
1149 case NL80211_IFTYPE_P2P_GO
:
1150 /* notify hostapd about link loss */
1151 cfg80211_cqm_pktloss_notify(ndev
, evt
->bssid
, 0,
1158 mutex_unlock(&wil
->mutex
);
1162 * Firmware reports EAPOL frame using WME event.
1163 * Reconstruct Ethernet frame and deliver it via normal Rx
1165 static void wmi_evt_eapol_rx(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1167 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1168 struct net_device
*ndev
= vif_to_ndev(vif
);
1169 struct wmi_eapol_rx_event
*evt
= d
;
1170 u16 eapol_len
= le16_to_cpu(evt
->eapol_len
);
1171 int sz
= eapol_len
+ ETH_HLEN
;
1172 struct sk_buff
*skb
;
1175 struct wil_net_stats
*stats
= NULL
;
1177 wil_dbg_wmi(wil
, "EAPOL len %d from %pM MID %d\n", eapol_len
,
1178 evt
->src_mac
, vif
->mid
);
1180 cid
= wil_find_cid(wil
, vif
->mid
, evt
->src_mac
);
1182 stats
= &wil
->sta
[cid
].stats
;
1184 if (eapol_len
> 196) { /* TODO: revisit size limit */
1185 wil_err(wil
, "EAPOL too large\n");
1189 skb
= alloc_skb(sz
, GFP_KERNEL
);
1191 wil_err(wil
, "Failed to allocate skb\n");
1195 eth
= skb_put(skb
, ETH_HLEN
);
1196 ether_addr_copy(eth
->h_dest
, ndev
->dev_addr
);
1197 ether_addr_copy(eth
->h_source
, evt
->src_mac
);
1198 eth
->h_proto
= cpu_to_be16(ETH_P_PAE
);
1199 skb_put_data(skb
, evt
->eapol
, eapol_len
);
1200 skb
->protocol
= eth_type_trans(skb
, ndev
);
1201 if (likely(netif_rx(skb
) == NET_RX_SUCCESS
)) {
1202 ndev
->stats
.rx_packets
++;
1203 ndev
->stats
.rx_bytes
+= sz
;
1205 stats
->rx_packets
++;
1206 stats
->rx_bytes
+= sz
;
1209 ndev
->stats
.rx_dropped
++;
1211 stats
->rx_dropped
++;
1215 static void wmi_evt_ring_en(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1217 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1218 struct wmi_ring_en_event
*evt
= d
;
1219 u8 vri
= evt
->ring_index
;
1220 struct wireless_dev
*wdev
= vif_to_wdev(vif
);
1221 struct wil_sta_info
*sta
;
1223 struct key_params params
;
1225 wil_dbg_wmi(wil
, "Enable vring %d MID %d\n", vri
, vif
->mid
);
1227 if (vri
>= ARRAY_SIZE(wil
->ring_tx
)) {
1228 wil_err(wil
, "Enable for invalid vring %d\n", vri
);
1232 if (wdev
->iftype
!= NL80211_IFTYPE_AP
|| !disable_ap_sme
||
1233 test_bit(wil_vif_ft_roam
, vif
->status
))
1234 /* in AP mode with disable_ap_sme that is not FT,
1235 * this is done by wil_cfg80211_change_station()
1237 wil
->ring_tx_data
[vri
].dot1x_open
= true;
1238 if (vri
== vif
->bcast_ring
) /* no BA for bcast */
1241 cid
= wil
->ring2cid_tid
[vri
][0];
1242 if (!wil_cid_valid(wil
, cid
)) {
1243 wil_err(wil
, "invalid cid %d for vring %d\n", cid
, vri
);
1247 /* In FT mode we get key but not store it as it is received
1248 * before WMI_CONNECT_EVENT received from FW.
1249 * wil_set_crypto_rx is called here to reset the security PN
1251 sta
= &wil
->sta
[cid
];
1252 if (test_bit(wil_vif_ft_roam
, vif
->status
)) {
1253 memset(¶ms
, 0, sizeof(params
));
1254 wil_set_crypto_rx(0, WMI_KEY_USE_PAIRWISE
, sta
, ¶ms
);
1255 if (wdev
->iftype
!= NL80211_IFTYPE_AP
)
1256 clear_bit(wil_vif_ft_roam
, vif
->status
);
1260 wil_addba_tx_request(wil
, vri
, agg_wsize
);
1263 static void wmi_evt_ba_status(struct wil6210_vif
*vif
, int id
,
1266 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1267 struct wmi_ba_status_event
*evt
= d
;
1268 struct wil_ring_tx_data
*txdata
;
1270 wil_dbg_wmi(wil
, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
1272 evt
->status
== WMI_BA_AGREED
? "OK" : "N/A",
1273 evt
->agg_wsize
, __le16_to_cpu(evt
->ba_timeout
),
1274 evt
->amsdu
? "+" : "-");
1276 if (evt
->ringid
>= WIL6210_MAX_TX_RINGS
) {
1277 wil_err(wil
, "invalid ring id %d\n", evt
->ringid
);
1281 if (evt
->status
!= WMI_BA_AGREED
) {
1282 evt
->ba_timeout
= 0;
1287 txdata
= &wil
->ring_tx_data
[evt
->ringid
];
1289 txdata
->agg_timeout
= le16_to_cpu(evt
->ba_timeout
);
1290 txdata
->agg_wsize
= evt
->agg_wsize
;
1291 txdata
->agg_amsdu
= evt
->amsdu
;
1292 txdata
->addba_in_progress
= false;
1295 static void wmi_evt_addba_rx_req(struct wil6210_vif
*vif
, int id
,
1298 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1300 struct wmi_rcp_addba_req_event
*evt
= d
;
1302 if (evt
->cidxtid
!= CIDXTID_EXTENDED_CID_TID
) {
1303 parse_cidxtid(evt
->cidxtid
, &cid
, &tid
);
1308 wil_addba_rx_request(wil
, vif
->mid
, cid
, tid
, evt
->dialog_token
,
1309 evt
->ba_param_set
, evt
->ba_timeout
,
1313 static void wmi_evt_delba(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1314 __acquires(&sta
->tid_rx_lock
) __releases(&sta
->tid_rx_lock
)
1316 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1317 struct wmi_delba_event
*evt
= d
;
1319 u16 reason
= __le16_to_cpu(evt
->reason
);
1320 struct wil_sta_info
*sta
;
1321 struct wil_tid_ampdu_rx
*r
;
1325 if (evt
->cidxtid
!= CIDXTID_EXTENDED_CID_TID
) {
1326 parse_cidxtid(evt
->cidxtid
, &cid
, &tid
);
1332 if (!wil_cid_valid(wil
, cid
)) {
1333 wil_err(wil
, "DELBA: Invalid CID %d\n", cid
);
1337 wil_dbg_wmi(wil
, "DELBA MID %d CID %d TID %d from %s reason %d\n",
1339 evt
->from_initiator
? "originator" : "recipient",
1341 if (!evt
->from_initiator
) {
1343 /* find Tx vring it belongs to */
1344 for (i
= 0; i
< ARRAY_SIZE(wil
->ring2cid_tid
); i
++) {
1345 if (wil
->ring2cid_tid
[i
][0] == cid
&&
1346 wil
->ring2cid_tid
[i
][1] == tid
) {
1347 struct wil_ring_tx_data
*txdata
=
1348 &wil
->ring_tx_data
[i
];
1350 wil_dbg_wmi(wil
, "DELBA Tx vring %d\n", i
);
1351 txdata
->agg_timeout
= 0;
1352 txdata
->agg_wsize
= 0;
1353 txdata
->addba_in_progress
= false;
1355 break; /* max. 1 matching ring */
1358 if (i
>= ARRAY_SIZE(wil
->ring2cid_tid
))
1359 wil_err(wil
, "DELBA: unable to find Tx vring\n");
1363 sta
= &wil
->sta
[cid
];
1365 spin_lock_bh(&sta
->tid_rx_lock
);
1367 r
= sta
->tid_rx
[tid
];
1368 sta
->tid_rx
[tid
] = NULL
;
1369 wil_tid_ampdu_rx_free(wil
, r
);
1371 spin_unlock_bh(&sta
->tid_rx_lock
);
1375 wmi_evt_sched_scan_result(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1377 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1378 struct wmi_sched_scan_result_event
*data
= d
;
1379 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
1380 struct ieee80211_mgmt
*rx_mgmt_frame
=
1381 (struct ieee80211_mgmt
*)data
->payload
;
1382 int flen
= len
- offsetof(struct wmi_sched_scan_result_event
, payload
);
1385 struct ieee80211_channel
*channel
;
1389 struct cfg80211_bss
*bss
;
1390 struct cfg80211_inform_bss bss_data
= {
1391 .boottime_ns
= ktime_to_ns(ktime_get_boottime()),
1395 wil_err(wil
, "sched scan result event too short, len %d\n",
1400 d_len
= le32_to_cpu(data
->info
.len
);
1401 if (d_len
!= flen
) {
1403 "sched scan result length mismatch, d_len %d should be %d\n",
1408 fc
= rx_mgmt_frame
->frame_control
;
1409 if (!ieee80211_is_probe_resp(fc
)) {
1410 wil_err(wil
, "sched scan result invalid frame, fc 0x%04x\n",
1415 ch_no
= data
->info
.channel
+ 1;
1416 freq
= ieee80211_channel_to_frequency(ch_no
, NL80211_BAND_60GHZ
);
1417 channel
= ieee80211_get_channel(wiphy
, freq
);
1418 if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING
, wil
->fw_capabilities
))
1419 signal
= 100 * data
->info
.rssi
;
1421 signal
= data
->info
.sqi
;
1423 wil_dbg_wmi(wil
, "sched scan result: channel %d MCS %s RSSI %d\n",
1424 data
->info
.channel
, WIL_EXTENDED_MCS_CHECK(data
->info
.mcs
),
1426 wil_dbg_wmi(wil
, "len %d qid %d mid %d cid %d\n",
1427 d_len
, data
->info
.qid
, data
->info
.mid
, data
->info
.cid
);
1428 wil_hex_dump_wmi("PROBE ", DUMP_PREFIX_OFFSET
, 16, 1, rx_mgmt_frame
,
1432 wil_err(wil
, "Frame on unsupported channel\n");
1436 bss_data
.signal
= signal
;
1437 bss_data
.chan
= channel
;
1438 bss
= cfg80211_inform_bss_frame_data(wiphy
, &bss_data
, rx_mgmt_frame
,
1441 wil_dbg_wmi(wil
, "Added BSS %pM\n", rx_mgmt_frame
->bssid
);
1442 cfg80211_put_bss(wiphy
, bss
);
1444 wil_err(wil
, "cfg80211_inform_bss_frame() failed\n");
1447 cfg80211_sched_scan_results(wiphy
, 0);
1450 static void wil_link_stats_store_basic(struct wil6210_vif
*vif
,
1451 struct wmi_link_stats_basic
*basic
)
1453 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1454 u8 cid
= basic
->cid
;
1455 struct wil_sta_info
*sta
;
1457 if (cid
>= wil
->max_assoc_sta
) {
1458 wil_err(wil
, "invalid cid %d\n", cid
);
1462 sta
= &wil
->sta
[cid
];
1463 sta
->fw_stats_basic
= *basic
;
1466 static void wil_link_stats_store_global(struct wil6210_vif
*vif
,
1467 struct wmi_link_stats_global
*global
)
1469 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1471 wil
->fw_stats_global
.stats
= *global
;
1474 static void wmi_link_stats_parse(struct wil6210_vif
*vif
, u64 tsf
,
1475 bool has_next
, void *payload
,
1476 size_t payload_size
)
1478 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1479 size_t hdr_size
= sizeof(struct wmi_link_stats_record
);
1480 size_t stats_size
, record_size
, expected_size
;
1481 struct wmi_link_stats_record
*hdr
;
1483 if (payload_size
< hdr_size
) {
1484 wil_err(wil
, "link stats wrong event size %zu\n", payload_size
);
1488 while (payload_size
>= hdr_size
) {
1490 stats_size
= le16_to_cpu(hdr
->record_size
);
1491 record_size
= hdr_size
+ stats_size
;
1493 if (payload_size
< record_size
) {
1494 wil_err(wil
, "link stats payload ended unexpectedly, size %zu < %zu\n",
1495 payload_size
, record_size
);
1499 switch (hdr
->record_type_id
) {
1500 case WMI_LINK_STATS_TYPE_BASIC
:
1501 expected_size
= sizeof(struct wmi_link_stats_basic
);
1502 if (stats_size
< expected_size
) {
1503 wil_err(wil
, "link stats invalid basic record size %zu < %zu\n",
1504 stats_size
, expected_size
);
1507 if (vif
->fw_stats_ready
) {
1508 /* clean old statistics */
1509 vif
->fw_stats_tsf
= 0;
1510 vif
->fw_stats_ready
= false;
1513 wil_link_stats_store_basic(vif
, payload
+ hdr_size
);
1516 vif
->fw_stats_tsf
= tsf
;
1517 vif
->fw_stats_ready
= true;
1521 case WMI_LINK_STATS_TYPE_GLOBAL
:
1522 expected_size
= sizeof(struct wmi_link_stats_global
);
1523 if (stats_size
< sizeof(struct wmi_link_stats_global
)) {
1524 wil_err(wil
, "link stats invalid global record size %zu < %zu\n",
1525 stats_size
, expected_size
);
1529 if (wil
->fw_stats_global
.ready
) {
1530 /* clean old statistics */
1531 wil
->fw_stats_global
.tsf
= 0;
1532 wil
->fw_stats_global
.ready
= false;
1535 wil_link_stats_store_global(vif
, payload
+ hdr_size
);
1538 wil
->fw_stats_global
.tsf
= tsf
;
1539 wil
->fw_stats_global
.ready
= true;
1547 /* skip to next record */
1548 payload
+= record_size
;
1549 payload_size
-= record_size
;
1554 wmi_evt_link_stats(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1556 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1557 struct wmi_link_stats_event
*evt
= d
;
1558 size_t payload_size
;
1560 if (len
< offsetof(struct wmi_link_stats_event
, payload
)) {
1561 wil_err(wil
, "stats event way too short %d\n", len
);
1564 payload_size
= le16_to_cpu(evt
->payload_size
);
1565 if (len
< sizeof(struct wmi_link_stats_event
) + payload_size
) {
1566 wil_err(wil
, "stats event too short %d\n", len
);
1570 wmi_link_stats_parse(vif
, le64_to_cpu(evt
->tsf
), evt
->has_next
,
1571 evt
->payload
, payload_size
);
1574 /* find cid and ringid for the station vif
1576 * return error, if other interfaces are used or ring was not found
1578 static int wil_find_cid_ringid_sta(struct wil6210_priv
*wil
,
1579 struct wil6210_vif
*vif
,
1583 struct wil_ring
*ring
;
1584 struct wil_ring_tx_data
*txdata
;
1585 int min_ring_id
= wil_get_min_tx_ring_id(wil
);
1589 if (!(vif
->wdev
.iftype
== NL80211_IFTYPE_STATION
||
1590 vif
->wdev
.iftype
== NL80211_IFTYPE_P2P_CLIENT
)) {
1591 wil_err(wil
, "invalid interface type %d\n", vif
->wdev
.iftype
);
1595 /* In the STA mode, it is expected to have only one ring
1596 * for the AP we are connected to.
1597 * find it and return the cid associated with it.
1599 for (i
= min_ring_id
; i
< WIL6210_MAX_TX_RINGS
; i
++) {
1600 ring
= &wil
->ring_tx
[i
];
1601 txdata
= &wil
->ring_tx_data
[i
];
1602 if (!ring
->va
|| !txdata
->enabled
|| txdata
->mid
!= vif
->mid
)
1605 lcid
= wil
->ring2cid_tid
[i
][0];
1606 if (lcid
>= wil
->max_assoc_sta
) /* skip BCAST */
1609 wil_dbg_wmi(wil
, "find sta -> ringid %d cid %d\n", i
, lcid
);
1615 wil_dbg_wmi(wil
, "find sta cid while no rings active?\n");
1621 wmi_evt_auth_status(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1623 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1624 struct net_device
*ndev
= vif_to_ndev(vif
);
1625 struct wmi_ft_auth_status_event
*data
= d
;
1626 int ie_len
= len
- offsetof(struct wmi_ft_auth_status_event
, ie_info
);
1627 int rc
, cid
= 0, ringid
= 0;
1628 struct cfg80211_ft_event_params ft
;
1630 /* auth_alg(u16) + auth_transaction(u16) + status_code(u16) */
1631 const size_t auth_ie_offset
= sizeof(u16
) * 3;
1632 struct auth_no_hdr
*auth
= (struct auth_no_hdr
*)data
->ie_info
;
1634 /* check the status */
1635 if (ie_len
>= 0 && data
->status
!= WMI_FW_STATUS_SUCCESS
) {
1636 wil_err(wil
, "FT: auth failed. status %d\n", data
->status
);
1640 if (ie_len
< auth_ie_offset
) {
1641 wil_err(wil
, "FT: auth event too short, len %d\n", len
);
1645 d_len
= le16_to_cpu(data
->ie_len
);
1646 if (d_len
!= ie_len
) {
1648 "FT: auth ie length mismatch, d_len %d should be %d\n",
1653 if (!test_bit(wil_vif_ft_roam
, wil
->status
)) {
1654 wil_err(wil
, "FT: Not in roaming state\n");
1658 if (le16_to_cpu(auth
->auth_transaction
) != 2) {
1659 wil_err(wil
, "FT: auth error. auth_transaction %d\n",
1660 le16_to_cpu(auth
->auth_transaction
));
1664 if (le16_to_cpu(auth
->auth_alg
) != WLAN_AUTH_FT
) {
1665 wil_err(wil
, "FT: auth error. auth_alg %d\n",
1666 le16_to_cpu(auth
->auth_alg
));
1670 wil_dbg_wmi(wil
, "FT: Auth to %pM successfully\n", data
->mac_addr
);
1671 wil_hex_dump_wmi("FT Auth ies : ", DUMP_PREFIX_OFFSET
, 16, 1,
1672 data
->ie_info
, d_len
, true);
1674 /* find cid and ringid */
1675 rc
= wil_find_cid_ringid_sta(wil
, vif
, &cid
, &ringid
);
1677 wil_err(wil
, "No valid cid found\n");
1682 /* For secure assoc, remove old keys */
1683 rc
= wmi_del_cipher_key(vif
, 0, wil
->sta
[cid
].addr
,
1684 WMI_KEY_USE_PAIRWISE
);
1686 wil_err(wil
, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
1689 rc
= wmi_del_cipher_key(vif
, 0, wil
->sta
[cid
].addr
,
1690 WMI_KEY_USE_RX_GROUP
);
1692 wil_err(wil
, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
1697 memset(&ft
, 0, sizeof(ft
));
1698 ft
.ies
= data
->ie_info
+ auth_ie_offset
;
1699 ft
.ies_len
= d_len
- auth_ie_offset
;
1700 ft
.target_ap
= data
->mac_addr
;
1701 cfg80211_ft_event(ndev
, &ft
);
1706 wil6210_disconnect(vif
, NULL
, WLAN_REASON_PREV_AUTH_NOT_VALID
);
1710 wmi_evt_reassoc_status(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1712 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1713 struct net_device
*ndev
= vif_to_ndev(vif
);
1714 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
1715 struct wmi_ft_reassoc_status_event
*data
= d
;
1716 int ies_len
= len
- offsetof(struct wmi_ft_reassoc_status_event
,
1718 int rc
= -ENOENT
, cid
= 0, ringid
= 0;
1719 int ch
; /* channel number (primary) */
1720 size_t assoc_req_ie_len
= 0, assoc_resp_ie_len
= 0;
1721 u8
*assoc_req_ie
= NULL
, *assoc_resp_ie
= NULL
;
1722 /* capinfo(u16) + listen_interval(u16) + current_ap mac addr + IEs */
1723 const size_t assoc_req_ie_offset
= sizeof(u16
) * 2 + ETH_ALEN
;
1724 /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
1725 const size_t assoc_resp_ie_offset
= sizeof(u16
) * 3;
1728 struct cfg80211_roam_info info
;
1731 wil_err(wil
, "ft reassoc event too short, len %d\n", len
);
1735 wil_dbg_wmi(wil
, "Reasoc Status event: status=%d, aid=%d",
1736 data
->status
, data
->aid
);
1737 wil_dbg_wmi(wil
, " mac_addr=%pM, beacon_ie_len=%d",
1738 data
->mac_addr
, data
->beacon_ie_len
);
1739 wil_dbg_wmi(wil
, " reassoc_req_ie_len=%d, reassoc_resp_ie_len=%d",
1740 le16_to_cpu(data
->reassoc_req_ie_len
),
1741 le16_to_cpu(data
->reassoc_resp_ie_len
));
1743 d_len
= le16_to_cpu(data
->beacon_ie_len
) +
1744 le16_to_cpu(data
->reassoc_req_ie_len
) +
1745 le16_to_cpu(data
->reassoc_resp_ie_len
);
1746 if (d_len
!= ies_len
) {
1748 "ft reassoc ie length mismatch, d_len %d should be %d\n",
1753 /* check the status */
1754 if (data
->status
!= WMI_FW_STATUS_SUCCESS
) {
1755 wil_err(wil
, "ft reassoc failed. status %d\n", data
->status
);
1759 /* find cid and ringid */
1760 rc
= wil_find_cid_ringid_sta(wil
, vif
, &cid
, &ringid
);
1762 wil_err(wil
, "No valid cid found\n");
1766 ch
= data
->channel
+ 1;
1767 wil_info(wil
, "FT: Roam %pM channel [%d] cid %d aid %d\n",
1768 data
->mac_addr
, ch
, cid
, data
->aid
);
1770 wil_hex_dump_wmi("reassoc AI : ", DUMP_PREFIX_OFFSET
, 16, 1,
1771 data
->ie_info
, len
- sizeof(*data
), true);
1773 /* figure out IE's */
1774 if (le16_to_cpu(data
->reassoc_req_ie_len
) > assoc_req_ie_offset
) {
1775 assoc_req_ie
= &data
->ie_info
[assoc_req_ie_offset
];
1776 assoc_req_ie_len
= le16_to_cpu(data
->reassoc_req_ie_len
) -
1777 assoc_req_ie_offset
;
1779 if (le16_to_cpu(data
->reassoc_resp_ie_len
) <= assoc_resp_ie_offset
) {
1780 wil_err(wil
, "FT: reassoc resp ie len is too short, len %d\n",
1781 le16_to_cpu(data
->reassoc_resp_ie_len
));
1785 assoc_resp_ie
= &data
->ie_info
[le16_to_cpu(data
->reassoc_req_ie_len
) +
1786 assoc_resp_ie_offset
];
1787 assoc_resp_ie_len
= le16_to_cpu(data
->reassoc_resp_ie_len
) -
1788 assoc_resp_ie_offset
;
1790 if (test_bit(wil_status_resetting
, wil
->status
) ||
1791 !test_bit(wil_status_fwready
, wil
->status
)) {
1792 wil_err(wil
, "FT: status_resetting, cancel reassoc event\n");
1793 /* no need for cleanup, wil_reset will do that */
1797 mutex_lock(&wil
->mutex
);
1799 /* ring modify to set the ring for the roamed AP settings */
1801 "ft modify tx config for connection CID %d ring %d\n",
1804 rc
= wil
->txrx_ops
.tx_ring_modify(vif
, ringid
, cid
, 0);
1806 wil_err(wil
, "modify TX for CID %d MID %d ring %d failed (%d)\n",
1807 cid
, vif
->mid
, ringid
, rc
);
1808 mutex_unlock(&wil
->mutex
);
1812 /* Update the driver STA members with the new bss */
1813 wil
->sta
[cid
].aid
= data
->aid
;
1814 wil
->sta
[cid
].stats
.ft_roams
++;
1815 ether_addr_copy(wil
->sta
[cid
].addr
, vif
->bss
->bssid
);
1816 mutex_unlock(&wil
->mutex
);
1817 del_timer_sync(&vif
->connect_timer
);
1819 cfg80211_ref_bss(wiphy
, vif
->bss
);
1820 freq
= ieee80211_channel_to_frequency(ch
, NL80211_BAND_60GHZ
);
1822 memset(&info
, 0, sizeof(info
));
1823 info
.links
[0].channel
= ieee80211_get_channel(wiphy
, freq
);
1824 info
.links
[0].bss
= vif
->bss
;
1825 info
.req_ie
= assoc_req_ie
;
1826 info
.req_ie_len
= assoc_req_ie_len
;
1827 info
.resp_ie
= assoc_resp_ie
;
1828 info
.resp_ie_len
= assoc_resp_ie_len
;
1829 cfg80211_roamed(ndev
, &info
, GFP_KERNEL
);
1835 wil6210_disconnect(vif
, NULL
, WLAN_REASON_PREV_AUTH_NOT_VALID
);
1839 wmi_evt_link_monitor(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1841 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1842 struct net_device
*ndev
= vif_to_ndev(vif
);
1843 struct wmi_link_monitor_event
*evt
= d
;
1844 enum nl80211_cqm_rssi_threshold_event event_type
;
1846 if (len
< sizeof(*evt
)) {
1847 wil_err(wil
, "link monitor event too short %d\n", len
);
1851 wil_dbg_wmi(wil
, "link monitor event, type %d rssi %d (stored %d)\n",
1852 evt
->type
, evt
->rssi_level
, wil
->cqm_rssi_thold
);
1854 if (evt
->type
!= WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT
)
1858 event_type
= (evt
->rssi_level
> wil
->cqm_rssi_thold
?
1859 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
:
1860 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
);
1861 cfg80211_cqm_rssi_notify(ndev
, event_type
, evt
->rssi_level
, GFP_KERNEL
);
1864 /* Some events are ignored for purpose; and need not be interpreted as
1865 * "unhandled events"
1867 static void wmi_evt_ignore(struct wil6210_vif
*vif
, int id
, void *d
, int len
)
1869 struct wil6210_priv
*wil
= vif_to_wil(vif
);
1871 wil_dbg_wmi(wil
, "Ignore event 0x%04x len %d\n", id
, len
);
1874 static const struct {
1876 void (*handler
)(struct wil6210_vif
*vif
,
1877 int eventid
, void *data
, int data_len
);
1878 } wmi_evt_handlers
[] = {
1879 {WMI_READY_EVENTID
, wmi_evt_ready
},
1880 {WMI_FW_READY_EVENTID
, wmi_evt_ignore
},
1881 {WMI_RX_MGMT_PACKET_EVENTID
, wmi_evt_rx_mgmt
},
1882 {WMI_TX_MGMT_PACKET_EVENTID
, wmi_evt_tx_mgmt
},
1883 {WMI_SCAN_COMPLETE_EVENTID
, wmi_evt_scan_complete
},
1884 {WMI_CONNECT_EVENTID
, wmi_evt_connect
},
1885 {WMI_DISCONNECT_EVENTID
, wmi_evt_disconnect
},
1886 {WMI_EAPOL_RX_EVENTID
, wmi_evt_eapol_rx
},
1887 {WMI_BA_STATUS_EVENTID
, wmi_evt_ba_status
},
1888 {WMI_RCP_ADDBA_REQ_EVENTID
, wmi_evt_addba_rx_req
},
1889 {WMI_DELBA_EVENTID
, wmi_evt_delba
},
1890 {WMI_RING_EN_EVENTID
, wmi_evt_ring_en
},
1891 {WMI_DATA_PORT_OPEN_EVENTID
, wmi_evt_ignore
},
1892 {WMI_SCHED_SCAN_RESULT_EVENTID
, wmi_evt_sched_scan_result
},
1893 {WMI_LINK_STATS_EVENTID
, wmi_evt_link_stats
},
1894 {WMI_FT_AUTH_STATUS_EVENTID
, wmi_evt_auth_status
},
1895 {WMI_FT_REASSOC_STATUS_EVENTID
, wmi_evt_reassoc_status
},
1896 {WMI_LINK_MONITOR_EVENTID
, wmi_evt_link_monitor
},
1900 * Run in IRQ context
1901 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
1902 * that will be eventually handled by the @wmi_event_worker in the thread
1903 * context of thread "wil6210_wmi"
1905 void wmi_recv_cmd(struct wil6210_priv
*wil
)
1907 struct wil6210_mbox_ring_desc d_tail
;
1908 struct wil6210_mbox_hdr hdr
;
1909 struct wil6210_mbox_ring
*r
= &wil
->mbox_ctl
.rx
;
1910 struct pending_wmi_event
*evt
;
1915 unsigned int num_immed_reply
= 0;
1917 if (!test_bit(wil_status_mbox_ready
, wil
->status
)) {
1918 wil_err(wil
, "Reset in progress. Cannot handle WMI event\n");
1922 if (test_bit(wil_status_suspended
, wil
->status
)) {
1923 wil_err(wil
, "suspended. cannot handle WMI event\n");
1930 bool immed_reply
= false;
1932 r
->head
= wil_r(wil
, RGF_MBOX
+
1933 offsetof(struct wil6210_mbox_ctl
, rx
.head
));
1934 if (r
->tail
== r
->head
)
1937 wil_dbg_wmi(wil
, "Mbox head %08x tail %08x\n",
1939 /* read cmd descriptor from tail */
1940 wil_memcpy_fromio_32(&d_tail
, wil
->csr
+ HOSTADDR(r
->tail
),
1941 sizeof(struct wil6210_mbox_ring_desc
));
1942 if (d_tail
.sync
== 0) {
1943 wil_err(wil
, "Mbox evt not owned by FW?\n");
1947 /* read cmd header from descriptor */
1948 if (0 != wmi_read_hdr(wil
, d_tail
.addr
, &hdr
)) {
1949 wil_err(wil
, "Mbox evt at 0x%08x?\n",
1950 le32_to_cpu(d_tail
.addr
));
1953 len
= le16_to_cpu(hdr
.len
);
1954 wil_dbg_wmi(wil
, "Mbox evt %04x %04x %04x %02x\n",
1955 le16_to_cpu(hdr
.seq
), len
, le16_to_cpu(hdr
.type
),
1958 /* read cmd buffer from descriptor */
1959 src
= wmi_buffer(wil
, d_tail
.addr
) +
1960 sizeof(struct wil6210_mbox_hdr
);
1961 evt
= kmalloc(ALIGN(offsetof(struct pending_wmi_event
,
1962 event
.wmi
) + len
, 4),
1967 evt
->event
.hdr
= hdr
;
1968 cmd
= (void *)&evt
->event
.wmi
;
1969 wil_memcpy_fromio_32(cmd
, src
, len
);
1970 /* mark entry as empty */
1971 wil_w(wil
, r
->tail
+
1972 offsetof(struct wil6210_mbox_ring_desc
, sync
), 0);
1974 if ((hdr
.type
== WIL_MBOX_HDR_TYPE_WMI
) &&
1975 (len
>= sizeof(struct wmi_cmd_hdr
))) {
1976 struct wmi_cmd_hdr
*wmi
= &evt
->event
.wmi
;
1977 u16 id
= le16_to_cpu(wmi
->command_id
);
1979 u32 tstamp
= le32_to_cpu(wmi
->fw_timestamp
);
1980 if (test_bit(wil_status_resuming
, wil
->status
)) {
1981 if (id
== WMI_TRAFFIC_RESUME_EVENTID
)
1982 clear_bit(wil_status_resuming
,
1986 "WMI evt %d while resuming\n",
1989 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
1990 if (wil
->reply_id
&& wil
->reply_id
== id
&&
1991 wil
->reply_mid
== mid
) {
1992 if (wil
->reply_buf
) {
1993 memcpy(wil
->reply_buf
, wmi
,
1994 min(len
, wil
->reply_size
));
1997 if (id
== WMI_TRAFFIC_SUSPEND_EVENTID
) {
1999 "set suspend_resp_rcvd\n");
2000 wil
->suspend_resp_rcvd
= true;
2003 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2005 wil_dbg_wmi(wil
, "recv %s (0x%04x) MID %d @%d msec\n",
2006 eventid2name(id
), id
, wmi
->mid
, tstamp
);
2007 trace_wil6210_wmi_event(wmi
, &wmi
[1],
2008 len
- sizeof(*wmi
));
2010 wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET
, 16, 1,
2011 &evt
->event
.hdr
, sizeof(hdr
) + len
, true);
2014 r
->tail
= r
->base
+ ((r
->tail
- r
->base
+
2015 sizeof(struct wil6210_mbox_ring_desc
)) % r
->size
);
2016 wil_w(wil
, RGF_MBOX
+
2017 offsetof(struct wil6210_mbox_ctl
, rx
.tail
), r
->tail
);
2020 wil_dbg_wmi(wil
, "recv_cmd: Complete WMI 0x%04x\n",
2024 complete(&wil
->wmi_call
);
2026 /* add to the pending list */
2027 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
2028 list_add_tail(&evt
->list
, &wil
->pending_wmi_ev
);
2029 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2030 q
= queue_work(wil
->wmi_wq
, &wil
->wmi_event_worker
);
2031 wil_dbg_wmi(wil
, "queue_work -> %d\n", q
);
2034 /* normally, 1 event per IRQ should be processed */
2035 wil_dbg_wmi(wil
, "recv_cmd: -> %d events queued, %d completed\n",
2036 n
- num_immed_reply
, num_immed_reply
);
2039 int wmi_call(struct wil6210_priv
*wil
, u16 cmdid
, u8 mid
, void *buf
, u16 len
,
2040 u16 reply_id
, void *reply
, u16 reply_size
, int to_msec
)
2043 unsigned long remain
;
2046 mutex_lock(&wil
->wmi_mutex
);
2048 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
2049 wil
->reply_id
= reply_id
;
2050 wil
->reply_mid
= mid
;
2051 wil
->reply_buf
= reply
;
2052 wil
->reply_size
= reply_size
;
2053 reinit_completion(&wil
->wmi_call
);
2054 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2056 rc
= __wmi_send(wil
, cmdid
, mid
, buf
, len
);
2060 remain
= wait_for_completion_timeout(&wil
->wmi_call
,
2061 msecs_to_jiffies(to_msec
));
2063 wil_err(wil
, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
2064 cmdid
, reply_id
, to_msec
);
2068 "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
2070 to_msec
- jiffies_to_msecs(remain
));
2074 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
2076 wil
->reply_mid
= U8_MAX
;
2077 wil
->reply_buf
= NULL
;
2078 wil
->reply_size
= 0;
2079 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
2081 mutex_unlock(&wil
->wmi_mutex
);
2086 int wmi_echo(struct wil6210_priv
*wil
)
2088 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2089 struct wmi_echo_cmd cmd
= {
2090 .value
= cpu_to_le32(0x12345678),
2093 return wmi_call(wil
, WMI_ECHO_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2094 WMI_ECHO_RSP_EVENTID
, NULL
, 0,
2095 WIL_WMI_CALL_GENERAL_TO_MS
);
2098 int wmi_set_mac_address(struct wil6210_priv
*wil
, const void *addr
)
2100 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2101 struct wmi_set_mac_address_cmd cmd
;
2103 ether_addr_copy(cmd
.mac
, addr
);
2105 wil_dbg_wmi(wil
, "Set MAC %pM\n", addr
);
2107 return wmi_send(wil
, WMI_SET_MAC_ADDRESS_CMDID
, vif
->mid
,
2111 int wmi_led_cfg(struct wil6210_priv
*wil
, bool enable
)
2113 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2115 struct wmi_led_cfg_cmd cmd
= {
2118 .slow_blink_cfg
.blink_on
=
2119 cpu_to_le32(led_blink_time
[WIL_LED_TIME_SLOW
].on_ms
),
2120 .slow_blink_cfg
.blink_off
=
2121 cpu_to_le32(led_blink_time
[WIL_LED_TIME_SLOW
].off_ms
),
2122 .medium_blink_cfg
.blink_on
=
2123 cpu_to_le32(led_blink_time
[WIL_LED_TIME_MED
].on_ms
),
2124 .medium_blink_cfg
.blink_off
=
2125 cpu_to_le32(led_blink_time
[WIL_LED_TIME_MED
].off_ms
),
2126 .fast_blink_cfg
.blink_on
=
2127 cpu_to_le32(led_blink_time
[WIL_LED_TIME_FAST
].on_ms
),
2128 .fast_blink_cfg
.blink_off
=
2129 cpu_to_le32(led_blink_time
[WIL_LED_TIME_FAST
].off_ms
),
2130 .led_polarity
= led_polarity
,
2133 struct wmi_cmd_hdr wmi
;
2134 struct wmi_led_cfg_done_event evt
;
2135 } __packed reply
= {
2136 .evt
= {.status
= cpu_to_le32(WMI_FW_STATUS_FAILURE
)},
2139 if (led_id
== WIL_LED_INVALID_ID
)
2142 if (led_id
> WIL_LED_MAX_ID
) {
2143 wil_err(wil
, "Invalid led id %d\n", led_id
);
2150 enable
? "enabling" : "disabling", led_id
);
2152 rc
= wmi_call(wil
, WMI_LED_CFG_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2153 WMI_LED_CFG_DONE_EVENTID
, &reply
, sizeof(reply
),
2154 WIL_WMI_CALL_GENERAL_TO_MS
);
2158 if (reply
.evt
.status
) {
2159 wil_err(wil
, "led %d cfg failed with status %d\n",
2160 led_id
, le32_to_cpu(reply
.evt
.status
));
2168 int wmi_rbufcap_cfg(struct wil6210_priv
*wil
, bool enable
, u16 threshold
)
2170 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2173 struct wmi_rbufcap_cfg_cmd cmd
= {
2175 .rx_desc_threshold
= cpu_to_le16(threshold
),
2178 struct wmi_cmd_hdr wmi
;
2179 struct wmi_rbufcap_cfg_event evt
;
2180 } __packed reply
= {
2181 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2184 rc
= wmi_call(wil
, WMI_RBUFCAP_CFG_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2185 WMI_RBUFCAP_CFG_EVENTID
, &reply
, sizeof(reply
),
2186 WIL_WMI_CALL_GENERAL_TO_MS
);
2190 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2191 wil_err(wil
, "RBUFCAP_CFG failed. status %d\n",
2199 int wmi_pcp_start(struct wil6210_vif
*vif
, int bi
, u8 wmi_nettype
,
2200 u8 chan
, u8 wmi_edmg_chan
, u8 hidden_ssid
, u8 is_go
)
2202 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2205 struct wmi_pcp_start_cmd cmd
= {
2206 .bcon_interval
= cpu_to_le16(bi
),
2207 .network_type
= wmi_nettype
,
2208 .disable_sec_offload
= 1,
2209 .channel
= chan
- 1,
2210 .edmg_channel
= wmi_edmg_chan
,
2211 .pcp_max_assoc_sta
= wil
->max_assoc_sta
,
2212 .hidden_ssid
= hidden_ssid
,
2214 .ap_sme_offload_mode
= disable_ap_sme
?
2215 WMI_AP_SME_OFFLOAD_PARTIAL
:
2216 WMI_AP_SME_OFFLOAD_FULL
,
2217 .abft_len
= wil
->abft_len
,
2220 struct wmi_cmd_hdr wmi
;
2221 struct wmi_pcp_started_event evt
;
2222 } __packed reply
= {
2223 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2227 cmd
.disable_sec
= 1;
2229 if ((cmd
.pcp_max_assoc_sta
> WIL6210_MAX_CID
) ||
2230 (cmd
.pcp_max_assoc_sta
<= 0)) {
2231 wil_err(wil
, "unexpected max_assoc_sta %d\n",
2232 cmd
.pcp_max_assoc_sta
);
2236 if (disable_ap_sme
&&
2237 !test_bit(WMI_FW_CAPABILITY_AP_SME_OFFLOAD_PARTIAL
,
2238 wil
->fw_capabilities
)) {
2239 wil_err(wil
, "disable_ap_sme not supported by FW\n");
2244 * Processing time may be huge, in case of secure AP it takes about
2245 * 3500ms for FW to start AP
2247 rc
= wmi_call(wil
, WMI_PCP_START_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2248 WMI_PCP_STARTED_EVENTID
, &reply
, sizeof(reply
), 5000);
2252 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
)
2255 if (wmi_nettype
!= WMI_NETTYPE_P2P
)
2256 /* Don't fail due to error in the led configuration */
2257 wmi_led_cfg(wil
, true);
2262 int wmi_pcp_stop(struct wil6210_vif
*vif
)
2264 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2267 rc
= wmi_led_cfg(wil
, false);
2271 return wmi_call(wil
, WMI_PCP_STOP_CMDID
, vif
->mid
, NULL
, 0,
2272 WMI_PCP_STOPPED_EVENTID
, NULL
, 0,
2273 WIL_WMI_PCP_STOP_TO_MS
);
2276 int wmi_set_ssid(struct wil6210_vif
*vif
, u8 ssid_len
, const void *ssid
)
2278 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2279 struct wmi_set_ssid_cmd cmd
= {
2280 .ssid_len
= cpu_to_le32(ssid_len
),
2283 if (ssid_len
> sizeof(cmd
.ssid
))
2286 memcpy(cmd
.ssid
, ssid
, ssid_len
);
2288 return wmi_send(wil
, WMI_SET_SSID_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
));
2291 int wmi_get_ssid(struct wil6210_vif
*vif
, u8
*ssid_len
, void *ssid
)
2293 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2296 struct wmi_cmd_hdr wmi
;
2297 struct wmi_set_ssid_cmd cmd
;
2299 int len
; /* reply.cmd.ssid_len in CPU order */
2301 memset(&reply
, 0, sizeof(reply
));
2303 rc
= wmi_call(wil
, WMI_GET_SSID_CMDID
, vif
->mid
, NULL
, 0,
2304 WMI_GET_SSID_EVENTID
, &reply
, sizeof(reply
),
2305 WIL_WMI_CALL_GENERAL_TO_MS
);
2309 len
= le32_to_cpu(reply
.cmd
.ssid_len
);
2310 if (len
> sizeof(reply
.cmd
.ssid
))
2314 memcpy(ssid
, reply
.cmd
.ssid
, len
);
2319 int wmi_set_channel(struct wil6210_priv
*wil
, int channel
)
2321 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2322 struct wmi_set_pcp_channel_cmd cmd
= {
2323 .channel
= channel
- 1,
2326 return wmi_send(wil
, WMI_SET_PCP_CHANNEL_CMDID
, vif
->mid
,
2330 int wmi_get_channel(struct wil6210_priv
*wil
, int *channel
)
2332 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2335 struct wmi_cmd_hdr wmi
;
2336 struct wmi_set_pcp_channel_cmd cmd
;
2339 memset(&reply
, 0, sizeof(reply
));
2341 rc
= wmi_call(wil
, WMI_GET_PCP_CHANNEL_CMDID
, vif
->mid
, NULL
, 0,
2342 WMI_GET_PCP_CHANNEL_EVENTID
, &reply
, sizeof(reply
),
2343 WIL_WMI_CALL_GENERAL_TO_MS
);
2347 if (reply
.cmd
.channel
> 3)
2350 *channel
= reply
.cmd
.channel
+ 1;
2355 int wmi_p2p_cfg(struct wil6210_vif
*vif
, int channel
, int bi
)
2357 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2359 struct wmi_p2p_cfg_cmd cmd
= {
2360 .discovery_mode
= WMI_DISCOVERY_MODE_PEER2PEER
,
2361 .bcon_interval
= cpu_to_le16(bi
),
2362 .channel
= channel
- 1,
2365 struct wmi_cmd_hdr wmi
;
2366 struct wmi_p2p_cfg_done_event evt
;
2367 } __packed reply
= {
2368 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2371 wil_dbg_wmi(wil
, "sending WMI_P2P_CFG_CMDID\n");
2373 rc
= wmi_call(wil
, WMI_P2P_CFG_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2374 WMI_P2P_CFG_DONE_EVENTID
, &reply
, sizeof(reply
), 300);
2375 if (!rc
&& reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2376 wil_err(wil
, "P2P_CFG failed. status %d\n", reply
.evt
.status
);
2383 int wmi_start_listen(struct wil6210_vif
*vif
)
2385 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2388 struct wmi_cmd_hdr wmi
;
2389 struct wmi_listen_started_event evt
;
2390 } __packed reply
= {
2391 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2394 wil_dbg_wmi(wil
, "sending WMI_START_LISTEN_CMDID\n");
2396 rc
= wmi_call(wil
, WMI_START_LISTEN_CMDID
, vif
->mid
, NULL
, 0,
2397 WMI_LISTEN_STARTED_EVENTID
, &reply
, sizeof(reply
), 300);
2398 if (!rc
&& reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2399 wil_err(wil
, "device failed to start listen. status %d\n",
2407 int wmi_start_search(struct wil6210_vif
*vif
)
2409 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2412 struct wmi_cmd_hdr wmi
;
2413 struct wmi_search_started_event evt
;
2414 } __packed reply
= {
2415 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2418 wil_dbg_wmi(wil
, "sending WMI_START_SEARCH_CMDID\n");
2420 rc
= wmi_call(wil
, WMI_START_SEARCH_CMDID
, vif
->mid
, NULL
, 0,
2421 WMI_SEARCH_STARTED_EVENTID
, &reply
, sizeof(reply
), 300);
2422 if (!rc
&& reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2423 wil_err(wil
, "device failed to start search. status %d\n",
2431 int wmi_stop_discovery(struct wil6210_vif
*vif
)
2433 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2436 wil_dbg_wmi(wil
, "sending WMI_DISCOVERY_STOP_CMDID\n");
2438 rc
= wmi_call(wil
, WMI_DISCOVERY_STOP_CMDID
, vif
->mid
, NULL
, 0,
2439 WMI_DISCOVERY_STOPPED_EVENTID
, NULL
, 0,
2440 WIL_WMI_CALL_GENERAL_TO_MS
);
2443 wil_err(wil
, "Failed to stop discovery\n");
2448 int wmi_del_cipher_key(struct wil6210_vif
*vif
, u8 key_index
,
2449 const void *mac_addr
, int key_usage
)
2451 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2452 struct wmi_delete_cipher_key_cmd cmd
= {
2453 .key_index
= key_index
,
2457 memcpy(cmd
.mac
, mac_addr
, WMI_MAC_LEN
);
2459 return wmi_send(wil
, WMI_DELETE_CIPHER_KEY_CMDID
, vif
->mid
,
2463 int wmi_add_cipher_key(struct wil6210_vif
*vif
, u8 key_index
,
2464 const void *mac_addr
, int key_len
, const void *key
,
2467 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2468 struct wmi_add_cipher_key_cmd cmd
= {
2469 .key_index
= key_index
,
2470 .key_usage
= key_usage
,
2474 if (key_len
> sizeof(cmd
.key
))
2477 /* key len = 0 is allowed only for usage of WMI_KEY_USE_APPLY */
2478 if ((key_len
== 0 || !key
) &&
2479 key_usage
!= WMI_KEY_USE_APPLY_PTK
)
2483 memcpy(cmd
.key
, key
, key_len
);
2486 memcpy(cmd
.mac
, mac_addr
, WMI_MAC_LEN
);
2488 return wmi_send(wil
, WMI_ADD_CIPHER_KEY_CMDID
, vif
->mid
,
2492 int wmi_set_ie(struct wil6210_vif
*vif
, u8 type
, u16 ie_len
, const void *ie
)
2494 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2495 static const char *const names
[] = {
2496 [WMI_FRAME_BEACON
] = "BEACON",
2497 [WMI_FRAME_PROBE_REQ
] = "PROBE_REQ",
2498 [WMI_FRAME_PROBE_RESP
] = "WMI_FRAME_PROBE_RESP",
2499 [WMI_FRAME_ASSOC_REQ
] = "WMI_FRAME_ASSOC_REQ",
2500 [WMI_FRAME_ASSOC_RESP
] = "WMI_FRAME_ASSOC_RESP",
2503 u16 len
= sizeof(struct wmi_set_appie_cmd
) + ie_len
;
2504 struct wmi_set_appie_cmd
*cmd
;
2511 cmd
= kzalloc(len
, GFP_KERNEL
);
2519 cmd
->mgmt_frm_type
= type
;
2520 /* BUG: FW API define ieLen as u8. Will fix FW */
2521 cmd
->ie_len
= cpu_to_le16(ie_len
);
2523 memcpy(cmd
->ie_info
, ie
, ie_len
);
2524 rc
= wmi_send(wil
, WMI_SET_APPIE_CMDID
, vif
->mid
, cmd
, len
);
2528 const char *name
= type
< ARRAY_SIZE(names
) ?
2530 wil_err(wil
, "set_ie(%d %s) failed : %d\n", type
, name
, rc
);
2536 int wmi_update_ft_ies(struct wil6210_vif
*vif
, u16 ie_len
, const void *ie
)
2538 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2540 struct wmi_update_ft_ies_cmd
*cmd
;
2546 len
= sizeof(struct wmi_update_ft_ies_cmd
) + ie_len
;
2548 wil_err(wil
, "wraparound. ie len %d\n", ie_len
);
2552 cmd
= kzalloc(len
, GFP_KERNEL
);
2558 cmd
->ie_len
= cpu_to_le16(ie_len
);
2560 memcpy(cmd
->ie_info
, ie
, ie_len
);
2561 rc
= wmi_send(wil
, WMI_UPDATE_FT_IES_CMDID
, vif
->mid
, cmd
, len
);
2566 wil_err(wil
, "update ft ies failed : %d\n", rc
);
2572 * wmi_rxon - turn radio on/off
2574 * @on: turn on if true, off otherwise
2576 * Only switch radio. Channel should be set separately.
2577 * No timeout for rxon - radio turned on forever unless some other call
2580 int wmi_rxon(struct wil6210_priv
*wil
, bool on
)
2582 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2585 struct wmi_cmd_hdr wmi
;
2586 struct wmi_listen_started_event evt
;
2587 } __packed reply
= {
2588 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2591 wil_info(wil
, "(%s)\n", on
? "on" : "off");
2594 rc
= wmi_call(wil
, WMI_START_LISTEN_CMDID
, vif
->mid
, NULL
, 0,
2595 WMI_LISTEN_STARTED_EVENTID
,
2596 &reply
, sizeof(reply
),
2597 WIL_WMI_CALL_GENERAL_TO_MS
);
2598 if ((rc
== 0) && (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
))
2601 rc
= wmi_call(wil
, WMI_DISCOVERY_STOP_CMDID
, vif
->mid
, NULL
, 0,
2602 WMI_DISCOVERY_STOPPED_EVENTID
, NULL
, 0,
2603 WIL_WMI_CALL_GENERAL_TO_MS
);
2609 int wmi_rx_chain_add(struct wil6210_priv
*wil
, struct wil_ring
*vring
)
2611 struct net_device
*ndev
= wil
->main_ndev
;
2612 struct wireless_dev
*wdev
= ndev
->ieee80211_ptr
;
2613 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
2614 struct wmi_cfg_rx_chain_cmd cmd
= {
2615 .action
= WMI_RX_CHAIN_ADD
,
2617 .max_mpdu_size
= cpu_to_le16(
2618 wil_mtu2macbuf(wil
->rx_buf_len
)),
2619 .ring_mem_base
= cpu_to_le64(vring
->pa
),
2620 .ring_size
= cpu_to_le16(vring
->size
),
2622 .mid
= 0, /* TODO - what is it? */
2623 .decap_trans_type
= WMI_DECAP_TYPE_802_3
,
2624 .reorder_type
= WMI_RX_SW_REORDER
,
2625 .host_thrsh
= cpu_to_le16(rx_ring_overflow_thrsh
),
2628 struct wmi_cmd_hdr wmi
;
2629 struct wmi_cfg_rx_chain_done_event evt
;
2633 memset(&evt
, 0, sizeof(evt
));
2635 if (wdev
->iftype
== NL80211_IFTYPE_MONITOR
) {
2636 struct ieee80211_channel
*ch
= wil
->monitor_chandef
.chan
;
2638 cmd
.sniffer_cfg
.mode
= cpu_to_le32(WMI_SNIFFER_ON
);
2640 cmd
.sniffer_cfg
.channel
= ch
->hw_value
- 1;
2641 cmd
.sniffer_cfg
.phy_info_mode
=
2642 cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED
);
2643 cmd
.sniffer_cfg
.phy_support
=
2644 cpu_to_le32((wil
->monitor_flags
& MONITOR_FLAG_CONTROL
)
2645 ? WMI_SNIFFER_CP
: WMI_SNIFFER_BOTH_PHYS
);
2647 /* Initialize offload (in non-sniffer mode).
2648 * Linux IP stack always calculates IP checksum
2649 * HW always calculate TCP/UDP checksum
2651 cmd
.l3_l4_ctrl
|= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS
);
2655 cmd
.l2_802_3_offload_ctrl
|=
2656 L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK
;
2658 /* typical time for secure PCP is 840ms */
2659 rc
= wmi_call(wil
, WMI_CFG_RX_CHAIN_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2660 WMI_CFG_RX_CHAIN_DONE_EVENTID
, &evt
, sizeof(evt
), 2000);
2664 if (le32_to_cpu(evt
.evt
.status
) != WMI_CFG_RX_CHAIN_SUCCESS
)
2667 vring
->hwtail
= le32_to_cpu(evt
.evt
.rx_ring_tail_ptr
);
2669 wil_dbg_misc(wil
, "Rx init: status %d tail 0x%08x\n",
2670 le32_to_cpu(evt
.evt
.status
), vring
->hwtail
);
2675 int wmi_get_temperature(struct wil6210_priv
*wil
, u32
*t_bb
, u32
*t_rf
)
2677 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2679 struct wmi_temp_sense_cmd cmd
= {
2680 .measure_baseband_en
= cpu_to_le32(!!t_bb
),
2681 .measure_rf_en
= cpu_to_le32(!!t_rf
),
2682 .measure_mode
= cpu_to_le32(TEMPERATURE_MEASURE_NOW
),
2685 struct wmi_cmd_hdr wmi
;
2686 struct wmi_temp_sense_done_event evt
;
2689 memset(&reply
, 0, sizeof(reply
));
2691 rc
= wmi_call(wil
, WMI_TEMP_SENSE_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
2692 WMI_TEMP_SENSE_DONE_EVENTID
, &reply
, sizeof(reply
),
2693 WIL_WMI_CALL_GENERAL_TO_MS
);
2698 *t_bb
= le32_to_cpu(reply
.evt
.baseband_t1000
);
2700 *t_rf
= le32_to_cpu(reply
.evt
.rf_t1000
);
2705 int wmi_get_all_temperatures(struct wil6210_priv
*wil
,
2706 struct wmi_temp_sense_all_done_event
2709 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2711 struct wmi_temp_sense_all_cmd cmd
= {
2712 .measure_baseband_en
= true,
2713 .measure_rf_en
= true,
2714 .measure_mode
= TEMPERATURE_MEASURE_NOW
,
2717 struct wmi_cmd_hdr wmi
;
2718 struct wmi_temp_sense_all_done_event evt
;
2721 if (!sense_all_evt
) {
2722 wil_err(wil
, "Invalid sense_all_evt value\n");
2726 memset(&reply
, 0, sizeof(reply
));
2727 reply
.evt
.status
= WMI_FW_STATUS_FAILURE
;
2728 rc
= wmi_call(wil
, WMI_TEMP_SENSE_ALL_CMDID
, vif
->mid
, &cmd
,
2729 sizeof(cmd
), WMI_TEMP_SENSE_ALL_DONE_EVENTID
,
2730 &reply
, sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
2734 if (reply
.evt
.status
== WMI_FW_STATUS_FAILURE
) {
2735 wil_err(wil
, "Failed getting TEMP_SENSE_ALL\n");
2739 memcpy(sense_all_evt
, &reply
.evt
, sizeof(reply
.evt
));
2743 int wmi_disconnect_sta(struct wil6210_vif
*vif
, const u8
*mac
, u16 reason
,
2746 struct wil6210_priv
*wil
= vif_to_wil(vif
);
2748 struct wmi_disconnect_sta_cmd disc_sta_cmd
= {
2749 .disconnect_reason
= cpu_to_le16(reason
),
2751 struct wmi_del_sta_cmd del_sta_cmd
= {
2752 .disconnect_reason
= cpu_to_le16(reason
),
2755 struct wmi_cmd_hdr wmi
;
2756 struct wmi_disconnect_event evt
;
2759 wil_dbg_wmi(wil
, "disconnect_sta: (%pM, reason %d)\n", mac
, reason
);
2761 memset(&reply
, 0, sizeof(reply
));
2762 vif
->locally_generated_disc
= true;
2764 ether_addr_copy(del_sta_cmd
.dst_mac
, mac
);
2765 rc
= wmi_call(wil
, WMI_DEL_STA_CMDID
, vif
->mid
, &del_sta_cmd
,
2766 sizeof(del_sta_cmd
), WMI_DISCONNECT_EVENTID
,
2767 &reply
, sizeof(reply
), 1000);
2769 ether_addr_copy(disc_sta_cmd
.dst_mac
, mac
);
2770 rc
= wmi_call(wil
, WMI_DISCONNECT_STA_CMDID
, vif
->mid
,
2771 &disc_sta_cmd
, sizeof(disc_sta_cmd
),
2772 WMI_DISCONNECT_EVENTID
,
2773 &reply
, sizeof(reply
), 1000);
2775 /* failure to disconnect in reasonable time treated as FW error */
2777 wil_fw_error_recovery(wil
);
2785 int wmi_addba(struct wil6210_priv
*wil
, u8 mid
,
2786 u8 ringid
, u8 size
, u16 timeout
)
2788 u8 amsdu
= wil
->use_enhanced_dma_hw
&& wil
->use_rx_hw_reordering
&&
2789 test_bit(WMI_FW_CAPABILITY_AMSDU
, wil
->fw_capabilities
) &&
2791 struct wmi_ring_ba_en_cmd cmd
= {
2793 .agg_max_wsize
= size
,
2794 .ba_timeout
= cpu_to_le16(timeout
),
2798 wil_dbg_wmi(wil
, "addba: (ring %d size %d timeout %d amsdu %d)\n",
2799 ringid
, size
, timeout
, amsdu
);
2801 return wmi_send(wil
, WMI_RING_BA_EN_CMDID
, mid
, &cmd
, sizeof(cmd
));
2804 int wmi_delba_tx(struct wil6210_priv
*wil
, u8 mid
, u8 ringid
, u16 reason
)
2806 struct wmi_ring_ba_dis_cmd cmd
= {
2808 .reason
= cpu_to_le16(reason
),
2811 wil_dbg_wmi(wil
, "delba_tx: (ring %d reason %d)\n", ringid
, reason
);
2813 return wmi_send(wil
, WMI_RING_BA_DIS_CMDID
, mid
, &cmd
, sizeof(cmd
));
2816 int wmi_delba_rx(struct wil6210_priv
*wil
, u8 mid
, u8 cid
, u8 tid
, u16 reason
)
2818 struct wmi_rcp_delba_cmd cmd
= {
2819 .reason
= cpu_to_le16(reason
),
2822 if (cid
>= WIL6210_RX_DESC_MAX_CID
) {
2823 cmd
.cidxtid
= CIDXTID_EXTENDED_CID_TID
;
2827 cmd
.cidxtid
= mk_cidxtid(cid
, tid
);
2830 wil_dbg_wmi(wil
, "delba_rx: (CID %d TID %d reason %d)\n", cid
,
2833 return wmi_send(wil
, WMI_RCP_DELBA_CMDID
, mid
, &cmd
, sizeof(cmd
));
2836 int wmi_addba_rx_resp(struct wil6210_priv
*wil
,
2837 u8 mid
, u8 cid
, u8 tid
, u8 token
,
2838 u16 status
, bool amsdu
, u16 agg_wsize
, u16 timeout
)
2841 struct wmi_rcp_addba_resp_cmd cmd
= {
2842 .dialog_token
= token
,
2843 .status_code
= cpu_to_le16(status
),
2844 /* bit 0: A-MSDU supported
2845 * bit 1: policy (controlled by FW)
2847 * bits 6..15: buffer size
2849 .ba_param_set
= cpu_to_le16((amsdu
? 1 : 0) | (tid
<< 2) |
2851 .ba_timeout
= cpu_to_le16(timeout
),
2854 struct wmi_cmd_hdr wmi
;
2855 struct wmi_rcp_addba_resp_sent_event evt
;
2856 } __packed reply
= {
2857 .evt
= {.status
= cpu_to_le16(WMI_FW_STATUS_FAILURE
)},
2860 if (cid
>= WIL6210_RX_DESC_MAX_CID
) {
2861 cmd
.cidxtid
= CIDXTID_EXTENDED_CID_TID
;
2865 cmd
.cidxtid
= mk_cidxtid(cid
, tid
);
2869 "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
2870 mid
, cid
, tid
, agg_wsize
,
2871 timeout
, status
, amsdu
? "+" : "-");
2873 rc
= wmi_call(wil
, WMI_RCP_ADDBA_RESP_CMDID
, mid
, &cmd
, sizeof(cmd
),
2874 WMI_RCP_ADDBA_RESP_SENT_EVENTID
, &reply
, sizeof(reply
),
2875 WIL_WMI_CALL_GENERAL_TO_MS
);
2879 if (reply
.evt
.status
) {
2880 wil_err(wil
, "ADDBA response failed with status %d\n",
2881 le16_to_cpu(reply
.evt
.status
));
2888 int wmi_addba_rx_resp_edma(struct wil6210_priv
*wil
, u8 mid
, u8 cid
, u8 tid
,
2889 u8 token
, u16 status
, bool amsdu
, u16 agg_wsize
,
2893 struct wmi_rcp_addba_resp_edma_cmd cmd
= {
2896 .dialog_token
= token
,
2897 .status_code
= cpu_to_le16(status
),
2898 /* bit 0: A-MSDU supported
2899 * bit 1: policy (controlled by FW)
2901 * bits 6..15: buffer size
2903 .ba_param_set
= cpu_to_le16((amsdu
? 1 : 0) | (tid
<< 2) |
2905 .ba_timeout
= cpu_to_le16(timeout
),
2906 /* route all the connections to status ring 0 */
2907 .status_ring_id
= WIL_DEFAULT_RX_STATUS_RING_ID
,
2910 struct wmi_cmd_hdr wmi
;
2911 struct wmi_rcp_addba_resp_sent_event evt
;
2912 } __packed reply
= {
2913 .evt
= {.status
= cpu_to_le16(WMI_FW_STATUS_FAILURE
)},
2917 "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s, sring_id %d\n",
2918 cid
, tid
, agg_wsize
, timeout
, status
, amsdu
? "+" : "-",
2919 WIL_DEFAULT_RX_STATUS_RING_ID
);
2921 rc
= wmi_call(wil
, WMI_RCP_ADDBA_RESP_EDMA_CMDID
, mid
, &cmd
,
2922 sizeof(cmd
), WMI_RCP_ADDBA_RESP_SENT_EVENTID
, &reply
,
2923 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
2927 if (reply
.evt
.status
) {
2928 wil_err(wil
, "ADDBA response failed with status %d\n",
2929 le16_to_cpu(reply
.evt
.status
));
2936 int wmi_ps_dev_profile_cfg(struct wil6210_priv
*wil
,
2937 enum wmi_ps_profile_type ps_profile
)
2939 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2941 struct wmi_ps_dev_profile_cfg_cmd cmd
= {
2942 .ps_profile
= ps_profile
,
2945 struct wmi_cmd_hdr wmi
;
2946 struct wmi_ps_dev_profile_cfg_event evt
;
2947 } __packed reply
= {
2948 .evt
= {.status
= cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR
)},
2952 wil_dbg_wmi(wil
, "Setting ps dev profile %d\n", ps_profile
);
2954 rc
= wmi_call(wil
, WMI_PS_DEV_PROFILE_CFG_CMDID
, vif
->mid
,
2956 WMI_PS_DEV_PROFILE_CFG_EVENTID
, &reply
, sizeof(reply
),
2957 WIL_WMI_CALL_GENERAL_TO_MS
);
2961 status
= le32_to_cpu(reply
.evt
.status
);
2963 if (status
!= WMI_PS_CFG_CMD_STATUS_SUCCESS
) {
2964 wil_err(wil
, "ps dev profile cfg failed with status %d\n",
2972 int wmi_set_mgmt_retry(struct wil6210_priv
*wil
, u8 retry_short
)
2974 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
2976 struct wmi_set_mgmt_retry_limit_cmd cmd
= {
2977 .mgmt_retry_limit
= retry_short
,
2980 struct wmi_cmd_hdr wmi
;
2981 struct wmi_set_mgmt_retry_limit_event evt
;
2982 } __packed reply
= {
2983 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
2986 wil_dbg_wmi(wil
, "Setting mgmt retry short %d\n", retry_short
);
2988 if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT
, wil
->fw_capabilities
))
2991 rc
= wmi_call(wil
, WMI_SET_MGMT_RETRY_LIMIT_CMDID
, vif
->mid
,
2993 WMI_SET_MGMT_RETRY_LIMIT_EVENTID
, &reply
, sizeof(reply
),
2994 WIL_WMI_CALL_GENERAL_TO_MS
);
2998 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
2999 wil_err(wil
, "set mgmt retry limit failed with status %d\n",
3007 int wmi_get_mgmt_retry(struct wil6210_priv
*wil
, u8
*retry_short
)
3009 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3012 struct wmi_cmd_hdr wmi
;
3013 struct wmi_get_mgmt_retry_limit_event evt
;
3016 wil_dbg_wmi(wil
, "getting mgmt retry short\n");
3018 if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT
, wil
->fw_capabilities
))
3021 memset(&reply
, 0, sizeof(reply
));
3022 rc
= wmi_call(wil
, WMI_GET_MGMT_RETRY_LIMIT_CMDID
, vif
->mid
, NULL
, 0,
3023 WMI_GET_MGMT_RETRY_LIMIT_EVENTID
, &reply
, sizeof(reply
),
3024 WIL_WMI_CALL_GENERAL_TO_MS
);
3029 *retry_short
= reply
.evt
.mgmt_retry_limit
;
3034 int wmi_abort_scan(struct wil6210_vif
*vif
)
3036 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3039 wil_dbg_wmi(wil
, "sending WMI_ABORT_SCAN_CMDID\n");
3041 rc
= wmi_send(wil
, WMI_ABORT_SCAN_CMDID
, vif
->mid
, NULL
, 0);
3043 wil_err(wil
, "Failed to abort scan (%d)\n", rc
);
3048 int wmi_new_sta(struct wil6210_vif
*vif
, const u8
*mac
, u8 aid
)
3050 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3052 struct wmi_new_sta_cmd cmd
= {
3056 wil_dbg_wmi(wil
, "new sta %pM, aid %d\n", mac
, aid
);
3058 ether_addr_copy(cmd
.dst_mac
, mac
);
3060 rc
= wmi_send(wil
, WMI_NEW_STA_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
));
3062 wil_err(wil
, "Failed to send new sta (%d)\n", rc
);
3067 void wmi_event_flush(struct wil6210_priv
*wil
)
3070 struct pending_wmi_event
*evt
, *t
;
3072 wil_dbg_wmi(wil
, "event_flush\n");
3074 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
3076 list_for_each_entry_safe(evt
, t
, &wil
->pending_wmi_ev
, list
) {
3077 list_del(&evt
->list
);
3081 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
3084 static const char *suspend_status2name(u8 status
)
3087 case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE
:
3088 return "LINK_NOT_IDLE";
3089 case WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT
:
3090 return "DISCONNECT";
3091 case WMI_TRAFFIC_SUSPEND_REJECTED_OTHER
:
3094 return "Untracked status";
3098 int wmi_suspend(struct wil6210_priv
*wil
)
3100 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3102 struct wmi_traffic_suspend_cmd cmd
= {
3103 .wakeup_trigger
= wil
->wakeup_trigger
,
3106 struct wmi_cmd_hdr wmi
;
3107 struct wmi_traffic_suspend_event evt
;
3108 } __packed reply
= {
3109 .evt
= {.status
= WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE
},
3112 u32 suspend_to
= WIL_WAIT_FOR_SUSPEND_RESUME_COMP
;
3114 wil
->suspend_resp_rcvd
= false;
3115 wil
->suspend_resp_comp
= false;
3117 rc
= wmi_call(wil
, WMI_TRAFFIC_SUSPEND_CMDID
, vif
->mid
,
3119 WMI_TRAFFIC_SUSPEND_EVENTID
, &reply
, sizeof(reply
),
3122 wil_err(wil
, "wmi_call for suspend req failed, rc=%d\n", rc
);
3125 wil
->suspend_stats
.rejected_by_device
++;
3127 wil
->suspend_stats
.rejected_by_host
++;
3131 wil_dbg_wmi(wil
, "waiting for suspend_response_completed\n");
3133 rc
= wait_event_interruptible_timeout(wil
->wq
,
3134 wil
->suspend_resp_comp
,
3135 msecs_to_jiffies(suspend_to
));
3137 wil_err(wil
, "TO waiting for suspend_response_completed\n");
3138 if (wil
->suspend_resp_rcvd
)
3139 /* Device responded but we TO due to another reason */
3140 wil
->suspend_stats
.rejected_by_host
++;
3142 wil
->suspend_stats
.rejected_by_device
++;
3147 wil_dbg_wmi(wil
, "suspend_response_completed rcvd\n");
3148 if (reply
.evt
.status
!= WMI_TRAFFIC_SUSPEND_APPROVED
) {
3149 wil_dbg_pm(wil
, "device rejected the suspend, %s\n",
3150 suspend_status2name(reply
.evt
.status
));
3151 wil
->suspend_stats
.rejected_by_device
++;
3153 rc
= reply
.evt
.status
;
3156 wil
->suspend_resp_rcvd
= false;
3157 wil
->suspend_resp_comp
= false;
3162 static void resume_triggers2string(u32 triggers
, char *string
, int str_size
)
3167 strlcat(string
, " UNKNOWN", str_size
);
3171 if (triggers
& WMI_RESUME_TRIGGER_HOST
)
3172 strlcat(string
, " HOST", str_size
);
3174 if (triggers
& WMI_RESUME_TRIGGER_UCAST_RX
)
3175 strlcat(string
, " UCAST_RX", str_size
);
3177 if (triggers
& WMI_RESUME_TRIGGER_BCAST_RX
)
3178 strlcat(string
, " BCAST_RX", str_size
);
3180 if (triggers
& WMI_RESUME_TRIGGER_WMI_EVT
)
3181 strlcat(string
, " WMI_EVT", str_size
);
3183 if (triggers
& WMI_RESUME_TRIGGER_DISCONNECT
)
3184 strlcat(string
, " DISCONNECT", str_size
);
3187 int wmi_resume(struct wil6210_priv
*wil
)
3189 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3193 struct wmi_cmd_hdr wmi
;
3194 struct wmi_traffic_resume_event evt
;
3195 } __packed reply
= {
3196 .evt
= {.status
= WMI_TRAFFIC_RESUME_FAILED
,
3198 cpu_to_le32(WMI_RESUME_TRIGGER_UNKNOWN
)},
3201 rc
= wmi_call(wil
, WMI_TRAFFIC_RESUME_CMDID
, vif
->mid
, NULL
, 0,
3202 WMI_TRAFFIC_RESUME_EVENTID
, &reply
, sizeof(reply
),
3203 WIL_WAIT_FOR_SUSPEND_RESUME_COMP
);
3206 resume_triggers2string(le32_to_cpu(reply
.evt
.resume_triggers
), string
,
3208 wil_dbg_pm(wil
, "device resume %s, resume triggers:%s (0x%x)\n",
3209 reply
.evt
.status
? "failed" : "passed", string
,
3210 le32_to_cpu(reply
.evt
.resume_triggers
));
3212 return reply
.evt
.status
;
3215 int wmi_port_allocate(struct wil6210_priv
*wil
, u8 mid
,
3216 const u8
*mac
, enum nl80211_iftype iftype
)
3219 struct wmi_port_allocate_cmd cmd
= {
3223 struct wmi_cmd_hdr wmi
;
3224 struct wmi_port_allocated_event evt
;
3225 } __packed reply
= {
3226 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3229 wil_dbg_misc(wil
, "port allocate, mid %d iftype %d, mac %pM\n",
3232 ether_addr_copy(cmd
.mac
, mac
);
3234 case NL80211_IFTYPE_STATION
:
3235 cmd
.port_role
= WMI_PORT_STA
;
3237 case NL80211_IFTYPE_AP
:
3238 cmd
.port_role
= WMI_PORT_AP
;
3240 case NL80211_IFTYPE_P2P_CLIENT
:
3241 cmd
.port_role
= WMI_PORT_P2P_CLIENT
;
3243 case NL80211_IFTYPE_P2P_GO
:
3244 cmd
.port_role
= WMI_PORT_P2P_GO
;
3246 /* what about monitor??? */
3248 wil_err(wil
, "unsupported iftype: %d\n", iftype
);
3252 rc
= wmi_call(wil
, WMI_PORT_ALLOCATE_CMDID
, mid
,
3254 WMI_PORT_ALLOCATED_EVENTID
, &reply
,
3255 sizeof(reply
), 300);
3257 wil_err(wil
, "failed to allocate port, status %d\n", rc
);
3260 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3261 wil_err(wil
, "WMI_PORT_ALLOCATE returned status %d\n",
3269 int wmi_port_delete(struct wil6210_priv
*wil
, u8 mid
)
3272 struct wmi_port_delete_cmd cmd
= {
3276 struct wmi_cmd_hdr wmi
;
3277 struct wmi_port_deleted_event evt
;
3278 } __packed reply
= {
3279 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3282 wil_dbg_misc(wil
, "port delete, mid %d\n", mid
);
3284 rc
= wmi_call(wil
, WMI_PORT_DELETE_CMDID
, mid
,
3286 WMI_PORT_DELETED_EVENTID
, &reply
,
3287 sizeof(reply
), 2000);
3289 wil_err(wil
, "failed to delete port, status %d\n", rc
);
3292 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3293 wil_err(wil
, "WMI_PORT_DELETE returned status %d\n",
3301 static bool wmi_evt_call_handler(struct wil6210_vif
*vif
, int id
,
3306 for (i
= 0; i
< ARRAY_SIZE(wmi_evt_handlers
); i
++) {
3307 if (wmi_evt_handlers
[i
].eventid
== id
) {
3308 wmi_evt_handlers
[i
].handler(vif
, id
, d
, len
);
3316 static void wmi_event_handle(struct wil6210_priv
*wil
,
3317 struct wil6210_mbox_hdr
*hdr
)
3319 u16 len
= le16_to_cpu(hdr
->len
);
3320 struct wil6210_vif
*vif
;
3322 if ((hdr
->type
== WIL_MBOX_HDR_TYPE_WMI
) &&
3323 (len
>= sizeof(struct wmi_cmd_hdr
))) {
3324 struct wmi_cmd_hdr
*wmi
= (void *)(&hdr
[1]);
3325 void *evt_data
= (void *)(&wmi
[1]);
3326 u16 id
= le16_to_cpu(wmi
->command_id
);
3329 wil_dbg_wmi(wil
, "Handle %s (0x%04x) (reply_id 0x%04x,%d)\n",
3330 eventid2name(id
), id
, wil
->reply_id
,
3333 if (mid
== MID_BROADCAST
)
3335 if (mid
>= GET_MAX_VIFS(wil
)) {
3336 wil_dbg_wmi(wil
, "invalid mid %d, event skipped\n",
3340 vif
= wil
->vifs
[mid
];
3342 wil_dbg_wmi(wil
, "event for empty VIF(%d), skipped\n",
3347 /* check if someone waits for this event */
3348 if (wil
->reply_id
&& wil
->reply_id
== id
&&
3349 wil
->reply_mid
== mid
) {
3350 if (wil
->reply_buf
) {
3351 /* event received while wmi_call is waiting
3352 * with a buffer. Such event should be handled
3353 * in wmi_recv_cmd function. Handling the event
3354 * here means a previous wmi_call was timeout.
3355 * Drop the event and do not handle it.
3358 "Old event (%d, %s) while wmi_call is waiting. Drop it and Continue waiting\n",
3359 id
, eventid2name(id
));
3363 wmi_evt_call_handler(vif
, id
, evt_data
,
3364 len
- sizeof(*wmi
));
3365 wil_dbg_wmi(wil
, "event_handle: Complete WMI 0x%04x\n",
3367 complete(&wil
->wmi_call
);
3370 /* unsolicited event */
3371 /* search for handler */
3372 if (!wmi_evt_call_handler(vif
, id
, evt_data
,
3373 len
- sizeof(*wmi
))) {
3374 wil_info(wil
, "Unhandled event 0x%04x\n", id
);
3377 wil_err(wil
, "Unknown event type\n");
3378 print_hex_dump(KERN_ERR
, "evt?? ", DUMP_PREFIX_OFFSET
, 16, 1,
3379 hdr
, sizeof(*hdr
) + len
, true);
3384 * Retrieve next WMI event from the pending list
3386 static struct list_head
*next_wmi_ev(struct wil6210_priv
*wil
)
3389 struct list_head
*ret
= NULL
;
3391 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
3393 if (!list_empty(&wil
->pending_wmi_ev
)) {
3394 ret
= wil
->pending_wmi_ev
.next
;
3398 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
3404 * Handler for the WMI events
3406 void wmi_event_worker(struct work_struct
*work
)
3408 struct wil6210_priv
*wil
= container_of(work
, struct wil6210_priv
,
3410 struct pending_wmi_event
*evt
;
3411 struct list_head
*lh
;
3413 wil_dbg_wmi(wil
, "event_worker: Start\n");
3414 while ((lh
= next_wmi_ev(wil
)) != NULL
) {
3415 evt
= list_entry(lh
, struct pending_wmi_event
, list
);
3416 wmi_event_handle(wil
, &evt
->event
.hdr
);
3419 wil_dbg_wmi(wil
, "event_worker: Finished\n");
3422 bool wil_is_wmi_idle(struct wil6210_priv
*wil
)
3425 struct wil6210_mbox_ring
*r
= &wil
->mbox_ctl
.rx
;
3428 spin_lock_irqsave(&wil
->wmi_ev_lock
, flags
);
3430 /* Check if there are pending WMI events in the events queue */
3431 if (!list_empty(&wil
->pending_wmi_ev
)) {
3432 wil_dbg_pm(wil
, "Pending WMI events in queue\n");
3436 /* Check if there is a pending WMI call */
3437 if (wil
->reply_id
) {
3438 wil_dbg_pm(wil
, "Pending WMI call\n");
3442 /* Check if there are pending RX events in mbox */
3443 r
->head
= wil_r(wil
, RGF_MBOX
+
3444 offsetof(struct wil6210_mbox_ctl
, rx
.head
));
3445 if (r
->tail
!= r
->head
)
3446 wil_dbg_pm(wil
, "Pending WMI mbox events\n");
3451 spin_unlock_irqrestore(&wil
->wmi_ev_lock
, flags
);
3456 wmi_sched_scan_set_ssids(struct wil6210_priv
*wil
,
3457 struct wmi_start_sched_scan_cmd
*cmd
,
3458 struct cfg80211_ssid
*ssids
, int n_ssids
,
3459 struct cfg80211_match_set
*match_sets
,
3464 if (n_match_sets
> WMI_MAX_PNO_SSID_NUM
) {
3465 wil_dbg_wmi(wil
, "too many match sets (%d), use first %d\n",
3466 n_match_sets
, WMI_MAX_PNO_SSID_NUM
);
3467 n_match_sets
= WMI_MAX_PNO_SSID_NUM
;
3469 cmd
->num_of_ssids
= n_match_sets
;
3471 for (i
= 0; i
< n_match_sets
; i
++) {
3472 struct wmi_sched_scan_ssid_match
*wmi_match
=
3473 &cmd
->ssid_for_match
[i
];
3474 struct cfg80211_match_set
*cfg_match
= &match_sets
[i
];
3477 wmi_match
->ssid_len
= cfg_match
->ssid
.ssid_len
;
3478 memcpy(wmi_match
->ssid
, cfg_match
->ssid
.ssid
,
3479 min_t(u8
, wmi_match
->ssid_len
, WMI_MAX_SSID_LEN
));
3480 wmi_match
->rssi_threshold
= S8_MIN
;
3481 if (cfg_match
->rssi_thold
>= S8_MIN
&&
3482 cfg_match
->rssi_thold
<= S8_MAX
)
3483 wmi_match
->rssi_threshold
= cfg_match
->rssi_thold
;
3485 for (j
= 0; j
< n_ssids
; j
++)
3486 if (wmi_match
->ssid_len
== ssids
[j
].ssid_len
&&
3487 memcmp(wmi_match
->ssid
, ssids
[j
].ssid
,
3488 wmi_match
->ssid_len
) == 0)
3489 wmi_match
->add_ssid_to_probe
= true;
3494 wmi_sched_scan_set_channels(struct wil6210_priv
*wil
,
3495 struct wmi_start_sched_scan_cmd
*cmd
,
3497 struct ieee80211_channel
**channels
)
3501 if (n_channels
> WMI_MAX_CHANNEL_NUM
) {
3502 wil_dbg_wmi(wil
, "too many channels (%d), use first %d\n",
3503 n_channels
, WMI_MAX_CHANNEL_NUM
);
3504 n_channels
= WMI_MAX_CHANNEL_NUM
;
3506 cmd
->num_of_channels
= n_channels
;
3508 for (i
= 0; i
< n_channels
; i
++) {
3509 struct ieee80211_channel
*cfg_chan
= channels
[i
];
3511 cmd
->channel_list
[i
] = cfg_chan
->hw_value
- 1;
3516 wmi_sched_scan_set_plans(struct wil6210_priv
*wil
,
3517 struct wmi_start_sched_scan_cmd
*cmd
,
3518 struct cfg80211_sched_scan_plan
*scan_plans
,
3523 if (n_scan_plans
> WMI_MAX_PLANS_NUM
) {
3524 wil_dbg_wmi(wil
, "too many plans (%d), use first %d\n",
3525 n_scan_plans
, WMI_MAX_PLANS_NUM
);
3526 n_scan_plans
= WMI_MAX_PLANS_NUM
;
3529 for (i
= 0; i
< n_scan_plans
; i
++) {
3530 struct cfg80211_sched_scan_plan
*cfg_plan
= &scan_plans
[i
];
3532 cmd
->scan_plans
[i
].interval_sec
=
3533 cpu_to_le16(cfg_plan
->interval
);
3534 cmd
->scan_plans
[i
].num_of_iterations
=
3535 cpu_to_le16(cfg_plan
->iterations
);
3539 int wmi_start_sched_scan(struct wil6210_priv
*wil
,
3540 struct cfg80211_sched_scan_request
*request
)
3542 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3544 struct wmi_start_sched_scan_cmd cmd
= {
3545 .min_rssi_threshold
= S8_MIN
,
3546 .initial_delay_sec
= cpu_to_le16(request
->delay
),
3549 struct wmi_cmd_hdr wmi
;
3550 struct wmi_start_sched_scan_event evt
;
3551 } __packed reply
= {
3552 .evt
= {.result
= WMI_PNO_REJECT
},
3555 if (!test_bit(WMI_FW_CAPABILITY_PNO
, wil
->fw_capabilities
))
3558 if (request
->min_rssi_thold
>= S8_MIN
&&
3559 request
->min_rssi_thold
<= S8_MAX
)
3560 cmd
.min_rssi_threshold
= request
->min_rssi_thold
;
3562 wmi_sched_scan_set_ssids(wil
, &cmd
, request
->ssids
, request
->n_ssids
,
3563 request
->match_sets
, request
->n_match_sets
);
3564 wmi_sched_scan_set_channels(wil
, &cmd
,
3565 request
->n_channels
, request
->channels
);
3566 wmi_sched_scan_set_plans(wil
, &cmd
,
3567 request
->scan_plans
, request
->n_scan_plans
);
3569 rc
= wmi_call(wil
, WMI_START_SCHED_SCAN_CMDID
, vif
->mid
,
3571 WMI_START_SCHED_SCAN_EVENTID
, &reply
, sizeof(reply
),
3572 WIL_WMI_CALL_GENERAL_TO_MS
);
3576 if (reply
.evt
.result
!= WMI_PNO_SUCCESS
) {
3577 wil_err(wil
, "start sched scan failed, result %d\n",
3585 int wmi_stop_sched_scan(struct wil6210_priv
*wil
)
3587 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3590 struct wmi_cmd_hdr wmi
;
3591 struct wmi_stop_sched_scan_event evt
;
3592 } __packed reply
= {
3593 .evt
= {.result
= WMI_PNO_REJECT
},
3596 if (!test_bit(WMI_FW_CAPABILITY_PNO
, wil
->fw_capabilities
))
3599 rc
= wmi_call(wil
, WMI_STOP_SCHED_SCAN_CMDID
, vif
->mid
, NULL
, 0,
3600 WMI_STOP_SCHED_SCAN_EVENTID
, &reply
, sizeof(reply
),
3601 WIL_WMI_CALL_GENERAL_TO_MS
);
3605 if (reply
.evt
.result
!= WMI_PNO_SUCCESS
) {
3606 wil_err(wil
, "stop sched scan failed, result %d\n",
3614 int wmi_mgmt_tx(struct wil6210_vif
*vif
, const u8
*buf
, size_t len
)
3617 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3618 struct ieee80211_mgmt
*mgmt_frame
= (void *)buf
;
3619 struct wmi_sw_tx_req_cmd
*cmd
;
3621 struct wmi_cmd_hdr wmi
;
3622 struct wmi_sw_tx_complete_event evt
;
3624 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3628 wil_dbg_misc(wil
, "mgmt_tx mid %d\n", vif
->mid
);
3629 wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET
, 16, 1, buf
,
3632 if (len
< sizeof(struct ieee80211_hdr_3addr
))
3635 total
= sizeof(*cmd
) + len
;
3637 wil_err(wil
, "mgmt_tx invalid len %zu\n", len
);
3641 cmd
= kmalloc(total
, GFP_KERNEL
);
3645 memcpy(cmd
->dst_mac
, mgmt_frame
->da
, WMI_MAC_LEN
);
3646 cmd
->len
= cpu_to_le16(len
);
3647 memcpy(cmd
->payload
, buf
, len
);
3649 rc
= wmi_call(wil
, WMI_SW_TX_REQ_CMDID
, vif
->mid
, cmd
, total
,
3650 WMI_SW_TX_COMPLETE_EVENTID
, &evt
, sizeof(evt
), 2000);
3651 if (!rc
&& evt
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3652 wil_dbg_wmi(wil
, "mgmt_tx failed with status %d\n",
3662 int wmi_mgmt_tx_ext(struct wil6210_vif
*vif
, const u8
*buf
, size_t len
,
3663 u8 channel
, u16 duration_ms
)
3666 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3667 struct ieee80211_mgmt
*mgmt_frame
= (void *)buf
;
3668 struct wmi_sw_tx_req_ext_cmd
*cmd
;
3670 struct wmi_cmd_hdr wmi
;
3671 struct wmi_sw_tx_complete_event evt
;
3673 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3677 wil_dbg_wmi(wil
, "mgmt_tx_ext mid %d channel %d duration %d\n",
3678 vif
->mid
, channel
, duration_ms
);
3679 wil_hex_dump_wmi("mgmt_tx_ext frame ", DUMP_PREFIX_OFFSET
, 16, 1, buf
,
3682 if (len
< sizeof(struct ieee80211_hdr_3addr
)) {
3683 wil_err(wil
, "short frame. len %zu\n", len
);
3687 total
= sizeof(*cmd
) + len
;
3689 wil_err(wil
, "mgmt_tx_ext invalid len %zu\n", len
);
3693 cmd
= kzalloc(total
, GFP_KERNEL
);
3697 memcpy(cmd
->dst_mac
, mgmt_frame
->da
, WMI_MAC_LEN
);
3698 cmd
->len
= cpu_to_le16(len
);
3699 memcpy(cmd
->payload
, buf
, len
);
3700 cmd
->channel
= channel
- 1;
3701 cmd
->duration_ms
= cpu_to_le16(duration_ms
);
3703 rc
= wmi_call(wil
, WMI_SW_TX_REQ_EXT_CMDID
, vif
->mid
, cmd
, total
,
3704 WMI_SW_TX_COMPLETE_EVENTID
, &evt
, sizeof(evt
), 2000);
3705 if (!rc
&& evt
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3706 wil_dbg_wmi(wil
, "mgmt_tx_ext failed with status %d\n",
3716 int wil_wmi_tx_sring_cfg(struct wil6210_priv
*wil
, int ring_id
)
3719 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
3720 struct wil_status_ring
*sring
= &wil
->srings
[ring_id
];
3721 struct wmi_tx_status_ring_add_cmd cmd
= {
3723 .ring_size
= cpu_to_le16(sring
->size
),
3725 .irq_index
= WIL_TX_STATUS_IRQ_IDX
3728 struct wmi_cmd_hdr hdr
;
3729 struct wmi_tx_status_ring_cfg_done_event evt
;
3730 } __packed reply
= {
3731 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3734 cmd
.ring_cfg
.ring_id
= ring_id
;
3736 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(sring
->pa
);
3737 rc
= wmi_call(wil
, WMI_TX_STATUS_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3738 sizeof(cmd
), WMI_TX_STATUS_RING_CFG_DONE_EVENTID
,
3739 &reply
, sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3741 wil_err(wil
, "TX_STATUS_RING_ADD_CMD failed, rc %d\n", rc
);
3745 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3746 wil_err(wil
, "TX_STATUS_RING_ADD_CMD failed, status %d\n",
3751 sring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3756 int wil_wmi_cfg_def_rx_offload(struct wil6210_priv
*wil
, u16 max_rx_pl_per_desc
)
3758 struct net_device
*ndev
= wil
->main_ndev
;
3759 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
3761 struct wmi_cfg_def_rx_offload_cmd cmd
= {
3762 .max_msdu_size
= cpu_to_le16(wil_mtu2macbuf(WIL_MAX_ETH_MTU
)),
3763 .max_rx_pl_per_desc
= cpu_to_le16(max_rx_pl_per_desc
),
3764 .decap_trans_type
= WMI_DECAP_TYPE_802_3
,
3765 .l2_802_3_offload_ctrl
= 0,
3766 .l3_l4_ctrl
= 1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS
,
3769 struct wmi_cmd_hdr hdr
;
3770 struct wmi_cfg_def_rx_offload_done_event evt
;
3771 } __packed reply
= {
3772 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3775 rc
= wmi_call(wil
, WMI_CFG_DEF_RX_OFFLOAD_CMDID
, vif
->mid
, &cmd
,
3776 sizeof(cmd
), WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID
, &reply
,
3777 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3779 wil_err(wil
, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, rc %d\n", rc
);
3783 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3784 wil_err(wil
, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, status %d\n",
3792 int wil_wmi_rx_sring_add(struct wil6210_priv
*wil
, u16 ring_id
)
3794 struct net_device
*ndev
= wil
->main_ndev
;
3795 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
3796 struct wil_status_ring
*sring
= &wil
->srings
[ring_id
];
3798 struct wmi_rx_status_ring_add_cmd cmd
= {
3800 .ring_size
= cpu_to_le16(sring
->size
),
3803 .rx_msg_type
= wil
->use_compressed_rx_status
?
3804 WMI_RX_MSG_TYPE_COMPRESSED
:
3805 WMI_RX_MSG_TYPE_EXTENDED
,
3806 .irq_index
= WIL_RX_STATUS_IRQ_IDX
,
3809 struct wmi_cmd_hdr hdr
;
3810 struct wmi_rx_status_ring_cfg_done_event evt
;
3811 } __packed reply
= {
3812 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3815 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(sring
->pa
);
3816 rc
= wmi_call(wil
, WMI_RX_STATUS_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3817 sizeof(cmd
), WMI_RX_STATUS_RING_CFG_DONE_EVENTID
, &reply
,
3818 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3820 wil_err(wil
, "RX_STATUS_RING_ADD_CMD failed, rc %d\n", rc
);
3824 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3825 wil_err(wil
, "RX_STATUS_RING_ADD_CMD failed, status %d\n",
3830 sring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3835 int wil_wmi_rx_desc_ring_add(struct wil6210_priv
*wil
, int status_ring_id
)
3837 struct net_device
*ndev
= wil
->main_ndev
;
3838 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
3839 struct wil_ring
*ring
= &wil
->ring_rx
;
3841 struct wmi_rx_desc_ring_add_cmd cmd
= {
3843 .ring_size
= cpu_to_le16(ring
->size
),
3844 .ring_id
= WIL_RX_DESC_RING_ID
,
3846 .status_ring_id
= status_ring_id
,
3847 .irq_index
= WIL_RX_STATUS_IRQ_IDX
,
3850 struct wmi_cmd_hdr hdr
;
3851 struct wmi_rx_desc_ring_cfg_done_event evt
;
3852 } __packed reply
= {
3853 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3856 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(ring
->pa
);
3857 cmd
.sw_tail_host_addr
= cpu_to_le64(ring
->edma_rx_swtail
.pa
);
3858 rc
= wmi_call(wil
, WMI_RX_DESC_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3859 sizeof(cmd
), WMI_RX_DESC_RING_CFG_DONE_EVENTID
, &reply
,
3860 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3862 wil_err(wil
, "WMI_RX_DESC_RING_ADD_CMD failed, rc %d\n", rc
);
3866 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3867 wil_err(wil
, "WMI_RX_DESC_RING_ADD_CMD failed, status %d\n",
3872 ring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3877 int wil_wmi_tx_desc_ring_add(struct wil6210_vif
*vif
, int ring_id
, int cid
,
3880 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3881 int sring_id
= wil
->tx_sring_idx
; /* there is only one TX sring */
3883 struct wil_ring
*ring
= &wil
->ring_tx
[ring_id
];
3884 struct wil_ring_tx_data
*txdata
= &wil
->ring_tx_data
[ring_id
];
3885 struct wmi_tx_desc_ring_add_cmd cmd
= {
3887 .ring_size
= cpu_to_le16(ring
->size
),
3890 .status_ring_id
= sring_id
,
3893 .encap_trans_type
= WMI_VRING_ENC_TYPE_802_3
,
3894 .max_msdu_size
= cpu_to_le16(wil_mtu2macbuf(mtu_max
)),
3896 .priority
= cpu_to_le16(0),
3897 .timeslot_us
= cpu_to_le16(0xfff),
3901 struct wmi_cmd_hdr hdr
;
3902 struct wmi_tx_desc_ring_cfg_done_event evt
;
3903 } __packed reply
= {
3904 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3907 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(ring
->pa
);
3908 rc
= wmi_call(wil
, WMI_TX_DESC_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3909 sizeof(cmd
), WMI_TX_DESC_RING_CFG_DONE_EVENTID
, &reply
,
3910 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3912 wil_err(wil
, "WMI_TX_DESC_RING_ADD_CMD failed, rc %d\n", rc
);
3916 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3917 wil_err(wil
, "WMI_TX_DESC_RING_ADD_CMD failed, status %d\n",
3922 spin_lock_bh(&txdata
->lock
);
3923 ring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3924 txdata
->mid
= vif
->mid
;
3925 txdata
->enabled
= 1;
3926 spin_unlock_bh(&txdata
->lock
);
3931 int wil_wmi_bcast_desc_ring_add(struct wil6210_vif
*vif
, int ring_id
)
3933 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3934 struct wil_ring
*ring
= &wil
->ring_tx
[ring_id
];
3936 struct wmi_bcast_desc_ring_add_cmd cmd
= {
3938 .ring_size
= cpu_to_le16(ring
->size
),
3941 .max_msdu_size
= cpu_to_le16(wil_mtu2macbuf(mtu_max
)),
3942 .status_ring_id
= wil
->tx_sring_idx
,
3943 .encap_trans_type
= WMI_VRING_ENC_TYPE_802_3
,
3946 struct wmi_cmd_hdr hdr
;
3947 struct wmi_rx_desc_ring_cfg_done_event evt
;
3948 } __packed reply
= {
3949 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3951 struct wil_ring_tx_data
*txdata
= &wil
->ring_tx_data
[ring_id
];
3953 cmd
.ring_cfg
.ring_mem_base
= cpu_to_le64(ring
->pa
);
3954 rc
= wmi_call(wil
, WMI_BCAST_DESC_RING_ADD_CMDID
, vif
->mid
, &cmd
,
3955 sizeof(cmd
), WMI_TX_DESC_RING_CFG_DONE_EVENTID
, &reply
,
3956 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3958 wil_err(wil
, "WMI_BCAST_DESC_RING_ADD_CMD failed, rc %d\n", rc
);
3962 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
3963 wil_err(wil
, "Broadcast Tx config failed, status %d\n",
3968 spin_lock_bh(&txdata
->lock
);
3969 ring
->hwtail
= le32_to_cpu(reply
.evt
.ring_tail_ptr
);
3970 txdata
->mid
= vif
->mid
;
3971 txdata
->enabled
= 1;
3972 spin_unlock_bh(&txdata
->lock
);
3977 int wmi_link_stats_cfg(struct wil6210_vif
*vif
, u32 type
, u8 cid
, u32 interval
)
3979 struct wil6210_priv
*wil
= vif_to_wil(vif
);
3980 struct wmi_link_stats_cmd cmd
= {
3981 .record_type_mask
= cpu_to_le32(type
),
3983 .action
= WMI_LINK_STATS_SNAPSHOT
,
3984 .interval_msec
= cpu_to_le32(interval
),
3987 struct wmi_cmd_hdr wmi
;
3988 struct wmi_link_stats_config_done_event evt
;
3989 } __packed reply
= {
3990 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
3994 rc
= wmi_call(wil
, WMI_LINK_STATS_CMDID
, vif
->mid
, &cmd
, sizeof(cmd
),
3995 WMI_LINK_STATS_CONFIG_DONE_EVENTID
, &reply
,
3996 sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
3998 wil_err(wil
, "WMI_LINK_STATS_CMDID failed, rc %d\n", rc
);
4002 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
4003 wil_err(wil
, "Link statistics config failed, status %d\n",
4011 int wmi_set_cqm_rssi_config(struct wil6210_priv
*wil
,
4012 s32 rssi_thold
, u32 rssi_hyst
)
4014 struct net_device
*ndev
= wil
->main_ndev
;
4015 struct wil6210_vif
*vif
= ndev_to_vif(ndev
);
4018 struct wmi_cmd_hdr hdr
;
4019 struct wmi_set_link_monitor_event evt
;
4020 } __packed reply
= {
4021 .evt
= {.status
= WMI_FW_STATUS_FAILURE
},
4023 DEFINE_FLEX(struct wmi_set_link_monitor_cmd
, cmd
,
4024 rssi_thresholds_list
, rssi_thresholds_list_size
, 1);
4026 cmd
->rssi_hyst
= rssi_hyst
;
4027 cmd
->rssi_thresholds_list
[0] = rssi_thold
;
4029 if (rssi_thold
> S8_MAX
|| rssi_thold
< S8_MIN
|| rssi_hyst
> U8_MAX
)
4032 rc
= wmi_call(wil
, WMI_SET_LINK_MONITOR_CMDID
, vif
->mid
, cmd
,
4033 __struct_size(cmd
), WMI_SET_LINK_MONITOR_EVENTID
,
4034 &reply
, sizeof(reply
), WIL_WMI_CALL_GENERAL_TO_MS
);
4036 wil_err(wil
, "WMI_SET_LINK_MONITOR_CMDID failed, rc %d\n", rc
);
4040 if (reply
.evt
.status
!= WMI_FW_STATUS_SUCCESS
) {
4041 wil_err(wil
, "WMI_SET_LINK_MONITOR_CMDID failed, status %d\n",