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