linux/drivers/net/wireless/ath/wil6210/wmi.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012-2016 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, S_IRUGO | S_IWUSR);
  28MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
  29
  30int agg_wsize; /* = 0; */
  31module_param(agg_wsize, int, S_IRUGO | S_IWUSR);
  32MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
  33                 " 0 - use default; < 0 - don't auto-establish");
  34
  35/**
  36 * WMI event receiving - theory of operations
  37 *
  38 * When firmware about to report WMI event, it fills memory area
  39 * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
  40 * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
  41 *
  42 * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
  43 * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
  44 * and handles events within the @wmi_event_worker. Every event get detached
  45 * from list, processed and deleted.
  46 *
  47 * Purpose for this mechanism is to release IRQ thread; otherwise,
  48 * if WMI event handling involves another WMI command flow, this 2-nd flow
  49 * won't be completed because of blocked IRQ thread.
  50 */
  51
  52/**
  53 * Addressing - theory of operations
  54 *
  55 * There are several buses present on the WIL6210 card.
  56 * Same memory areas are visible at different address on
  57 * the different busses. There are 3 main bus masters:
  58 *  - MAC CPU (ucode)
  59 *  - User CPU (firmware)
  60 *  - AHB (host)
  61 *
  62 * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
  63 * AHB addresses starting from 0x880000
  64 *
  65 * Internally, firmware uses addresses that allows faster access but
  66 * are invisible from the host. To read from these addresses, alternative
  67 * AHB address must be used.
  68 *
  69 * Memory mapping
  70 * Linker address         PCI/Host address
  71 *                        0x880000 .. 0xa80000  2Mb BAR0
  72 * 0x800000 .. 0x807000   0x900000 .. 0x907000  28k DCCM
  73 * 0x840000 .. 0x857000   0x908000 .. 0x91f000  92k PERIPH
  74 */
  75
  76/**
  77 * @fw_mapping provides memory remapping table
  78 *
  79 * array size should be in sync with the declaration in the wil6210.h
  80 */
  81const struct fw_map fw_mapping[] = {
  82        {0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM      256k */
  83        {0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM       32k */
  84        {0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
  85        {0x880000, 0x88a000, 0x880000, "rgf"},     /* various RGF       40k */
  86        {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table          4k */
  87        {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf       4k */
  88        {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf  512b */
  89        {0x8c0000, 0x949000, 0x8c0000, "upper"},   /* upper area       548k */
  90        /*
  91         * 920000..930000 ucode code RAM
  92         * 930000..932000 ucode data RAM
  93         * 932000..949000 back-door debug data
  94         */
  95};
  96
  97/**
  98 * return AHB address for given firmware/ucode internal (linker) address
  99 * @x - internal address
 100 * If address have no valid AHB mapping, return 0
 101 */
 102static u32 wmi_addr_remap(u32 x)
 103{
 104        uint i;
 105
 106        for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
 107                if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to))
 108                        return x + fw_mapping[i].host - fw_mapping[i].from;
 109        }
 110
 111        return 0;
 112}
 113
 114/**
 115 * Check address validity for WMI buffer; remap if needed
 116 * @ptr - internal (linker) fw/ucode address
 117 *
 118 * Valid buffer should be DWORD aligned
 119 *
 120 * return address for accessing buffer from the host;
 121 * if buffer is not valid, return NULL.
 122 */
 123void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
 124{
 125        u32 off;
 126        u32 ptr = le32_to_cpu(ptr_);
 127
 128        if (ptr % 4)
 129                return NULL;
 130
 131        ptr = wmi_addr_remap(ptr);
 132        if (ptr < WIL6210_FW_HOST_OFF)
 133                return NULL;
 134
 135        off = HOSTADDR(ptr);
 136        if (off > WIL6210_MEM_SIZE - 4)
 137                return NULL;
 138
 139        return wil->csr + off;
 140}
 141
 142/**
 143 * Check address validity
 144 */
 145void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
 146{
 147        u32 off;
 148
 149        if (ptr % 4)
 150                return NULL;
 151
 152        if (ptr < WIL6210_FW_HOST_OFF)
 153                return NULL;
 154
 155        off = HOSTADDR(ptr);
 156        if (off > WIL6210_MEM_SIZE - 4)
 157                return NULL;
 158
 159        return wil->csr + off;
 160}
 161
 162int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
 163                 struct wil6210_mbox_hdr *hdr)
 164{
 165        void __iomem *src = wmi_buffer(wil, ptr);
 166
 167        if (!src)
 168                return -EINVAL;
 169
 170        wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
 171
 172        return 0;
 173}
 174
 175static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 176{
 177        struct {
 178                struct wil6210_mbox_hdr hdr;
 179                struct wil6210_mbox_hdr_wmi wmi;
 180        } __packed cmd = {
 181                .hdr = {
 182                        .type = WIL_MBOX_HDR_TYPE_WMI,
 183                        .flags = 0,
 184                        .len = cpu_to_le16(sizeof(cmd.wmi) + len),
 185                },
 186                .wmi = {
 187                        .mid = 0,
 188                        .id = cpu_to_le16(cmdid),
 189                },
 190        };
 191        struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
 192        struct wil6210_mbox_ring_desc d_head;
 193        u32 next_head;
 194        void __iomem *dst;
 195        void __iomem *head = wmi_addr(wil, r->head);
 196        uint retry;
 197
 198        if (sizeof(cmd) + len > r->entry_size) {
 199                wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
 200                        (int)(sizeof(cmd) + len), r->entry_size);
 201                return -ERANGE;
 202        }
 203
 204        might_sleep();
 205
 206        if (!test_bit(wil_status_fwready, wil->status)) {
 207                wil_err(wil, "WMI: cannot send command while FW not ready\n");
 208                return -EAGAIN;
 209        }
 210
 211        if (!head) {
 212                wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
 213                return -EINVAL;
 214        }
 215        /* read Tx head till it is not busy */
 216        for (retry = 5; retry > 0; retry--) {
 217                wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
 218                if (d_head.sync == 0)
 219                        break;
 220                msleep(20);
 221        }
 222        if (d_head.sync != 0) {
 223                wil_err(wil, "WMI head busy\n");
 224                return -EBUSY;
 225        }
 226        /* next head */
 227        next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
 228        wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
 229        /* wait till FW finish with previous command */
 230        for (retry = 5; retry > 0; retry--) {
 231                if (!test_bit(wil_status_fwready, wil->status)) {
 232                        wil_err(wil, "WMI: cannot send command while FW not ready\n");
 233                        return -EAGAIN;
 234                }
 235                r->tail = wil_r(wil, RGF_MBOX +
 236                                offsetof(struct wil6210_mbox_ctl, tx.tail));
 237                if (next_head != r->tail)
 238                        break;
 239                msleep(20);
 240        }
 241        if (next_head == r->tail) {
 242                wil_err(wil, "WMI ring full\n");
 243                return -EBUSY;
 244        }
 245        dst = wmi_buffer(wil, d_head.addr);
 246        if (!dst) {
 247                wil_err(wil, "invalid WMI buffer: 0x%08x\n",
 248                        le32_to_cpu(d_head.addr));
 249                return -EINVAL;
 250        }
 251        cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
 252        /* set command */
 253        wil_dbg_wmi(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
 254        wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
 255                         sizeof(cmd), true);
 256        wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
 257                         len, true);
 258        wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
 259        wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
 260        /* mark entry as full */
 261        wil_w(wil, r->head + offsetof(struct wil6210_mbox_ring_desc, sync), 1);
 262        /* advance next ptr */
 263        wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, tx.head),
 264              r->head = next_head);
 265
 266        trace_wil6210_wmi_cmd(&cmd.wmi, buf, len);
 267
 268        /* interrupt to FW */
 269        wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS),
 270              SW_INT_MBOX);
 271
 272        return 0;
 273}
 274
 275int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 276{
 277        int rc;
 278
 279        mutex_lock(&wil->wmi_mutex);
 280        rc = __wmi_send(wil, cmdid, buf, len);
 281        mutex_unlock(&wil->wmi_mutex);
 282
 283        return rc;
 284}
 285
 286/*=== Event handlers ===*/
 287static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
 288{
 289        struct wireless_dev *wdev = wil->wdev;
 290        struct wmi_ready_event *evt = d;
 291
 292        wil->fw_version = le32_to_cpu(evt->sw_version);
 293        wil->n_mids = evt->numof_additional_mids;
 294
 295        wil_info(wil, "FW ver. %d; MAC %pM; %d MID's\n", wil->fw_version,
 296                 evt->mac, wil->n_mids);
 297        /* ignore MAC address, we already have it from the boot loader */
 298        snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
 299                 "%d", wil->fw_version);
 300
 301        wil_set_recovery_state(wil, fw_recovery_idle);
 302        set_bit(wil_status_fwready, wil->status);
 303        /* let the reset sequence continue */
 304        complete(&wil->wmi_ready);
 305}
 306
 307static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 308{
 309        struct wmi_rx_mgmt_packet_event *data = d;
 310        struct wiphy *wiphy = wil_to_wiphy(wil);
 311        struct ieee80211_mgmt *rx_mgmt_frame =
 312                        (struct ieee80211_mgmt *)data->payload;
 313        int flen = len - offsetof(struct wmi_rx_mgmt_packet_event, payload);
 314        int ch_no;
 315        u32 freq;
 316        struct ieee80211_channel *channel;
 317        s32 signal;
 318        __le16 fc;
 319        u32 d_len;
 320        u16 d_status;
 321
 322        if (flen < 0) {
 323                wil_err(wil, "MGMT Rx: short event, len %d\n", len);
 324                return;
 325        }
 326
 327        d_len = le32_to_cpu(data->info.len);
 328        if (d_len != flen) {
 329                wil_err(wil,
 330                        "MGMT Rx: length mismatch, d_len %d should be %d\n",
 331                        d_len, flen);
 332                return;
 333        }
 334
 335        ch_no = data->info.channel + 1;
 336        freq = ieee80211_channel_to_frequency(ch_no, IEEE80211_BAND_60GHZ);
 337        channel = ieee80211_get_channel(wiphy, freq);
 338        signal = data->info.sqi;
 339        d_status = le16_to_cpu(data->info.status);
 340        fc = rx_mgmt_frame->frame_control;
 341
 342        wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d SNR %d SQI %d%%\n",
 343                    data->info.channel, data->info.mcs, data->info.snr,
 344                    data->info.sqi);
 345        wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
 346                    le16_to_cpu(fc));
 347        wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
 348                    data->info.qid, data->info.mid, data->info.cid);
 349        wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
 350                         d_len, true);
 351
 352        if (!channel) {
 353                wil_err(wil, "Frame on unsupported channel\n");
 354                return;
 355        }
 356
 357        if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
 358                struct cfg80211_bss *bss;
 359                u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
 360                u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
 361                u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
 362                const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
 363                size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
 364                                                 u.beacon.variable);
 365                wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
 366                wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
 367                wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
 368                wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
 369                                 ie_len, true);
 370
 371                bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
 372                                                d_len, signal, GFP_KERNEL);
 373                if (bss) {
 374                        wil_dbg_wmi(wil, "Added BSS %pM\n",
 375                                    rx_mgmt_frame->bssid);
 376                        cfg80211_put_bss(wiphy, bss);
 377                } else {
 378                        wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
 379                }
 380        } else {
 381                cfg80211_rx_mgmt(wil->wdev, freq, signal,
 382                                 (void *)rx_mgmt_frame, d_len, 0);
 383        }
 384}
 385
 386static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 387{
 388        struct wmi_tx_mgmt_packet_event *data = d;
 389        struct ieee80211_mgmt *mgmt_frame =
 390                        (struct ieee80211_mgmt *)data->payload;
 391        int flen = len - offsetof(struct wmi_tx_mgmt_packet_event, payload);
 392
 393        wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET, 16, 1, mgmt_frame,
 394                         flen, true);
 395}
 396
 397static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
 398                                  void *d, int len)
 399{
 400        if (wil->scan_request) {
 401                struct wmi_scan_complete_event *data = d;
 402                bool aborted = (data->status != WMI_SCAN_SUCCESS);
 403
 404                wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
 405                wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
 406                             wil->scan_request, aborted);
 407
 408                del_timer_sync(&wil->scan_timer);
 409                cfg80211_scan_done(wil->scan_request, aborted);
 410                wil->scan_request = NULL;
 411        } else {
 412                wil_err(wil, "SCAN_COMPLETE while not scanning\n");
 413        }
 414}
 415
 416static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 417{
 418        struct net_device *ndev = wil_to_ndev(wil);
 419        struct wireless_dev *wdev = wil->wdev;
 420        struct wmi_connect_event *evt = d;
 421        int ch; /* channel number */
 422        struct station_info sinfo;
 423        u8 *assoc_req_ie, *assoc_resp_ie;
 424        size_t assoc_req_ielen, assoc_resp_ielen;
 425        /* capinfo(u16) + listen_interval(u16) + IEs */
 426        const size_t assoc_req_ie_offset = sizeof(u16) * 2;
 427        /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
 428        const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
 429        int rc;
 430
 431        if (len < sizeof(*evt)) {
 432                wil_err(wil, "Connect event too short : %d bytes\n", len);
 433                return;
 434        }
 435        if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
 436                   evt->assoc_resp_len) {
 437                wil_err(wil,
 438                        "Connect event corrupted : %d != %d + %d + %d + %d\n",
 439                        len, (int)sizeof(*evt), evt->beacon_ie_len,
 440                        evt->assoc_req_len, evt->assoc_resp_len);
 441                return;
 442        }
 443        if (evt->cid >= WIL6210_MAX_CID) {
 444                wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
 445                return;
 446        }
 447
 448        ch = evt->channel + 1;
 449        wil_info(wil, "Connect %pM channel [%d] cid %d\n",
 450                 evt->bssid, ch, evt->cid);
 451        wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
 452                         evt->assoc_info, len - sizeof(*evt), true);
 453
 454        /* figure out IE's */
 455        assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
 456                                        assoc_req_ie_offset];
 457        assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
 458        if (evt->assoc_req_len <= assoc_req_ie_offset) {
 459                assoc_req_ie = NULL;
 460                assoc_req_ielen = 0;
 461        }
 462
 463        assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
 464                                         evt->assoc_req_len +
 465                                         assoc_resp_ie_offset];
 466        assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
 467        if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
 468                assoc_resp_ie = NULL;
 469                assoc_resp_ielen = 0;
 470        }
 471
 472        mutex_lock(&wil->mutex);
 473        if (test_bit(wil_status_resetting, wil->status) ||
 474            !test_bit(wil_status_fwready, wil->status)) {
 475                wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
 476                        evt->cid);
 477                mutex_unlock(&wil->mutex);
 478                /* no need for cleanup, wil_reset will do that */
 479                return;
 480        }
 481
 482        if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
 483            (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
 484                if (!test_bit(wil_status_fwconnecting, wil->status)) {
 485                        wil_err(wil, "Not in connecting state\n");
 486                        mutex_unlock(&wil->mutex);
 487                        return;
 488                }
 489                del_timer_sync(&wil->connect_timer);
 490        }
 491
 492        /* FIXME FW can transmit only ucast frames to peer */
 493        /* FIXME real ring_id instead of hard coded 0 */
 494        ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
 495        wil->sta[evt->cid].status = wil_sta_conn_pending;
 496
 497        rc = wil_tx_init(wil, evt->cid);
 498        if (rc) {
 499                wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n",
 500                        __func__, evt->cid, rc);
 501                wmi_disconnect_sta(wil, wil->sta[evt->cid].addr,
 502                                   WLAN_REASON_UNSPECIFIED, false);
 503        } else {
 504                wil_info(wil, "%s: successful connection to CID %d\n",
 505                         __func__, evt->cid);
 506        }
 507
 508        if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
 509            (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
 510                if (rc) {
 511                        netif_tx_stop_all_queues(ndev);
 512                        netif_carrier_off(ndev);
 513                        wil_err(wil,
 514                                "%s: cfg80211_connect_result with failure\n",
 515                                __func__);
 516                        cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
 517                                                NULL, 0,
 518                                                WLAN_STATUS_UNSPECIFIED_FAILURE,
 519                                                GFP_KERNEL);
 520                        goto out;
 521                } else {
 522                        cfg80211_connect_result(ndev, evt->bssid,
 523                                                assoc_req_ie, assoc_req_ielen,
 524                                                assoc_resp_ie, assoc_resp_ielen,
 525                                                WLAN_STATUS_SUCCESS,
 526                                                GFP_KERNEL);
 527                }
 528        } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
 529                   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
 530                if (rc)
 531                        goto out;
 532
 533                memset(&sinfo, 0, sizeof(sinfo));
 534
 535                sinfo.generation = wil->sinfo_gen++;
 536
 537                if (assoc_req_ie) {
 538                        sinfo.assoc_req_ies = assoc_req_ie;
 539                        sinfo.assoc_req_ies_len = assoc_req_ielen;
 540                }
 541
 542                cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
 543        } else {
 544                wil_err(wil, "%s: unhandled iftype %d for CID %d\n",
 545                        __func__, wdev->iftype, evt->cid);
 546                goto out;
 547        }
 548
 549        wil->sta[evt->cid].status = wil_sta_connected;
 550        set_bit(wil_status_fwconnected, wil->status);
 551        netif_tx_wake_all_queues(ndev);
 552
 553out:
 554        if (rc)
 555                wil->sta[evt->cid].status = wil_sta_unused;
 556        clear_bit(wil_status_fwconnecting, wil->status);
 557        mutex_unlock(&wil->mutex);
 558}
 559
 560static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
 561                               void *d, int len)
 562{
 563        struct wmi_disconnect_event *evt = d;
 564        u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
 565
 566        wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
 567                 evt->bssid, reason_code, evt->disconnect_reason);
 568
 569        wil->sinfo_gen++;
 570
 571        mutex_lock(&wil->mutex);
 572        wil6210_disconnect(wil, evt->bssid, reason_code, true);
 573        mutex_unlock(&wil->mutex);
 574}
 575
 576/*
 577 * Firmware reports EAPOL frame using WME event.
 578 * Reconstruct Ethernet frame and deliver it via normal Rx
 579 */
 580static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
 581                             void *d, int len)
 582{
 583        struct net_device *ndev = wil_to_ndev(wil);
 584        struct wmi_eapol_rx_event *evt = d;
 585        u16 eapol_len = le16_to_cpu(evt->eapol_len);
 586        int sz = eapol_len + ETH_HLEN;
 587        struct sk_buff *skb;
 588        struct ethhdr *eth;
 589        int cid;
 590        struct wil_net_stats *stats = NULL;
 591
 592        wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
 593                    evt->src_mac);
 594
 595        cid = wil_find_cid(wil, evt->src_mac);
 596        if (cid >= 0)
 597                stats = &wil->sta[cid].stats;
 598
 599        if (eapol_len > 196) { /* TODO: revisit size limit */
 600                wil_err(wil, "EAPOL too large\n");
 601                return;
 602        }
 603
 604        skb = alloc_skb(sz, GFP_KERNEL);
 605        if (!skb) {
 606                wil_err(wil, "Failed to allocate skb\n");
 607                return;
 608        }
 609
 610        eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
 611        ether_addr_copy(eth->h_dest, ndev->dev_addr);
 612        ether_addr_copy(eth->h_source, evt->src_mac);
 613        eth->h_proto = cpu_to_be16(ETH_P_PAE);
 614        memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len);
 615        skb->protocol = eth_type_trans(skb, ndev);
 616        if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
 617                ndev->stats.rx_packets++;
 618                ndev->stats.rx_bytes += sz;
 619                if (stats) {
 620                        stats->rx_packets++;
 621                        stats->rx_bytes += sz;
 622                }
 623        } else {
 624                ndev->stats.rx_dropped++;
 625                if (stats)
 626                        stats->rx_dropped++;
 627        }
 628}
 629
 630static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
 631{
 632        struct wmi_vring_en_event *evt = d;
 633        u8 vri = evt->vring_index;
 634
 635        wil_dbg_wmi(wil, "Enable vring %d\n", vri);
 636
 637        if (vri >= ARRAY_SIZE(wil->vring_tx)) {
 638                wil_err(wil, "Enable for invalid vring %d\n", vri);
 639                return;
 640        }
 641        wil->vring_tx_data[vri].dot1x_open = true;
 642        if (vri == wil->bcast_vring) /* no BA for bcast */
 643                return;
 644        if (agg_wsize >= 0)
 645                wil_addba_tx_request(wil, vri, agg_wsize);
 646}
 647
 648static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
 649                              int len)
 650{
 651        struct wmi_vring_ba_status_event *evt = d;
 652        struct vring_tx_data *txdata;
 653
 654        wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
 655                    evt->ringid,
 656                    evt->status == WMI_BA_AGREED ? "OK" : "N/A",
 657                    evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
 658                    evt->amsdu ? "+" : "-");
 659
 660        if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
 661                wil_err(wil, "invalid ring id %d\n", evt->ringid);
 662                return;
 663        }
 664
 665        if (evt->status != WMI_BA_AGREED) {
 666                evt->ba_timeout = 0;
 667                evt->agg_wsize = 0;
 668                evt->amsdu = 0;
 669        }
 670
 671        txdata = &wil->vring_tx_data[evt->ringid];
 672
 673        txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
 674        txdata->agg_wsize = evt->agg_wsize;
 675        txdata->agg_amsdu = evt->amsdu;
 676        txdata->addba_in_progress = false;
 677}
 678
 679static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
 680                                 int len)
 681{
 682        struct wmi_rcp_addba_req_event *evt = d;
 683
 684        wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
 685                             evt->ba_param_set, evt->ba_timeout,
 686                             evt->ba_seq_ctrl);
 687}
 688
 689static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
 690__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 691{
 692        struct wmi_delba_event *evt = d;
 693        u8 cid, tid;
 694        u16 reason = __le16_to_cpu(evt->reason);
 695        struct wil_sta_info *sta;
 696        struct wil_tid_ampdu_rx *r;
 697
 698        might_sleep();
 699        parse_cidxtid(evt->cidxtid, &cid, &tid);
 700        wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
 701                    cid, tid,
 702                    evt->from_initiator ? "originator" : "recipient",
 703                    reason);
 704        if (!evt->from_initiator) {
 705                int i;
 706                /* find Tx vring it belongs to */
 707                for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
 708                        if ((wil->vring2cid_tid[i][0] == cid) &&
 709                            (wil->vring2cid_tid[i][1] == tid)) {
 710                                struct vring_tx_data *txdata =
 711                                        &wil->vring_tx_data[i];
 712
 713                                wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
 714                                txdata->agg_timeout = 0;
 715                                txdata->agg_wsize = 0;
 716                                txdata->addba_in_progress = false;
 717
 718                                break; /* max. 1 matching ring */
 719                        }
 720                }
 721                if (i >= ARRAY_SIZE(wil->vring2cid_tid))
 722                        wil_err(wil, "DELBA: unable to find Tx vring\n");
 723                return;
 724        }
 725
 726        sta = &wil->sta[cid];
 727
 728        spin_lock_bh(&sta->tid_rx_lock);
 729
 730        r = sta->tid_rx[tid];
 731        sta->tid_rx[tid] = NULL;
 732        wil_tid_ampdu_rx_free(wil, r);
 733
 734        spin_unlock_bh(&sta->tid_rx_lock);
 735}
 736
 737/**
 738 * Some events are ignored for purpose; and need not be interpreted as
 739 * "unhandled events"
 740 */
 741static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
 742{
 743        wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
 744}
 745
 746static const struct {
 747        int eventid;
 748        void (*handler)(struct wil6210_priv *wil, int eventid,
 749                        void *data, int data_len);
 750} wmi_evt_handlers[] = {
 751        {WMI_READY_EVENTID,             wmi_evt_ready},
 752        {WMI_FW_READY_EVENTID,                  wmi_evt_ignore},
 753        {WMI_RX_MGMT_PACKET_EVENTID,    wmi_evt_rx_mgmt},
 754        {WMI_TX_MGMT_PACKET_EVENTID,            wmi_evt_tx_mgmt},
 755        {WMI_SCAN_COMPLETE_EVENTID,     wmi_evt_scan_complete},
 756        {WMI_CONNECT_EVENTID,           wmi_evt_connect},
 757        {WMI_DISCONNECT_EVENTID,        wmi_evt_disconnect},
 758        {WMI_EAPOL_RX_EVENTID,          wmi_evt_eapol_rx},
 759        {WMI_BA_STATUS_EVENTID,         wmi_evt_ba_status},
 760        {WMI_RCP_ADDBA_REQ_EVENTID,     wmi_evt_addba_rx_req},
 761        {WMI_DELBA_EVENTID,             wmi_evt_delba},
 762        {WMI_VRING_EN_EVENTID,          wmi_evt_vring_en},
 763        {WMI_DATA_PORT_OPEN_EVENTID,            wmi_evt_ignore},
 764};
 765
 766/*
 767 * Run in IRQ context
 768 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
 769 * that will be eventually handled by the @wmi_event_worker in the thread
 770 * context of thread "wil6210_wmi"
 771 */
 772void wmi_recv_cmd(struct wil6210_priv *wil)
 773{
 774        struct wil6210_mbox_ring_desc d_tail;
 775        struct wil6210_mbox_hdr hdr;
 776        struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
 777        struct pending_wmi_event *evt;
 778        u8 *cmd;
 779        void __iomem *src;
 780        ulong flags;
 781        unsigned n;
 782        unsigned int num_immed_reply = 0;
 783
 784        if (!test_bit(wil_status_mbox_ready, wil->status)) {
 785                wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
 786                return;
 787        }
 788
 789        for (n = 0;; n++) {
 790                u16 len;
 791                bool q;
 792                bool immed_reply = false;
 793
 794                r->head = wil_r(wil, RGF_MBOX +
 795                                offsetof(struct wil6210_mbox_ctl, rx.head));
 796                if (r->tail == r->head)
 797                        break;
 798
 799                wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
 800                            r->head, r->tail);
 801                /* read cmd descriptor from tail */
 802                wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
 803                                     sizeof(struct wil6210_mbox_ring_desc));
 804                if (d_tail.sync == 0) {
 805                        wil_err(wil, "Mbox evt not owned by FW?\n");
 806                        break;
 807                }
 808
 809                /* read cmd header from descriptor */
 810                if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
 811                        wil_err(wil, "Mbox evt at 0x%08x?\n",
 812                                le32_to_cpu(d_tail.addr));
 813                        break;
 814                }
 815                len = le16_to_cpu(hdr.len);
 816                wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
 817                            le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
 818                            hdr.flags);
 819
 820                /* read cmd buffer from descriptor */
 821                src = wmi_buffer(wil, d_tail.addr) +
 822                      sizeof(struct wil6210_mbox_hdr);
 823                evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
 824                                             event.wmi) + len, 4),
 825                              GFP_KERNEL);
 826                if (!evt)
 827                        break;
 828
 829                evt->event.hdr = hdr;
 830                cmd = (void *)&evt->event.wmi;
 831                wil_memcpy_fromio_32(cmd, src, len);
 832                /* mark entry as empty */
 833                wil_w(wil, r->tail +
 834                      offsetof(struct wil6210_mbox_ring_desc, sync), 0);
 835                /* indicate */
 836                if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
 837                    (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
 838                        struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi;
 839                        u16 id = le16_to_cpu(wmi->id);
 840                        u32 tstamp = le32_to_cpu(wmi->timestamp);
 841                        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
 842                        if (wil->reply_id && wil->reply_id == id) {
 843                                if (wil->reply_buf) {
 844                                        memcpy(wil->reply_buf, wmi,
 845                                               min(len, wil->reply_size));
 846                                        immed_reply = true;
 847                                }
 848                        }
 849                        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 850
 851                        wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
 852                                    id, wmi->mid, tstamp);
 853                        trace_wil6210_wmi_event(wmi, &wmi[1],
 854                                                len - sizeof(*wmi));
 855                }
 856                wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
 857                                 &evt->event.hdr, sizeof(hdr) + len, true);
 858
 859                /* advance tail */
 860                r->tail = r->base + ((r->tail - r->base +
 861                          sizeof(struct wil6210_mbox_ring_desc)) % r->size);
 862                wil_w(wil, RGF_MBOX +
 863                      offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail);
 864
 865                if (immed_reply) {
 866                        wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n",
 867                                    __func__, wil->reply_id);
 868                        kfree(evt);
 869                        num_immed_reply++;
 870                        complete(&wil->wmi_call);
 871                } else {
 872                        /* add to the pending list */
 873                        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
 874                        list_add_tail(&evt->list, &wil->pending_wmi_ev);
 875                        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 876                        q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
 877                        wil_dbg_wmi(wil, "queue_work -> %d\n", q);
 878                }
 879        }
 880        /* normally, 1 event per IRQ should be processed */
 881        wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__,
 882                    n - num_immed_reply, num_immed_reply);
 883}
 884
 885int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
 886             u16 reply_id, void *reply, u8 reply_size, int to_msec)
 887{
 888        int rc;
 889        unsigned long remain;
 890
 891        mutex_lock(&wil->wmi_mutex);
 892
 893        spin_lock(&wil->wmi_ev_lock);
 894        wil->reply_id = reply_id;
 895        wil->reply_buf = reply;
 896        wil->reply_size = reply_size;
 897        spin_unlock(&wil->wmi_ev_lock);
 898
 899        rc = __wmi_send(wil, cmdid, buf, len);
 900        if (rc)
 901                goto out;
 902
 903        remain = wait_for_completion_timeout(&wil->wmi_call,
 904                                             msecs_to_jiffies(to_msec));
 905        if (0 == remain) {
 906                wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
 907                        cmdid, reply_id, to_msec);
 908                rc = -ETIME;
 909        } else {
 910                wil_dbg_wmi(wil,
 911                            "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
 912                            cmdid, reply_id,
 913                            to_msec - jiffies_to_msecs(remain));
 914        }
 915
 916out:
 917        spin_lock(&wil->wmi_ev_lock);
 918        wil->reply_id = 0;
 919        wil->reply_buf = NULL;
 920        wil->reply_size = 0;
 921        spin_unlock(&wil->wmi_ev_lock);
 922
 923        mutex_unlock(&wil->wmi_mutex);
 924
 925        return rc;
 926}
 927
 928int wmi_echo(struct wil6210_priv *wil)
 929{
 930        struct wmi_echo_cmd cmd = {
 931                .value = cpu_to_le32(0x12345678),
 932        };
 933
 934        return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
 935                        WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
 936}
 937
 938int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
 939{
 940        struct wmi_set_mac_address_cmd cmd;
 941
 942        ether_addr_copy(cmd.mac, addr);
 943
 944        wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
 945
 946        return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
 947}
 948
 949int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 950                  u8 chan, u8 hidden_ssid)
 951{
 952        int rc;
 953
 954        struct wmi_pcp_start_cmd cmd = {
 955                .bcon_interval = cpu_to_le16(bi),
 956                .network_type = wmi_nettype,
 957                .disable_sec_offload = 1,
 958                .channel = chan - 1,
 959                .pcp_max_assoc_sta = max_assoc_sta,
 960                .hidden_ssid = hidden_ssid,
 961        };
 962        struct {
 963                struct wil6210_mbox_hdr_wmi wmi;
 964                struct wmi_pcp_started_event evt;
 965        } __packed reply;
 966
 967        if (!wil->privacy)
 968                cmd.disable_sec = 1;
 969
 970        if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
 971            (cmd.pcp_max_assoc_sta <= 0)) {
 972                wil_info(wil,
 973                         "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
 974                         max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
 975                cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
 976        }
 977
 978        /*
 979         * Processing time may be huge, in case of secure AP it takes about
 980         * 3500ms for FW to start AP
 981         */
 982        rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
 983                      WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
 984        if (rc)
 985                return rc;
 986
 987        if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
 988                rc = -EINVAL;
 989
 990        return rc;
 991}
 992
 993int wmi_pcp_stop(struct wil6210_priv *wil)
 994{
 995        return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
 996                        WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
 997}
 998
 999int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
