linux/drivers/staging/wfx/sta.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Implementation of mac80211 API.
   4 *
   5 * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
   6 * Copyright (c) 2010, ST-Ericsson
   7 */
   8#include <linux/etherdevice.h>
   9#include <net/mac80211.h>
  10
  11#include "sta.h"
  12#include "wfx.h"
  13#include "fwio.h"
  14#include "bh.h"
  15#include "key.h"
  16#include "scan.h"
  17#include "debug.h"
  18#include "hif_tx.h"
  19#include "hif_tx_mib.h"
  20
  21#define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2
  22
  23u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
  24{
  25        int i;
  26        u32 ret = 0;
  27        // WFx only support 2GHz
  28        struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
  29
  30        for (i = 0; i < sband->n_bitrates; i++) {
  31                if (rates & BIT(i)) {
  32                        if (i >= sband->n_bitrates)
  33                                dev_warn(wdev->dev, "unsupported basic rate\n");
  34                        else
  35                                ret |= BIT(sband->bitrates[i].hw_value);
  36                }
  37        }
  38        return ret;
  39}
  40
  41void wfx_cooling_timeout_work(struct work_struct *work)
  42{
  43        struct wfx_dev *wdev = container_of(to_delayed_work(work),
  44                                            struct wfx_dev,
  45                                            cooling_timeout_work);
  46
  47        wdev->chip_frozen = true;
  48        wfx_tx_unlock(wdev);
  49}
  50
  51void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd)
  52{
  53        if (cmd == STA_NOTIFY_AWAKE) {
  54                // Device recover normal temperature
  55                if (cancel_delayed_work(&wdev->cooling_timeout_work))
  56                        wfx_tx_unlock(wdev);
  57        } else {
  58                // Device is too hot
  59                schedule_delayed_work(&wdev->cooling_timeout_work, 10 * HZ);
  60                wfx_tx_lock(wdev);
  61        }
  62}
  63
  64static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
  65{
  66        static const struct hif_ie_table_entry filter_ies[] = {
  67                {
  68                        .ie_id        = WLAN_EID_VENDOR_SPECIFIC,
  69                        .has_changed  = 1,
  70                        .no_longer    = 1,
  71                        .has_appeared = 1,
  72                        .oui          = { 0x50, 0x6F, 0x9A },
  73                }, {
  74                        .ie_id        = WLAN_EID_HT_OPERATION,
  75                        .has_changed  = 1,
  76                        .no_longer    = 1,
  77                        .has_appeared = 1,
  78                }, {
  79                        .ie_id        = WLAN_EID_ERP_INFO,
  80                        .has_changed  = 1,
  81                        .no_longer    = 1,
  82                        .has_appeared = 1,
  83                }
  84        };
  85
  86        if (!filter_beacon) {
  87                hif_beacon_filter_control(wvif, 0, 1);
  88        } else {
  89                hif_set_beacon_filter_table(wvif, 3, filter_ies);
  90                hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0);
  91        }
  92}
  93
  94void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
  95                          unsigned int *total_flags, u64 unused)
  96{
  97        struct wfx_vif *wvif = NULL;
  98        struct wfx_dev *wdev = hw->priv;
  99        bool filter_bssid, filter_prbreq, filter_beacon;
 100
 101        // Notes:
 102        //   - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered
 103        //   - PS-Poll (FIF_PSPOLL) are never filtered
 104        //   - RTS, CTS and Ack (FIF_CONTROL) are always filtered
 105        //   - Broken frames (FIF_FCSFAIL and FIF_PLCPFAIL) are always filtered
 106        //   - Firmware does (yet) allow to forward unicast traffic sent to
 107        //     other stations (aka. promiscuous mode)
 108        *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS |
 109                        FIF_PROBE_REQ | FIF_PSPOLL;
 110
 111        mutex_lock(&wdev->conf_mutex);
 112        while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
 113                mutex_lock(&wvif->scan_lock);
 114
 115                // Note: FIF_BCN_PRBRESP_PROMISC covers probe response and
 116                // beacons from other BSS
 117                if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
 118                        filter_beacon = false;
 119                else
 120                        filter_beacon = true;
 121                wfx_filter_beacon(wvif, filter_beacon);
 122
 123                if (*total_flags & FIF_OTHER_BSS)
 124                        filter_bssid = false;
 125                else
 126                        filter_bssid = true;
 127
 128                // In AP mode, chip can reply to probe request itself
 129                if (*total_flags & FIF_PROBE_REQ &&
 130                    wvif->vif->type == NL80211_IFTYPE_AP) {
 131                        dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
 132                        *total_flags &= ~FIF_PROBE_REQ;
 133                }
 134
 135                if (*total_flags & FIF_PROBE_REQ)
 136                        filter_prbreq = false;
 137                else
 138                        filter_prbreq = true;
 139                hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
 140
 141                mutex_unlock(&wvif->scan_lock);
 142        }
 143        mutex_unlock(&wdev->conf_mutex);
 144}
 145
 146static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
 147{
 148        struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
 149        struct ieee80211_conf *conf = &wvif->wdev->hw->conf;
 150
 151        WARN(!wvif->vif->bss_conf.assoc && enable_ps,
 152             "enable_ps is reliable only if associated");
 153        if (wdev_to_wvif(wvif->wdev, 0))
 154                chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan;
 155        if (wdev_to_wvif(wvif->wdev, 1))
 156                chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan;
 157        if (chan0 && chan1 && chan0->hw_value != chan1->hw_value &&
 158            wvif->vif->type != NL80211_IFTYPE_AP) {
 159                // It is necessary to enable powersave if channels
 160                // are different.
 161                if (enable_ps)
 162                        *enable_ps = true;
 163                if (wvif->wdev->force_ps_timeout > -1)
 164                        return wvif->wdev->force_ps_timeout;
 165                else if (wfx_api_older_than(wvif->wdev, 3, 2))
 166                        return 0;
 167                else
 168                        return 30;
 169        }
 170        if (enable_ps)
 171                *enable_ps = wvif->vif->bss_conf.ps;
 172        if (wvif->wdev->force_ps_timeout > -1)
 173                return wvif->wdev->force_ps_timeout;
 174        else if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps)
 175                return conf->dynamic_ps_timeout;
 176        else
 177                return -1;
 178}
 179
 180int wfx_update_pm(struct wfx_vif *wvif)
 181{
 182        int ps_timeout;
 183        bool ps;
 184
 185        if (!wvif->vif->bss_conf.assoc)
 186                return 0;
 187        ps_timeout = wfx_get_ps_timeout(wvif, &ps);
 188        if (!ps)
 189                ps_timeout = 0;
 190        WARN_ON(ps_timeout < 0);
 191        if (wvif->uapsd_mask)
 192                ps_timeout = 0;
 193
 194        if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
 195                                         TU_TO_JIFFIES(512)))
 196                dev_warn(wvif->wdev->dev,
 197                         "timeout while waiting of set_pm_mode_complete\n");
 198        return hif_set_pm(wvif, ps, ps_timeout);
 199}
 200
 201int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 202                u16 queue, const struct ieee80211_tx_queue_params *params)
 203{
 204        struct wfx_dev *wdev = hw->priv;
 205        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 206        int old_uapsd = wvif->uapsd_mask;
 207
 208        WARN_ON(queue >= hw->queues);
 209
 210        mutex_lock(&wdev->conf_mutex);
 211        assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
 212        hif_set_edca_queue_params(wvif, queue, params);
 213        if (wvif->vif->type == NL80211_IFTYPE_STATION &&
 214            old_uapsd != wvif->uapsd_mask) {
 215                hif_set_uapsd_info(wvif, wvif->uapsd_mask);
 216                wfx_update_pm(wvif);
 217        }
 218        mutex_unlock(&wdev->conf_mutex);
 219        return 0;
 220}
 221
 222int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 223{
 224        struct wfx_dev *wdev = hw->priv;
 225        struct wfx_vif *wvif = NULL;
 226
 227        while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
 228                hif_rts_threshold(wvif, value);
 229        return 0;
 230}
 231
 232/* WSM callbacks */
 233
 234void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
 235{
 236        /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
 237         * RSSI = RCPI / 2 - 110
 238         */
 239        int rcpi_rssi;
 240        int cqm_evt;
 241
 242        rcpi_rssi = raw_rcpi_rssi / 2 - 110;
 243        if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold)
 244                cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
 245        else
 246                cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
 247        ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
 248}
 249
 250static void wfx_beacon_loss_work(struct work_struct *work)
 251{
 252        struct wfx_vif *wvif = container_of(to_delayed_work(work),
 253                                            struct wfx_vif, beacon_loss_work);
 254        struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
 255
 256        ieee80211_beacon_loss(wvif->vif);
 257        schedule_delayed_work(to_delayed_work(work),
 258                              msecs_to_jiffies(bss_conf->beacon_int));
 259}
 260
 261void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
 262                                 struct ieee80211_vif *vif, int idx)
 263{
 264        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 265
 266        hif_wep_default_key_id(wvif, idx);
 267}
 268
 269void wfx_reset(struct wfx_vif *wvif)
 270{
 271        struct wfx_dev *wdev = wvif->wdev;
 272
 273        wfx_tx_lock_flush(wdev);
 274        hif_reset(wvif, false);
 275        wfx_tx_policy_init(wvif);
 276        if (wvif_count(wdev) <= 1)
 277                hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
 278        wfx_tx_unlock(wdev);
 279        wvif->join_in_progress = false;
 280        cancel_delayed_work_sync(&wvif->beacon_loss_work);
 281        wvif =  NULL;
 282        while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
 283                wfx_update_pm(wvif);
 284}
 285
 286int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 287                struct ieee80211_sta *sta)
 288{
 289        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 290        struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
 291
 292        sta_priv->vif_id = wvif->id;
 293
 294        if (vif->type == NL80211_IFTYPE_STATION)
 295                hif_set_mfp(wvif, sta->mfp, sta->mfp);
 296
 297        // In station mode, the firmware interprets new link-id as a TDLS peer.
 298        if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
 299                return 0;
 300        sta_priv->link_id = ffz(wvif->link_id_map);
 301        wvif->link_id_map |= BIT(sta_priv->link_id);
 302        WARN_ON(!sta_priv->link_id);
 303        WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX);
 304        hif_map_link(wvif, false, sta->addr, sta_priv->link_id, sta->mfp);
 305
 306        return 0;
 307}
 308
 309int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 310                   struct ieee80211_sta *sta)
 311{
 312        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 313        struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
 314
 315        // See note in wfx_sta_add()
 316        if (!sta_priv->link_id)
 317                return 0;
 318        // FIXME add a mutex?
 319        hif_map_link(wvif, true, sta->addr, sta_priv->link_id, false);
 320        wvif->link_id_map &= ~BIT(sta_priv->link_id);
 321        return 0;
 322}
 323
 324static int wfx_upload_ap_templates(struct wfx_vif *wvif)
 325{
 326        struct sk_buff *skb;
 327
 328        skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
 329        if (!skb)
 330                return -ENOMEM;
 331        hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN,
 332                               API_RATE_INDEX_B_1MBPS);
 333        dev_kfree_skb(skb);
 334
 335        skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
 336        if (!skb)
 337                return -ENOMEM;
 338        hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES,
 339                               API_RATE_INDEX_B_1MBPS);
 340        dev_kfree_skb(skb);
 341        return 0;
 342}
 343
 344static void wfx_set_mfp_ap(struct wfx_vif *wvif)
 345{
 346        struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
 347        const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
 348        const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN,
 349                                                 skb->data + ieoffset,
 350                                                 skb->len - ieoffset);
 351        const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
 352        const int pairwise_cipher_suite_size = 4 / sizeof(u16);
 353        const int akm_suite_size = 4 / sizeof(u16);
 354
 355        if (ptr) {
 356                ptr += pairwise_cipher_suite_count_offset;
 357                if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
 358                        return;
 359                ptr += 1 + pairwise_cipher_suite_size * *ptr;
 360                if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
 361                        return;
 362                ptr += 1 + akm_suite_size * *ptr;
 363                if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
 364                        return;
 365                hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6));
 366        }
 367}
 368
 369int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 370{
 371        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 372        struct wfx_dev *wdev = wvif->wdev;
 373        int ret;
 374
 375        wvif =  NULL;
 376        while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
 377                wfx_update_pm(wvif);
 378        wvif = (struct wfx_vif *)vif->drv_priv;
 379        wfx_upload_ap_templates(wvif);
 380        ret = hif_start(wvif, &vif->bss_conf, wvif->channel);
 381        if (ret > 0)
 382                return -EIO;
 383        wfx_set_mfp_ap(wvif);
 384        return ret;
 385}
 386
 387void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 388{
 389        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 390
 391        wfx_reset(wvif);
 392}
 393
 394static void wfx_join(struct wfx_vif *wvif)
 395{
 396        int ret;
 397        struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
 398        struct cfg80211_bss *bss = NULL;
 399        u8 ssid[IEEE80211_MAX_SSID_LEN];
 400        const u8 *ssidie = NULL;
 401        int ssidlen = 0;
 402
 403        wfx_tx_lock_flush(wvif->wdev);
 404
 405        bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel,
 406                               conf->bssid, NULL, 0,
 407                               IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
 408        if (!bss && !conf->ibss_joined) {
 409                wfx_tx_unlock(wvif->wdev);
 410                return;
 411        }
 412
 413        rcu_read_lock(); // protect ssidie
 414        if (bss)
 415                ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
 416        if (ssidie) {
 417                ssidlen = ssidie[1];
 418                if (ssidlen > IEEE80211_MAX_SSID_LEN)
 419                        ssidlen = IEEE80211_MAX_SSID_LEN;
 420                memcpy(ssid, &ssidie[2], ssidlen);
 421        }
 422        rcu_read_unlock();
 423
 424        cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
 425
 426        wvif->join_in_progress = true;
 427        ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
 428        if (ret) {
 429                ieee80211_connection_loss(wvif->vif);
 430                wfx_reset(wvif);
 431        } else {
 432                /* Due to beacon filtering it is possible that the
 433                 * AP's beacon is not known for the mac80211 stack.
 434                 * Disable filtering temporary to make sure the stack
 435                 * receives at least one
 436                 */
 437                wfx_filter_beacon(wvif, false);
 438        }
 439        wfx_tx_unlock(wvif->wdev);
 440}
 441
 442static void wfx_join_finalize(struct wfx_vif *wvif,
 443                              struct ieee80211_bss_conf *info)
 444{
 445        struct ieee80211_sta *sta = NULL;
 446        int ampdu_density = 0;
 447        bool greenfield = false;
 448
 449        rcu_read_lock(); // protect sta
 450        if (info->bssid && !info->ibss_joined)
 451                sta = ieee80211_find_sta(wvif->vif, info->bssid);
 452        if (sta && sta->ht_cap.ht_supported)
 453                ampdu_density = sta->ht_cap.ampdu_density;
 454        if (sta && sta->ht_cap.ht_supported &&
 455            !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT))
 456                greenfield = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
 457        rcu_read_unlock();
 458
 459        wvif->join_in_progress = false;
 460        hif_set_association_mode(wvif, ampdu_density, greenfield,
 461                                 info->use_short_preamble);
 462        hif_keep_alive_period(wvif, 0);
 463        // beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use
 464        // the same value.
 465        hif_set_bss_params(wvif, info->aid, 7);
 466        hif_set_beacon_wakeup_period(wvif, 1, 1);
 467        wfx_update_pm(wvif);
 468}
 469
 470int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 471{
 472        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 473
 474        wfx_upload_ap_templates(wvif);
 475        wfx_join(wvif);
 476        return 0;
 477}
 478
 479void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 480{
 481        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 482
 483        wfx_reset(wvif);
 484}
 485
 486static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
 487{
 488        // Driver has Content After DTIM Beacon in queue. Driver is waiting for
 489        // a signal from the firmware. Since we are going to stop to send
 490        // beacons, this signal will never happens. See also
 491        // wfx_suspend_resume_mc()
 492        if (!enable && wfx_tx_queues_has_cab(wvif)) {
 493                wvif->after_dtim_tx_allowed = true;
 494                wfx_bh_request_tx(wvif->wdev);
 495        }
 496        hif_beacon_transmit(wvif, enable);
 497}
 498
 499void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 500                          struct ieee80211_bss_conf *info, u32 changed)
 501{
 502        struct wfx_dev *wdev = hw->priv;
 503        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 504        int i;
 505
 506        mutex_lock(&wdev->conf_mutex);
 507
 508        if (changed & BSS_CHANGED_BASIC_RATES ||
 509            changed & BSS_CHANGED_BEACON_INT ||
 510            changed & BSS_CHANGED_BSSID) {
 511                if (vif->type == NL80211_IFTYPE_STATION)
 512                        wfx_join(wvif);
 513        }
 514
 515        if (changed & BSS_CHANGED_ASSOC) {
 516                if (info->assoc || info->ibss_joined)
 517                        wfx_join_finalize(wvif, info);
 518                else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION)
 519                        wfx_reset(wvif);
 520                else
 521                        dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n",
 522                                 __func__);
 523        }
 524
 525        if (changed & BSS_CHANGED_BEACON_INFO) {
 526                if (vif->type != NL80211_IFTYPE_STATION)
 527                        dev_warn(wdev->dev, "%s: misunderstood change: BEACON_INFO\n",
 528                                 __func__);
 529                hif_set_beacon_wakeup_period(wvif, info->dtim_period,
 530                                             info->dtim_period);
 531                // We temporary forwarded beacon for join process. It is now no
 532                // more necessary.
 533                wfx_filter_beacon(wvif, true);
 534        }
 535
 536        if (changed & BSS_CHANGED_ARP_FILTER) {
 537                for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
 538                        __be32 *arp_addr = &info->arp_addr_list[i];
 539
 540                        if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
 541                                arp_addr = NULL;
 542                        if (i >= info->arp_addr_cnt)
 543                                arp_addr = NULL;
 544                        hif_set_arp_ipv4_filter(wvif, i, arp_addr);
 545                }
 546        }
 547
 548        if (changed & BSS_CHANGED_AP_PROBE_RESP ||
 549            changed & BSS_CHANGED_BEACON)
 550                wfx_upload_ap_templates(wvif);
 551
 552        if (changed & BSS_CHANGED_BEACON_ENABLED)
 553                wfx_enable_beacon(wvif, info->enable_beacon);
 554
 555        if (changed & BSS_CHANGED_KEEP_ALIVE)
 556                hif_keep_alive_period(wvif, info->max_idle_period *
 557                                            USEC_PER_TU / USEC_PER_MSEC);
 558
 559        if (changed & BSS_CHANGED_ERP_CTS_PROT)
 560                hif_erp_use_protection(wvif, info->use_cts_prot);
 561
 562        if (changed & BSS_CHANGED_ERP_SLOT)
 563                hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
 564
 565        if (changed & BSS_CHANGED_CQM)
 566                hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold,
 567                                            info->cqm_rssi_hyst);
 568
 569        if (changed & BSS_CHANGED_TXPOWER)
 570                hif_set_output_power(wvif, info->txpower);
 571
 572        if (changed & BSS_CHANGED_PS)
 573                wfx_update_pm(wvif);
 574
 575        mutex_unlock(&wdev->conf_mutex);
 576}
 577
 578static int wfx_update_tim(struct wfx_vif *wvif)
 579{
 580        struct sk_buff *skb;
 581        u16 tim_offset, tim_length;
 582        u8 *tim_ptr;
 583
 584        skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
 585                                       &tim_offset, &tim_length);
 586        if (!skb)
 587                return -ENOENT;
 588        tim_ptr = skb->data + tim_offset;
 589
 590        if (tim_offset && tim_length >= 6) {
 591                /* Ignore DTIM count from mac80211:
 592                 * firmware handles DTIM internally.
 593                 */
 594                tim_ptr[2] = 0;
 595
 596                /* Set/reset aid0 bit */
 597                if (wfx_tx_queues_has_cab(wvif))
 598                        tim_ptr[4] |= 1;
 599                else
 600                        tim_ptr[4] &= ~1;
 601        }
 602
 603        hif_update_ie_beacon(wvif, tim_ptr, tim_length);
 604        dev_kfree_skb(skb);
 605
 606        return 0;
 607}
 608
 609static void wfx_update_tim_work(struct work_struct *work)
 610{
 611        struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
 612
 613        wfx_update_tim(wvif);
 614}
 615
 616int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
 617{
 618        struct wfx_dev *wdev = hw->priv;
 619        struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv;
 620        struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
 621
 622        if (!wvif) {
 623                dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__);
 624                return -EIO;
 625        }
 626        schedule_work(&wvif->update_tim_work);
 627        return 0;
 628}
 629
 630void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
 631{
 632        if (notify_cmd != STA_NOTIFY_AWAKE)
 633                return;
 634        WARN(!wfx_tx_queues_has_cab(wvif), "incorrect sequence");
 635        WARN(wvif->after_dtim_tx_allowed, "incorrect sequence");
 636        wvif->after_dtim_tx_allowed = true;
 637        wfx_bh_request_tx(wvif->wdev);
 638}
 639
 640int wfx_ampdu_action(struct ieee80211_hw *hw,
 641                     struct ieee80211_vif *vif,
 642                     struct ieee80211_ampdu_params *params)
 643{
 644        // Aggregation is implemented fully in firmware
 645        switch (params->action) {
 646        case IEEE80211_AMPDU_RX_START:
 647        case IEEE80211_AMPDU_RX_STOP:
 648                // Just acknowledge it to enable frame re-ordering
 649                return 0;
 650        default:
 651                // Leave the firmware doing its business for tx aggregation
 652                return -ENOTSUPP;
 653        }
 654}
 655
 656int wfx_add_chanctx(struct ieee80211_hw *hw,
 657                    struct ieee80211_chanctx_conf *conf)
 658{
 659        return 0;
 660}
 661
 662void wfx_remove_chanctx(struct ieee80211_hw *hw,
 663                        struct ieee80211_chanctx_conf *conf)
 664{
 665}
 666
 667void wfx_change_chanctx(struct ieee80211_hw *hw,
 668                        struct ieee80211_chanctx_conf *conf,
 669                        u32 changed)
 670{
 671}
 672
 673int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 674                           struct ieee80211_chanctx_conf *conf)
 675{
 676        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 677        struct ieee80211_channel *ch = conf->def.chan;
 678
 679        WARN(wvif->channel, "channel overwrite");
 680        wvif->channel = ch;
 681
 682        return 0;
 683}
 684
 685void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
 686                              struct ieee80211_vif *vif,
 687                              struct ieee80211_chanctx_conf *conf)
 688{
 689        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 690        struct ieee80211_channel *ch = conf->def.chan;
 691
 692        WARN(wvif->channel != ch, "channel mismatch");
 693        wvif->channel = NULL;
 694}
 695
 696int wfx_config(struct ieee80211_hw *hw, u32 changed)
 697{
 698        return 0;
 699}
 700
 701int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 702{
 703        int i, ret = 0;
 704        struct wfx_dev *wdev = hw->priv;
 705        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 706
 707        vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
 708                             IEEE80211_VIF_SUPPORTS_UAPSD |
 709                             IEEE80211_VIF_SUPPORTS_CQM_RSSI;
 710
 711        mutex_lock(&wdev->conf_mutex);
 712
 713        switch (vif->type) {
 714        case NL80211_IFTYPE_STATION:
 715        case NL80211_IFTYPE_ADHOC:
 716        case NL80211_IFTYPE_AP:
 717                break;
 718        default:
 719                mutex_unlock(&wdev->conf_mutex);
 720                return -EOPNOTSUPP;
 721        }
 722
 723        // FIXME: prefer use of container_of() to get vif
 724        wvif->vif = vif;
 725        wvif->wdev = wdev;
 726
 727        wvif->link_id_map = 1; // link-id 0 is reserved for multicast
 728        INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
 729        INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
 730
 731        init_completion(&wvif->set_pm_mode_complete);
 732        complete(&wvif->set_pm_mode_complete);
 733        INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
 734
 735        mutex_init(&wvif->scan_lock);
 736        init_completion(&wvif->scan_complete);
 737        INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
 738
 739        wfx_tx_queues_init(wvif);
 740        wfx_tx_policy_init(wvif);
 741
 742        for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
 743                if (!wdev->vif[i]) {
 744                        wdev->vif[i] = vif;
 745                        wvif->id = i;
 746                        break;
 747                }
 748        }
 749        WARN(i == ARRAY_SIZE(wdev->vif), "try to instantiate more vif than supported");
 750
 751        hif_set_macaddr(wvif, vif->addr);
 752
 753        mutex_unlock(&wdev->conf_mutex);
 754
 755        wvif = NULL;
 756        while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
 757                // Combo mode does not support Block Acks. We can re-enable them
 758                if (wvif_count(wdev) == 1)
 759                        hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
 760                else
 761                        hif_set_block_ack_policy(wvif, 0x00, 0x00);
 762        }
 763        return ret;
 764}
 765
 766void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 767{
 768        struct wfx_dev *wdev = hw->priv;
 769        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 770
 771        wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
 772        wfx_tx_queues_check_empty(wvif);
 773
 774        mutex_lock(&wdev->conf_mutex);
 775        WARN(wvif->link_id_map != 1, "corrupted state");
 776
 777        hif_reset(wvif, false);
 778        hif_set_macaddr(wvif, NULL);
 779        wfx_tx_policy_init(wvif);
 780
 781        cancel_delayed_work_sync(&wvif->beacon_loss_work);
 782        wdev->vif[wvif->id] = NULL;
 783        wvif->vif = NULL;
 784
 785        mutex_unlock(&wdev->conf_mutex);
 786
 787        wvif = NULL;
 788        while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
 789                // Combo mode does not support Block Acks. We can re-enable them
 790                if (wvif_count(wdev) == 1)
 791                        hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
 792                else
 793                        hif_set_block_ack_policy(wvif, 0x00, 0x00);
 794        }
 795}
 796
 797int wfx_start(struct ieee80211_hw *hw)
 798{
 799        return 0;
 800}
 801
 802void wfx_stop(struct ieee80211_hw *hw)
 803{
 804        struct wfx_dev *wdev = hw->priv;
 805
 806        WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending));
 807}
 808