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