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