root/drivers/net/wireless/ath/wil6210/wmi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wmi_addr_remap
  2. wil_find_fw_mapping
  3. wmi_buffer_block
  4. wmi_buffer
  5. wmi_addr
  6. wmi_read_hdr
  7. cmdid2name
  8. eventid2name
  9. __wmi_send
  10. wmi_send
  11. wmi_evt_ready
  12. wmi_evt_rx_mgmt
  13. wmi_evt_tx_mgmt
  14. wmi_evt_scan_complete
  15. wmi_evt_connect
  16. wmi_evt_disconnect
  17. wmi_evt_eapol_rx
  18. wmi_evt_ring_en
  19. wmi_evt_ba_status
  20. wmi_evt_addba_rx_req
  21. wmi_evt_delba
  22. wmi_evt_sched_scan_result
  23. wil_link_stats_store_basic
  24. wil_link_stats_store_global
  25. wmi_link_stats_parse
  26. wmi_evt_link_stats
  27. wil_find_cid_ringid_sta
  28. wmi_evt_auth_status
  29. wmi_evt_reassoc_status
  30. wmi_evt_ignore
  31. wmi_recv_cmd
  32. wmi_call
  33. wmi_echo
  34. wmi_set_mac_address
  35. wmi_led_cfg
  36. wmi_rbufcap_cfg
  37. wmi_pcp_start
  38. wmi_pcp_stop
  39. wmi_set_ssid
  40. wmi_get_ssid
  41. wmi_set_channel
  42. wmi_get_channel
  43. wmi_p2p_cfg
  44. wmi_start_listen
  45. wmi_start_search
  46. wmi_stop_discovery
  47. wmi_del_cipher_key
  48. wmi_add_cipher_key
  49. wmi_set_ie
  50. wmi_update_ft_ies
  51. wmi_rxon
  52. wmi_rx_chain_add
  53. wmi_get_temperature
  54. wmi_get_all_temperatures
  55. wmi_disconnect_sta
  56. wmi_addba
  57. wmi_delba_tx
  58. wmi_delba_rx
  59. wmi_addba_rx_resp
  60. wmi_addba_rx_resp_edma
  61. wmi_ps_dev_profile_cfg
  62. wmi_set_mgmt_retry
  63. wmi_get_mgmt_retry
  64. wmi_abort_scan
  65. wmi_new_sta
  66. wmi_event_flush
  67. suspend_status2name
  68. wmi_suspend
  69. resume_triggers2string
  70. wmi_resume
  71. wmi_port_allocate
  72. wmi_port_delete
  73. wmi_evt_call_handler
  74. wmi_event_handle
  75. next_wmi_ev
  76. wmi_event_worker
  77. wil_is_wmi_idle
  78. wmi_sched_scan_set_ssids
  79. wmi_sched_scan_set_channels
  80. wmi_sched_scan_set_plans
  81. wmi_start_sched_scan
  82. wmi_stop_sched_scan
  83. wmi_mgmt_tx
  84. wmi_mgmt_tx_ext
  85. wil_wmi_tx_sring_cfg
  86. wil_wmi_cfg_def_rx_offload
  87. wil_wmi_rx_sring_add
  88. wil_wmi_rx_desc_ring_add
  89. wil_wmi_tx_desc_ring_add
  90. wil_wmi_bcast_desc_ring_add
  91. wmi_link_stats_cfg

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

/* [<][>][^][v][top][bottom][index][help] */