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