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