linux/drivers/net/wireless/ath/wil6210/wmi.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include <linux/moduleparam.h>
  18#include <linux/etherdevice.h>
  19#include <linux/if_arp.h>
  20
  21#include "wil6210.h"
  22#include "txrx.h"
  23#include "wmi.h"
  24#include "trace.h"
  25
  26static uint max_assoc_sta = WIL6210_MAX_CID;
  27module_param(max_assoc_sta, uint, 0644);
  28MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
  29
  30int agg_wsize; /* = 0; */
  31module_param(agg_wsize, int, 0644);
  32MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
  33                 " 0 - use default; < 0 - don't auto-establish");
  34
  35u8 led_id = WIL_LED_INVALID_ID;
  36module_param(led_id, byte, 0444);
  37MODULE_PARM_DESC(led_id,
  38                 " 60G device led enablement. Set the led ID (0-2) to enable");
  39
  40#define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
  41
  42/**
  43 * WMI event receiving - theory of operations
  44 *
  45 * When firmware about to report WMI event, it fills memory area
  46 * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
  47 * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
  48 *
  49 * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
  50 * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
  51 * and handles events within the @wmi_event_worker. Every event get detached
  52 * from list, processed and deleted.
  53 *
  54 * Purpose for this mechanism is to release IRQ thread; otherwise,
  55 * if WMI event handling involves another WMI command flow, this 2-nd flow
  56 * won't be completed because of blocked IRQ thread.
  57 */
  58
  59/**
  60 * Addressing - theory of operations
  61 *
  62 * There are several buses present on the WIL6210 card.
  63 * Same memory areas are visible at different address on
  64 * the different busses. There are 3 main bus masters:
  65 *  - MAC CPU (ucode)
  66 *  - User CPU (firmware)
  67 *  - AHB (host)
  68 *
  69 * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
  70 * AHB addresses starting from 0x880000
  71 *
  72 * Internally, firmware uses addresses that allows faster access but
  73 * are invisible from the host. To read from these addresses, alternative
  74 * AHB address must be used.
  75 *
  76 * Memory mapping
  77 * Linker address         PCI/Host address
  78 *                        0x880000 .. 0xa80000  2Mb BAR0
  79 * 0x800000 .. 0x807000   0x900000 .. 0x907000  28k DCCM
  80 * 0x840000 .. 0x857000   0x908000 .. 0x91f000  92k PERIPH
  81 */
  82
  83/**
  84 * @fw_mapping provides memory remapping table
  85 *
  86 * array size should be in sync with the declaration in the wil6210.h
  87 */
  88const struct fw_map fw_mapping[] = {
  89        /* FW code RAM 256k */
  90        {0x000000, 0x040000, 0x8c0000, "fw_code", true},
  91        /* FW data RAM 32k */
  92        {0x800000, 0x808000, 0x900000, "fw_data", true},
  93        /* periph data 128k */
  94        {0x840000, 0x860000, 0x908000, "fw_peri", true},
  95        /* various RGF 40k */
  96        {0x880000, 0x88a000, 0x880000, "rgf", true},
  97        /* AGC table   4k */
  98        {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
  99        /* Pcie_ext_rgf 4k */
 100        {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
 101        /* mac_ext_rgf 512b */
 102        {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true},
 103        /* upper area 548k */
 104        {0x8c0000, 0x949000, 0x8c0000, "upper", true},
 105        /* UCODE areas - accessible by debugfs blobs but not by
 106         * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
 107         */
 108        /* ucode code RAM 128k */
 109        {0x000000, 0x020000, 0x920000, "uc_code", false},
 110        /* ucode data RAM 16k */
 111        {0x800000, 0x804000, 0x940000, "uc_data", false},
 112};
 113
 114struct blink_on_off_time led_blink_time[] = {
 115        {WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS},
 116        {WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS},
 117        {WIL_LED_BLINK_ON_FAST_MS, WIL_LED_BLINK_OFF_FAST_MS},
 118};
 119
 120u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
 121
 122/**
 123 * return AHB address for given firmware internal (linker) address
 124 * @x - internal address
 125 * If address have no valid AHB mapping, return 0
 126 */
 127static u32 wmi_addr_remap(u32 x)
 128{
 129        uint i;
 130
 131        for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
 132                if (fw_mapping[i].fw &&
 133                    ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)))
 134                        return x + fw_mapping[i].host - fw_mapping[i].from;
 135        }
 136
 137        return 0;
 138}
 139
 140/**
 141 * Check address validity for WMI buffer; remap if needed
 142 * @ptr - internal (linker) fw/ucode address
 143 *
 144 * Valid buffer should be DWORD aligned
 145 *
 146 * return address for accessing buffer from the host;
 147 * if buffer is not valid, return NULL.
 148 */
 149void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
 150{
 151        u32 off;
 152        u32 ptr = le32_to_cpu(ptr_);
 153
 154        if (ptr % 4)
 155                return NULL;
 156
 157        ptr = wmi_addr_remap(ptr);
 158        if (ptr < WIL6210_FW_HOST_OFF)
 159                return NULL;
 160
 161        off = HOSTADDR(ptr);
 162        if (off > wil->bar_size - 4)
 163                return NULL;
 164
 165        return wil->csr + off;
 166}
 167
 168/**
 169 * Check address validity
 170 */
 171void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
 172{
 173        u32 off;
 174
 175        if (ptr % 4)
 176                return NULL;
 177
 178        if (ptr < WIL6210_FW_HOST_OFF)
 179                return NULL;
 180
 181        off = HOSTADDR(ptr);
 182        if (off > wil->bar_size - 4)
 183                return NULL;
 184
 185        return wil->csr + off;
 186}
 187
 188int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
 189                 struct wil6210_mbox_hdr *hdr)
 190{
 191        void __iomem *src = wmi_buffer(wil, ptr);
 192
 193        if (!src)
 194                return -EINVAL;
 195
 196        wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
 197
 198        return 0;
 199}
 200
 201static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 202{
 203        struct {
 204                struct wil6210_mbox_hdr hdr;
 205                struct wmi_cmd_hdr wmi;
 206        } __packed cmd = {
 207                .hdr = {
 208                        .type = WIL_MBOX_HDR_TYPE_WMI,
 209                        .flags = 0,
 210                        .len = cpu_to_le16(sizeof(cmd.wmi) + len),
 211                },
 212                .wmi = {
 213                        .mid = 0,
 214                        .command_id = cpu_to_le16(cmdid),
 215                },
 216        };
 217        struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
 218        struct wil6210_mbox_ring_desc d_head;
 219        u32 next_head;
 220        void __iomem *dst;
 221        void __iomem *head = wmi_addr(wil, r->head);
 222        uint retry;
 223        int rc = 0;
 224
 225        if (sizeof(cmd) + len > r->entry_size) {
 226                wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
 227                        (int)(sizeof(cmd) + len), r->entry_size);
 228                return -ERANGE;
 229        }
 230
 231        might_sleep();
 232
 233        if (!test_bit(wil_status_fwready, wil->status)) {
 234                wil_err(wil, "WMI: cannot send command while FW not ready\n");
 235                return -EAGAIN;
 236        }
 237
 238        /* Allow sending only suspend / resume commands during susepnd flow */
 239        if ((test_bit(wil_status_suspending, wil->status) ||
 240             test_bit(wil_status_suspended, wil->status) ||
 241             test_bit(wil_status_resuming, wil->status)) &&
 242             ((cmdid != WMI_TRAFFIC_SUSPEND_CMDID) &&
 243              (cmdid != WMI_TRAFFIC_RESUME_CMDID))) {
 244                wil_err(wil, "WMI: reject send_command during suspend\n");
 245                return -EINVAL;
 246        }
 247
 248        if (!head) {
 249                wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
 250                return -EINVAL;
 251        }
 252
 253        wil_halp_vote(wil);
 254
 255        /* read Tx head till it is not busy */
 256        for (retry = 5; retry > 0; retry--) {
 257                wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
 258                if (d_head.sync == 0)
 259                        break;
 260                msleep(20);
 261        }
 262        if (d_head.sync != 0) {
 263                wil_err(wil, "WMI head busy\n");
 264                rc = -EBUSY;
 265                goto out;
 266        }
 267        /* next head */
 268        next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
 269        wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
 270        /* wait till FW finish with previous command */
 271        for (retry = 5; retry > 0; retry--) {
 272                if (!test_bit(wil_status_fwready, wil->status)) {
 273                        wil_err(wil, "WMI: cannot send command while FW not ready\n");
 274                        rc = -EAGAIN;
 275                        goto out;
 276                }
 277                r->tail = wil_r(wil, RGF_MBOX +
 278                                offsetof(struct wil6210_mbox_ctl, tx.tail));
 279                if (next_head != r->tail)
 280                        break;
 281                msleep(20);
 282        }
 283        if (next_head == r->tail) {
 284                wil_err(wil, "WMI ring full\n");
 285                rc = -EBUSY;
 286                goto out;
 287        }
 288        dst = wmi_buffer(wil, d_head.addr);
 289        if (!dst) {
 290                wil_err(wil, "invalid WMI buffer: 0x%08x\n",
 291                        le32_to_cpu(d_head.addr));
 292                rc = -EAGAIN;
 293                goto out;
 294        }
 295        cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
 296        /* set command */
 297        wil_dbg_wmi(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
 298        wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
 299                         sizeof(cmd), true);
 300        wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
 301                         len, true);
 302        wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
 303        wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
 304        /* mark entry as full */
 305        wil_w(wil, r->head + offsetof(struct wil6210_mbox_ring_desc, sync), 1);
 306        /* advance next ptr */
 307        wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, tx.head),
 308              r->head = next_head);
 309
 310        trace_wil6210_wmi_cmd(&cmd.wmi, buf, len);
 311
 312        /* interrupt to FW */
 313        wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS),
 314              SW_INT_MBOX);
 315
 316out:
 317        wil_halp_unvote(wil);
 318        return rc;
 319}
 320
 321int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 322{
 323        int rc;
 324
 325        mutex_lock(&wil->wmi_mutex);
 326        rc = __wmi_send(wil, cmdid, buf, len);
 327        mutex_unlock(&wil->wmi_mutex);
 328
 329        return rc;
 330}
 331
 332/*=== Event handlers ===*/
 333static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
 334{
 335        struct wireless_dev *wdev = wil->wdev;
 336        struct wmi_ready_event *evt = d;
 337
 338        wil->n_mids = evt->numof_additional_mids;
 339
 340        wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
 341                 wil->fw_version, le32_to_cpu(evt->sw_version),
 342                 evt->mac, wil->n_mids);
 343        /* ignore MAC address, we already have it from the boot loader */
 344        strlcpy(wdev->wiphy->fw_version, wil->fw_version,
 345                sizeof(wdev->wiphy->fw_version));
 346
 347        if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) {
 348                wil_dbg_wmi(wil, "rfc calibration result %d\n",
 349                            evt->rfc_read_calib_result);
 350                wil->fw_calib_result = evt->rfc_read_calib_result;
 351        }
 352        wil_set_recovery_state(wil, fw_recovery_idle);
 353        set_bit(wil_status_fwready, wil->status);
 354        /* let the reset sequence continue */
 355        complete(&wil->wmi_ready);
 356}
 357
 358static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 359{
 360        struct wmi_rx_mgmt_packet_event *data = d;
 361        struct wiphy *wiphy = wil_to_wiphy(wil);
 362        struct ieee80211_mgmt *rx_mgmt_frame =
 363                        (struct ieee80211_mgmt *)data->payload;
 364        int flen = len - offsetof(struct wmi_rx_mgmt_packet_event, payload);
 365        int ch_no;
 366        u32 freq;
 367        struct ieee80211_channel *channel;
 368        s32 signal;
 369        __le16 fc;
 370        u32 d_len;
 371        u16 d_status;
 372
 373        if (flen < 0) {
 374                wil_err(wil, "MGMT Rx: short event, len %d\n", len);
 375                return;
 376        }
 377
 378        d_len = le32_to_cpu(data->info.len);
 379        if (d_len != flen) {
 380                wil_err(wil,
 381                        "MGMT Rx: length mismatch, d_len %d should be %d\n",
 382                        d_len, flen);
 383                return;
 384        }
 385
 386        ch_no = data->info.channel + 1;
 387        freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ);
 388        channel = ieee80211_get_channel(wiphy, freq);
 389        if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities))
 390                signal = 100 * data->info.rssi;
 391        else
 392                signal = data->info.sqi;
 393        d_status = le16_to_cpu(data->info.status);
 394        fc = rx_mgmt_frame->frame_control;
 395
 396        wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n",
 397                    data->info.channel, data->info.mcs, data->info.rssi,
 398                    data->info.sqi);
 399        wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
 400                    le16_to_cpu(fc));
 401        wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
 402                    data->info.qid, data->info.mid, data->info.cid);
 403        wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
 404                         d_len, true);
 405
 406        if (!channel) {
 407                wil_err(wil, "Frame on unsupported channel\n");
 408                return;
 409        }
 410
 411        if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
 412                struct cfg80211_bss *bss;
 413                u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
 414                u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
 415                u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
 416                const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
 417                size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
 418                                                 u.beacon.variable);
 419                wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
 420                wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
 421                wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
 422                wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
 423                                 ie_len, true);
 424
 425                wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
 426
 427                bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
 428                                                d_len, signal, GFP_KERNEL);
 429                if (bss) {
 430                        wil_dbg_wmi(wil, "Added BSS %pM\n",
 431                                    rx_mgmt_frame->bssid);
 432                        cfg80211_put_bss(wiphy, bss);
 433                } else {
 434                        wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
 435                }
 436        } else {
 437                mutex_lock(&wil->p2p_wdev_mutex);
 438                cfg80211_rx_mgmt(wil->radio_wdev, freq, signal,
 439                                 (void *)rx_mgmt_frame, d_len, 0);
 440                mutex_unlock(&wil->p2p_wdev_mutex);
 441        }
 442}
 443
 444static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 445{
 446        struct wmi_tx_mgmt_packet_event *data = d;
 447        struct ieee80211_mgmt *mgmt_frame =
 448                        (struct ieee80211_mgmt *)data->payload;
 449        int flen = len - offsetof(struct wmi_tx_mgmt_packet_event, payload);
 450
 451        wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET, 16, 1, mgmt_frame,
 452                         flen, true);
 453}
 454
 455static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
 456                                  void *d, int len)
 457{
 458        mutex_lock(&wil->p2p_wdev_mutex);
 459        if (wil->scan_request) {
 460                struct wmi_scan_complete_event *data = d;
 461                int status = le32_to_cpu(data->status);
 462                struct cfg80211_scan_info info = {
 463                        .aborted = ((status != WMI_SCAN_SUCCESS) &&
 464                                (status != WMI_SCAN_ABORT_REJECTED)),
 465                };
 466
 467                wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status);
 468                wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
 469                             wil->scan_request, info.aborted);
 470                del_timer_sync(&wil->scan_timer);
 471                cfg80211_scan_done(wil->scan_request, &info);
 472                wil->radio_wdev = wil->wdev;
 473                wil->scan_request = NULL;
 474                wake_up_interruptible(&wil->wq);
 475                if (wil->p2p.pending_listen_wdev) {
 476                        wil_dbg_misc(wil, "Scheduling delayed listen\n");
 477                        schedule_work(&wil->p2p.delayed_listen_work);
 478                }
 479        } else {
 480                wil_err(wil, "SCAN_COMPLETE while not scanning\n");
 481        }
 482        mutex_unlock(&wil->p2p_wdev_mutex);
 483}
 484
 485static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 486{
 487        struct net_device *ndev = wil_to_ndev(wil);
 488        struct wireless_dev *wdev = wil->wdev;
 489        struct wmi_connect_event *evt = d;
 490        int ch; /* channel number */
 491        struct station_info sinfo;
 492        u8 *assoc_req_ie, *assoc_resp_ie;
 493        size_t assoc_req_ielen, assoc_resp_ielen;
 494        /* capinfo(u16) + listen_interval(u16) + IEs */
 495        const size_t assoc_req_ie_offset = sizeof(u16) * 2;
 496        /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
 497        const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
 498        int rc;
 499
 500        if (len < sizeof(*evt)) {
 501                wil_err(wil, "Connect event too short : %d bytes\n", len);
 502                return;
 503        }
 504        if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
 505                   evt->assoc_resp_len) {
 506                wil_err(wil,
 507                        "Connect event corrupted : %d != %d + %d + %d + %d\n",
 508                        len, (int)sizeof(*evt), evt->beacon_ie_len,
 509                        evt->assoc_req_len, evt->assoc_resp_len);
 510                return;
 511        }
 512        if (evt->cid >= WIL6210_MAX_CID) {
 513                wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
 514                return;
 515        }
 516
 517        ch = evt->channel + 1;
 518        wil_info(wil, "Connect %pM channel [%d] cid %d aid %d\n",
 519                 evt->bssid, ch, evt->cid, evt->aid);
 520        wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
 521                         evt->assoc_info, len - sizeof(*evt), true);
 522
 523        /* figure out IE's */
 524        assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
 525                                        assoc_req_ie_offset];
 526        assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
 527        if (evt->assoc_req_len <= assoc_req_ie_offset) {
 528                assoc_req_ie = NULL;
 529                assoc_req_ielen = 0;
 530        }
 531
 532        assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
 533                                         evt->assoc_req_len +
 534                                         assoc_resp_ie_offset];
 535        assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
 536        if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
 537                assoc_resp_ie = NULL;
 538                assoc_resp_ielen = 0;
 539        }
 540
 541        if (test_bit(wil_status_resetting, wil->status) ||
 542            !test_bit(wil_status_fwready, wil->status)) {
 543                wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
 544                        evt->cid);
 545                /* no need for cleanup, wil_reset will do that */
 546                return;
 547        }
 548
 549        mutex_lock(&wil->mutex);
 550
 551        if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
 552            (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
 553                if (!test_bit(wil_status_fwconnecting, wil->status)) {
 554                        wil_err(wil, "Not in connecting state\n");
 555                        mutex_unlock(&wil->mutex);
 556                        return;
 557                }
 558                del_timer_sync(&wil->connect_timer);
 559        } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
 560                   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
 561                if (wil->sta[evt->cid].status != wil_sta_unused) {
 562                        wil_err(wil, "AP: Invalid status %d for CID %d\n",
 563                                wil->sta[evt->cid].status, evt->cid);
 564                        mutex_unlock(&wil->mutex);
 565                        return;
 566                }
 567        }
 568
 569        /* FIXME FW can transmit only ucast frames to peer */
 570        /* FIXME real ring_id instead of hard coded 0 */
 571        ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
 572        wil->sta[evt->cid].status = wil_sta_conn_pending;
 573
 574        rc = wil_tx_init(wil, evt->cid);
 575        if (rc) {
 576                wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n",
 577                        evt->cid, rc);
 578                wmi_disconnect_sta(wil, wil->sta[evt->cid].addr,
 579                                   WLAN_REASON_UNSPECIFIED, false, false);
 580        } else {
 581                wil_info(wil, "successful connection to CID %d\n", evt->cid);
 582        }
 583
 584        if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
 585            (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
 586                if (rc) {
 587                        netif_carrier_off(ndev);
 588                        wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
 589                        wil_err(wil, "cfg80211_connect_result with failure\n");
 590                        cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
 591                                                NULL, 0,
 592                                                WLAN_STATUS_UNSPECIFIED_FAILURE,
 593                                                GFP_KERNEL);
 594                        goto out;
 595                } else {
 596                        struct wiphy *wiphy = wil_to_wiphy(wil);
 597
 598                        cfg80211_ref_bss(wiphy, wil->bss);
 599                        cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
 600                                             assoc_req_ie, assoc_req_ielen,
 601                                             assoc_resp_ie, assoc_resp_ielen,
 602                                             WLAN_STATUS_SUCCESS, GFP_KERNEL,
 603                                             NL80211_TIMEOUT_UNSPECIFIED);
 604                }
 605                wil->bss = NULL;
 606        } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
 607                   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
 608                if (rc) {
 609                        if (disable_ap_sme)
 610                                /* notify new_sta has failed */
 611                                cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL);
 612                        goto out;
 613                }
 614
 615                memset(&sinfo, 0, sizeof(sinfo));
 616
 617                sinfo.generation = wil->sinfo_gen++;
 618
 619                if (assoc_req_ie) {
 620                        sinfo.assoc_req_ies = assoc_req_ie;
 621                        sinfo.assoc_req_ies_len = assoc_req_ielen;
 622                }
 623
 624                cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
 625        } else {
 626                wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype,
 627                        evt->cid);
 628                goto out;
 629        }
 630
 631        wil->sta[evt->cid].status = wil_sta_connected;
 632        wil->sta[evt->cid].aid = evt->aid;
 633        set_bit(wil_status_fwconnected, wil->status);
 634        wil_update_net_queues_bh(wil, NULL, false);
 635
 636out:
 637        if (rc)
 638                wil->sta[evt->cid].status = wil_sta_unused;
 639        clear_bit(wil_status_fwconnecting, wil->status);
 640        mutex_unlock(&wil->mutex);
 641}
 642
 643static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
 644                               void *d, int len)
 645{
 646        struct wmi_disconnect_event *evt = d;
 647        u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
 648
 649        wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
 650                 evt->bssid, reason_code, evt->disconnect_reason);
 651
 652        wil->sinfo_gen++;
 653
 654        if (test_bit(wil_status_resetting, wil->status) ||
 655            !test_bit(wil_status_fwready, wil->status)) {
 656                wil_err(wil, "status_resetting, cancel disconnect event\n");
 657                /* no need for cleanup, wil_reset will do that */
 658                return;
 659        }
 660
 661        mutex_lock(&wil->mutex);
 662        wil6210_disconnect(wil, evt->bssid, reason_code, true);
 663        mutex_unlock(&wil->mutex);
 664}
 665
 666/*
 667 * Firmware reports EAPOL frame using WME event.
 668 * Reconstruct Ethernet frame and deliver it via normal Rx
 669 */
 670static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
 671                             void *d, int len)
 672{
 673        struct net_device *ndev = wil_to_ndev(wil);
 674        struct wmi_eapol_rx_event *evt = d;
 675        u16 eapol_len = le16_to_cpu(evt->eapol_len);
 676        int sz = eapol_len + ETH_HLEN;
 677        struct sk_buff *skb;
 678        struct ethhdr *eth;
 679        int cid;
 680        struct wil_net_stats *stats = NULL;
 681
 682        wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
 683                    evt->src_mac);
 684
 685        cid = wil_find_cid(wil, evt->src_mac);
 686        if (cid >= 0)
 687                stats = &wil->sta[cid].stats;
 688
 689        if (eapol_len > 196) { /* TODO: revisit size limit */
 690                wil_err(wil, "EAPOL too large\n");
 691                return;
 692        }
 693
 694        skb = alloc_skb(sz, GFP_KERNEL);
 695        if (!skb) {
 696                wil_err(wil, "Failed to allocate skb\n");
 697                return;
 698        }
 699
 700        eth = skb_put(skb, ETH_HLEN);
 701        ether_addr_copy(eth->h_dest, ndev->dev_addr);
 702        ether_addr_copy(eth->h_source, evt->src_mac);
 703        eth->h_proto = cpu_to_be16(ETH_P_PAE);
 704        skb_put_data(skb, evt->eapol, eapol_len);
 705        skb->protocol = eth_type_trans(skb, ndev);
 706        if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
 707                ndev->stats.rx_packets++;
 708                ndev->stats.rx_bytes += sz;
 709                if (stats) {
 710                        stats->rx_packets++;
 711                        stats->rx_bytes += sz;
 712                }
 713        } else {
 714                ndev->stats.rx_dropped++;
 715                if (stats)
 716                        stats->rx_dropped++;
 717        }
 718}
 719
 720static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
 721{
 722        struct wmi_vring_en_event *evt = d;
 723        u8 vri = evt->vring_index;
 724        struct wireless_dev *wdev = wil_to_wdev(wil);
 725
 726        wil_dbg_wmi(wil, "Enable vring %d\n", vri);
 727
 728        if (vri >= ARRAY_SIZE(wil->vring_tx)) {
 729                wil_err(wil, "Enable for invalid vring %d\n", vri);
 730                return;
 731        }
 732
 733        if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme)
 734                /* in AP mode with disable_ap_sme, this is done by
 735                 * wil_cfg80211_change_station()
 736                 */
 737                wil->vring_tx_data[vri].dot1x_open = true;
 738        if (vri == wil->bcast_vring) /* no BA for bcast */
 739                return;
 740        if (agg_wsize >= 0)
 741                wil_addba_tx_request(wil, vri, agg_wsize);
 742}
 743
 744static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
 745                              int len)
 746{
 747        struct wmi_ba_status_event *evt = d;
 748        struct vring_tx_data *txdata;
 749
 750        wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
 751                    evt->ringid,
 752                    evt->status == WMI_BA_AGREED ? "OK" : "N/A",
 753                    evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
 754                    evt->amsdu ? "+" : "-");
 755
 756        if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
 757                wil_err(wil, "invalid ring id %d\n", evt->ringid);
 758                return;
 759        }
 760
 761        if (evt->status != WMI_BA_AGREED) {
 762                evt->ba_timeout = 0;
 763                evt->agg_wsize = 0;
 764                evt->amsdu = 0;
 765        }
 766
 767        txdata = &wil->vring_tx_data[evt->ringid];
 768
 769        txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
 770        txdata->agg_wsize = evt->agg_wsize;
 771        txdata->agg_amsdu = evt->amsdu;
 772        txdata->addba_in_progress = false;
 773}
 774
 775static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
 776                                 int len)
 777{
 778        struct wmi_rcp_addba_req_event *evt = d;
 779
 780        wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
 781                             evt->ba_param_set, evt->ba_timeout,
 782                             evt->ba_seq_ctrl);
 783}
 784
 785static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
 786__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 787{
 788        struct wmi_delba_event *evt = d;
 789        u8 cid, tid;
 790        u16 reason = __le16_to_cpu(evt->reason);
 791        struct wil_sta_info *sta;
 792        struct wil_tid_ampdu_rx *r;
 793
 794        might_sleep();
 795        parse_cidxtid(evt->cidxtid, &cid, &tid);
 796        wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
 797                    cid, tid,
 798                    evt->from_initiator ? "originator" : "recipient",
 799                    reason);
 800        if (!evt->from_initiator) {
 801                int i;
 802                /* find Tx vring it belongs to */
 803                for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
 804                        if ((wil->vring2cid_tid[i][0] == cid) &&
 805                            (wil->vring2cid_tid[i][1] == tid)) {
 806                                struct vring_tx_data *txdata =
 807                                        &wil->vring_tx_data[i];
 808
 809                                wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
 810                                txdata->agg_timeout = 0;
 811                                txdata->agg_wsize = 0;
 812                                txdata->addba_in_progress = false;
 813
 814                                break; /* max. 1 matching ring */
 815                        }
 816                }
 817                if (i >= ARRAY_SIZE(wil->vring2cid_tid))
 818                        wil_err(wil, "DELBA: unable to find Tx vring\n");
 819                return;
 820        }
 821
 822        sta = &wil->sta[cid];
 823
 824        spin_lock_bh(&sta->tid_rx_lock);
 825
 826        r = sta->tid_rx[tid];
 827        sta->tid_rx[tid] = NULL;
 828        wil_tid_ampdu_rx_free(wil, r);
 829
 830        spin_unlock_bh(&sta->tid_rx_lock);
 831}
 832
 833/**
 834 * Some events are ignored for purpose; and need not be interpreted as
 835 * "unhandled events"
 836 */
 837static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
 838{
 839        wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
 840}
 841
 842static const struct {
 843        int eventid;
 844        void (*handler)(struct wil6210_priv *wil, int eventid,
 845                        void *data, int data_len);
 846} wmi_evt_handlers[] = {
 847        {WMI_READY_EVENTID,             wmi_evt_ready},
 848        {WMI_FW_READY_EVENTID,                  wmi_evt_ignore},
 849        {WMI_RX_MGMT_PACKET_EVENTID,    wmi_evt_rx_mgmt},
 850        {WMI_TX_MGMT_PACKET_EVENTID,            wmi_evt_tx_mgmt},
 851        {WMI_SCAN_COMPLETE_EVENTID,     wmi_evt_scan_complete},
 852        {WMI_CONNECT_EVENTID,           wmi_evt_connect},
 853        {WMI_DISCONNECT_EVENTID,        wmi_evt_disconnect},
 854        {WMI_EAPOL_RX_EVENTID,          wmi_evt_eapol_rx},
 855        {WMI_BA_STATUS_EVENTID,         wmi_evt_ba_status},
 856        {WMI_RCP_ADDBA_REQ_EVENTID,     wmi_evt_addba_rx_req},
 857        {WMI_DELBA_EVENTID,             wmi_evt_delba},
 858        {WMI_VRING_EN_EVENTID,          wmi_evt_vring_en},
 859        {WMI_DATA_PORT_OPEN_EVENTID,            wmi_evt_ignore},
 860};
 861
 862/*
 863 * Run in IRQ context
 864 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
 865 * that will be eventually handled by the @wmi_event_worker in the thread
 866 * context of thread "wil6210_wmi"
 867 */
 868void wmi_recv_cmd(struct wil6210_priv *wil)
 869{
 870        struct wil6210_mbox_ring_desc d_tail;
 871        struct wil6210_mbox_hdr hdr;
 872        struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
 873        struct pending_wmi_event *evt;
 874        u8 *cmd;
 875        void __iomem *src;
 876        ulong flags;
 877        unsigned n;
 878        unsigned int num_immed_reply = 0;
 879
 880        if (!test_bit(wil_status_mbox_ready, wil->status)) {
 881                wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
 882                return;
 883        }
 884
 885        if (test_bit(wil_status_suspended, wil->status)) {
 886                wil_err(wil, "suspended. cannot handle WMI event\n");
 887                return;
 888        }
 889
 890        for (n = 0;; n++) {
 891                u16 len;
 892                bool q;
 893                bool immed_reply = false;
 894
 895                r->head = wil_r(wil, RGF_MBOX +
 896                                offsetof(struct wil6210_mbox_ctl, rx.head));
 897                if (r->tail == r->head)
 898                        break;
 899
 900                wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
 901                            r->head, r->tail);
 902                /* read cmd descriptor from tail */
 903                wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
 904                                     sizeof(struct wil6210_mbox_ring_desc));
 905                if (d_tail.sync == 0) {
 906                        wil_err(wil, "Mbox evt not owned by FW?\n");
 907                        break;
 908                }
 909
 910                /* read cmd header from descriptor */
 911                if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
 912                        wil_err(wil, "Mbox evt at 0x%08x?\n",
 913                                le32_to_cpu(d_tail.addr));
 914                        break;
 915                }
 916                len = le16_to_cpu(hdr.len);
 917                wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
 918                            le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
 919                            hdr.flags);
 920
 921                /* read cmd buffer from descriptor */
 922                src = wmi_buffer(wil, d_tail.addr) +
 923                      sizeof(struct wil6210_mbox_hdr);
 924                evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
 925                                             event.wmi) + len, 4),
 926                              GFP_KERNEL);
 927                if (!evt)
 928                        break;
 929
 930                evt->event.hdr = hdr;
 931                cmd = (void *)&evt->event.wmi;
 932                wil_memcpy_fromio_32(cmd, src, len);
 933                /* mark entry as empty */
 934                wil_w(wil, r->tail +
 935                      offsetof(struct wil6210_mbox_ring_desc, sync), 0);
 936                /* indicate */
 937                if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
 938                    (len >= sizeof(struct wmi_cmd_hdr))) {
 939                        struct wmi_cmd_hdr *wmi = &evt->event.wmi;
 940                        u16 id = le16_to_cpu(wmi->command_id);
 941                        u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
 942                        if (test_bit(wil_status_resuming, wil->status)) {
 943                                if (id == WMI_TRAFFIC_RESUME_EVENTID)
 944                                        clear_bit(wil_status_resuming,
 945                                                  wil->status);
 946                                else
 947                                        wil_err(wil,
 948                                                "WMI evt %d while resuming\n",
 949                                                id);
 950                        }
 951                        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
 952                        if (wil->reply_id && wil->reply_id == id) {
 953                                if (wil->reply_buf) {
 954                                        memcpy(wil->reply_buf, wmi,
 955                                               min(len, wil->reply_size));
 956                                        immed_reply = true;
 957                                }
 958                                if (id == WMI_TRAFFIC_SUSPEND_EVENTID) {
 959                                        wil_dbg_wmi(wil,
 960                                                    "set suspend_resp_rcvd\n");
 961                                        wil->suspend_resp_rcvd = true;
 962                                }
 963                        }
 964                        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 965
 966                        wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
 967                                    id, wmi->mid, tstamp);
 968                        trace_wil6210_wmi_event(wmi, &wmi[1],
 969                                                len - sizeof(*wmi));
 970                }
 971                wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
 972                                 &evt->event.hdr, sizeof(hdr) + len, true);
 973
 974                /* advance tail */
 975                r->tail = r->base + ((r->tail - r->base +
 976                          sizeof(struct wil6210_mbox_ring_desc)) % r->size);
 977                wil_w(wil, RGF_MBOX +
 978                      offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail);
 979
 980                if (immed_reply) {
 981                        wil_dbg_wmi(wil, "recv_cmd: Complete WMI 0x%04x\n",
 982                                    wil->reply_id);
 983                        kfree(evt);
 984                        num_immed_reply++;
 985                        complete(&wil->wmi_call);
 986                } else {
 987                        /* add to the pending list */
 988                        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
 989                        list_add_tail(&evt->list, &wil->pending_wmi_ev);
 990                        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 991                        q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
 992                        wil_dbg_wmi(wil, "queue_work -> %d\n", q);
 993                }
 994        }
 995        /* normally, 1 event per IRQ should be processed */
 996        wil_dbg_wmi(wil, "recv_cmd: -> %d events queued, %d completed\n",
 997                    n - num_immed_reply, num_immed_reply);
 998}
 999
