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