1000{
1001        struct wmi_set_ssid_cmd cmd = {
1002                .ssid_len = cpu_to_le32(ssid_len),
1003        };
1004
1005        if (ssid_len > sizeof(cmd.ssid))
1006                return -EINVAL;
1007
1008        memcpy(cmd.ssid, ssid, ssid_len);
1009
1010        return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
1011}
1012
1013int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
1014{
1015        int rc;
1016        struct {
1017                struct wil6210_mbox_hdr_wmi wmi;
1018                struct wmi_set_ssid_cmd cmd;
1019        } __packed reply;
1020        int len; /* reply.cmd.ssid_len in CPU order */
1021
1022        rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
1023                      &reply, sizeof(reply), 20);
1024        if (rc)
1025                return rc;
1026
1027        len = le32_to_cpu(reply.cmd.ssid_len);
1028        if (len > sizeof(reply.cmd.ssid))
1029                return -EINVAL;
1030
1031        *ssid_len = len;
1032        memcpy(ssid, reply.cmd.ssid, len);
1033
1034        return 0;
1035}
1036
1037int wmi_set_channel(struct wil6210_priv *wil, int channel)
1038{
1039        struct wmi_set_pcp_channel_cmd cmd = {
1040                .channel = channel - 1,
1041        };
1042
1043        return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
1044}
1045
1046int wmi_get_channel(struct wil6210_priv *wil, int *channel)
1047{
1048        int rc;
1049        struct {
1050                struct wil6210_mbox_hdr_wmi wmi;
1051                struct wmi_set_pcp_channel_cmd cmd;
1052        } __packed reply;
1053
1054        rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
1055                      WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
1056        if (rc)
1057                return rc;
1058
1059        if (reply.cmd.channel > 3)
1060                return -EINVAL;
1061
1062        *channel = reply.cmd.channel + 1;
1063
1064        return 0;
1065}
1066
1067int wmi_p2p_cfg(struct wil6210_priv *wil, int channel)
1068{
1069        struct wmi_p2p_cfg_cmd cmd = {
1070                .discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD,
1071                .channel = channel - 1,
1072        };
1073
1074        return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd));
1075}
1076
1077int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
1078                       const void *mac_addr, int key_usage)
1079{
1080        struct wmi_delete_cipher_key_cmd cmd = {
1081                .key_index = key_index,
1082        };
1083
1084        if (mac_addr)
1085                memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1086
1087        return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1088}
1089
1090int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
1091                       const void *mac_addr, int key_len, const void *key,
1092                       int key_usage)
1093{
1094        struct wmi_add_cipher_key_cmd cmd = {
1095                .key_index = key_index,
1096                .key_usage = key_usage,
1097                .key_len = key_len,
1098        };
1099
1100        if (!key || (key_len > sizeof(cmd.key)))
1101                return -EINVAL;
1102
1103        memcpy(cmd.key, key, key_len);
1104        if (mac_addr)
1105                memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1106
1107        return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1108}
1109
1110int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
1111{
1112        static const char *const names[] = {
1113                [WMI_FRAME_BEACON]      = "BEACON",
1114                [WMI_FRAME_PROBE_REQ]   = "PROBE_REQ",
1115                [WMI_FRAME_PROBE_RESP]  = "WMI_FRAME_PROBE_RESP",
1116                [WMI_FRAME_ASSOC_REQ]   = "WMI_FRAME_ASSOC_REQ",
1117                [WMI_FRAME_ASSOC_RESP]  = "WMI_FRAME_ASSOC_RESP",
1118        };
1119        int rc;
1120        u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
1121        struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
1122
1123        if (!cmd) {
1124                rc = -ENOMEM;
1125                goto out;
1126        }
1127        if (!ie)
1128                ie_len = 0;
1129
1130        cmd->mgmt_frm_type = type;
1131        /* BUG: FW API define ieLen as u8. Will fix FW */
1132        cmd->ie_len = cpu_to_le16(ie_len);
1133        memcpy(cmd->ie_info, ie, ie_len);
1134        rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
1135        kfree(cmd);
1136out:
1137        if (rc) {
1138                const char *name = type < ARRAY_SIZE(names) ?
1139                                   names[type] : "??";
1140                wil_err(wil, "set_ie(%d %s) failed : %d\n", type, name, rc);
1141        }
1142
1143        return rc;
1144}
1145
1146/**
1147 * wmi_rxon - turn radio on/off
1148 * @on:         turn on if true, off otherwise
1149 *
1150 * Only switch radio. Channel should be set separately.
1151 * No timeout for rxon - radio turned on forever unless some other call
1152 * turns it off
1153 */
1154int wmi_rxon(struct wil6210_priv *wil, bool on)
1155{
1156        int rc;
1157        struct {
1158                struct wil6210_mbox_hdr_wmi wmi;
1159                struct wmi_listen_started_event evt;
1160        } __packed reply;
1161
1162        wil_info(wil, "%s(%s)\n", __func__, on ? "on" : "off");
1163
1164        if (on) {
1165                rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
1166                              WMI_LISTEN_STARTED_EVENTID,
1167                              &reply, sizeof(reply), 100);
1168                if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
1169                        rc = -EINVAL;
1170        } else {
1171                rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
1172                              WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
1173        }
1174
1175        return rc;
1176}
1177
1178int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
1179{
1180        struct wireless_dev *wdev = wil->wdev;
1181        struct net_device *ndev = wil_to_ndev(wil);
1182        struct wmi_cfg_rx_chain_cmd cmd = {
1183                .action = WMI_RX_CHAIN_ADD,
1184                .rx_sw_ring = {
1185                        .max_mpdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
1186                        .ring_mem_base = cpu_to_le64(vring->pa),
1187                        .ring_size = cpu_to_le16(vring->size),
1188                },
1189                .mid = 0, /* TODO - what is it? */
1190                .decap_trans_type = WMI_DECAP_TYPE_802_3,
1191                .reorder_type = WMI_RX_SW_REORDER,
1192                .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
1193        };
1194        struct {
1195                struct wil6210_mbox_hdr_wmi wmi;
1196                struct wmi_cfg_rx_chain_done_event evt;
1197        } __packed evt;
1198        int rc;
1199
1200        if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
1201                struct ieee80211_channel *ch = wdev->preset_chandef.chan;
1202
1203                cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
1204                if (ch)
1205                        cmd.sniffer_cfg.channel = ch->hw_value - 1;
1206                cmd.sniffer_cfg.phy_info_mode =
1207                        cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
1208                cmd.sniffer_cfg.phy_support =
1209                        cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
1210                                    ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
1211        } else {
1212                /* Initialize offload (in non-sniffer mode).
1213                 * Linux IP stack always calculates IP checksum
1214                 * HW always calculate TCP/UDP checksum
1215                 */
1216                cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
1217        }
1218
1219        if (rx_align_2)
1220                cmd.l2_802_3_offload_ctrl |=
1221                                L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
1222
1223        /* typical time for secure PCP is 840ms */
1224        rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
1225                      WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
1226        if (rc)
1227                return rc;
1228
1229        vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
1230
1231        wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
1232                     le32_to_cpu(evt.evt.status), vring->hwtail);
1233
1234        if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
1235                rc = -EINVAL;
1236
1237        return rc;
1238}
1239
1240int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
1241{
1242        int rc;
1243        struct wmi_temp_sense_cmd cmd = {
1244                .measure_baseband_en = cpu_to_le32(!!t_bb),
1245                .measure_rf_en = cpu_to_le32(!!t_rf),
1246                .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
1247        };
1248        struct {
1249                struct wil6210_mbox_hdr_wmi wmi;
1250                struct wmi_temp_sense_done_event evt;
1251        } __packed reply;
1252
1253        rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
1254                      WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
1255        if (rc)
1256                return rc;
1257
1258        if (t_bb)
1259                *t_bb = le32_to_cpu(reply.evt.baseband_t1000);
1260        if (t_rf)
1261                *t_rf = le32_to_cpu(reply.evt.rf_t1000);
1262
1263        return 0;
1264}
1265
1266int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason,
1267                       bool full_disconnect)
1268{
1269        int rc;
1270        u16 reason_code;
1271        struct wmi_disconnect_sta_cmd cmd = {
1272                .disconnect_reason = cpu_to_le16(reason),
1273        };
1274        struct {
1275                struct wil6210_mbox_hdr_wmi wmi;
1276                struct wmi_disconnect_event evt;
1277        } __packed reply;
1278
1279        ether_addr_copy(cmd.dst_mac, mac);
1280
1281        wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason);
1282
1283        rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd),
1284                      WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000);
1285        /* failure to disconnect in reasonable time treated as FW error */
1286        if (rc) {
1287                wil_fw_error_recovery(wil);
1288                return rc;
1289        }
1290
1291        if (full_disconnect) {
1292                /* call event handler manually after processing wmi_call,
1293                 * to avoid deadlock - disconnect event handler acquires
1294                 * wil->mutex while it is already held here
1295                 */
1296                reason_code = le16_to_cpu(reply.evt.protocol_reason_status);
1297
1298                wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
1299                            reply.evt.bssid, reason_code,
1300                            reply.evt.disconnect_reason);
1301
1302                wil->sinfo_gen++;
1303                wil6210_disconnect(wil, reply.evt.bssid, reason_code, true);
1304        }
1305        return 0;
1306}
1307
1308int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
1309{
1310        struct wmi_vring_ba_en_cmd cmd = {
1311                .ringid = ringid,
1312                .agg_max_wsize = size,
1313                .ba_timeout = cpu_to_le16(timeout),
1314                .amsdu = 0,
1315        };
1316
1317        wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__,
1318                    ringid, size, timeout);
1319
1320        return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
1321}
1322
1323int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
1324{
1325        struct wmi_vring_ba_dis_cmd cmd = {
1326                .ringid = ringid,
1327                .reason = cpu_to_le16(reason),
1328        };
1329
1330        wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__,
1331                    ringid, reason);
1332
1333        return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
1334}
1335
1336int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
1337{
1338        struct wmi_rcp_delba_cmd cmd = {
1339                .cidxtid = cidxtid,
1340                .reason = cpu_to_le16(reason),
1341        };
1342
1343        wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__,
1344                    cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason);
1345
1346        return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
1347}
1348
1349int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
1350                      u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
1351{
1352        int rc;
1353        struct wmi_rcp_addba_resp_cmd cmd = {
1354                .cidxtid = mk_cidxtid(cid, tid),
1355                .dialog_token = token,
1356                .status_code = cpu_to_le16(status),
1357                /* bit 0: A-MSDU supported
1358                 * bit 1: policy (should be 0 for us)
1359                 * bits 2..5: TID
1360                 * bits 6..15: buffer size
1361                 */
1362                .ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
1363                                            (agg_wsize << 6)),
1364                .ba_timeout = cpu_to_le16(timeout),
1365        };
1366        struct {
1367                struct wil6210_mbox_hdr_wmi wmi;
1368                struct wmi_rcp_addba_resp_sent_event evt;
1369        } __packed reply;
1370
1371        wil_dbg_wmi(wil,
1372                    "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
1373                    cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
1374
1375        rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
1376                      WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
1377                      100);
1378        if (rc)
1379                return rc;
1380
1381        if (reply.evt.status) {
1382                wil_err(wil, "ADDBA response failed with status %d\n",
1383                        le16_to_cpu(reply.evt.status));
1384                rc = -EINVAL;
1385        }
1386
1387        return rc;
1388}
1389
1390void wmi_event_flush(struct wil6210_priv *wil)
1391{
1392        struct pending_wmi_event *evt, *t;
1393
1394        wil_dbg_wmi(wil, "%s()\n", __func__);
1395
1396        list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
1397                list_del(&evt->list);
1398                kfree(evt);
1399        }
1400}
1401
1402static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
1403                                 void *d, int len)
1404{
1405        uint i;
1406
1407        for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
1408                if (wmi_evt_handlers[i].eventid == id) {
1409                        wmi_evt_handlers[i].handler(wil, id, d, len);
1410                        return true;
1411                }
1412        }
1413
1414        return false;
1415}
1416
1417static void wmi_event_handle(struct wil6210_priv *wil,
1418                             struct wil6210_mbox_hdr *hdr)
1419{
1420        u16 len = le16_to_cpu(hdr->len);
1421
1422        if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
1423            (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
1424                struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]);
1425                void *evt_data = (void *)(&wmi[1]);
1426                u16 id = le16_to_cpu(wmi->id);
1427
1428                wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n",
1429                            id, wil->reply_id);
1430                /* check if someone waits for this event */
1431                if (wil->reply_id && wil->reply_id == id) {
1432                        WARN_ON(wil->reply_buf);
1433                        wmi_evt_call_handler(wil, id, evt_data,
1434                                             len - sizeof(*wmi));
1435                        wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n",
1436                                    __func__, id);
1437                        complete(&wil->wmi_call);
1438                        return;
1439                }
1440                /* unsolicited event */
1441                /* search for handler */
1442                if (!wmi_evt_call_handler(wil, id, evt_data,
1443                                          len - sizeof(*wmi))) {
1444                        wil_info(wil, "Unhandled event 0x%04x\n", id);
1445                }
1446        } else {
1447                wil_err(wil, "Unknown event type\n");
1448                print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
1449                               hdr, sizeof(*hdr) + len, true);
1450        }
1451}
1452
1453/*
1454 * Retrieve next WMI event from the pending list
1455 */
1456static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
1457{
1458        ulong flags;
1459        struct list_head *ret = NULL;
1460
1461        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1462
1463        if (!list_empty(&wil->pending_wmi_ev)) {
1464                ret = wil->pending_wmi_ev.next;
1465                list_del(ret);
1466        }
1467
1468        spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
1469
1470        return ret;
1471}
1472
1473/*
1474 * Handler for the WMI events
1475 */
1476void wmi_event_worker(struct work_struct *work)
1477{
1478        struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
1479                                                 wmi_event_worker);
1480        struct pending_wmi_event *evt;
1481        struct list_head *lh;
1482
1483        wil_dbg_wmi(wil, "Start %s\n", __func__);
1484        while ((lh = next_wmi_ev(wil)) != NULL) {
1485                evt = list_entry(lh, struct pending_wmi_event, list);
1486                wmi_event_handle(wil, &evt->event.hdr);
1487                kfree(evt);
1488        }
1489        wil_dbg_wmi(wil, "Finished %s\n", __func__);
1490}
1491