linux/drivers/net/wireless/ath/wil6210/cfg80211.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include <linux/etherdevice.h>
  18#include <linux/moduleparam.h>
  19#include <net/netlink.h>
  20#include "wil6210.h"
  21#include "wmi.h"
  22
  23#define WIL_MAX_ROC_DURATION_MS 5000
  24
  25bool disable_ap_sme;
  26module_param(disable_ap_sme, bool, 0444);
  27MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME");
  28
  29#ifdef CONFIG_PM
  30static struct wiphy_wowlan_support wil_wowlan_support = {
  31        .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
  32};
  33#endif
  34
  35#define CHAN60G(_channel, _flags) {                             \
  36        .band                   = NL80211_BAND_60GHZ,           \
  37        .center_freq            = 56160 + (2160 * (_channel)),  \
  38        .hw_value               = (_channel),                   \
  39        .flags                  = (_flags),                     \
  40        .max_antenna_gain       = 0,                            \
  41        .max_power              = 40,                           \
  42}
  43
  44static struct ieee80211_channel wil_60ghz_channels[] = {
  45        CHAN60G(1, 0),
  46        CHAN60G(2, 0),
  47        CHAN60G(3, 0),
  48/* channel 4 not supported yet */
  49};
  50
  51/* Vendor id to be used in vendor specific command and events
  52 * to user space.
  53 * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID,
  54 * vendor subcmd definitions prefixed with QCA_NL80211_VENDOR_SUBCMD, and
  55 * qca_wlan_vendor_attr is open source file src/common/qca-vendor.h in
  56 * git://w1.fi/srv/git/hostap.git; the values here are just a copy of that
  57 */
  58
  59#define QCA_NL80211_VENDOR_ID   0x001374
  60
  61#define WIL_MAX_RF_SECTORS (128)
  62#define WIL_CID_ALL (0xff)
  63
  64enum qca_wlan_vendor_attr_rf_sector {
  65        QCA_ATTR_MAC_ADDR = 6,
  66        QCA_ATTR_PAD = 13,
  67        QCA_ATTR_TSF = 29,
  68        QCA_ATTR_DMG_RF_SECTOR_INDEX = 30,
  69        QCA_ATTR_DMG_RF_SECTOR_TYPE = 31,
  70        QCA_ATTR_DMG_RF_MODULE_MASK = 32,
  71        QCA_ATTR_DMG_RF_SECTOR_CFG = 33,
  72        QCA_ATTR_DMG_RF_SECTOR_MAX,
  73};
  74
  75enum qca_wlan_vendor_attr_dmg_rf_sector_type {
  76        QCA_ATTR_DMG_RF_SECTOR_TYPE_RX,
  77        QCA_ATTR_DMG_RF_SECTOR_TYPE_TX,
  78        QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX
  79};
  80
  81enum qca_wlan_vendor_attr_dmg_rf_sector_cfg {
  82        QCA_ATTR_DMG_RF_SECTOR_CFG_INVALID = 0,
  83        QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
  84        QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
  85        QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
  86        QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
  87        QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
  88        QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
  89        QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
  90
  91        /* keep last */
  92        QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST,
  93        QCA_ATTR_DMG_RF_SECTOR_CFG_MAX =
  94        QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1
  95};
  96
  97static const struct
  98nla_policy wil_rf_sector_policy[QCA_ATTR_DMG_RF_SECTOR_MAX + 1] = {
  99        [QCA_ATTR_MAC_ADDR] = { .len = ETH_ALEN },
 100        [QCA_ATTR_DMG_RF_SECTOR_INDEX] = { .type = NLA_U16 },
 101        [QCA_ATTR_DMG_RF_SECTOR_TYPE] = { .type = NLA_U8 },
 102        [QCA_ATTR_DMG_RF_MODULE_MASK] = { .type = NLA_U32 },
 103        [QCA_ATTR_DMG_RF_SECTOR_CFG] = { .type = NLA_NESTED },
 104};
 105
 106static const struct
 107nla_policy wil_rf_sector_cfg_policy[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1] = {
 108        [QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] = { .type = NLA_U8 },
 109        [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] = { .type = NLA_U32 },
 110        [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] = { .type = NLA_U32 },
 111        [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] = { .type = NLA_U32 },
 112        [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] = { .type = NLA_U32 },
 113        [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] = { .type = NLA_U32 },
 114        [QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16] = { .type = NLA_U32 },
 115};
 116
 117enum qca_nl80211_vendor_subcmds {
 118        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG = 139,
 119        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140,
 120        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141,
 121        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142,
 122};
 123
 124static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
 125                                 struct wireless_dev *wdev,
 126                                 const void *data, int data_len);
 127static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
 128                                 struct wireless_dev *wdev,
 129                                 const void *data, int data_len);
 130static int wil_rf_sector_get_selected(struct wiphy *wiphy,
 131                                      struct wireless_dev *wdev,
 132                                      const void *data, int data_len);
 133static int wil_rf_sector_set_selected(struct wiphy *wiphy,
 134                                      struct wireless_dev *wdev,
 135                                      const void *data, int data_len);
 136
 137/* vendor specific commands */
 138static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
 139        {
 140                .info.vendor_id = QCA_NL80211_VENDOR_ID,
 141                .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
 142                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
 143                         WIPHY_VENDOR_CMD_NEED_RUNNING,
 144                .doit = wil_rf_sector_get_cfg
 145        },
 146        {
 147                .info.vendor_id = QCA_NL80211_VENDOR_ID,
 148                .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
 149                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
 150                         WIPHY_VENDOR_CMD_NEED_RUNNING,
 151                .doit = wil_rf_sector_set_cfg
 152        },
 153        {
 154                .info.vendor_id = QCA_NL80211_VENDOR_ID,
 155                .info.subcmd =
 156                        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
 157                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
 158                         WIPHY_VENDOR_CMD_NEED_RUNNING,
 159                .doit = wil_rf_sector_get_selected
 160        },
 161        {
 162                .info.vendor_id = QCA_NL80211_VENDOR_ID,
 163                .info.subcmd =
 164                        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
 165                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
 166                         WIPHY_VENDOR_CMD_NEED_RUNNING,
 167                .doit = wil_rf_sector_set_selected
 168        },
 169};
 170
 171static struct ieee80211_supported_band wil_band_60ghz = {
 172        .channels = wil_60ghz_channels,
 173        .n_channels = ARRAY_SIZE(wil_60ghz_channels),
 174        .ht_cap = {
 175                .ht_supported = true,
 176                .cap = 0, /* TODO */
 177                .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */
 178                .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */
 179                .mcs = {
 180                                /* MCS 1..12 - SC PHY */
 181                        .rx_mask = {0xfe, 0x1f}, /* 1..12 */
 182                        .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */
 183                },
 184        },
 185};
 186
 187static const struct ieee80211_txrx_stypes
 188wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 189        [NL80211_IFTYPE_STATION] = {
 190                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 191                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
 192                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 193                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
 194        },
 195        [NL80211_IFTYPE_AP] = {
 196                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 197                BIT(IEEE80211_STYPE_PROBE_RESP >> 4) |
 198                BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) |
 199                BIT(IEEE80211_STYPE_DISASSOC >> 4),
 200                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 201                BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
 202                BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
 203                BIT(IEEE80211_STYPE_DISASSOC >> 4) |
 204                BIT(IEEE80211_STYPE_AUTH >> 4) |
 205                BIT(IEEE80211_STYPE_DEAUTH >> 4) |
 206                BIT(IEEE80211_STYPE_REASSOC_REQ >> 4)
 207        },
 208        [NL80211_IFTYPE_P2P_CLIENT] = {
 209                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 210                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
 211                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 212                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
 213        },
 214        [NL80211_IFTYPE_P2P_GO] = {
 215                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 216                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
 217                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 218                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
 219        },
 220        [NL80211_IFTYPE_P2P_DEVICE] = {
 221                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 222                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
 223                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 224                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
 225        },
 226};
 227
 228static const u32 wil_cipher_suites[] = {
 229        WLAN_CIPHER_SUITE_GCMP,
 230};
 231
 232static const char * const key_usage_str[] = {
 233        [WMI_KEY_USE_PAIRWISE]  = "PTK",
 234        [WMI_KEY_USE_RX_GROUP]  = "RX_GTK",
 235        [WMI_KEY_USE_TX_GROUP]  = "TX_GTK",
 236};
 237
 238int wil_iftype_nl2wmi(enum nl80211_iftype type)
 239{
 240        static const struct {
 241                enum nl80211_iftype nl;
 242                enum wmi_network_type wmi;
 243        } __nl2wmi[] = {
 244                {NL80211_IFTYPE_ADHOC,          WMI_NETTYPE_ADHOC},
 245                {NL80211_IFTYPE_STATION,        WMI_NETTYPE_INFRA},
 246                {NL80211_IFTYPE_AP,             WMI_NETTYPE_AP},
 247                {NL80211_IFTYPE_P2P_CLIENT,     WMI_NETTYPE_P2P},
 248                {NL80211_IFTYPE_P2P_GO,         WMI_NETTYPE_P2P},
 249                {NL80211_IFTYPE_MONITOR,        WMI_NETTYPE_ADHOC}, /* FIXME */
 250        };
 251        uint i;
 252
 253        for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) {
 254                if (__nl2wmi[i].nl == type)
 255                        return __nl2wmi[i].wmi;
 256        }
 257
 258        return -EOPNOTSUPP;
 259}
 260
 261int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
 262                       struct station_info *sinfo)
 263{
 264        struct wmi_notify_req_cmd cmd = {
 265                .cid = cid,
 266                .interval_usec = 0,
 267        };
 268        struct {
 269                struct wmi_cmd_hdr wmi;
 270                struct wmi_notify_req_done_event evt;
 271        } __packed reply;
 272        struct wil_net_stats *stats = &wil->sta[cid].stats;
 273        int rc;
 274
 275        rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
 276                      WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20);
 277        if (rc)
 278                return rc;
 279
 280        wil_dbg_wmi(wil, "Link status for CID %d: {\n"
 281                    "  MCS %d TSF 0x%016llx\n"
 282                    "  BF status 0x%08x RSSI %d SQI %d%%\n"
 283                    "  Tx Tpt %d goodput %d Rx goodput %d\n"
 284                    "  Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
 285                    cid, le16_to_cpu(reply.evt.bf_mcs),
 286                    le64_to_cpu(reply.evt.tsf), reply.evt.status,
 287                    reply.evt.rssi,
 288                    reply.evt.sqi,
 289                    le32_to_cpu(reply.evt.tx_tpt),
 290                    le32_to_cpu(reply.evt.tx_goodput),
 291                    le32_to_cpu(reply.evt.rx_goodput),
 292                    le16_to_cpu(reply.evt.my_rx_sector),
 293                    le16_to_cpu(reply.evt.my_tx_sector),
 294                    le16_to_cpu(reply.evt.other_rx_sector),
 295                    le16_to_cpu(reply.evt.other_tx_sector));
 296
 297        sinfo->generation = wil->sinfo_gen;
 298
 299        sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) |
 300                        BIT(NL80211_STA_INFO_TX_BYTES) |
 301                        BIT(NL80211_STA_INFO_RX_PACKETS) |
 302                        BIT(NL80211_STA_INFO_TX_PACKETS) |
 303                        BIT(NL80211_STA_INFO_RX_BITRATE) |
 304                        BIT(NL80211_STA_INFO_TX_BITRATE) |
 305                        BIT(NL80211_STA_INFO_RX_DROP_MISC) |
 306                        BIT(NL80211_STA_INFO_TX_FAILED);
 307
 308        sinfo->txrate.flags = RATE_INFO_FLAGS_60G;
 309        sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
 310        sinfo->rxrate.mcs = stats->last_mcs_rx;
 311        sinfo->rx_bytes = stats->rx_bytes;
 312        sinfo->rx_packets = stats->rx_packets;
 313        sinfo->rx_dropped_misc = stats->rx_dropped;
 314        sinfo->tx_bytes = stats->tx_bytes;
 315        sinfo->tx_packets = stats->tx_packets;
 316        sinfo->tx_failed = stats->tx_errors;
 317
 318        if (test_bit(wil_status_fwconnected, wil->status)) {
 319                sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
 320                if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING,
 321                             wil->fw_capabilities))
 322                        sinfo->signal = reply.evt.rssi;
 323                else
 324                        sinfo->signal = reply.evt.sqi;
 325        }
 326
 327        return rc;
 328}
 329
 330static int wil_cfg80211_get_station(struct wiphy *wiphy,
 331                                    struct net_device *ndev,
 332                                    const u8 *mac, struct station_info *sinfo)
 333{
 334        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 335        int rc;
 336
 337        int cid = wil_find_cid(wil, mac);
 338
 339        wil_dbg_misc(wil, "get_station: %pM CID %d\n", mac, cid);
 340        if (cid < 0)
 341                return cid;
 342
 343        rc = wil_cid_fill_sinfo(wil, cid, sinfo);
 344
 345        return rc;
 346}
 347
 348/*
 349 * Find @idx-th active STA for station dump.
 350 */
 351static int wil_find_cid_by_idx(struct wil6210_priv *wil, int idx)
 352{
 353        int i;
 354
 355        for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
 356                if (wil->sta[i].status == wil_sta_unused)
 357                        continue;
 358                if (idx == 0)
 359                        return i;
 360                idx--;
 361        }
 362
 363        return -ENOENT;
 364}
 365
 366static int wil_cfg80211_dump_station(struct wiphy *wiphy,
 367                                     struct net_device *dev, int idx,
 368                                     u8 *mac, struct station_info *sinfo)
 369{
 370        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 371        int rc;
 372        int cid = wil_find_cid_by_idx(wil, idx);
 373
 374        if (cid < 0)
 375                return -ENOENT;
 376
 377        ether_addr_copy(mac, wil->sta[cid].addr);
 378        wil_dbg_misc(wil, "dump_station: %pM CID %d\n", mac, cid);
 379
 380        rc = wil_cid_fill_sinfo(wil, cid, sinfo);
 381
 382        return rc;
 383}
 384
 385static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
 386                                         struct wireless_dev *wdev)
 387{
 388        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 389
 390        wil_dbg_misc(wil, "start_p2p_device: entered\n");
 391        wil->p2p.p2p_dev_started = 1;
 392        return 0;
 393}
 394
 395static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
 396                                         struct wireless_dev *wdev)
 397{
 398        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 399        struct wil_p2p_info *p2p = &wil->p2p;
 400
 401        if (!p2p->p2p_dev_started)
 402                return;
 403
 404        wil_dbg_misc(wil, "stop_p2p_device: entered\n");
 405        mutex_lock(&wil->mutex);
 406        mutex_lock(&wil->p2p_wdev_mutex);
 407        wil_p2p_stop_radio_operations(wil);
 408        p2p->p2p_dev_started = 0;
 409        mutex_unlock(&wil->p2p_wdev_mutex);
 410        mutex_unlock(&wil->mutex);
 411}
 412
 413static struct wireless_dev *
 414wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name,
 415                       unsigned char name_assign_type,
 416                       enum nl80211_iftype type,
 417                       struct vif_params *params)
 418{
 419        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 420        struct net_device *ndev = wil_to_ndev(wil);
 421        struct wireless_dev *p2p_wdev;
 422
 423        wil_dbg_misc(wil, "add_iface\n");
 424
 425        if (type != NL80211_IFTYPE_P2P_DEVICE) {
 426                wil_err(wil, "unsupported iftype %d\n", type);
 427                return ERR_PTR(-EINVAL);
 428        }
 429
 430        if (wil->p2p_wdev) {
 431                wil_err(wil, "P2P_DEVICE interface already created\n");
 432                return ERR_PTR(-EINVAL);
 433        }
 434
 435        p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL);
 436        if (!p2p_wdev)
 437                return ERR_PTR(-ENOMEM);
 438
 439        p2p_wdev->iftype = type;
 440        p2p_wdev->wiphy = wiphy;
 441        /* use our primary ethernet address */
 442        ether_addr_copy(p2p_wdev->address, ndev->perm_addr);
 443
 444        wil->p2p_wdev = p2p_wdev;
 445
 446        return p2p_wdev;
 447}
 448
 449static int wil_cfg80211_del_iface(struct wiphy *wiphy,
 450                                  struct wireless_dev *wdev)
 451{
 452        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 453
 454        wil_dbg_misc(wil, "del_iface\n");
 455
 456        if (wdev != wil->p2p_wdev) {
 457                wil_err(wil, "delete of incorrect interface 0x%p\n", wdev);
 458                return -EINVAL;
 459        }
 460
 461        wil_cfg80211_stop_p2p_device(wiphy, wdev);
 462        wil_p2p_wdev_free(wil);
 463
 464        return 0;
 465}
 466
 467static int wil_cfg80211_change_iface(struct wiphy *wiphy,
 468                                     struct net_device *ndev,
 469                                     enum nl80211_iftype type,
 470                                     struct vif_params *params)
 471{
 472        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 473        struct wireless_dev *wdev = wil_to_wdev(wil);
 474        int rc;
 475
 476        wil_dbg_misc(wil, "change_iface: type=%d\n", type);
 477
 478        if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) {
 479                wil_dbg_misc(wil, "interface is up. resetting...\n");
 480                mutex_lock(&wil->mutex);
 481                __wil_down(wil);
 482                rc = __wil_up(wil);
 483                mutex_unlock(&wil->mutex);
 484
 485                if (rc)
 486                        return rc;
 487        }
 488
 489        switch (type) {
 490        case NL80211_IFTYPE_STATION:
 491        case NL80211_IFTYPE_AP:
 492        case NL80211_IFTYPE_P2P_CLIENT:
 493        case NL80211_IFTYPE_P2P_GO:
 494                break;
 495        case NL80211_IFTYPE_MONITOR:
 496                if (params->flags)
 497                        wil->monitor_flags = params->flags;
 498                break;
 499        default:
 500                return -EOPNOTSUPP;
 501        }
 502
 503        wdev->iftype = type;
 504
 505        return 0;
 506}
 507
 508static int wil_cfg80211_scan(struct wiphy *wiphy,
 509                             struct cfg80211_scan_request *request)
 510{
 511        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 512        struct wireless_dev *wdev = request->wdev;
 513        struct {
 514                struct wmi_start_scan_cmd cmd;
 515                u16 chnl[4];
 516        } __packed cmd;
 517        uint i, n;
 518        int rc;
 519
 520        wil_dbg_misc(wil, "scan: wdev=0x%p iftype=%d\n", wdev, wdev->iftype);
 521
 522        /* check we are client side */
 523        switch (wdev->iftype) {
 524        case NL80211_IFTYPE_STATION:
 525        case NL80211_IFTYPE_P2P_CLIENT:
 526        case NL80211_IFTYPE_P2P_DEVICE:
 527                break;
 528        default:
 529                return -EOPNOTSUPP;
 530        }
 531
 532        /* FW don't support scan after connection attempt */
 533        if (test_bit(wil_status_dontscan, wil->status)) {
 534                wil_err(wil, "Can't scan now\n");
 535                return -EBUSY;
 536        }
 537
 538        mutex_lock(&wil->mutex);
 539
 540        mutex_lock(&wil->p2p_wdev_mutex);
 541        if (wil->scan_request || wil->p2p.discovery_started) {
 542                wil_err(wil, "Already scanning\n");
 543                mutex_unlock(&wil->p2p_wdev_mutex);
 544                rc = -EAGAIN;
 545                goto out;
 546        }
 547        mutex_unlock(&wil->p2p_wdev_mutex);
 548
 549        if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
 550                if (!wil->p2p.p2p_dev_started) {
 551                        wil_err(wil, "P2P search requested on stopped P2P device\n");
 552                        rc = -EIO;
 553                        goto out;
 554                }
 555                /* social scan on P2P_DEVICE is handled as p2p search */
 556                if (wil_p2p_is_social_scan(request)) {
 557                        wil->scan_request = request;
 558                        wil->radio_wdev = wdev;
 559                        rc = wil_p2p_search(wil, request);
 560                        if (rc) {
 561                                wil->radio_wdev = wil_to_wdev(wil);
 562                                wil->scan_request = NULL;
 563                        }
 564                        goto out;
 565                }
 566        }
 567
 568        (void)wil_p2p_stop_discovery(wil);
 569
 570        wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
 571        wil_dbg_misc(wil, "SSID count: %d", request->n_ssids);
 572
 573        for (i = 0; i < request->n_ssids; i++) {
 574                wil_dbg_misc(wil, "SSID[%d]", i);
 575                wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
 576                                  request->ssids[i].ssid,
 577                                  request->ssids[i].ssid_len, true);
 578        }
 579
 580        if (request->n_ssids)
 581                rc = wmi_set_ssid(wil, request->ssids[0].ssid_len,
 582                                  request->ssids[0].ssid);
 583        else
 584                rc = wmi_set_ssid(wil, 0, NULL);
 585
 586        if (rc) {
 587                wil_err(wil, "set SSID for scan request failed: %d\n", rc);
 588                goto out;
 589        }
 590
 591        wil->scan_request = request;
 592        mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
 593
 594        memset(&cmd, 0, sizeof(cmd));
 595        cmd.cmd.scan_type = WMI_ACTIVE_SCAN;
 596        cmd.cmd.num_channels = 0;
 597        n = min(request->n_channels, 4U);
 598        for (i = 0; i < n; i++) {
 599                int ch = request->channels[i]->hw_value;
 600
 601                if (ch == 0) {
 602                        wil_err(wil,
 603                                "Scan requested for unknown frequency %dMhz\n",
 604                                request->channels[i]->center_freq);
 605                        continue;
 606                }
 607                /* 0-based channel indexes */
 608                cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
 609                wil_dbg_misc(wil, "Scan for ch %d  : %d MHz\n", ch,
 610                             request->channels[i]->center_freq);
 611        }
 612
 613        if (request->ie_len)
 614                wil_hex_dump_misc("Scan IE ", DUMP_PREFIX_OFFSET, 16, 1,
 615                                  request->ie, request->ie_len, true);
 616        else
 617                wil_dbg_misc(wil, "Scan has no IE's\n");
 618
 619        rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie);
 620        if (rc)
 621                goto out_restore;
 622
 623        if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {
 624                cmd.cmd.discovery_mode = 1;
 625                wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
 626        }
 627
 628        wil->radio_wdev = wdev;
 629        rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
 630                        cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
 631
 632out_restore:
 633        if (rc) {
 634                del_timer_sync(&wil->scan_timer);
 635                wil->radio_wdev = wil_to_wdev(wil);
 636                wil->scan_request = NULL;
 637        }
 638out:
 639        mutex_unlock(&wil->mutex);
 640        return rc;
 641}
 642
 643static void wil_cfg80211_abort_scan(struct wiphy *wiphy,
 644                                    struct wireless_dev *wdev)
 645{
 646        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 647
 648        wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype);
 649
 650        mutex_lock(&wil->mutex);
 651        mutex_lock(&wil->p2p_wdev_mutex);
 652
 653        if (!wil->scan_request)
 654                goto out;
 655
 656        if (wdev != wil->scan_request->wdev) {
 657                wil_dbg_misc(wil, "abort scan was called on the wrong iface\n");
 658                goto out;
 659        }
 660
 661        if (wil->radio_wdev == wil->p2p_wdev)
 662                wil_p2p_stop_radio_operations(wil);
 663        else
 664                wil_abort_scan(wil, true);
 665
 666out:
 667        mutex_unlock(&wil->p2p_wdev_mutex);
 668        mutex_unlock(&wil->mutex);
 669}
 670
 671static void wil_print_crypto(struct wil6210_priv *wil,
 672                             struct cfg80211_crypto_settings *c)
 673{
 674        int i, n;
 675
 676        wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n",
 677                     c->wpa_versions, c->cipher_group);
 678        wil_dbg_misc(wil, "Pairwise ciphers [%d] {\n", c->n_ciphers_pairwise);
 679        n = min_t(int, c->n_ciphers_pairwise, ARRAY_SIZE(c->ciphers_pairwise));
 680        for (i = 0; i < n; i++)
 681                wil_dbg_misc(wil, "  [%d] = 0x%08x\n", i,
 682                             c->ciphers_pairwise[i]);
 683        wil_dbg_misc(wil, "}\n");
 684        wil_dbg_misc(wil, "AKM suites [%d] {\n", c->n_akm_suites);
 685        n = min_t(int, c->n_akm_suites, ARRAY_SIZE(c->akm_suites));
 686        for (i = 0; i < n; i++)
 687                wil_dbg_misc(wil, "  [%d] = 0x%08x\n", i,
 688                             c->akm_suites[i]);
 689        wil_dbg_misc(wil, "}\n");
 690        wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n",
 691                     c->control_port, be16_to_cpu(c->control_port_ethertype),
 692                     c->control_port_no_encrypt);
 693}
 694
 695static void wil_print_connect_params(struct wil6210_priv *wil,
 696                                     struct cfg80211_connect_params *sme)
 697{
 698        wil_info(wil, "Connecting to:\n");
 699        if (sme->channel) {
 700                wil_info(wil, "  Channel: %d freq %d\n",
 701                         sme->channel->hw_value, sme->channel->center_freq);
 702        }
 703        if (sme->bssid)
 704                wil_info(wil, "  BSSID: %pM\n", sme->bssid);
 705        if (sme->ssid)
 706                print_hex_dump(KERN_INFO, "  SSID: ", DUMP_PREFIX_OFFSET,
 707                               16, 1, sme->ssid, sme->ssid_len, true);
 708        wil_info(wil, "  Privacy: %s\n", sme->privacy ? "secure" : "open");
 709        wil_info(wil, "  PBSS: %d\n", sme->pbss);
 710        wil_print_crypto(wil, &sme->crypto);
 711}
 712
 713static int wil_cfg80211_connect(struct wiphy *wiphy,
 714                                struct net_device *ndev,
 715                                struct cfg80211_connect_params *sme)
 716{
 717        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 718        struct cfg80211_bss *bss;
 719        struct wmi_connect_cmd conn;
 720        const u8 *ssid_eid;
 721        const u8 *rsn_eid;
 722        int ch;
 723        int rc = 0;
 724        enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS;
 725
 726        wil_dbg_misc(wil, "connect\n");
 727        wil_print_connect_params(wil, sme);
 728
 729        if (test_bit(wil_status_fwconnecting, wil->status) ||
 730            test_bit(wil_status_fwconnected, wil->status))
 731                return -EALREADY;
 732
 733        if (sme->ie_len > WMI_MAX_IE_LEN) {
 734                wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len);
 735                return -ERANGE;
 736        }
 737
 738        rsn_eid = sme->ie ?
 739                        cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
 740                        NULL;
 741        if (sme->privacy && !rsn_eid)
 742                wil_info(wil, "WSC connection\n");
 743
 744        if (sme->pbss)
 745                bss_type = IEEE80211_BSS_TYPE_PBSS;
 746
 747        bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
 748                               sme->ssid, sme->ssid_len,
 749                               bss_type, IEEE80211_PRIVACY_ANY);
 750        if (!bss) {
 751                wil_err(wil, "Unable to find BSS\n");
 752                return -ENOENT;
 753        }
 754
 755        ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
 756        if (!ssid_eid) {
 757                wil_err(wil, "No SSID\n");
 758                rc = -ENOENT;
 759                goto out;
 760        }
 761        wil->privacy = sme->privacy;
 762        wil->pbss = sme->pbss;
 763
 764        if (wil->privacy) {
 765                /* For secure assoc, remove old keys */
 766                rc = wmi_del_cipher_key(wil, 0, bss->bssid,
 767                                        WMI_KEY_USE_PAIRWISE);
 768                if (rc) {
 769                        wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
 770                        goto out;
 771                }
 772                rc = wmi_del_cipher_key(wil, 0, bss->bssid,
 773                                        WMI_KEY_USE_RX_GROUP);
 774                if (rc) {
 775                        wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
 776                        goto out;
 777                }
 778        }
 779
 780        /* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info
 781         * elements. Send it also in case it's empty, to erase previously set
 782         * ies in FW.
 783         */
 784        rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
 785        if (rc)
 786                goto out;
 787
 788        /* WMI_CONNECT_CMD */
 789        memset(&conn, 0, sizeof(conn));
 790        switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
 791        case WLAN_CAPABILITY_DMG_TYPE_AP:
 792                conn.network_type = WMI_NETTYPE_INFRA;
 793                break;
 794        case WLAN_CAPABILITY_DMG_TYPE_PBSS:
 795                conn.network_type = WMI_NETTYPE_P2P;
 796                break;
 797        default:
 798                wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
 799                        bss->capability);
 800                goto out;
 801        }
 802        if (wil->privacy) {
 803                if (rsn_eid) { /* regular secure connection */
 804                        conn.dot11_auth_mode = WMI_AUTH11_SHARED;
 805                        conn.auth_mode = WMI_AUTH_WPA2_PSK;
 806                        conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
 807                        conn.pairwise_crypto_len = 16;
 808                        conn.group_crypto_type = WMI_CRYPT_AES_GCMP;
 809                        conn.group_crypto_len = 16;
 810                } else { /* WSC */
 811                        conn.dot11_auth_mode = WMI_AUTH11_WSC;
 812                        conn.auth_mode = WMI_AUTH_NONE;
 813                }
 814        } else { /* insecure connection */
 815                conn.dot11_auth_mode = WMI_AUTH11_OPEN;
 816                conn.auth_mode = WMI_AUTH_NONE;
 817        }
 818
 819        conn.ssid_len = min_t(u8, ssid_eid[1], 32);
 820        memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
 821
 822        ch = bss->channel->hw_value;
 823        if (ch == 0) {
 824                wil_err(wil, "BSS at unknown frequency %dMhz\n",
 825                        bss->channel->center_freq);
 826                rc = -EOPNOTSUPP;
 827                goto out;
 828        }
 829        conn.channel = ch - 1;
 830
 831        ether_addr_copy(conn.bssid, bss->bssid);
 832        ether_addr_copy(conn.dst_mac, bss->bssid);
 833
 834        set_bit(wil_status_fwconnecting, wil->status);
 835
 836        rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
 837        if (rc == 0) {
 838                netif_carrier_on(ndev);
 839                wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
 840                wil->bss = bss;
 841                /* Connect can take lots of time */
 842                mod_timer(&wil->connect_timer,
 843                          jiffies + msecs_to_jiffies(5000));
 844        } else {
 845                clear_bit(wil_status_fwconnecting, wil->status);
 846        }
 847
 848 out:
 849        cfg80211_put_bss(wiphy, bss);
 850
 851        return rc;
 852}
 853
 854static int wil_cfg80211_disconnect(struct wiphy *wiphy,
 855                                   struct net_device *ndev,
 856                                   u16 reason_code)
 857{
 858        int rc;
 859        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 860
 861        wil_dbg_misc(wil, "disconnect: reason=%d\n", reason_code);
 862
 863        if (!(test_bit(wil_status_fwconnecting, wil->status) ||
 864              test_bit(wil_status_fwconnected, wil->status))) {
 865                wil_err(wil, "Disconnect was called while disconnected\n");
 866                return 0;
 867        }
 868
 869        wil->locally_generated_disc = true;
 870        rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
 871                      WMI_DISCONNECT_EVENTID, NULL, 0,
 872                      WIL6210_DISCONNECT_TO_MS);
 873        if (rc)
 874                wil_err(wil, "disconnect error %d\n", rc);
 875
 876        return rc;
 877}
 878
 879static int wil_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 880{
 881        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 882        int rc;
 883
 884        /* these parameters are explicitly not supported */
 885        if (changed & (WIPHY_PARAM_RETRY_LONG |
 886                       WIPHY_PARAM_FRAG_THRESHOLD |
 887                       WIPHY_PARAM_RTS_THRESHOLD))
 888                return -ENOTSUPP;
 889
 890        if (changed & WIPHY_PARAM_RETRY_SHORT) {
 891                rc = wmi_set_mgmt_retry(wil, wiphy->retry_short);
 892                if (rc)
 893                        return rc;
 894        }
 895
 896        return 0;
 897}
 898
 899int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 900                         struct cfg80211_mgmt_tx_params *params,
 901                         u64 *cookie)
 902{
 903        const u8 *buf = params->buf;
 904        size_t len = params->len;
 905        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 906        int rc;
 907        bool tx_status = false;
 908        struct ieee80211_mgmt *mgmt_frame = (void *)buf;
 909        struct wmi_sw_tx_req_cmd *cmd;
 910        struct {
 911                struct wmi_cmd_hdr wmi;
 912                struct wmi_sw_tx_complete_event evt;
 913        } __packed evt;
 914
 915        /* Note, currently we do not support the "wait" parameter, user-space
 916         * must call remain_on_channel before mgmt_tx or listen on a channel
 917         * another way (AP/PCP or connected station)
 918         * in addition we need to check if specified "chan" argument is
 919         * different from currently "listened" channel and fail if it is.
 920         */
 921
 922        wil_dbg_misc(wil, "mgmt_tx\n");
 923        wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
 924                          len, true);
 925
 926        if (len < sizeof(struct ieee80211_hdr_3addr))
 927                return -EINVAL;
 928
 929        cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
 930        if (!cmd) {
 931                rc = -ENOMEM;
 932                goto out;
 933        }
 934
 935        memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
 936        cmd->len = cpu_to_le16(len);
 937        memcpy(cmd->payload, buf, len);
 938
 939        rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
 940                      WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
 941        if (rc == 0)
 942                tx_status = !evt.evt.status;
 943
 944        kfree(cmd);
 945 out:
 946        cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len,
 947                                tx_status, GFP_KERNEL);
 948        return rc;
 949}
 950
 951static int wil_cfg80211_set_channel(struct wiphy *wiphy,
 952                                    struct cfg80211_chan_def *chandef)
 953{
 954        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 955        struct wireless_dev *wdev = wil_to_wdev(wil);
 956
 957        wdev->preset_chandef = *chandef;
 958
 959        return 0;
 960}
 961
 962static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
 963                                               bool pairwise)
 964{
 965        struct wireless_dev *wdev = wil_to_wdev(wil);
 966        enum wmi_key_usage rc;
 967
 968        if (pairwise) {
 969                rc = WMI_KEY_USE_PAIRWISE;
 970        } else {
 971                switch (wdev->iftype) {
 972                case NL80211_IFTYPE_STATION:
 973                case NL80211_IFTYPE_P2P_CLIENT:
 974                        rc = WMI_KEY_USE_RX_GROUP;
 975                        break;
 976                case NL80211_IFTYPE_AP:
 977                case NL80211_IFTYPE_P2P_GO:
 978                        rc = WMI_KEY_USE_TX_GROUP;
 979                        break;
 980                default:
 981                        /* TODO: Rx GTK or Tx GTK? */
 982                        wil_err(wil, "Can't determine GTK type\n");
 983                        rc = WMI_KEY_USE_RX_GROUP;
 984                        break;
 985                }
 986        }
 987        wil_dbg_misc(wil, "detect_key_usage: -> %s\n", key_usage_str[rc]);
 988
 989        return rc;
 990}
 991
 992static struct wil_sta_info *
 993wil_find_sta_by_key_usage(struct wil6210_priv *wil,
 994                          enum wmi_key_usage key_usage, const u8 *mac_addr)
 995{
 996        int cid = -EINVAL;
 997
 998        if (key_usage == WMI_KEY_USE_TX_GROUP)
 999                return NULL; /* not needed */
1000
1001        /* supplicant provides Rx group key in STA mode with NULL MAC address */
1002        if (mac_addr)
1003                cid = wil_find_cid(wil, mac_addr);
1004        else if (key_usage == WMI_KEY_USE_RX_GROUP)
1005                cid = wil_find_cid_by_idx(wil, 0);
1006        if (cid < 0) {
1007                wil_err(wil, "No CID for %pM %s\n", mac_addr,
1008                        key_usage_str[key_usage]);
1009                return ERR_PTR(cid);
1010        }
1011
1012        return &wil->sta[cid];
1013}
1014
1015static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
1016                              struct wil_sta_info *cs,
1017                              struct key_params *params)
1018{
1019        struct wil_tid_crypto_rx_single *cc;
1020        int tid;
1021
1022        if (!cs)
1023                return;
1024
1025        switch (key_usage) {
1026        case WMI_KEY_USE_PAIRWISE:
1027                for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
1028                        cc = &cs->tid_crypto_rx[tid].key_id[key_index];
1029                        if (params->seq)
1030                                memcpy(cc->pn, params->seq,
1031                                       IEEE80211_GCMP_PN_LEN);
1032                        else
1033                                memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
1034                        cc->key_set = true;
1035                }
1036                break;
1037        case WMI_KEY_USE_RX_GROUP:
1038                cc = &cs->group_crypto_rx.key_id[key_index];
1039                if (params->seq)
1040                        memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
1041                else
1042                        memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
1043                cc->key_set = true;
1044                break;
1045        default:
1046                break;
1047        }
1048}
1049
1050static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage,
1051                           struct wil_sta_info *cs)
1052{
1053        struct wil_tid_crypto_rx_single *cc;
1054        int tid;
1055
1056        if (!cs)
1057                return;
1058
1059        switch (key_usage) {
1060        case WMI_KEY_USE_PAIRWISE:
1061                for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
1062                        cc = &cs->tid_crypto_rx[tid].key_id[key_index];
1063                        cc->key_set = false;
1064                }
1065                break;
1066        case WMI_KEY_USE_RX_GROUP:
1067                cc = &cs->group_crypto_rx.key_id[key_index];
1068                cc->key_set = false;
1069                break;
1070        default:
1071                break;
1072        }
1073}
1074
1075static int wil_cfg80211_add_key(struct wiphy *wiphy,
1076                                struct net_device *ndev,
1077                                u8 key_index, bool pairwise,
1078                                const u8 *mac_addr,
1079                                struct key_params *params)
1080{
1081        int rc;
1082        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1083        enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
1084        struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
1085                                                            mac_addr);
1086
1087        if (!params) {
1088                wil_err(wil, "NULL params\n");
1089                return -EINVAL;
1090        }
1091
1092        wil_dbg_misc(wil, "add_key: %pM %s[%d] PN %*phN\n",
1093                     mac_addr, key_usage_str[key_usage], key_index,
1094                     params->seq_len, params->seq);
1095
1096        if (IS_ERR(cs)) {
1097                wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n",
1098                        mac_addr, key_usage_str[key_usage], key_index,
1099                        params->seq_len, params->seq);
1100                return -EINVAL;
1101        }
1102
1103        wil_del_rx_key(key_index, key_usage, cs);
1104
1105        if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
1106                wil_err(wil,
1107                        "Wrong PN len %d, %pM %s[%d] PN %*phN\n",
1108                        params->seq_len, mac_addr,
1109                        key_usage_str[key_usage], key_index,
1110                        params->seq_len, params->seq);
1111                return -EINVAL;
1112        }
1113
1114        rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
1115                                params->key, key_usage);
1116        if (!rc)
1117                wil_set_crypto_rx(key_index, key_usage, cs, params);
1118
1119        return rc;
1120}
1121
1122static int wil_cfg80211_del_key(struct wiphy *wiphy,
1123                                struct net_device *ndev,
1124                                u8 key_index, bool pairwise,
1125                                const u8 *mac_addr)
1126{
1127        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1128        enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
1129        struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
1130                                                            mac_addr);
1131
1132        wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr,
1133                     key_usage_str[key_usage], key_index);
1134
1135        if (IS_ERR(cs))
1136                wil_info(wil, "Not connected, %pM %s[%d]\n",
1137                         mac_addr, key_usage_str[key_usage], key_index);
1138
1139        if (!IS_ERR_OR_NULL(cs))
1140                wil_del_rx_key(key_index, key_usage, cs);
1141
1142        return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
1143}
1144
1145/* Need to be present or wiphy_new() will WARN */
1146static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
1147                                        struct net_device *ndev,
1148                                        u8 key_index, bool unicast,
1149                                        bool multicast)
1150{
1151        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1152
1153        wil_dbg_misc(wil, "set_default_key: entered\n");
1154        return 0;
1155}
1156
1157static int wil_remain_on_channel(struct wiphy *wiphy,
1158                                 struct wireless_dev *wdev,
1159                                 struct ieee80211_channel *chan,
1160                                 unsigned int duration,
1161                                 u64 *cookie)
1162{
1163        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1164        int rc;
1165
1166        wil_dbg_misc(wil,
1167                     "remain_on_channel: center_freq=%d, duration=%d iftype=%d\n",
1168                     chan->center_freq, duration, wdev->iftype);
1169
1170        rc = wil_p2p_listen(wil, wdev, duration, chan, cookie);
1171        return rc;
1172}
1173
1174static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
1175                                        struct wireless_dev *wdev,
1176                                        u64 cookie)
1177{
1178        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1179
1180        wil_dbg_misc(wil, "cancel_remain_on_channel\n");
1181
1182        return wil_p2p_cancel_listen(wil, cookie);
1183}
1184
1185/**
1186 * find a specific IE in a list of IEs
1187 * return a pointer to the beginning of IE in the list
1188 * or NULL if not found
1189 */
1190static const u8 *_wil_cfg80211_find_ie(const u8 *ies, u16 ies_len, const u8 *ie,
1191                                       u16 ie_len)
1192{
1193        struct ieee80211_vendor_ie *vie;
1194        u32 oui;
1195
1196        /* IE tag at offset 0, length at offset 1 */
1197        if (ie_len < 2 || 2 + ie[1] > ie_len)
1198                return NULL;
1199
1200        if (ie[0] != WLAN_EID_VENDOR_SPECIFIC)
1201                return cfg80211_find_ie(ie[0], ies, ies_len);
1202
1203        /* make sure there is room for 3 bytes OUI + 1 byte OUI type */
1204        if (ie[1] < 4)
1205                return NULL;
1206        vie = (struct ieee80211_vendor_ie *)ie;
1207        oui = vie->oui[0] << 16 | vie->oui[1] << 8 | vie->oui[2];
1208        return cfg80211_find_vendor_ie(oui, vie->oui_type, ies,
1209                                       ies_len);
1210}
1211
1212/**
1213 * merge the IEs in two lists into a single list.
1214 * do not include IEs from the second list which exist in the first list.
1215 * add only vendor specific IEs from second list to keep
1216 * the merged list sorted (since vendor-specific IE has the
1217 * highest tag number)
1218 * caller must free the allocated memory for merged IEs
1219 */
1220static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
1221                                         const u8 *ies2, u16 ies2_len,
1222                                         u8 **merged_ies, u16 *merged_len)
1223{
1224        u8 *buf, *dpos;
1225        const u8 *spos;
1226
1227        if (ies1_len == 0 && ies2_len == 0) {
1228                *merged_ies = NULL;
1229                *merged_len = 0;
1230                return 0;
1231        }
1232
1233        buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL);
1234        if (!buf)
1235                return -ENOMEM;
1236        memcpy(buf, ies1, ies1_len);
1237        dpos = buf + ies1_len;
1238        spos = ies2;
1239        while (spos + 1 < ies2 + ies2_len) {
1240                /* IE tag at offset 0, length at offset 1 */
1241                u16 ielen = 2 + spos[1];
1242
1243                if (spos + ielen > ies2 + ies2_len)
1244                        break;
1245                if (spos[0] == WLAN_EID_VENDOR_SPECIFIC &&
1246                    !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) {
1247                        memcpy(dpos, spos, ielen);
1248                        dpos += ielen;
1249                }
1250                spos += ielen;
1251        }
1252
1253        *merged_ies = buf;
1254        *merged_len = dpos - buf;
1255        return 0;
1256}
1257
1258static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
1259{
1260        wil_hex_dump_misc("head     ", DUMP_PREFIX_OFFSET, 16, 1,
1261                          b->head, b->head_len, true);
1262        wil_hex_dump_misc("tail     ", DUMP_PREFIX_OFFSET, 16, 1,
1263                          b->tail, b->tail_len, true);
1264        wil_hex_dump_misc("BCON IE  ", DUMP_PREFIX_OFFSET, 16, 1,
1265                          b->beacon_ies, b->beacon_ies_len, true);
1266        wil_hex_dump_misc("PROBE    ", DUMP_PREFIX_OFFSET, 16, 1,
1267                          b->probe_resp, b->probe_resp_len, true);
1268        wil_hex_dump_misc("PROBE IE ", DUMP_PREFIX_OFFSET, 16, 1,
1269                          b->proberesp_ies, b->proberesp_ies_len, true);
1270        wil_hex_dump_misc("ASSOC IE ", DUMP_PREFIX_OFFSET, 16, 1,
1271                          b->assocresp_ies, b->assocresp_ies_len, true);
1272}
1273
1274/* internal functions for device reset and starting AP */
1275static int _wil_cfg80211_set_ies(struct wiphy *wiphy,
1276                                 struct cfg80211_beacon_data *bcon)
1277{
1278        int rc;
1279        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1280        u16 len = 0, proberesp_len = 0;
1281        u8 *ies = NULL, *proberesp = NULL;
1282
1283        if (bcon->probe_resp) {
1284                struct ieee80211_mgmt *f =
1285                        (struct ieee80211_mgmt *)bcon->probe_resp;
1286                size_t hlen = offsetof(struct ieee80211_mgmt,
1287                                       u.probe_resp.variable);
1288                proberesp = f->u.probe_resp.variable;
1289                proberesp_len = bcon->probe_resp_len - hlen;
1290        }
1291        rc = _wil_cfg80211_merge_extra_ies(proberesp,
1292                                           proberesp_len,
1293                                           bcon->proberesp_ies,
1294                                           bcon->proberesp_ies_len,
1295                                           &ies, &len);
1296
1297        if (rc)
1298                goto out;
1299
1300        rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies);
1301        if (rc)
1302                goto out;
1303
1304        if (bcon->assocresp_ies)
1305                rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP,
1306                                bcon->assocresp_ies_len, bcon->assocresp_ies);
1307        else
1308                rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies);
1309#if 0 /* to use beacon IE's, remove this #if 0 */
1310        if (rc)
1311                goto out;
1312
1313        rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail);
1314#endif
1315out:
1316        kfree(ies);
1317        return rc;
1318}
1319
1320static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
1321                                  struct net_device *ndev,
1322                                  const u8 *ssid, size_t ssid_len, u32 privacy,
1323                                  int bi, u8 chan,
1324                                  struct cfg80211_beacon_data *bcon,
1325                                  u8 hidden_ssid, u32 pbss)
1326{
1327        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1328        int rc;
1329        struct wireless_dev *wdev = ndev->ieee80211_ptr;
1330        u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
1331        u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO);
1332
1333        if (pbss)
1334                wmi_nettype = WMI_NETTYPE_P2P;
1335
1336        wil_dbg_misc(wil, "start_ap: is_go=%d\n", is_go);
1337        if (is_go && !pbss) {
1338                wil_err(wil, "P2P GO must be in PBSS\n");
1339                return -ENOTSUPP;
1340        }
1341
1342        wil_set_recovery_state(wil, fw_recovery_idle);
1343
1344        mutex_lock(&wil->mutex);
1345
1346        __wil_down(wil);
1347        rc = __wil_up(wil);
1348        if (rc)
1349                goto out;
1350
1351        rc = wmi_set_ssid(wil, ssid_len, ssid);
1352        if (rc)
1353                goto out;
1354
1355        rc = _wil_cfg80211_set_ies(wiphy, bcon);
1356        if (rc)
1357                goto out;
1358
1359        wil->privacy = privacy;
1360        wil->channel = chan;
1361        wil->hidden_ssid = hidden_ssid;
1362        wil->pbss = pbss;
1363
1364        netif_carrier_on(ndev);
1365        wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
1366
1367        rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go);
1368        if (rc)
1369                goto err_pcp_start;
1370
1371        rc = wil_bcast_init(wil);
1372        if (rc)
1373                goto err_bcast;
1374
1375        goto out; /* success */
1376
1377err_bcast:
1378        wmi_pcp_stop(wil);
1379err_pcp_start:
1380        netif_carrier_off(ndev);
1381        wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
1382out:
1383        mutex_unlock(&wil->mutex);
1384        return rc;
1385}
1386
1387static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
1388                                      struct net_device *ndev,
1389                                      struct cfg80211_beacon_data *bcon)
1390{
1391        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1392        int rc;
1393        u32 privacy = 0;
1394
1395        wil_dbg_misc(wil, "change_beacon\n");
1396        wil_print_bcon_data(bcon);
1397
1398        if (bcon->tail &&
1399            cfg80211_find_ie(WLAN_EID_RSN, bcon->tail,
1400                             bcon->tail_len))
1401                privacy = 1;
1402
1403        /* in case privacy has changed, need to restart the AP */
1404        if (wil->privacy != privacy) {
1405                struct wireless_dev *wdev = ndev->ieee80211_ptr;
1406
1407                wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n",
1408                             wil->privacy, privacy);
1409
1410                rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid,
1411                                            wdev->ssid_len, privacy,
1412                                            wdev->beacon_interval,
1413                                            wil->channel, bcon,
1414                                            wil->hidden_ssid,
1415                                            wil->pbss);
1416        } else {
1417                rc = _wil_cfg80211_set_ies(wiphy, bcon);
1418        }
1419
1420        return rc;
1421}
1422
1423static int wil_cfg80211_start_ap(struct wiphy *wiphy,
1424                                 struct net_device *ndev,
1425                                 struct cfg80211_ap_settings *info)
1426{
1427        int rc;
1428        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1429        struct ieee80211_channel *channel = info->chandef.chan;
1430        struct cfg80211_beacon_data *bcon = &info->beacon;
1431        struct cfg80211_crypto_settings *crypto = &info->crypto;
1432        u8 hidden_ssid;
1433
1434        wil_dbg_misc(wil, "start_ap\n");
1435
1436        if (!channel) {
1437                wil_err(wil, "AP: No channel???\n");
1438                return -EINVAL;
1439        }
1440
1441        switch (info->hidden_ssid) {
1442        case NL80211_HIDDEN_SSID_NOT_IN_USE:
1443                hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
1444                break;
1445
1446        case NL80211_HIDDEN_SSID_ZERO_LEN:
1447                hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY;
1448                break;
1449
1450        case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
1451                hidden_ssid = WMI_HIDDEN_SSID_CLEAR;
1452                break;
1453
1454        default:
1455                wil_err(wil, "AP: Invalid hidden SSID %d\n", info->hidden_ssid);
1456                return -EOPNOTSUPP;
1457        }
1458        wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
1459                     channel->center_freq, info->privacy ? "secure" : "open");
1460        wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
1461                     info->privacy, info->auth_type);
1462        wil_dbg_misc(wil, "Hidden SSID mode: %d\n",
1463                     info->hidden_ssid);
1464        wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
1465                     info->dtim_period);
1466        wil_dbg_misc(wil, "PBSS %d\n", info->pbss);
1467        wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
1468                          info->ssid, info->ssid_len, true);
1469        wil_print_bcon_data(bcon);
1470        wil_print_crypto(wil, crypto);
1471
1472        rc = _wil_cfg80211_start_ap(wiphy, ndev,
1473                                    info->ssid, info->ssid_len, info->privacy,
1474                                    info->beacon_interval, channel->hw_value,
1475                                    bcon, hidden_ssid, info->pbss);
1476
1477        return rc;
1478}
1479
1480static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
1481                                struct net_device *ndev)
1482{
1483        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1484
1485        wil_dbg_misc(wil, "stop_ap\n");
1486
1487        netif_carrier_off(ndev);
1488        wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
1489        wil_set_recovery_state(wil, fw_recovery_idle);
1490
1491        set_bit(wil_status_resetting, wil->status);
1492
1493        mutex_lock(&wil->mutex);
1494
1495        wmi_pcp_stop(wil);
1496
1497        __wil_down(wil);
1498
1499        mutex_unlock(&wil->mutex);
1500
1501        return 0;
1502}
1503
1504static int wil_cfg80211_add_station(struct wiphy *wiphy,
1505                                    struct net_device *dev,
1506                                    const u8 *mac,
1507                                    struct station_parameters *params)
1508{
1509        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1510
1511        wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid);
1512
1513        if (!disable_ap_sme) {
1514                wil_err(wil, "not supported with AP SME enabled\n");
1515                return -EOPNOTSUPP;
1516        }
1517
1518        if (params->aid > WIL_MAX_DMG_AID) {
1519                wil_err(wil, "invalid aid\n");
1520                return -EINVAL;
1521        }
1522
1523        return wmi_new_sta(wil, mac, params->aid);
1524}
1525
1526static int wil_cfg80211_del_station(struct wiphy *wiphy,
1527                                    struct net_device *dev,
1528                                    struct station_del_parameters *params)
1529{
1530        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1531
1532        wil_dbg_misc(wil, "del_station: %pM, reason=%d\n", params->mac,
1533                     params->reason_code);
1534
1535        mutex_lock(&wil->mutex);
1536        wil6210_disconnect(wil, params->mac, params->reason_code, false);
1537        mutex_unlock(&wil->mutex);
1538
1539        return 0;
1540}
1541
1542static int wil_cfg80211_change_station(struct wiphy *wiphy,
1543                                       struct net_device *dev,
1544                                       const u8 *mac,
1545                                       struct station_parameters *params)
1546{
1547        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1548        int authorize;
1549        int cid, i;
1550        struct vring_tx_data *txdata = NULL;
1551
1552        wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac,
1553                     params->sta_flags_mask, params->sta_flags_set);
1554
1555        if (!disable_ap_sme) {
1556                wil_dbg_misc(wil, "not supported with AP SME enabled\n");
1557                return -EOPNOTSUPP;
1558        }
1559
1560        if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
1561                return 0;
1562
1563        cid = wil_find_cid(wil, mac);
1564        if (cid < 0) {
1565                wil_err(wil, "station not found\n");
1566                return -ENOLINK;
1567        }
1568
1569        for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++)
1570                if (wil->vring2cid_tid[i][0] == cid) {
1571                        txdata = &wil->vring_tx_data[i];
1572                        break;
1573                }
1574
1575        if (!txdata) {
1576                wil_err(wil, "vring data not found\n");
1577                return -ENOLINK;
1578        }
1579
1580        authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED);
1581        txdata->dot1x_open = authorize ? 1 : 0;
1582        wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i,
1583                     txdata->dot1x_open);
1584
1585        return 0;
1586}
1587
1588/* probe_client handling */
1589static void wil_probe_client_handle(struct wil6210_priv *wil,
1590                                    struct wil_probe_client_req *req)
1591{
1592        struct net_device *ndev = wil_to_ndev(wil);
1593        struct wil_sta_info *sta = &wil->sta[req->cid];
1594        /* assume STA is alive if it is still connected,
1595         * else FW will disconnect it
1596         */
1597        bool alive = (sta->status == wil_sta_connected);
1598
1599        cfg80211_probe_status(ndev, sta->addr, req->cookie, alive, GFP_KERNEL);
1600}
1601
1602static struct list_head *next_probe_client(struct wil6210_priv *wil)
1603{
1604        struct list_head *ret = NULL;
1605
1606        mutex_lock(&wil->probe_client_mutex);
1607
1608        if (!list_empty(&wil->probe_client_pending)) {
1609                ret = wil->probe_client_pending.next;
1610                list_del(ret);
1611        }
1612
1613        mutex_unlock(&wil->probe_client_mutex);
1614
1615        return ret;
1616}
1617
1618void wil_probe_client_worker(struct work_struct *work)
1619{
1620        struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
1621                                                probe_client_worker);
1622        struct wil_probe_client_req *req;
1623        struct list_head *lh;
1624
1625        while ((lh = next_probe_client(wil)) != NULL) {
1626                req = list_entry(lh, struct wil_probe_client_req, list);
1627
1628                wil_probe_client_handle(wil, req);
1629                kfree(req);
1630        }
1631}
1632
1633void wil_probe_client_flush(struct wil6210_priv *wil)
1634{
1635        struct wil_probe_client_req *req, *t;
1636
1637        wil_dbg_misc(wil, "probe_client_flush\n");
1638
1639        mutex_lock(&wil->probe_client_mutex);
1640
1641        list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) {
1642                list_del(&req->list);
1643                kfree(req);
1644        }
1645
1646        mutex_unlock(&wil->probe_client_mutex);
1647}
1648
1649static int wil_cfg80211_probe_client(struct wiphy *wiphy,
1650                                     struct net_device *dev,
1651                                     const u8 *peer, u64 *cookie)
1652{
1653        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1654        struct wil_probe_client_req *req;
1655        int cid = wil_find_cid(wil, peer);
1656
1657        wil_dbg_misc(wil, "probe_client: %pM => CID %d\n", peer, cid);
1658
1659        if (cid < 0)
1660                return -ENOLINK;
1661
1662        req = kzalloc(sizeof(*req), GFP_KERNEL);
1663        if (!req)
1664                return -ENOMEM;
1665
1666        req->cid = cid;
1667        req->cookie = cid;
1668
1669        mutex_lock(&wil->probe_client_mutex);
1670        list_add_tail(&req->list, &wil->probe_client_pending);
1671        mutex_unlock(&wil->probe_client_mutex);
1672
1673        *cookie = req->cookie;
1674        queue_work(wil->wq_service, &wil->probe_client_worker);
1675        return 0;
1676}
1677
1678static int wil_cfg80211_change_bss(struct wiphy *wiphy,
1679                                   struct net_device *dev,
1680                                   struct bss_parameters *params)
1681{
1682        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1683
1684        if (params->ap_isolate >= 0) {
1685                wil_dbg_misc(wil, "change_bss: ap_isolate %d => %d\n",
1686                             wil->ap_isolate, params->ap_isolate);
1687                wil->ap_isolate = params->ap_isolate;
1688        }
1689
1690        return 0;
1691}
1692
1693static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1694                                       struct net_device *dev,
1695                                       bool enabled, int timeout)
1696{
1697        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1698        enum wmi_ps_profile_type ps_profile;
1699
1700        wil_dbg_misc(wil, "enabled=%d, timeout=%d\n",
1701                     enabled, timeout);
1702
1703        if (enabled)
1704                ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
1705        else
1706                ps_profile = WMI_PS_PROFILE_TYPE_PS_DISABLED;
1707
1708        return wil_ps_update(wil, ps_profile);
1709}
1710
1711static int wil_cfg80211_suspend(struct wiphy *wiphy,
1712                                struct cfg80211_wowlan *wow)
1713{
1714        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1715        int rc;
1716
1717        /* Setting the wakeup trigger based on wow is TBD */
1718
1719        if (test_bit(wil_status_suspended, wil->status)) {
1720                wil_dbg_pm(wil, "trying to suspend while suspended\n");
1721                return 0;
1722        }
1723
1724        rc = wil_can_suspend(wil, false);
1725        if (rc)
1726                goto out;
1727
1728        wil_dbg_pm(wil, "suspending\n");
1729
1730        wil_p2p_stop_discovery(wil);
1731
1732        wil_abort_scan(wil, true);
1733
1734out:
1735        return rc;
1736}
1737
1738static int wil_cfg80211_resume(struct wiphy *wiphy)
1739{
1740        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1741
1742        wil_dbg_pm(wil, "resuming\n");
1743
1744        return 0;
1745}
1746
1747static const struct cfg80211_ops wil_cfg80211_ops = {
1748        .add_virtual_intf = wil_cfg80211_add_iface,
1749        .del_virtual_intf = wil_cfg80211_del_iface,
1750        .scan = wil_cfg80211_scan,
1751        .abort_scan = wil_cfg80211_abort_scan,
1752        .connect = wil_cfg80211_connect,
1753        .disconnect = wil_cfg80211_disconnect,
1754        .set_wiphy_params = wil_cfg80211_set_wiphy_params,
1755        .change_virtual_intf = wil_cfg80211_change_iface,
1756        .get_station = wil_cfg80211_get_station,
1757        .dump_station = wil_cfg80211_dump_station,
1758        .remain_on_channel = wil_remain_on_channel,
1759        .cancel_remain_on_channel = wil_cancel_remain_on_channel,
1760        .mgmt_tx = wil_cfg80211_mgmt_tx,
1761        .set_monitor_channel = wil_cfg80211_set_channel,
1762        .add_key = wil_cfg80211_add_key,
1763        .del_key = wil_cfg80211_del_key,
1764        .set_default_key = wil_cfg80211_set_default_key,
1765        /* AP mode */
1766        .change_beacon = wil_cfg80211_change_beacon,
1767        .start_ap = wil_cfg80211_start_ap,
1768        .stop_ap = wil_cfg80211_stop_ap,
1769        .add_station = wil_cfg80211_add_station,
1770        .del_station = wil_cfg80211_del_station,
1771        .change_station = wil_cfg80211_change_station,
1772        .probe_client = wil_cfg80211_probe_client,
1773        .change_bss = wil_cfg80211_change_bss,
1774        /* P2P device */
1775        .start_p2p_device = wil_cfg80211_start_p2p_device,
1776        .stop_p2p_device = wil_cfg80211_stop_p2p_device,
1777        .set_power_mgmt = wil_cfg80211_set_power_mgmt,
1778        .suspend = wil_cfg80211_suspend,
1779        .resume = wil_cfg80211_resume,
1780};
1781
1782static void wil_wiphy_init(struct wiphy *wiphy)
1783{
1784        wiphy->max_scan_ssids = 1;
1785        wiphy->max_scan_ie_len = WMI_MAX_IE_LEN;
1786        wiphy->max_remain_on_channel_duration = WIL_MAX_ROC_DURATION_MS;
1787        wiphy->max_num_pmkids = 0 /* TODO: */;
1788        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1789                                 BIT(NL80211_IFTYPE_AP) |
1790                                 BIT(NL80211_IFTYPE_P2P_CLIENT) |
1791                                 BIT(NL80211_IFTYPE_P2P_GO) |
1792                                 BIT(NL80211_IFTYPE_P2P_DEVICE) |
1793                                 BIT(NL80211_IFTYPE_MONITOR);
1794        wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
1795                        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
1796                        WIPHY_FLAG_PS_ON_BY_DEFAULT;
1797        if (!disable_ap_sme)
1798                wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
1799        dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
1800                __func__, wiphy->flags);
1801        wiphy->probe_resp_offload =
1802                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
1803                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
1804                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
1805
1806        wiphy->bands[NL80211_BAND_60GHZ] = &wil_band_60ghz;
1807
1808        /* may change after reading FW capabilities */
1809        wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
1810
1811        wiphy->cipher_suites = wil_cipher_suites;
1812        wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);
1813        wiphy->mgmt_stypes = wil_mgmt_stypes;
1814        wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
1815
1816        wiphy->n_vendor_commands = ARRAY_SIZE(wil_nl80211_vendor_commands);
1817        wiphy->vendor_commands = wil_nl80211_vendor_commands;
1818
1819#ifdef CONFIG_PM
1820        wiphy->wowlan = &wil_wowlan_support;
1821#endif
1822}
1823
1824struct wireless_dev *wil_cfg80211_init(struct device *dev)
1825{
1826        int rc = 0;
1827        struct wireless_dev *wdev;
1828
1829        dev_dbg(dev, "%s()\n", __func__);
1830
1831        wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
1832        if (!wdev)
1833                return ERR_PTR(-ENOMEM);
1834
1835        wdev->wiphy = wiphy_new(&wil_cfg80211_ops,
1836                                sizeof(struct wil6210_priv));
1837        if (!wdev->wiphy) {
1838                rc = -ENOMEM;
1839                goto out;
1840        }
1841
1842        set_wiphy_dev(wdev->wiphy, dev);
1843        wil_wiphy_init(wdev->wiphy);
1844
1845        return wdev;
1846
1847out:
1848        kfree(wdev);
1849
1850        return ERR_PTR(rc);
1851}
1852
1853void wil_wdev_free(struct wil6210_priv *wil)
1854{
1855        struct wireless_dev *wdev = wil_to_wdev(wil);
1856
1857        dev_dbg(wil_to_dev(wil), "%s()\n", __func__);
1858
1859        if (!wdev)
1860                return;
1861
1862        wiphy_free(wdev->wiphy);
1863        kfree(wdev);
1864}
1865
1866void wil_p2p_wdev_free(struct wil6210_priv *wil)
1867{
1868        struct wireless_dev *p2p_wdev;
1869
1870        mutex_lock(&wil->p2p_wdev_mutex);
1871        p2p_wdev = wil->p2p_wdev;
1872        wil->p2p_wdev = NULL;
1873        wil->radio_wdev = wil_to_wdev(wil);
1874        mutex_unlock(&wil->p2p_wdev_mutex);
1875        if (p2p_wdev) {
1876                cfg80211_unregister_wdev(p2p_wdev);
1877                kfree(p2p_wdev);
1878        }
1879}
1880
1881static int wil_rf_sector_status_to_rc(u8 status)
1882{
1883        switch (status) {
1884        case WMI_RF_SECTOR_STATUS_SUCCESS:
1885                return 0;
1886        case WMI_RF_SECTOR_STATUS_BAD_PARAMETERS_ERROR:
1887                return -EINVAL;
1888        case WMI_RF_SECTOR_STATUS_BUSY_ERROR:
1889                return -EAGAIN;
1890        case WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR:
1891                return -EOPNOTSUPP;
1892        default:
1893                return -EINVAL;
1894        }
1895}
1896
1897static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
1898                                 struct wireless_dev *wdev,
1899                                 const void *data, int data_len)
1900{
1901        struct wil6210_priv *wil = wdev_to_wil(wdev);
1902        int rc;
1903        struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
1904        u16 sector_index;
1905        u8 sector_type;
1906        u32 rf_modules_vec;
1907        struct wmi_get_rf_sector_params_cmd cmd;
1908        struct {
1909                struct wmi_cmd_hdr wmi;
1910                struct wmi_get_rf_sector_params_done_event evt;
1911        } __packed reply;
1912        struct sk_buff *msg;
1913        struct nlattr *nl_cfgs, *nl_cfg;
1914        u32 i;
1915        struct wmi_rf_sector_info *si;
1916
1917        if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
1918                return -EOPNOTSUPP;
1919
1920        rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
1921                       wil_rf_sector_policy, NULL);
1922        if (rc) {
1923                wil_err(wil, "Invalid rf sector ATTR\n");
1924                return rc;
1925        }
1926
1927        if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
1928            !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
1929            !tb[QCA_ATTR_DMG_RF_MODULE_MASK]) {
1930                wil_err(wil, "Invalid rf sector spec\n");
1931                return -EINVAL;
1932        }
1933
1934        sector_index = nla_get_u16(
1935                tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
1936        if (sector_index >= WIL_MAX_RF_SECTORS) {
1937                wil_err(wil, "Invalid sector index %d\n", sector_index);
1938                return -EINVAL;
1939        }
1940
1941        sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
1942        if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
1943                wil_err(wil, "Invalid sector type %d\n", sector_type);
1944                return -EINVAL;
1945        }
1946
1947        rf_modules_vec = nla_get_u32(
1948                tb[QCA_ATTR_DMG_RF_MODULE_MASK]);
1949        if (rf_modules_vec >= BIT(WMI_MAX_RF_MODULES_NUM)) {
1950                wil_err(wil, "Invalid rf module mask 0x%x\n", rf_modules_vec);
1951                return -EINVAL;
1952        }
1953
1954        cmd.sector_idx = cpu_to_le16(sector_index);
1955        cmd.sector_type = sector_type;
1956        cmd.rf_modules_vec = rf_modules_vec & 0xFF;
1957        memset(&reply, 0, sizeof(reply));
1958        rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
1959                      WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID,
1960                      &reply, sizeof(reply),
1961                      500);
1962        if (rc)
1963                return rc;
1964        if (reply.evt.status) {
1965                wil_err(wil, "get rf sector cfg failed with status %d\n",
1966                        reply.evt.status);
1967                return wil_rf_sector_status_to_rc(reply.evt.status);
1968        }
1969
1970        msg = cfg80211_vendor_cmd_alloc_reply_skb(
1971                wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
1972        if (!msg)
1973                return -ENOMEM;
1974
1975        if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
1976                              le64_to_cpu(reply.evt.tsf),
1977                              QCA_ATTR_PAD))
1978                goto nla_put_failure;
1979
1980        nl_cfgs = nla_nest_start(msg, QCA_ATTR_DMG_RF_SECTOR_CFG);
1981        if (!nl_cfgs)
1982                goto nla_put_failure;
1983        for (i = 0; i < WMI_MAX_RF_MODULES_NUM; i++) {
1984                if (!(rf_modules_vec & BIT(i)))
1985                        continue;
1986                nl_cfg = nla_nest_start(msg, i);
1987                if (!nl_cfg)
1988                        goto nla_put_failure;
1989                si = &reply.evt.sectors_info[i];
1990                if (nla_put_u8(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
1991                               i) ||
1992                    nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
1993                                le32_to_cpu(si->etype0)) ||
1994                    nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
1995                                le32_to_cpu(si->etype1)) ||
1996                    nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
1997                                le32_to_cpu(si->etype2)) ||
1998                    nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
1999                                le32_to_cpu(si->psh_hi)) ||
2000                    nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
2001                                le32_to_cpu(si->psh_lo)) ||
2002                    nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
2003                                le32_to_cpu(si->dtype_swch_off)))
2004                        goto nla_put_failure;
2005                nla_nest_end(msg, nl_cfg);
2006        }
2007
2008        nla_nest_end(msg, nl_cfgs);
2009        rc = cfg80211_vendor_cmd_reply(msg);
2010        return rc;
2011nla_put_failure:
2012        kfree_skb(msg);
2013        return -ENOBUFS;
2014}
2015
2016static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
2017                                 struct wireless_dev *wdev,
2018                                 const void *data, int data_len)
2019{
2020        struct wil6210_priv *wil = wdev_to_wil(wdev);
2021        int rc, tmp;
2022        struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
2023        struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1];
2024        u16 sector_index, rf_module_index;
2025        u8 sector_type;
2026        u32 rf_modules_vec = 0;
2027        struct wmi_set_rf_sector_params_cmd cmd;
2028        struct {
2029                struct wmi_cmd_hdr wmi;
2030                struct wmi_set_rf_sector_params_done_event evt;
2031        } __packed reply;
2032        struct nlattr *nl_cfg;
2033        struct wmi_rf_sector_info *si;
2034
2035        if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
2036                return -EOPNOTSUPP;
2037
2038        rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2039                       wil_rf_sector_policy, NULL);
2040        if (rc) {
2041                wil_err(wil, "Invalid rf sector ATTR\n");
2042                return rc;
2043        }
2044
2045        if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
2046            !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
2047            !tb[QCA_ATTR_DMG_RF_SECTOR_CFG]) {
2048                wil_err(wil, "Invalid rf sector spec\n");
2049                return -EINVAL;
2050        }
2051
2052        sector_index = nla_get_u16(
2053                tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
2054        if (sector_index >= WIL_MAX_RF_SECTORS) {
2055                wil_err(wil, "Invalid sector index %d\n", sector_index);
2056                return -EINVAL;
2057        }
2058
2059        sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
2060        if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
2061                wil_err(wil, "Invalid sector type %d\n", sector_type);
2062                return -EINVAL;
2063        }
2064
2065        memset(&cmd, 0, sizeof(cmd));
2066
2067        cmd.sector_idx = cpu_to_le16(sector_index);
2068        cmd.sector_type = sector_type;
2069        nla_for_each_nested(nl_cfg, tb[QCA_ATTR_DMG_RF_SECTOR_CFG],
2070                            tmp) {
2071                rc = nla_parse_nested(tb2, QCA_ATTR_DMG_RF_SECTOR_CFG_MAX,
2072                                      nl_cfg, wil_rf_sector_cfg_policy,
2073                                      NULL);
2074                if (rc) {
2075                        wil_err(wil, "invalid sector cfg\n");
2076                        return -EINVAL;
2077                }
2078
2079                if (!tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] ||
2080                    !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] ||
2081                    !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] ||
2082                    !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] ||
2083                    !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] ||
2084                    !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] ||
2085                    !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]) {
2086                        wil_err(wil, "missing cfg params\n");
2087                        return -EINVAL;
2088                }
2089
2090                rf_module_index = nla_get_u8(
2091                        tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX]);
2092                if (rf_module_index >= WMI_MAX_RF_MODULES_NUM) {
2093                        wil_err(wil, "invalid RF module index %d\n",
2094                                rf_module_index);
2095                        return -EINVAL;
2096                }
2097                rf_modules_vec |= BIT(rf_module_index);
2098                si = &cmd.sectors_info[rf_module_index];
2099                si->etype0 = cpu_to_le32(nla_get_u32(
2100                        tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0]));
2101                si->etype1 = cpu_to_le32(nla_get_u32(
2102                        tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1]));
2103                si->etype2 = cpu_to_le32(nla_get_u32(
2104                        tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2]));
2105                si->psh_hi = cpu_to_le32(nla_get_u32(
2106                        tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI]));
2107                si->psh_lo = cpu_to_le32(nla_get_u32(
2108                        tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO]));
2109                si->dtype_swch_off = cpu_to_le32(nla_get_u32(
2110                        tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]));
2111        }
2112
2113        cmd.rf_modules_vec = rf_modules_vec & 0xFF;
2114        memset(&reply, 0, sizeof(reply));
2115        rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
2116                      WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID,
2117                      &reply, sizeof(reply),
2118                      500);
2119        if (rc)
2120                return rc;
2121        return wil_rf_sector_status_to_rc(reply.evt.status);
2122}
2123
2124static int wil_rf_sector_get_selected(struct wiphy *wiphy,
2125                                      struct wireless_dev *wdev,
2126                                      const void *data, int data_len)
2127{
2128        struct wil6210_priv *wil = wdev_to_wil(wdev);
2129        int rc;
2130        struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
2131        u8 sector_type, mac_addr[ETH_ALEN];
2132        int cid = 0;
2133        struct wmi_get_selected_rf_sector_index_cmd cmd;
2134        struct {
2135                struct wmi_cmd_hdr wmi;
2136                struct wmi_get_selected_rf_sector_index_done_event evt;
2137        } __packed reply;
2138        struct sk_buff *msg;
2139
2140        if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
2141                return -EOPNOTSUPP;
2142
2143        rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2144                       wil_rf_sector_policy, NULL);
2145        if (rc) {
2146                wil_err(wil, "Invalid rf sector ATTR\n");
2147                return rc;
2148        }
2149
2150        if (!tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
2151                wil_err(wil, "Invalid rf sector spec\n");
2152                return -EINVAL;
2153        }
2154        sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
2155        if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
2156                wil_err(wil, "Invalid sector type %d\n", sector_type);
2157                return -EINVAL;
2158        }
2159
2160        if (tb[QCA_ATTR_MAC_ADDR]) {
2161                ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
2162                cid = wil_find_cid(wil, mac_addr);
2163                if (cid < 0) {
2164                        wil_err(wil, "invalid MAC address %pM\n", mac_addr);
2165                        return -ENOENT;
2166                }
2167        } else {
2168                if (test_bit(wil_status_fwconnected, wil->status)) {
2169                        wil_err(wil, "must specify MAC address when connected\n");
2170                        return -EINVAL;
2171                }
2172        }
2173
2174        memset(&cmd, 0, sizeof(cmd));
2175        cmd.cid = (u8)cid;
2176        cmd.sector_type = sector_type;
2177        memset(&reply, 0, sizeof(reply));
2178        rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID,
2179                      &cmd, sizeof(cmd),
2180                      WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
2181                      &reply, sizeof(reply),
2182                      500);
2183        if (rc)
2184                return rc;
2185        if (reply.evt.status) {
2186                wil_err(wil, "get rf selected sector cfg failed with status %d\n",
2187                        reply.evt.status);
2188                return wil_rf_sector_status_to_rc(reply.evt.status);
2189        }
2190
2191        msg = cfg80211_vendor_cmd_alloc_reply_skb(
2192                wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
2193        if (!msg)
2194                return -ENOMEM;
2195
2196        if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
2197                              le64_to_cpu(reply.evt.tsf),
2198                              QCA_ATTR_PAD) ||
2199            nla_put_u16(msg, QCA_ATTR_DMG_RF_SECTOR_INDEX,
2200                        le16_to_cpu(reply.evt.sector_idx)))
2201                goto nla_put_failure;
2202
2203        rc = cfg80211_vendor_cmd_reply(msg);
2204        return rc;
2205nla_put_failure:
2206        kfree_skb(msg);
2207        return -ENOBUFS;
2208}
2209
2210static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil,
2211                                          u16 sector_index,
2212                                          u8 sector_type, u8 cid)
2213{
2214        struct wmi_set_selected_rf_sector_index_cmd cmd;
2215        struct {
2216                struct wmi_cmd_hdr wmi;
2217                struct wmi_set_selected_rf_sector_index_done_event evt;
2218        } __packed reply;
2219        int rc;
2220
2221        memset(&cmd, 0, sizeof(cmd));
2222        cmd.sector_idx = cpu_to_le16(sector_index);
2223        cmd.sector_type = sector_type;
2224        cmd.cid = (u8)cid;
2225        memset(&reply, 0, sizeof(reply));
2226        rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID,
2227                      &cmd, sizeof(cmd),
2228                      WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
2229                      &reply, sizeof(reply),
2230                      500);
2231        if (rc)
2232                return rc;
2233        return wil_rf_sector_status_to_rc(reply.evt.status);
2234}
2235
2236static int wil_rf_sector_set_selected(struct wiphy *wiphy,
2237                                      struct wireless_dev *wdev,
2238                                      const void *data, int data_len)
2239{
2240        struct wil6210_priv *wil = wdev_to_wil(wdev);
2241        int rc;
2242        struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
2243        u16 sector_index;
2244        u8 sector_type, mac_addr[ETH_ALEN], i;
2245        int cid = 0;
2246
2247        if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
2248                return -EOPNOTSUPP;
2249
2250        rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2251                       wil_rf_sector_policy, NULL);
2252        if (rc) {
2253                wil_err(wil, "Invalid rf sector ATTR\n");
2254                return rc;
2255        }
2256
2257        if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
2258            !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
2259                wil_err(wil, "Invalid rf sector spec\n");
2260                return -EINVAL;
2261        }
2262
2263        sector_index = nla_get_u16(
2264                tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
2265        if (sector_index >= WIL_MAX_RF_SECTORS &&
2266            sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
2267                wil_err(wil, "Invalid sector index %d\n", sector_index);
2268                return -EINVAL;
2269        }
2270
2271        sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
2272        if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
2273                wil_err(wil, "Invalid sector type %d\n", sector_type);
2274                return -EINVAL;
2275        }
2276
2277        if (tb[QCA_ATTR_MAC_ADDR]) {
2278                ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
2279                if (!is_broadcast_ether_addr(mac_addr)) {
2280                        cid = wil_find_cid(wil, mac_addr);
2281                        if (cid < 0) {
2282                                wil_err(wil, "invalid MAC address %pM\n",
2283                                        mac_addr);
2284                                return -ENOENT;
2285                        }
2286                } else {
2287                        if (sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
2288                                wil_err(wil, "broadcast MAC valid only with unlocking\n");
2289                                return -EINVAL;
2290                        }
2291                        cid = -1;
2292                }
2293        } else {
2294                if (test_bit(wil_status_fwconnected, wil->status)) {
2295                        wil_err(wil, "must specify MAC address when connected\n");
2296                        return -EINVAL;
2297                }
2298                /* otherwise, using cid=0 for unassociated station */
2299        }
2300
2301        if (cid >= 0) {
2302                rc = wil_rf_sector_wmi_set_selected(wil, sector_index,
2303                                                    sector_type, cid);
2304        } else {
2305                /* unlock all cids */
2306                rc = wil_rf_sector_wmi_set_selected(
2307                        wil, WMI_INVALID_RF_SECTOR_INDEX, sector_type,
2308                        WIL_CID_ALL);
2309                if (rc == -EINVAL) {
2310                        for (i = 0; i < WIL6210_MAX_CID; i++) {
2311                                rc = wil_rf_sector_wmi_set_selected(
2312                                        wil, WMI_INVALID_RF_SECTOR_INDEX,
2313                                        sector_type, i);
2314                                /* the FW will silently ignore and return
2315                                 * success for unused cid, so abort the loop
2316                                 * on any other error
2317                                 */
2318                                if (rc) {
2319                                        wil_err(wil, "unlock cid %d failed with status %d\n",
2320                                                i, rc);
2321                                        break;
2322                                }
2323                        }
2324                }
2325        }
2326
2327        return rc;
2328}
2329