1000int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
1001             u16 reply_id, void *reply, u8 reply_size, int to_msec)
1002{
1003        int rc;
1004        unsigned long remain;
1005
1006        mutex_lock(&wil->wmi_mutex);
1007
1008        spin_lock(&wil->wmi_ev_lock);
1009        wil->reply_id = reply_id;
1010        wil->reply_buf = reply;
1011        wil->reply_size = reply_size;
1012        reinit_completion(&wil->wmi_call);
1013        spin_unlock(&wil->wmi_ev_lock);
1014
1015        rc = __wmi_send(wil, cmdid, buf, len);
1016        if (rc)
1017                goto out;
1018
1019        remain = wait_for_completion_timeout(&wil->wmi_call,
1020                                             msecs_to_jiffies(to_msec));
1021        if (0 == remain) {
1022                wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
1023                        cmdid, reply_id, to_msec);
1024                rc = -ETIME;
1025        } else {
1026                wil_dbg_wmi(wil,
1027                            "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
1028                            cmdid, reply_id,
1029                            to_msec - jiffies_to_msecs(remain));
1030        }
1031
1032out:
1033        spin_lock(&wil->wmi_ev_lock);
1034        wil->reply_id = 0;
1035        wil->reply_buf = NULL;
1036        wil->reply_size = 0;
1037        spin_unlock(&wil->wmi_ev_lock);
1038
1039        mutex_unlock(&wil->wmi_mutex);
1040
1041        return rc;
1042}
1043
1044int wmi_echo(struct wil6210_priv *wil)
1045{
1046        struct wmi_echo_cmd cmd = {
1047                .value = cpu_to_le32(0x12345678),
1048        };
1049
1050        return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
1051                        WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
1052}
1053
1054int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
1055{
1056        struct wmi_set_mac_address_cmd cmd;
1057
1058        ether_addr_copy(cmd.mac, addr);
1059
1060        wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
1061
1062        return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
1063}
1064
1065int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
1066{
1067        int rc = 0;
1068        struct wmi_led_cfg_cmd cmd = {
1069                .led_mode = enable,
1070                .id = led_id,
1071                .slow_blink_cfg.blink_on =
1072                        cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].on_ms),
1073                .slow_blink_cfg.blink_off =
1074                        cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].off_ms),
1075                .medium_blink_cfg.blink_on =
1076                        cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].on_ms),
1077                .medium_blink_cfg.blink_off =
1078                        cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].off_ms),
1079                .fast_blink_cfg.blink_on =
1080                        cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].on_ms),
1081                .fast_blink_cfg.blink_off =
1082                        cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].off_ms),
1083                .led_polarity = led_polarity,
1084        };
1085        struct {
1086                struct wmi_cmd_hdr wmi;
1087                struct wmi_led_cfg_done_event evt;
1088        } __packed reply;
1089
1090        if (led_id == WIL_LED_INVALID_ID)
1091                goto out;
1092
1093        if (led_id > WIL_LED_MAX_ID) {
1094                wil_err(wil, "Invalid led id %d\n", led_id);
1095                rc = -EINVAL;
1096                goto out;
1097        }
1098
1099        wil_dbg_wmi(wil,
1100                    "%s led %d\n",
1101                    enable ? "enabling" : "disabling", led_id);
1102
1103        rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd),
1104                      WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
1105                      100);
1106        if (rc)
1107                goto out;
1108
1109        if (reply.evt.status) {
1110                wil_err(wil, "led %d cfg failed with status %d\n",
1111                        led_id, le32_to_cpu(reply.evt.status));
1112                rc = -EINVAL;
1113        }
1114
1115out:
1116        return rc;
1117}
1118
1119int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
1120                  u8 chan, u8 hidden_ssid, u8 is_go)
1121{
1122        int rc;
1123
1124        struct wmi_pcp_start_cmd cmd = {
1125                .bcon_interval = cpu_to_le16(bi),
1126                .network_type = wmi_nettype,
1127                .disable_sec_offload = 1,
1128                .channel = chan - 1,
1129                .pcp_max_assoc_sta = max_assoc_sta,
1130                .hidden_ssid = hidden_ssid,
1131                .is_go = is_go,
1132                .disable_ap_sme = disable_ap_sme,
1133                .abft_len = wil->abft_len,
1134        };
1135        struct {
1136                struct wmi_cmd_hdr wmi;
1137                struct wmi_pcp_started_event evt;
1138        } __packed reply;
1139
1140        if (!wil->privacy)
1141                cmd.disable_sec = 1;
1142
1143        if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
1144            (cmd.pcp_max_assoc_sta <= 0)) {
1145                wil_info(wil,
1146                         "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
1147                         max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
1148                cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
1149        }
1150
1151        if (disable_ap_sme &&
1152            !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME,
1153                      wil->fw_capabilities)) {
1154                wil_err(wil, "disable_ap_sme not supported by FW\n");
1155                return -EOPNOTSUPP;
1156        }
1157
1158        /*
1159         * Processing time may be huge, in case of secure AP it takes about
1160         * 3500ms for FW to start AP
1161         */
1162        rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
1163                      WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
1164        if (rc)
1165                return rc;
1166
1167        if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
1168                rc = -EINVAL;
1169
1170        if (wmi_nettype != WMI_NETTYPE_P2P)
1171                /* Don't fail due to error in the led configuration */
1172                wmi_led_cfg(wil, true);
1173
1174        return rc;
1175}
1176
1177int wmi_pcp_stop(struct wil6210_priv *wil)
1178{
1179        int rc;
1180
1181        rc = wmi_led_cfg(wil, false);
1182        if (rc)
1183                return rc;
1184
1185        return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
1186                        WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
1187}
1188
1189int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
1190{
1191        struct wmi_set_ssid_cmd cmd = {
1192                .ssid_len = cpu_to_le32(ssid_len),
1193        };
1194
1195        if (ssid_len > sizeof(cmd.ssid))
1196                return -EINVAL;
1197
1198        memcpy(cmd.ssid, ssid, ssid_len);
1199
1200        return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
1201}
1202
1203int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
1204{
1205        int rc;
1206        struct {
1207                struct wmi_cmd_hdr wmi;
1208                struct wmi_set_ssid_cmd cmd;
1209        } __packed reply;
1210        int len; /* reply.cmd.ssid_len in CPU order */
1211
1212        rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
1213                      &reply, sizeof(reply), 20);
1214        if (rc)
1215                return rc;
1216
1217        len = le32_to_cpu(reply.cmd.ssid_len);
1218        if (len > sizeof(reply.cmd.ssid))
1219                return -EINVAL;
1220
1221        *ssid_len = len;
1222        memcpy(ssid, reply.cmd.ssid, len);
1223
1224        return 0;
1225}
1226
1227int wmi_set_channel(struct wil6210_priv *wil, int channel)
1228{
1229        struct wmi_set_pcp_channel_cmd cmd = {
1230                .channel = channel - 1,
1231        };
1232
1233        return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
1234}
1235
1236int wmi_get_channel(struct wil6210_priv *wil, int *channel)
1237{
1238        int rc;
1239        struct {
1240                struct wmi_cmd_hdr wmi;
1241                struct wmi_set_pcp_channel_cmd cmd;
1242        } __packed reply;
1243
1244        rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
1245                      WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
1246        if (rc)
1247                return rc;
1248
1249        if (reply.cmd.channel > 3)
1250                return -EINVAL;
1251
1252        *channel = reply.cmd.channel + 1;
1253
1254        return 0;
1255}
1256
1257int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
1258{
1259        int rc;
1260        struct wmi_p2p_cfg_cmd cmd = {
1261                .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER,
1262                .bcon_interval = cpu_to_le16(bi),
1263                .channel = channel - 1,
1264        };
1265        struct {
1266                struct wmi_cmd_hdr wmi;
1267                struct wmi_p2p_cfg_done_event evt;
1268        } __packed reply;
1269
1270        wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n");
1271
1272        rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd),
1273                      WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300);
1274        if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
1275                wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status);
1276                rc = -EINVAL;
1277        }
1278
1279        return rc;
1280}
1281
1282int wmi_start_listen(struct wil6210_priv *wil)
1283{
1284        int rc;
1285        struct {
1286                struct wmi_cmd_hdr wmi;
1287                struct wmi_listen_started_event evt;
1288        } __packed reply;
1289
1290        wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n");
1291
1292        rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
1293                      WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300);
1294        if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
1295                wil_err(wil, "device failed to start listen. status %d\n",
1296                        reply.evt.status);
1297                rc = -EINVAL;
1298        }
1299
1300        return rc;
1301}
1302
1303int wmi_start_search(struct wil6210_priv *wil)
1304{
1305        int rc;
1306        struct {
1307                struct wmi_cmd_hdr wmi;
1308                struct wmi_search_started_event evt;
1309        } __packed reply;
1310
1311        wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n");
1312
1313        rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0,
1314                      WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300);
1315        if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
1316                wil_err(wil, "device failed to start search. status %d\n",
1317                        reply.evt.status);
1318                rc = -EINVAL;
1319        }
1320
1321        return rc;
1322}
1323
1324int wmi_stop_discovery(struct wil6210_priv *wil)
1325{
1326        int rc;
1327
1328        wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
1329
1330        rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
1331                      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
1332
1333        if (rc)
1334                wil_err(wil, "Failed to stop discovery\n");
1335
1336        return rc;
1337}
1338
1339int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
1340                       const void *mac_addr, int key_usage)
1341{
1342        struct wmi_delete_cipher_key_cmd cmd = {
1343                .key_index = key_index,
1344        };
1345
1346        if (mac_addr)
1347                memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1348
1349        return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1350}
1351
1352int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
1353                       const void *mac_addr, int key_len, const void *key,
1354                       int key_usage)
1355{
1356        struct wmi_add_cipher_key_cmd cmd = {
1357                .key_index = key_index,
1358                .key_usage = key_usage,
1359                .key_len = key_len,
1360        };
1361
1362        if (!key || (key_len > sizeof(cmd.key)))
1363                return -EINVAL;
1364
1365        memcpy(cmd.key, key, key_len);
1366        if (mac_addr)
1367                memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1368
1369        return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1370}
1371
1372int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
1373{
1374        static const char *const names[] = {
1375                [WMI_FRAME_BEACON]      = "BEACON",
1376                [WMI_FRAME_PROBE_REQ]   = "PROBE_REQ",
1377                [WMI_FRAME_PROBE_RESP]  = "WMI_FRAME_PROBE_RESP",
1378                [WMI_FRAME_ASSOC_REQ]   = "WMI_FRAME_ASSOC_REQ",
1379                [WMI_FRAME_ASSOC_RESP]  = "WMI_FRAME_ASSOC_RESP",
1380        };
1381        int rc;
1382        u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
1383        struct wmi_set_appie_cmd *cmd;
1384
1385        if (len < ie_len) {
1386                rc = -EINVAL;
1387                goto out;
1388        }
1389
1390        cmd = kzalloc(len, GFP_KERNEL);
1391        if (!cmd) {
1392                rc = -ENOMEM;
1393                goto out;
1394        }
1395        if (!ie)
1396                ie_len = 0;
1397
1398        cmd->mgmt_frm_type = type;
1399        /* BUG: FW API define ieLen as u8. Will fix FW */
1400        cmd->ie_len = cpu_to_le16(ie_len);
1401        memcpy(cmd->ie_info, ie, ie_len);
1402        rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
1403        kfree(cmd);
1404out:
1405        if (rc) {
1406                const char *name = type < ARRAY_SIZE(names) ?
1407                                   names[type] : "??";
1408                wil_err(wil, "set_ie(%d %s) failed : %d\n", type, name, rc);
1409        }
1410
1411        return rc;
1412}
1413
1414/**
1415 * wmi_rxon - turn radio on/off
1416 * @on:         turn on if true, off otherwise
1417 *
1418 * Only switch radio. Channel should be set separately.
1419 * No timeout for rxon - radio turned on forever unless some other call
1420 * turns it off
1421 */
1422int wmi_rxon(struct wil6210_priv *wil, bool on)
1423{
1424        int rc;
1425        struct {
1426                struct wmi_cmd_hdr wmi;
1427                struct wmi_listen_started_event evt;
1428        } __packed reply;
1429
1430        wil_info(wil, "(%s)\n", on ? "on" : "off");
1431
1432        if (on) {
1433                rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
1434                              WMI_LISTEN_STARTED_EVENTID,
1435                              &reply, sizeof(reply), 100);
1436                if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
1437                        rc = -EINVAL;
1438        } else {
1439                rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
1440                              WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
1441        }
1442
1443        return rc;
1444}
1445
1446int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
1447{
1448        struct wireless_dev *wdev = wil->wdev;
1449        struct net_device *ndev = wil_to_ndev(wil);
1450        struct wmi_cfg_rx_chain_cmd cmd = {
1451                .action = WMI_RX_CHAIN_ADD,
1452                .rx_sw_ring = {
1453                        .max_mpdu_size = cpu_to_le16(
1454                                wil_mtu2macbuf(wil->rx_buf_len)),
1455                        .ring_mem_base = cpu_to_le64(vring->pa),
1456                        .ring_size = cpu_to_le16(vring->size),
1457                },
1458                .mid = 0, /* TODO - what is it? */
1459                .decap_trans_type = WMI_DECAP_TYPE_802_3,
1460                .reorder_type = WMI_RX_SW_REORDER,
1461                .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
1462        };
1463        struct {
1464                struct wmi_cmd_hdr wmi;
1465                struct wmi_cfg_rx_chain_done_event evt;
1466        } __packed evt;
1467        int rc;
1468
1469        if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
1470                struct ieee80211_channel *ch = wdev->preset_chandef.chan;
1471
1472                cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
1473                if (ch)
1474                        cmd.sniffer_cfg.channel = ch->hw_value - 1;
1475                cmd.sniffer_cfg.phy_info_mode =
1476                        cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
1477                cmd.sniffer_cfg.phy_support =
1478                        cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
1479                                    ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
1480        } else {
1481                /* Initialize offload (in non-sniffer mode).
1482                 * Linux IP stack always calculates IP checksum
1483                 * HW always calculate TCP/UDP checksum
1484                 */
1485                cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
1486        }
1487
1488        if (rx_align_2)
1489                cmd.l2_802_3_offload_ctrl |=
1490                                L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
1491
1492        /* typical time for secure PCP is 840ms */
1493        rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
1494                      WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
1495        if (rc)
1496                return rc;
1497
1498        vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
1499
1500        wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
1501                     le32_to_cpu(evt.evt.status), vring->hwtail);
1502
1503        if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
1504                rc = -EINVAL;
1505
1506        return rc;
1507}
1508
1509int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
1510{
1511        int rc;
1512        struct wmi_temp_sense_cmd cmd = {
1513                .measure_baseband_en = cpu_to_le32(!!t_bb),
1514                .measure_rf_en = cpu_to_le32(!!t_rf),
1515                .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
1516        };
1517        struct {
1518                struct wmi_cmd_hdr wmi;
1519                struct wmi_temp_sense_done_event evt;
1520        } __packed reply;
1521
1522        rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
1523                      WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
1524        if (rc)
1525                return rc;
1526
1527        if (t_bb)
1528                *t_bb = le32_to_cpu(reply.evt.baseband_t1000);
1529        if (t_rf)
1530                *t_rf = le32_to_cpu(reply.evt.rf_t1000);
1531
1532        return 0;
1533}
1534
1535int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
1536                       u16 reason, bool full_disconnect, bool del_sta)
1537{
1538        int rc;
1539        u16 reason_code;
1540        struct wmi_disconnect_sta_cmd disc_sta_cmd = {
1541                .disconnect_reason = cpu_to_le16(reason),
1542        };
1543        struct wmi_del_sta_cmd del_sta_cmd = {
1544                .disconnect_reason = cpu_to_le16(reason),
1545        };
1546        struct {
1547                struct wmi_cmd_hdr wmi;
1548                struct wmi_disconnect_event evt;
1549        } __packed reply;
1550
1551        wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
1552
1553        wil->locally_generated_disc = true;
1554        if (del_sta) {
1555                ether_addr_copy(del_sta_cmd.dst_mac, mac);
1556                rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd,
1557                              sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID,
1558                              &reply, sizeof(reply), 1000);
1559        } else {
1560                ether_addr_copy(disc_sta_cmd.dst_mac, mac);
1561                rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd,
1562                              sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID,
1563                              &reply, sizeof(reply), 1000);
1564        }
1565        /* failure to disconnect in reasonable time treated as FW error */
1566        if (rc) {
1567                wil_fw_error_recovery(wil);
1568                return rc;
1569        }
1570
1571        if (full_disconnect) {
1572                /* call event handler manually after processing wmi_call,
1573                 * to avoid deadlock - disconnect event handler acquires
1574                 * wil->mutex while it is already held here
1575                 */
1576                reason_code = le16_to_cpu(reply.evt.protocol_reason_status);
1577
1578                wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
1579                            reply.evt.bssid, reason_code,
1580                            reply.evt.disconnect_reason);
1581
1582                wil->sinfo_gen++;
1583                wil6210_disconnect(wil, reply.evt.bssid, reason_code, true);
1584        }
1585        return 0;
1586}
1587
1588int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
1589{
1590        struct wmi_vring_ba_en_cmd cmd = {
1591                .ringid = ringid,
1592                .agg_max_wsize = size,
1593                .ba_timeout = cpu_to_le16(timeout),
1594                .amsdu = 0,
1595        };
1596
1597        wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size,
1598                    timeout);
1599
1600        return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
1601}
1602
1603int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
1604{
1605        struct wmi_vring_ba_dis_cmd cmd = {
1606                .ringid = ringid,
1607                .reason = cpu_to_le16(reason),
1608        };
1609
1610        wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason);
1611
1612        return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
1613}
1614
1615int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
1616{
1617        struct wmi_rcp_delba_cmd cmd = {
1618                .cidxtid = cidxtid,
1619                .reason = cpu_to_le16(reason),
1620        };
1621
1622        wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf,
1623                    (cidxtid >> 4) & 0xf, reason);
1624
1625        return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
1626}
1627
1628int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
1629                      u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
1630{
1631        int rc;
1632        struct wmi_rcp_addba_resp_cmd cmd = {
1633                .cidxtid = mk_cidxtid(cid, tid),
1634                .dialog_token = token,
1635                .status_code = cpu_to_le16(status),
1636                /* bit 0: A-MSDU supported
1637                 * bit 1: policy (should be 0 for us)
1638                 * bits 2..5: TID
1639                 * bits 6..15: buffer size
1640                 */
1641                .ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
1642                                            (agg_wsize << 6)),
1643                .ba_timeout = cpu_to_le16(timeout),
1644        };
1645        struct {
1646                struct wmi_cmd_hdr wmi;
1647                struct wmi_rcp_addba_resp_sent_event evt;
1648        } __packed reply;
1649
1650        wil_dbg_wmi(wil,
1651                    "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
1652                    cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
1653
1654        rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
1655                      WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
1656                      100);
1657        if (rc)
1658                return rc;
1659
1660        if (reply.evt.status) {
1661                wil_err(wil, "ADDBA response failed with status %d\n",
1662                        le16_to_cpu(reply.evt.status));
1663                rc = -EINVAL;
1664        }
1665
1666        return rc;
1667}
1668
1669int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
1670                           enum wmi_ps_profile_type ps_profile)
1671{
1672        int rc;
1673        struct wmi_ps_dev_profile_cfg_cmd cmd = {
1674                .ps_profile = ps_profile,
1675        };
1676        struct {
1677                struct wmi_cmd_hdr wmi;
1678                struct wmi_ps_dev_profile_cfg_event evt;
1679        } __packed reply;
1680        u32 status;
1681
1682        wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile);
1683
1684        reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR);
1685
1686        rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd),
1687                      WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
1688                      100);
1689        if (rc)
1690                return rc;
1691
1692        status = le32_to_cpu(reply.evt.status);
1693
1694        if (status != WMI_PS_CFG_CMD_STATUS_SUCCESS) {
1695                wil_err(wil, "ps dev profile cfg failed with status %d\n",
1696                        status);
1697                rc = -EINVAL;
1698        }
1699
1700        return rc;
1701}
1702
1703int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
1704{
1705        int rc;
1706        struct wmi_set_mgmt_retry_limit_cmd cmd = {
1707                .mgmt_retry_limit = retry_short,
1708        };
1709        struct {
1710                struct wmi_cmd_hdr wmi;
1711                struct wmi_set_mgmt_retry_limit_event evt;
1712        } __packed reply;
1713
1714        wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short);
1715
1716        if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
1717                return -ENOTSUPP;
1718
1719        reply.evt.status = WMI_FW_STATUS_FAILURE;
1720
1721        rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd),
1722                      WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
1723                      100);
1724        if (rc)
1725                return rc;
1726
1727        if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
1728                wil_err(wil, "set mgmt retry limit failed with status %d\n",
1729                        reply.evt.status);
1730                rc = -EINVAL;
1731        }
1732
1733        return rc;
1734}
1735
1736int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
1737{
1738        int rc;
1739        struct {
1740                struct wmi_cmd_hdr wmi;
1741                struct wmi_get_mgmt_retry_limit_event evt;
1742        } __packed reply;
1743
1744        wil_dbg_wmi(wil, "getting mgmt retry short\n");
1745
1746        if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
1747                return -ENOTSUPP;
1748
1749        reply.evt.mgmt_retry_limit = 0;
1750        rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0,
1751                      WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
1752                      100);
1753        if (rc)
1754                return rc;
1755
1756        if (retry_short)
1757                *retry_short = reply.evt.mgmt_retry_limit;
1758
1759        return 0;
1760}
1761
1762int wmi_abort_scan(struct wil6210_priv *wil)
1763{
1764        int rc;
1765
1766        wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n");
1767
1768        rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0);
1769        if (rc)
1770                wil_err(wil, "Failed to abort scan (%d)\n", rc);
1771
1772        return rc;
1773}
1774
1775int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid)
1776{
1777        int rc;
1778        struct wmi_new_sta_cmd cmd = {
1779                .aid = aid,
1780        };
1781
1782        wil_dbg_wmi(wil, "new sta %pM, aid %d\n", mac, aid);
1783
1784        ether_addr_copy(cmd.dst_mac, mac);
1785
1786        rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd));
1787        if (rc)
1788                wil_err(wil, "Failed to send new sta (%d)\n", rc);
1789
1790        return rc;
1791}
1792
1793void wmi_event_flush(struct wil6210_priv *wil)
1794{
1795        ulong flags;
1796        struct pending_wmi_event *evt, *t;
1797
1798        wil_dbg_wmi(wil, "event_flush\n");
1799
1800        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1801
1802        list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
1803                list_del(&evt->list);
1804                kfree(evt);
1805        }
1806
1807        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
1808}
1809
1810int wmi_suspend(struct wil6210_priv *wil)
1811{
1812        int rc;
1813        struct wmi_traffic_suspend_cmd cmd = {
1814                .wakeup_trigger = wil->wakeup_trigger,
1815        };
1816        struct {
1817                struct wmi_cmd_hdr wmi;
1818                struct wmi_traffic_suspend_event evt;
1819        } __packed reply;
1820        u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP;
1821
1822        wil->suspend_resp_rcvd = false;
1823        wil->suspend_resp_comp = false;
1824
1825        reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED;
1826
1827        rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd),
1828                      WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
1829                      suspend_to);
1830        if (rc) {
1831                wil_err(wil, "wmi_call for suspend req failed, rc=%d\n", rc);
1832                if (rc == -ETIME)
1833                        /* wmi_call TO */
1834                        wil->suspend_stats.rejected_by_device++;
1835                else
1836                        wil->suspend_stats.rejected_by_host++;
1837                goto out;
1838        }
1839
1840        wil_dbg_wmi(wil, "waiting for suspend_response_completed\n");
1841
1842        rc = wait_event_interruptible_timeout(wil->wq,
1843                                              wil->suspend_resp_comp,
1844                                              msecs_to_jiffies(suspend_to));
1845        if (rc == 0) {
1846                wil_err(wil, "TO waiting for suspend_response_completed\n");
1847                if (wil->suspend_resp_rcvd)
1848                        /* Device responded but we TO due to another reason */
1849                        wil->suspend_stats.rejected_by_host++;
1850                else
1851                        wil->suspend_stats.rejected_by_device++;
1852                rc = -EBUSY;
1853                goto out;
1854        }
1855
1856        wil_dbg_wmi(wil, "suspend_response_completed rcvd\n");
1857        if (reply.evt.status == WMI_TRAFFIC_SUSPEND_REJECTED) {
1858                wil_dbg_pm(wil, "device rejected the suspend\n");
1859                wil->suspend_stats.rejected_by_device++;
1860        }
1861        rc = reply.evt.status;
1862
1863out:
1864        wil->suspend_resp_rcvd = false;
1865        wil->suspend_resp_comp = false;
1866
1867        return rc;
1868}
1869
1870int wmi_resume(struct wil6210_priv *wil)
1871{
1872        int rc;
1873        struct {
1874                struct wmi_cmd_hdr wmi;
1875                struct wmi_traffic_resume_event evt;
1876        } __packed reply;
1877
1878        reply.evt.status = WMI_TRAFFIC_RESUME_FAILED;
1879
1880        rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0,
1881                      WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
1882                      WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
1883        if (rc)
1884                return rc;
1885
1886        return reply.evt.status;
1887}
1888
1889static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
1890                                 void *d, int len)
1891{
1892        uint i;
1893
1894        for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
1895                if (wmi_evt_handlers[i].eventid == id) {
1896                        wmi_evt_handlers[i].handler(wil, id, d, len);
1897                        return true;
1898                }
1899        }
1900
1901        return false;
1902}
1903
1904static void wmi_event_handle(struct wil6210_priv *wil,
1905                             struct wil6210_mbox_hdr *hdr)
1906{
1907        u16 len = le16_to_cpu(hdr->len);
1908
1909        if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
1910            (len >= sizeof(struct wmi_cmd_hdr))) {
1911                struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
1912                void *evt_data = (void *)(&wmi[1]);
1913                u16 id = le16_to_cpu(wmi->command_id);
1914
1915                wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n",
1916                            id, wil->reply_id);
1917                /* check if someone waits for this event */
1918                if (wil->reply_id && wil->reply_id == id) {
1919                        WARN_ON(wil->reply_buf);
1920                        wmi_evt_call_handler(wil, id, evt_data,
1921                                             len - sizeof(*wmi));
1922                        wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n",
1923                                    id);
1924                        complete(&wil->wmi_call);
1925                        return;
1926                }
1927                /* unsolicited event */
1928                /* search for handler */
1929                if (!wmi_evt_call_handler(wil, id, evt_data,
1930                                          len - sizeof(*wmi))) {
1931                        wil_info(wil, "Unhandled event 0x%04x\n", id);
1932                }
1933        } else {
1934                wil_err(wil, "Unknown event type\n");
1935                print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
1936                               hdr, sizeof(*hdr) + len, true);
1937        }
1938}
1939
1940/*
1941 * Retrieve next WMI event from the pending list
1942 */
1943static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
1944{
1945        ulong flags;
1946        struct list_head *ret = NULL;
1947
1948        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1949
1950        if (!list_empty(&wil->pending_wmi_ev)) {
1951                ret = wil->pending_wmi_ev.next;
1952                list_del(ret);
1953        }
1954
1955        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
1956
1957        return ret;
1958}
1959
1960/*
1961 * Handler for the WMI events
1962 */
1963void wmi_event_worker(struct work_struct *work)
1964{
1965        struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
1966                                                 wmi_event_worker);
1967        struct pending_wmi_event *evt;
1968        struct list_head *lh;
1969
1970        wil_dbg_wmi(wil, "event_worker: Start\n");
1971        while ((lh = next_wmi_ev(wil)) != NULL) {
1972                evt = list_entry(lh, struct pending_wmi_event, list);
1973                wmi_event_handle(wil, &evt->event.hdr);
1974                kfree(evt);
1975        }
1976        wil_dbg_wmi(wil, "event_worker: Finished\n");
1977}
1978
1979bool wil_is_wmi_idle(struct wil6210_priv *wil)
1980{
1981        ulong flags;
1982        struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
1983        bool rc = false;
1984
1985        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1986
1987        /* Check if there are pending WMI events in the events queue */
1988        if (!list_empty(&wil->pending_wmi_ev)) {
1989                wil_dbg_pm(wil, "Pending WMI events in queue\n");
1990                goto out;
1991        }
1992
1993        /* Check if there is a pending WMI call */
1994        if (wil->reply_id) {
1995                wil_dbg_pm(wil, "Pending WMI call\n");
1996                goto out;
1997        }
1998
1999        /* Check if there are pending RX events in mbox */
2000        r->head = wil_r(wil, RGF_MBOX +
2001                        offsetof(struct wil6210_mbox_ctl, rx.head));
2002        if (r->tail != r->head)
2003                wil_dbg_pm(wil, "Pending WMI mbox events\n");
2004        else
2005                rc = true;
2006
2007out:
2008        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
2009        return rc;
2010}
2011