linux/drivers/net/wireless/quantenna/qtnfmac/commands.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
   3
   4#include <linux/types.h>
   5#include <linux/skbuff.h>
   6
   7#include "cfg80211.h"
   8#include "core.h"
   9#include "qlink.h"
  10#include "qlink_util.h"
  11#include "bus.h"
  12#include "commands.h"
  13
  14/* Let device itself to select best values for current conditions */
  15#define QTNF_SCAN_TIME_AUTO     0
  16
  17#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT          90
  18#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT         100
  19#define QTNF_SCAN_SAMPLE_DURATION_DEFAULT       QTNF_SCAN_TIME_AUTO
  20
  21static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp,
  22                                       u16 cmd_id, u8 mac_id, u8 vif_id,
  23                                       size_t resp_size)
  24{
  25        if (unlikely(le16_to_cpu(resp->cmd_id) != cmd_id)) {
  26                pr_warn("VIF%u.%u CMD%x: bad cmd_id in response: 0x%.4X\n",
  27                        mac_id, vif_id, cmd_id, le16_to_cpu(resp->cmd_id));
  28                return -EINVAL;
  29        }
  30
  31        if (unlikely(resp->macid != mac_id)) {
  32                pr_warn("VIF%u.%u CMD%x: bad MAC in response: %u\n",
  33                        mac_id, vif_id, cmd_id, resp->macid);
  34                return -EINVAL;
  35        }
  36
  37        if (unlikely(resp->vifid != vif_id)) {
  38                pr_warn("VIF%u.%u CMD%x: bad VIF in response: %u\n",
  39                        mac_id, vif_id, cmd_id, resp->vifid);
  40                return -EINVAL;
  41        }
  42
  43        if (unlikely(le16_to_cpu(resp->mhdr.len) < resp_size)) {
  44                pr_warn("VIF%u.%u CMD%x: bad response size %u < %zu\n",
  45                        mac_id, vif_id, cmd_id,
  46                        le16_to_cpu(resp->mhdr.len), resp_size);
  47                return -ENOSPC;
  48        }
  49
  50        return 0;
  51}
  52
  53static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode)
  54{
  55        switch (qcode) {
  56        case QLINK_CMD_RESULT_OK:
  57                return 0;
  58        case QLINK_CMD_RESULT_INVALID:
  59                return -EINVAL;
  60        case QLINK_CMD_RESULT_ENOTSUPP:
  61                return -ENOTSUPP;
  62        case QLINK_CMD_RESULT_ENOTFOUND:
  63                return -ENOENT;
  64        case QLINK_CMD_RESULT_EALREADY:
  65                return -EALREADY;
  66        case QLINK_CMD_RESULT_EADDRINUSE:
  67                return -EADDRINUSE;
  68        case QLINK_CMD_RESULT_EADDRNOTAVAIL:
  69                return -EADDRNOTAVAIL;
  70        case QLINK_CMD_RESULT_EBUSY:
  71                return -EBUSY;
  72        default:
  73                return -EFAULT;
  74        }
  75}
  76
  77static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
  78                                    struct sk_buff *cmd_skb,
  79                                    struct sk_buff **response_skb,
  80                                    size_t const_resp_size,
  81                                    size_t *var_resp_size)
  82{
  83        struct qlink_cmd *cmd;
  84        struct qlink_resp *resp = NULL;
  85        struct sk_buff *resp_skb = NULL;
  86        int resp_res = 0;
  87        u16 cmd_id;
  88        u8 mac_id;
  89        u8 vif_id;
  90        int ret;
  91
  92        cmd = (struct qlink_cmd *)cmd_skb->data;
  93        cmd_id = le16_to_cpu(cmd->cmd_id);
  94        mac_id = cmd->macid;
  95        vif_id = cmd->vifid;
  96        cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
  97
  98        pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id);
  99
 100        if (!qtnf_fw_is_up(bus) && cmd_id != QLINK_CMD_FW_INIT) {
 101                pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
 102                        mac_id, vif_id, cmd_id, bus->fw_state);
 103                dev_kfree_skb(cmd_skb);
 104                return -ENODEV;
 105        }
 106
 107        ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb);
 108        if (ret)
 109                goto out;
 110
 111        if (WARN_ON(!resp_skb || !resp_skb->data)) {
 112                ret = -EFAULT;
 113                goto out;
 114        }
 115
 116        resp = (struct qlink_resp *)resp_skb->data;
 117        resp_res = le16_to_cpu(resp->result);
 118        ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
 119                                          const_resp_size);
 120        if (ret)
 121                goto out;
 122
 123        /* Return length of variable part of response */
 124        if (response_skb && var_resp_size)
 125                *var_resp_size = le16_to_cpu(resp->mhdr.len) - const_resp_size;
 126
 127out:
 128        if (response_skb)
 129                *response_skb = resp_skb;
 130        else
 131                consume_skb(resp_skb);
 132
 133        if (!ret)
 134                return qtnf_cmd_resp_result_decode(resp_res);
 135
 136        pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n",
 137                mac_id, vif_id, cmd_id, ret);
 138
 139        return ret;
 140}
 141
 142static inline int qtnf_cmd_send(struct qtnf_bus *bus, struct sk_buff *cmd_skb)
 143{
 144        return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL,
 145                                        sizeof(struct qlink_resp), NULL);
 146}
 147
 148static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no,
 149                                                 size_t cmd_size)
 150{
 151        struct qlink_cmd *cmd;
 152        struct sk_buff *cmd_skb;
 153
 154        cmd_skb = __dev_alloc_skb(sizeof(*cmd) +
 155                                  QTNF_MAX_CMD_BUF_SIZE, GFP_KERNEL);
 156        if (unlikely(!cmd_skb)) {
 157                pr_err("VIF%u.%u CMD %u: alloc failed\n", macid, vifid, cmd_no);
 158                return NULL;
 159        }
 160
 161        skb_put_zero(cmd_skb, cmd_size);
 162
 163        cmd = (struct qlink_cmd *)cmd_skb->data;
 164        cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
 165        cmd->mhdr.type = cpu_to_le16(QLINK_MSG_TYPE_CMD);
 166        cmd->cmd_id = cpu_to_le16(cmd_no);
 167        cmd->macid = macid;
 168        cmd->vifid = vifid;
 169
 170        return cmd_skb;
 171}
 172
 173static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type,
 174                                    const u8 *buf, size_t len)
 175{
 176        struct qlink_tlv_ie_set *tlv;
 177
 178        tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) +
 179                                                 round_up(len, QLINK_ALIGN));
 180        tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET);
 181        tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr));
 182        tlv->type = frame_type;
 183        tlv->flags = 0;
 184
 185        if (len && buf)
 186                memcpy(tlv->ie_data, buf, len);
 187}
 188
 189static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
 190                                      const struct cfg80211_ap_settings *s)
 191{
 192        unsigned int len = sizeof(struct qlink_cmd_start_ap);
 193
 194        len += round_up(s->ssid_len, QLINK_ALIGN);
 195        len += round_up(s->beacon.head_len, QLINK_ALIGN);
 196        len += round_up(s->beacon.tail_len, QLINK_ALIGN);
 197        len += round_up(s->beacon.beacon_ies_len, QLINK_ALIGN);
 198        len += round_up(s->beacon.proberesp_ies_len, QLINK_ALIGN);
 199        len += round_up(s->beacon.assocresp_ies_len, QLINK_ALIGN);
 200        len += round_up(s->beacon.probe_resp_len, QLINK_ALIGN);
 201
 202        if (cfg80211_chandef_valid(&s->chandef))
 203                len += sizeof(struct qlink_tlv_chandef);
 204
 205        if (s->acl) {
 206                unsigned int acl_len = struct_size(s->acl, mac_addrs,
 207                                                   s->acl->n_acl_entries);
 208
 209                len += sizeof(struct qlink_tlv_hdr) +
 210                        round_up(acl_len, QLINK_ALIGN);
 211        }
 212
 213        if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
 214                pr_err("VIF%u.%u: can not fit AP settings: %u\n",
 215                       vif->mac->macid, vif->vifid, len);
 216                return false;
 217        }
 218
 219        return true;
 220}
 221
 222static void qtnf_cmd_tlv_ie_ext_add(struct sk_buff *cmd_skb, u8 eid_ext,
 223                                    const void *buf, size_t len)
 224{
 225        struct qlink_tlv_ext_ie *tlv;
 226
 227        tlv = (struct qlink_tlv_ext_ie *)skb_put(cmd_skb, sizeof(*tlv) + len);
 228        tlv->hdr.type = cpu_to_le16(WLAN_EID_EXTENSION);
 229        tlv->hdr.len = cpu_to_le16(sizeof(*tlv) + len - sizeof(tlv->hdr));
 230        tlv->eid_ext = eid_ext;
 231
 232        if (len && buf)
 233                memcpy(tlv->ie_data, buf, len);
 234}
 235
 236int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
 237                           const struct cfg80211_ap_settings *s)
 238{
 239        struct sk_buff *cmd_skb;
 240        struct qlink_cmd_start_ap *cmd;
 241        struct qlink_auth_encr *aen;
 242        int ret;
 243        int i;
 244
 245        if (!qtnf_cmd_start_ap_can_fit(vif, s))
 246                return -E2BIG;
 247
 248        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 249                                            QLINK_CMD_START_AP,
 250                                            sizeof(*cmd));
 251        if (!cmd_skb)
 252                return -ENOMEM;
 253
 254        cmd = (struct qlink_cmd_start_ap *)cmd_skb->data;
 255        cmd->dtim_period = s->dtim_period;
 256        cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
 257        cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
 258        cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout);
 259        cmd->smps_mode = s->smps_mode;
 260        cmd->p2p_ctwindow = s->p2p_ctwindow;
 261        cmd->p2p_opp_ps = s->p2p_opp_ps;
 262        cmd->pbss = s->pbss;
 263        cmd->ht_required = s->ht_required;
 264        cmd->vht_required = s->vht_required;
 265        cmd->twt_responder = s->twt_responder;
 266        if (s->he_obss_pd.enable) {
 267                cmd->sr_params.sr_control |= QLINK_SR_SRG_INFORMATION_PRESENT;
 268                cmd->sr_params.srg_obss_pd_min_offset =
 269                        s->he_obss_pd.min_offset;
 270                cmd->sr_params.srg_obss_pd_max_offset =
 271                        s->he_obss_pd.max_offset;
 272        }
 273
 274        aen = &cmd->aen;
 275        aen->auth_type = s->auth_type;
 276        aen->privacy = !!s->privacy;
 277        aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
 278        aen->cipher_group = cpu_to_le32(s->crypto.cipher_group);
 279        aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
 280        for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
 281                aen->ciphers_pairwise[i] =
 282                                cpu_to_le32(s->crypto.ciphers_pairwise[i]);
 283        aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
 284        for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
 285                aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
 286        aen->control_port = s->crypto.control_port;
 287        aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt;
 288        aen->control_port_ethertype =
 289                cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype));
 290
 291        if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
 292                qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
 293                                         s->ssid_len);
 294
 295        if (cfg80211_chandef_valid(&s->chandef)) {
 296                struct qlink_tlv_chandef *chtlv =
 297                        (struct qlink_tlv_chandef *)skb_put(cmd_skb,
 298                                                            sizeof(*chtlv));
 299
 300                chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF);
 301                chtlv->hdr.len = cpu_to_le16(sizeof(*chtlv) -
 302                                             sizeof(chtlv->hdr));
 303                qlink_chandef_cfg2q(&s->chandef, &chtlv->chdef);
 304        }
 305
 306        qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_HEAD,
 307                                s->beacon.head, s->beacon.head_len);
 308        qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_TAIL,
 309                                s->beacon.tail, s->beacon.tail_len);
 310        qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_IES,
 311                                s->beacon.beacon_ies, s->beacon.beacon_ies_len);
 312        qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP,
 313                                s->beacon.probe_resp, s->beacon.probe_resp_len);
 314        qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP_IES,
 315                                s->beacon.proberesp_ies,
 316                                s->beacon.proberesp_ies_len);
 317        qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_RESP,
 318                                s->beacon.assocresp_ies,
 319                                s->beacon.assocresp_ies_len);
 320
 321        if (s->ht_cap) {
 322                struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
 323                        skb_put(cmd_skb, sizeof(*tlv) +
 324                                round_up(sizeof(*s->ht_cap), QLINK_ALIGN));
 325
 326                tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
 327                tlv->len = cpu_to_le16(sizeof(*s->ht_cap));
 328                memcpy(tlv->val, s->ht_cap, sizeof(*s->ht_cap));
 329        }
 330
 331        if (s->vht_cap) {
 332                struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
 333                        skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->vht_cap));
 334
 335                tlv->type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
 336                tlv->len = cpu_to_le16(sizeof(*s->vht_cap));
 337                memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap));
 338        }
 339
 340        if (s->he_cap)
 341                qtnf_cmd_tlv_ie_ext_add(cmd_skb, WLAN_EID_EXT_HE_CAPABILITY,
 342                                        s->he_cap, sizeof(*s->he_cap));
 343
 344        if (s->acl) {
 345                size_t acl_size = struct_size(s->acl, mac_addrs,
 346                                              s->acl->n_acl_entries);
 347                struct qlink_tlv_hdr *tlv =
 348                        skb_put(cmd_skb,
 349                                sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN));
 350
 351                tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
 352                tlv->len = cpu_to_le16(acl_size);
 353                qlink_acl_data_cfg2q(s->acl, (struct qlink_acl_data *)tlv->val);
 354        }
 355
 356        qtnf_bus_lock(vif->mac->bus);
 357        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
 358        if (ret)
 359                goto out;
 360
 361        netif_carrier_on(vif->netdev);
 362
 363out:
 364        qtnf_bus_unlock(vif->mac->bus);
 365
 366        return ret;
 367}
 368
 369int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
 370{
 371        struct sk_buff *cmd_skb;
 372        int ret;
 373
 374        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 375                                            QLINK_CMD_STOP_AP,
 376                                            sizeof(struct qlink_cmd));
 377        if (!cmd_skb)
 378                return -ENOMEM;
 379
 380        qtnf_bus_lock(vif->mac->bus);
 381        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
 382        qtnf_bus_unlock(vif->mac->bus);
 383
 384        return ret;
 385}
 386
 387int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
 388{
 389        struct sk_buff *cmd_skb;
 390        struct qlink_cmd_mgmt_frame_register *cmd;
 391        int ret;
 392
 393        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 394                                            QLINK_CMD_REGISTER_MGMT,
 395                                            sizeof(*cmd));
 396        if (!cmd_skb)
 397                return -ENOMEM;
 398
 399        qtnf_bus_lock(vif->mac->bus);
 400
 401        cmd = (struct qlink_cmd_mgmt_frame_register *)cmd_skb->data;
 402        cmd->frame_type = cpu_to_le16(frame_type);
 403        cmd->do_register = reg;
 404
 405        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
 406
 407        qtnf_bus_unlock(vif->mac->bus);
 408
 409        return ret;
 410}
 411
 412int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
 413                        u16 freq, const u8 *buf, size_t len)
 414{
 415        struct sk_buff *cmd_skb;
 416        struct qlink_cmd_frame_tx *cmd;
 417        int ret;
 418
 419        if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
 420                pr_warn("VIF%u.%u: frame is too big: %zu\n", vif->mac->macid,
 421                        vif->vifid, len);
 422                return -E2BIG;
 423        }
 424
 425        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 426                                            QLINK_CMD_SEND_FRAME,
 427                                            sizeof(*cmd));
 428        if (!cmd_skb)
 429                return -ENOMEM;
 430
 431        qtnf_bus_lock(vif->mac->bus);
 432
 433        cmd = (struct qlink_cmd_frame_tx *)cmd_skb->data;
 434        cmd->cookie = cpu_to_le32(cookie);
 435        cmd->freq = cpu_to_le16(freq);
 436        cmd->flags = cpu_to_le16(flags);
 437
 438        if (len && buf)
 439                qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
 440
 441        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
 442
 443        qtnf_bus_unlock(vif->mac->bus);
 444
 445        return ret;
 446}
 447
 448int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
 449                                 const u8 *buf, size_t len)
 450{
 451        struct sk_buff *cmd_skb;
 452        int ret;
 453
 454        if (len > QTNF_MAX_CMD_BUF_SIZE) {
 455                pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
 456                        vif->vifid, frame_type, len);
 457                return -E2BIG;
 458        }
 459
 460        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 461                                            QLINK_CMD_MGMT_SET_APPIE,
 462                                            sizeof(struct qlink_cmd));
 463        if (!cmd_skb)
 464                return -ENOMEM;
 465
 466        qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len);
 467
 468        qtnf_bus_lock(vif->mac->bus);
 469        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
 470        qtnf_bus_unlock(vif->mac->bus);
 471
 472        return ret;
 473}
 474
 475static void
 476qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
 477                         const struct qlink_sta_info_rate *rate_src)
 478{
 479        rate_dst->legacy = get_unaligned_le16(&rate_src->rate) * 10;
 480
 481        rate_dst->mcs = rate_src->mcs;
 482        rate_dst->nss = rate_src->nss;
 483        rate_dst->flags = 0;
 484
 485        switch (rate_src->bw) {
 486        case QLINK_CHAN_WIDTH_5:
 487                rate_dst->bw = RATE_INFO_BW_5;
 488                break;
 489        case QLINK_CHAN_WIDTH_10:
 490                rate_dst->bw = RATE_INFO_BW_10;
 491                break;
 492        case QLINK_CHAN_WIDTH_20:
 493        case QLINK_CHAN_WIDTH_20_NOHT:
 494                rate_dst->bw = RATE_INFO_BW_20;
 495                break;
 496        case QLINK_CHAN_WIDTH_40:
 497                rate_dst->bw = RATE_INFO_BW_40;
 498                break;
 499        case QLINK_CHAN_WIDTH_80:
 500                rate_dst->bw = RATE_INFO_BW_80;
 501                break;
 502        case QLINK_CHAN_WIDTH_160:
 503                rate_dst->bw = RATE_INFO_BW_160;
 504                break;
 505        default:
 506                rate_dst->bw = 0;
 507                break;
 508        }
 509
 510        if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HT_MCS)
 511                rate_dst->flags |= RATE_INFO_FLAGS_MCS;
 512        else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
 513                rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
 514        else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HE_MCS)
 515                rate_dst->flags |= RATE_INFO_FLAGS_HE_MCS;
 516
 517        if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI)
 518                rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI;
 519}
 520
 521static void
 522qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst,
 523                          const struct qlink_sta_info_state *src)
 524{
 525        u32 mask, value;
 526
 527        dst->mask = 0;
 528        dst->set = 0;
 529
 530        mask = le32_to_cpu(src->mask);
 531        value = le32_to_cpu(src->value);
 532
 533        if (mask & QLINK_STA_FLAG_AUTHORIZED) {
 534                dst->mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
 535                if (value & QLINK_STA_FLAG_AUTHORIZED)
 536                        dst->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
 537        }
 538
 539        if (mask & QLINK_STA_FLAG_SHORT_PREAMBLE) {
 540                dst->mask |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
 541                if (value & QLINK_STA_FLAG_SHORT_PREAMBLE)
 542                        dst->set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
 543        }
 544
 545        if (mask & QLINK_STA_FLAG_WME) {
 546                dst->mask |= BIT(NL80211_STA_FLAG_WME);
 547                if (value & QLINK_STA_FLAG_WME)
 548                        dst->set |= BIT(NL80211_STA_FLAG_WME);
 549        }
 550
 551        if (mask & QLINK_STA_FLAG_MFP) {
 552                dst->mask |= BIT(NL80211_STA_FLAG_MFP);
 553                if (value & QLINK_STA_FLAG_MFP)
 554                        dst->set |= BIT(NL80211_STA_FLAG_MFP);
 555        }
 556
 557        if (mask & QLINK_STA_FLAG_AUTHENTICATED) {
 558                dst->mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
 559                if (value & QLINK_STA_FLAG_AUTHENTICATED)
 560                        dst->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
 561        }
 562
 563        if (mask & QLINK_STA_FLAG_TDLS_PEER) {
 564                dst->mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 565                if (value & QLINK_STA_FLAG_TDLS_PEER)
 566                        dst->set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 567        }
 568
 569        if (mask & QLINK_STA_FLAG_ASSOCIATED) {
 570                dst->mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
 571                if (value & QLINK_STA_FLAG_ASSOCIATED)
 572                        dst->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
 573        }
 574}
 575
 576static void
 577qtnf_cmd_sta_info_parse(struct station_info *sinfo, const u8 *data,
 578                        size_t resp_size)
 579{
 580        const struct qlink_tlv_hdr *tlv;
 581        const struct qlink_sta_stats *stats = NULL;
 582        const u8 *map = NULL;
 583        unsigned int map_len = 0;
 584        unsigned int stats_len = 0;
 585        u16 tlv_len;
 586
 587#define qtnf_sta_stat_avail(stat_name, bitn)    \
 588        (qtnf_utils_is_bit_set(map, bitn, map_len) && \
 589         (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len))
 590
 591        qlink_for_each_tlv(tlv, data, resp_size) {
 592                tlv_len = le16_to_cpu(tlv->len);
 593
 594                switch (le16_to_cpu(tlv->type)) {
 595                case QTN_TLV_ID_BITMAP:
 596                        map_len = tlv_len;
 597                        map = tlv->val;
 598                        break;
 599                case QTN_TLV_ID_STA_STATS:
 600                        stats_len = tlv_len;
 601                        stats = (const struct qlink_sta_stats *)tlv->val;
 602                        break;
 603                default:
 604                        break;
 605                }
 606        }
 607
 608        if (!qlink_tlv_parsing_ok(tlv, data, resp_size)) {
 609                pr_err("Malformed TLV buffer\n");
 610                return;
 611        }
 612
 613        if (!map || !stats)
 614                return;
 615
 616        if (qtnf_sta_stat_avail(inactive_time, QLINK_STA_INFO_INACTIVE_TIME)) {
 617                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
 618                sinfo->inactive_time = le32_to_cpu(stats->inactive_time);
 619        }
 620
 621        if (qtnf_sta_stat_avail(connected_time,
 622                                QLINK_STA_INFO_CONNECTED_TIME)) {
 623                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME);
 624                sinfo->connected_time = le32_to_cpu(stats->connected_time);
 625        }
 626
 627        if (qtnf_sta_stat_avail(signal, QLINK_STA_INFO_SIGNAL)) {
 628                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
 629                sinfo->signal = stats->signal - QLINK_RSSI_OFFSET;
 630        }
 631
 632        if (qtnf_sta_stat_avail(signal_avg, QLINK_STA_INFO_SIGNAL_AVG)) {
 633                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
 634                sinfo->signal_avg = stats->signal_avg - QLINK_RSSI_OFFSET;
 635        }
 636
 637        if (qtnf_sta_stat_avail(rxrate, QLINK_STA_INFO_RX_BITRATE)) {
 638                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
 639                qtnf_sta_info_parse_rate(&sinfo->rxrate, &stats->rxrate);
 640        }
 641
 642        if (qtnf_sta_stat_avail(txrate, QLINK_STA_INFO_TX_BITRATE)) {
 643                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
 644                qtnf_sta_info_parse_rate(&sinfo->txrate, &stats->txrate);
 645        }
 646
 647        if (qtnf_sta_stat_avail(sta_flags, QLINK_STA_INFO_STA_FLAGS)) {
 648                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_STA_FLAGS);
 649                qtnf_sta_info_parse_flags(&sinfo->sta_flags, &stats->sta_flags);
 650        }
 651
 652        if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES)) {
 653                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
 654                sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
 655        }
 656
 657        if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES)) {
 658                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
 659                sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
 660        }
 661
 662        if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES64)) {
 663                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
 664                sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
 665        }
 666
 667        if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES64)) {
 668                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
 669                sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
 670        }
 671
 672        if (qtnf_sta_stat_avail(rx_packets, QLINK_STA_INFO_RX_PACKETS)) {
 673                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
 674                sinfo->rx_packets = le32_to_cpu(stats->rx_packets);
 675        }
 676
 677        if (qtnf_sta_stat_avail(tx_packets, QLINK_STA_INFO_TX_PACKETS)) {
 678                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
 679                sinfo->tx_packets = le32_to_cpu(stats->tx_packets);
 680        }
 681
 682        if (qtnf_sta_stat_avail(rx_beacon, QLINK_STA_INFO_BEACON_RX)) {
 683                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX);
 684                sinfo->rx_beacon = le64_to_cpu(stats->rx_beacon);
 685        }
 686
 687        if (qtnf_sta_stat_avail(rx_dropped_misc, QLINK_STA_INFO_RX_DROP_MISC)) {
 688                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC);
 689                sinfo->rx_dropped_misc = le32_to_cpu(stats->rx_dropped_misc);
 690        }
 691
 692        if (qtnf_sta_stat_avail(tx_failed, QLINK_STA_INFO_TX_FAILED)) {
 693                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
 694                sinfo->tx_failed = le32_to_cpu(stats->tx_failed);
 695        }
 696
 697#undef qtnf_sta_stat_avail
 698}
 699
 700int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
 701                          struct station_info *sinfo)
 702{
 703        struct sk_buff *cmd_skb, *resp_skb = NULL;
 704        struct qlink_cmd_get_sta_info *cmd;
 705        const struct qlink_resp_get_sta_info *resp;
 706        size_t var_resp_len = 0;
 707        int ret = 0;
 708
 709        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 710                                            QLINK_CMD_GET_STA_INFO,
 711                                            sizeof(*cmd));
 712        if (!cmd_skb)
 713                return -ENOMEM;
 714
 715        qtnf_bus_lock(vif->mac->bus);
 716
 717        cmd = (struct qlink_cmd_get_sta_info *)cmd_skb->data;
 718        ether_addr_copy(cmd->sta_addr, sta_mac);
 719
 720        ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
 721                                       sizeof(*resp), &var_resp_len);
 722        if (ret)
 723                goto out;
 724
 725        resp = (const struct qlink_resp_get_sta_info *)resp_skb->data;
 726
 727        if (!ether_addr_equal(sta_mac, resp->sta_addr)) {
 728                pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n",
 729                       vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac);
 730                ret = -EINVAL;
 731                goto out;
 732        }
 733
 734        qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len);
 735
 736out:
 737        qtnf_bus_unlock(vif->mac->bus);
 738        consume_skb(resp_skb);
 739
 740        return ret;
 741}
 742
 743static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
 744                                         enum nl80211_iftype iftype,
 745                                         int use4addr,
 746                                         u8 *mac_addr,
 747                                         enum qlink_cmd_type cmd_type)
 748{
 749        struct sk_buff *cmd_skb, *resp_skb = NULL;
 750        struct qlink_cmd_manage_intf *cmd;
 751        const struct qlink_resp_manage_intf *resp;
 752        int ret = 0;
 753
 754        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 755                                            cmd_type,
 756                                            sizeof(*cmd));
 757        if (!cmd_skb)
 758                return -ENOMEM;
 759
 760        qtnf_bus_lock(vif->mac->bus);
 761
 762        cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
 763        cmd->intf_info.use4addr = use4addr;
 764
 765        switch (iftype) {
 766        case NL80211_IFTYPE_AP:
 767                cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
 768                break;
 769        case NL80211_IFTYPE_STATION:
 770                cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
 771                break;
 772        default:
 773                pr_err("VIF%u.%u: unsupported type %d\n", vif->mac->macid,
 774                       vif->vifid, iftype);
 775                ret = -EINVAL;
 776                goto out;
 777        }
 778
 779        if (mac_addr)
 780                ether_addr_copy(cmd->intf_info.mac_addr, mac_addr);
 781        else
 782                eth_zero_addr(cmd->intf_info.mac_addr);
 783
 784        ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
 785                                       sizeof(*resp), NULL);
 786        if (ret)
 787                goto out;
 788
 789        resp = (const struct qlink_resp_manage_intf *)resp_skb->data;
 790        ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr);
 791
 792out:
 793        qtnf_bus_unlock(vif->mac->bus);
 794        consume_skb(resp_skb);
 795
 796        return ret;
 797}
 798
 799int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
 800                           int use4addr, u8 *mac_addr)
 801{
 802        return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
 803                        QLINK_CMD_ADD_INTF);
 804}
 805
 806int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
 807                                   enum nl80211_iftype iftype,
 808                                   int use4addr,
 809                                   u8 *mac_addr)
 810{
 811        int ret;
 812
 813        ret = qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
 814                                            QLINK_CMD_CHANGE_INTF);
 815
 816        /* Regulatory settings may be different for different interface types */
 817        if (ret == 0 && vif->wdev.iftype != iftype) {
 818                enum nl80211_band band;
 819                struct wiphy *wiphy = priv_to_wiphy(vif->mac);
 820
 821                for (band = 0; band < NUM_NL80211_BANDS; ++band) {
 822                        if (!wiphy->bands[band])
 823                                continue;
 824
 825                        qtnf_cmd_band_info_get(vif->mac, wiphy->bands[band]);
 826                }
 827        }
 828
 829        return ret;
 830}
 831
 832int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
 833{
 834        struct sk_buff *cmd_skb;
 835        struct qlink_cmd_manage_intf *cmd;
 836        int ret = 0;
 837
 838        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
 839                                            QLINK_CMD_DEL_INTF,
 840                                            sizeof(*cmd));
 841        if (!cmd_skb)
 842                return -ENOMEM;
 843
 844        qtnf_bus_lock(vif->mac->bus);
 845
 846        cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
 847
 848        switch (vif->wdev.iftype) {
 849        case NL80211_IFTYPE_AP:
 850                cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
 851                break;
 852        case NL80211_IFTYPE_STATION:
 853                cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
 854                break;
 855        default:
 856                pr_warn("VIF%u.%u: unsupported iftype %d\n", vif->mac->macid,
 857                        vif->vifid, vif->wdev.iftype);
 858                dev_kfree_skb(cmd_skb);
 859                ret = -EINVAL;
 860                goto out;
 861        }
 862
 863        eth_zero_addr(cmd->intf_info.mac_addr);
 864
 865        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
 866        if (ret)
 867                goto out;
 868
 869out:
 870        qtnf_bus_unlock(vif->mac->bus);
 871        return ret;
 872}
 873
 874static int
 875qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
 876                           const struct qlink_resp_get_hw_info *resp,
 877                           size_t info_len)
 878{
 879        struct qtnf_hw_info *hwinfo = &bus->hw_info;
 880        const struct qlink_tlv_hdr *tlv;
 881        const char *bld_name = NULL;
 882        const char *bld_rev = NULL;
 883        const char *bld_type = NULL;
 884        const char *bld_label = NULL;
 885        u32 bld_tmstamp = 0;
 886        u32 plat_id = 0;
 887        const char *hw_id = NULL;
 888        const char *calibration_ver = NULL;
 889        const char *uboot_ver = NULL;
 890        u32 hw_ver = 0;
 891        u16 tlv_type;
 892        u16 tlv_len;
 893
 894        hwinfo->num_mac = resp->num_mac;
 895        hwinfo->mac_bitmap = resp->mac_bitmap;
 896        hwinfo->fw_ver = le32_to_cpu(resp->fw_ver);
 897        hwinfo->total_tx_chain = resp->total_tx_chain;
 898        hwinfo->total_rx_chain = resp->total_rx_chain;
 899
 900        bld_tmstamp = le32_to_cpu(resp->bld_tmstamp);
 901        plat_id = le32_to_cpu(resp->plat_id);
 902        hw_ver = le32_to_cpu(resp->hw_ver);
 903
 904        qlink_for_each_tlv(tlv, resp->info, info_len) {
 905                tlv_type = le16_to_cpu(tlv->type);
 906                tlv_len = le16_to_cpu(tlv->len);
 907
 908                switch (tlv_type) {
 909                case QTN_TLV_ID_BUILD_NAME:
 910                        bld_name = (const void *)tlv->val;
 911                        break;
 912                case QTN_TLV_ID_BUILD_REV:
 913                        bld_rev = (const void *)tlv->val;
 914                        break;
 915                case QTN_TLV_ID_BUILD_TYPE:
 916                        bld_type = (const void *)tlv->val;
 917                        break;
 918                case QTN_TLV_ID_BUILD_LABEL:
 919                        bld_label = (const void *)tlv->val;
 920                        break;
 921                case QTN_TLV_ID_HW_ID:
 922                        hw_id = (const void *)tlv->val;
 923                        break;
 924                case QTN_TLV_ID_CALIBRATION_VER:
 925                        calibration_ver = (const void *)tlv->val;
 926                        break;
 927                case QTN_TLV_ID_UBOOT_VER:
 928                        uboot_ver = (const void *)tlv->val;
 929                        break;
 930                case QTN_TLV_ID_BITMAP:
 931                        memcpy(hwinfo->hw_capab, tlv->val,
 932                               min(sizeof(hwinfo->hw_capab), (size_t)tlv_len));
 933                        break;
 934                default:
 935                        break;
 936                }
 937        }
 938
 939        if (!qlink_tlv_parsing_ok(tlv, resp->info, info_len)) {
 940                pr_err("Malformed TLV buffer\n");
 941                return -EINVAL;
 942        }
 943
 944        pr_info("\nBuild name:            %s\n"
 945                "Build revision:        %s\n"
 946                "Build type:            %s\n"
 947                "Build label:           %s\n"
 948                "Build timestamp:       %lu\n"
 949                "Platform ID:           %lu\n"
 950                "Hardware ID:           %s\n"
 951                "Calibration version:   %s\n"
 952                "U-Boot version:        %s\n"
 953                "Hardware version:      0x%08x\n"
 954                "Qlink ver:             %u.%u\n"
 955                "MACs map:              %#x\n"
 956                "Chains Rx-Tx:          %ux%u\n"
 957                "FW version:            0x%x\n",
 958                bld_name, bld_rev, bld_type, bld_label,
 959                (unsigned long)bld_tmstamp,
 960                (unsigned long)plat_id,
 961                hw_id, calibration_ver, uboot_ver, hw_ver,
 962                QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver),
 963                QLINK_VER_MINOR(bus->hw_info.ql_proto_ver),
 964                hwinfo->mac_bitmap,
 965                hwinfo->total_rx_chain, hwinfo->total_tx_chain,
 966                hwinfo->fw_ver);
 967
 968        strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
 969        hwinfo->hw_version = hw_ver;
 970
 971        return 0;
 972}
 973
 974static void
 975qtnf_parse_wowlan_info(struct qtnf_wmac *mac,
 976                       const struct qlink_wowlan_capab_data *wowlan)
 977{
 978        struct qtnf_mac_info *mac_info = &mac->macinfo;
 979        const struct qlink_wowlan_support *data1;
 980        struct wiphy_wowlan_support *supp;
 981
 982        supp = kzalloc(sizeof(*supp), GFP_KERNEL);
 983        if (!supp)
 984                return;
 985
 986        switch (le16_to_cpu(wowlan->version)) {
 987        case 0x1:
 988                data1 = (struct qlink_wowlan_support *)wowlan->data;
 989
 990                supp->flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT;
 991                supp->n_patterns = le32_to_cpu(data1->n_patterns);
 992                supp->pattern_max_len = le32_to_cpu(data1->pattern_max_len);
 993                supp->pattern_min_len = le32_to_cpu(data1->pattern_min_len);
 994
 995                mac_info->wowlan = supp;
 996                break;
 997        default:
 998                pr_warn("MAC%u: unsupported WoWLAN version 0x%x\n",
 999                        mac->macid, le16_to_cpu(wowlan->version));
1000                kfree(supp);
1001                break;
1002        }
1003}
1004
1005static int
1006qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
1007                             const struct qlink_resp_get_mac_info *resp,
1008                             size_t tlv_buf_size)
1009{
1010        struct ieee80211_iface_combination *comb = mac->macinfo.if_comb;
1011        size_t n_comb = 0;
1012        struct ieee80211_iface_limit *limits;
1013        const struct qlink_iface_limit_record *rec;
1014        const struct qlink_iface_limit *lim;
1015        const struct qlink_wowlan_capab_data *wowlan;
1016        u16 rec_len;
1017        u16 tlv_type;
1018        u16 tlv_value_len;
1019        const struct qlink_tlv_hdr *tlv;
1020        u8 *ext_capa = NULL;
1021        u8 *ext_capa_mask = NULL;
1022        u8 ext_capa_len = 0;
1023        u8 ext_capa_mask_len = 0;
1024        int i = 0;
1025        struct ieee80211_reg_rule *rule;
1026        unsigned int rule_idx = 0;
1027        const struct qlink_tlv_reg_rule *tlv_rule;
1028
1029        if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
1030                return -E2BIG;
1031
1032        mac->rd = kzalloc(struct_size(mac->rd, reg_rules, resp->n_reg_rules),
1033                          GFP_KERNEL);
1034        if (!mac->rd)
1035                return -ENOMEM;
1036
1037        mac->rd->n_reg_rules = resp->n_reg_rules;
1038        mac->rd->alpha2[0] = resp->alpha2[0];
1039        mac->rd->alpha2[1] = resp->alpha2[1];
1040
1041        switch (resp->dfs_region) {
1042        case QLINK_DFS_FCC:
1043                mac->rd->dfs_region = NL80211_DFS_FCC;
1044                break;
1045        case QLINK_DFS_ETSI:
1046                mac->rd->dfs_region = NL80211_DFS_ETSI;
1047                break;
1048        case QLINK_DFS_JP:
1049                mac->rd->dfs_region = NL80211_DFS_JP;
1050                break;
1051        case QLINK_DFS_UNSET:
1052        default:
1053                mac->rd->dfs_region = NL80211_DFS_UNSET;
1054                break;
1055        }
1056
1057        qlink_for_each_tlv(tlv, resp->var_info, tlv_buf_size) {
1058                tlv_type = le16_to_cpu(tlv->type);
1059                tlv_value_len = le16_to_cpu(tlv->len);
1060
1061                switch (tlv_type) {
1062                case QTN_TLV_ID_IFACE_LIMIT:
1063                        if (unlikely(!comb)) {
1064                                pr_warn("MAC%u: no combinations advertised\n",
1065                                        mac->macid);
1066                                return -EINVAL;
1067                        }
1068
1069                        if (n_comb >= mac->macinfo.n_if_comb) {
1070                                pr_warn("MAC%u: combinations count exceeded\n",
1071                                        mac->macid);
1072                                n_comb++;
1073                                break;
1074                        }
1075
1076                        rec = (void *)tlv->val;
1077                        rec_len = sizeof(*rec) + rec->n_limits * sizeof(*lim);
1078
1079                        if (unlikely(tlv_value_len != rec_len)) {
1080                                pr_warn("MAC%u: record %zu size mismatch\n",
1081                                        mac->macid, n_comb);
1082                                return -EINVAL;
1083                        }
1084
1085                        limits = kcalloc(rec->n_limits, sizeof(*limits),
1086                                         GFP_KERNEL);
1087                        if (!limits)
1088                                return -ENOMEM;
1089
1090                        comb[n_comb].num_different_channels =
1091                                rec->num_different_channels;
1092                        comb[n_comb].max_interfaces =
1093                                le16_to_cpu(rec->max_interfaces);
1094                        comb[n_comb].n_limits = rec->n_limits;
1095                        comb[n_comb].limits = limits;
1096
1097                        for (i = 0; i < rec->n_limits; i++) {
1098                                lim = &rec->limits[i];
1099                                limits[i].max = le16_to_cpu(lim->max_num);
1100                                limits[i].types =
1101                                        qlink_iface_type_to_nl_mask(le16_to_cpu(lim->type));
1102                                pr_debug("MAC%u: comb[%zu]: MAX:%u TYPES:%.4X\n",
1103                                         mac->macid, n_comb,
1104                                         limits[i].max, limits[i].types);
1105                        }
1106
1107                        n_comb++;
1108                        break;
1109                case WLAN_EID_EXT_CAPABILITY:
1110                        if (unlikely(tlv_value_len > U8_MAX))
1111                                return -EINVAL;
1112                        ext_capa = (u8 *)tlv->val;
1113                        ext_capa_len = tlv_value_len;
1114                        break;
1115                case QTN_TLV_ID_EXT_CAPABILITY_MASK:
1116                        if (unlikely(tlv_value_len > U8_MAX))
1117                                return -EINVAL;
1118                        ext_capa_mask = (u8 *)tlv->val;
1119                        ext_capa_mask_len = tlv_value_len;
1120                        break;
1121                case QTN_TLV_ID_WOWLAN_CAPAB:
1122                        if (tlv_value_len < sizeof(*wowlan))
1123                                return -EINVAL;
1124
1125                        wowlan = (void *)tlv->val;
1126                        if (!le16_to_cpu(wowlan->len)) {
1127                                pr_warn("MAC%u: skip empty WoWLAN data\n",
1128                                        mac->macid);
1129                                break;
1130                        }
1131
1132                        rec_len = sizeof(*wowlan) + le16_to_cpu(wowlan->len);
1133                        if (unlikely(tlv_value_len != rec_len)) {
1134                                pr_warn("MAC%u: WoWLAN data size mismatch\n",
1135                                        mac->macid);
1136                                return -EINVAL;
1137                        }
1138
1139                        kfree(mac->macinfo.wowlan);
1140                        mac->macinfo.wowlan = NULL;
1141                        qtnf_parse_wowlan_info(mac, wowlan);
1142                        break;
1143                case QTN_TLV_ID_REG_RULE:
1144                        if (rule_idx >= resp->n_reg_rules) {
1145                                pr_warn("unexpected number of rules: %u\n",
1146                                        resp->n_reg_rules);
1147                                return -EINVAL;
1148                        }
1149
1150                        if (tlv_value_len != sizeof(*tlv_rule) - sizeof(*tlv)) {
1151                                pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
1152                                        tlv_type, tlv_value_len);
1153                                return -EINVAL;
1154                        }
1155
1156                        tlv_rule = (const struct qlink_tlv_reg_rule *)tlv;
1157                        rule = &mac->rd->reg_rules[rule_idx++];
1158                        qlink_utils_regrule_q2nl(rule, tlv_rule);
1159                        break;
1160                default:
1161                        pr_warn("MAC%u: unknown TLV type %u\n",
1162                                mac->macid, tlv_type);
1163                        break;
1164                }
1165        }
1166
1167        if (!qlink_tlv_parsing_ok(tlv, resp->var_info, tlv_buf_size)) {
1168                pr_err("Malformed TLV buffer\n");
1169                return -EINVAL;
1170        }
1171
1172        if (mac->macinfo.n_if_comb != n_comb) {
1173                pr_err("MAC%u: combination mismatch: reported=%zu parsed=%zu\n",
1174                       mac->macid, mac->macinfo.n_if_comb, n_comb);
1175                return -EINVAL;
1176        }
1177
1178        if (ext_capa_len != ext_capa_mask_len) {
1179                pr_err("MAC%u: ext_capa/_mask lengths mismatch: %u != %u\n",
1180                       mac->macid, ext_capa_len, ext_capa_mask_len);
1181                return -EINVAL;
1182        }
1183
1184        if (rule_idx != resp->n_reg_rules) {
1185                pr_warn("unexpected number of rules: expected %u got %u\n",
1186                        resp->n_reg_rules, rule_idx);
1187                return -EINVAL;
1188        }
1189
1190        if (ext_capa_len > 0) {
1191                ext_capa = kmemdup(ext_capa, ext_capa_len, GFP_KERNEL);
1192                if (!ext_capa)
1193                        return -ENOMEM;
1194
1195                ext_capa_mask =
1196                        kmemdup(ext_capa_mask, ext_capa_mask_len, GFP_KERNEL);
1197                if (!ext_capa_mask) {
1198                        kfree(ext_capa);
1199                        return -ENOMEM;
1200                }
1201        } else {
1202                ext_capa = NULL;
1203                ext_capa_mask = NULL;
1204        }
1205
1206        qtnf_mac_ext_caps_free(mac);
1207        mac->macinfo.extended_capabilities = ext_capa;
1208        mac->macinfo.extended_capabilities_mask = ext_capa_mask;
1209        mac->macinfo.extended_capabilities_len = ext_capa_len;
1210
1211        return 0;
1212}
1213
1214static int
1215qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
1216                            const struct qlink_resp_get_mac_info *resp_info)
1217{
1218        struct qtnf_mac_info *mac_info;
1219        struct qtnf_vif *vif;
1220
1221        qtnf_mac_iface_comb_free(mac);
1222
1223        mac_info = &mac->macinfo;
1224
1225        mac_info->bands_cap = resp_info->bands_cap;
1226        ether_addr_copy(mac->macaddr, resp_info->dev_mac);
1227
1228        vif = qtnf_mac_get_base_vif(mac);
1229        if (vif)
1230                ether_addr_copy(vif->mac_addr, mac->macaddr);
1231        else
1232                pr_err("could not get valid base vif\n");
1233
1234        mac_info->num_tx_chain = resp_info->num_tx_chain;
1235        mac_info->num_rx_chain = resp_info->num_rx_chain;
1236
1237        mac_info->max_ap_assoc_sta = le16_to_cpu(resp_info->max_ap_assoc_sta);
1238        mac_info->radar_detect_widths =
1239                        qlink_chan_width_mask_to_nl(le16_to_cpu(
1240                                        resp_info->radar_detect_widths));
1241        mac_info->max_acl_mac_addrs = le16_to_cpu(resp_info->max_acl_mac_addrs);
1242        mac_info->frag_thr = le32_to_cpu(resp_info->frag_threshold);
1243        mac_info->rts_thr = le32_to_cpu(resp_info->rts_threshold);
1244        mac_info->sretry_limit = resp_info->retry_short;
1245        mac_info->lretry_limit = resp_info->retry_long;
1246        mac_info->coverage_class = resp_info->coverage_class;
1247        mac_info->max_scan_ssids = resp_info->max_scan_ssids;
1248
1249        memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask,
1250               sizeof(mac_info->ht_cap_mod_mask));
1251        memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask,
1252               sizeof(mac_info->vht_cap_mod_mask));
1253
1254        mac_info->n_if_comb = resp_info->n_iface_combinations;
1255        mac_info->if_comb = kcalloc(mac->macinfo.n_if_comb,
1256                                    sizeof(*mac->macinfo.if_comb),
1257                                    GFP_KERNEL);
1258
1259        if (!mac->macinfo.if_comb)
1260                return -ENOMEM;
1261
1262        return 0;
1263}
1264
1265static void qtnf_cmd_resp_band_fill_htcap(const u8 *info,
1266                                          struct ieee80211_sta_ht_cap *bcap)
1267{
1268        const struct ieee80211_ht_cap *ht_cap =
1269                (const struct ieee80211_ht_cap *)info;
1270
1271        bcap->ht_supported = true;
1272        bcap->cap = le16_to_cpu(ht_cap->cap_info);
1273        bcap->ampdu_factor =
1274                ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
1275        bcap->ampdu_density =
1276                (ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >>
1277                IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
1278        memcpy(&bcap->mcs, &ht_cap->mcs, sizeof(bcap->mcs));
1279}
1280
1281static void qtnf_cmd_resp_band_fill_vhtcap(const u8 *info,
1282                                           struct ieee80211_sta_vht_cap *bcap)
1283{
1284        const struct ieee80211_vht_cap *vht_cap =
1285                (const struct ieee80211_vht_cap *)info;
1286
1287        bcap->vht_supported = true;
1288        bcap->cap = le32_to_cpu(vht_cap->vht_cap_info);
1289        memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs));
1290}
1291
1292static void qtnf_cmd_conv_iftype(struct ieee80211_sband_iftype_data
1293                                  *iftype_data,
1294                                  const struct qlink_sband_iftype_data
1295                                  *qlink_data)
1296{
1297        iftype_data->types_mask = le16_to_cpu(qlink_data->types_mask);
1298
1299        iftype_data->he_cap.has_he = true;
1300        memcpy(&iftype_data->he_cap.he_cap_elem, &qlink_data->he_cap_elem,
1301               sizeof(qlink_data->he_cap_elem));
1302        memcpy(iftype_data->he_cap.ppe_thres, qlink_data->ppe_thres,
1303               ARRAY_SIZE(qlink_data->ppe_thres));
1304
1305        iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80 =
1306                qlink_data->he_mcs_nss_supp.rx_mcs_80;
1307        iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80 =
1308                qlink_data->he_mcs_nss_supp.tx_mcs_80;
1309        iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_160 =
1310                qlink_data->he_mcs_nss_supp.rx_mcs_160;
1311        iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160 =
1312                qlink_data->he_mcs_nss_supp.tx_mcs_160;
1313        iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80p80 =
1314                qlink_data->he_mcs_nss_supp.rx_mcs_80p80;
1315        iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80p80 =
1316                qlink_data->he_mcs_nss_supp.tx_mcs_80p80;
1317}
1318
1319static int qtnf_cmd_band_fill_iftype(const u8 *data,
1320                                     struct ieee80211_supported_band *band)
1321{
1322        unsigned int i;
1323        struct ieee80211_sband_iftype_data *iftype_data;
1324        const struct qlink_tlv_iftype_data *tlv =
1325                (const struct qlink_tlv_iftype_data *)data;
1326        size_t payload_len = tlv->n_iftype_data * sizeof(*tlv->iftype_data) +
1327                sizeof(*tlv) -
1328                sizeof(struct qlink_tlv_hdr);
1329
1330        if (tlv->hdr.len != cpu_to_le16(payload_len)) {
1331                pr_err("bad IFTYPE_DATA TLV len %u\n", tlv->hdr.len);
1332                return -EINVAL;
1333        }
1334
1335        kfree(band->iftype_data);
1336        band->iftype_data = NULL;
1337        band->n_iftype_data = tlv->n_iftype_data;
1338        if (band->n_iftype_data == 0)
1339                return 0;
1340
1341        iftype_data = kcalloc(band->n_iftype_data, sizeof(*iftype_data),
1342                              GFP_KERNEL);
1343        if (!iftype_data) {
1344                band->n_iftype_data = 0;
1345                return -ENOMEM;
1346        }
1347        band->iftype_data = iftype_data;
1348
1349        for (i = 0; i < band->n_iftype_data; i++)
1350                qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]);
1351
1352        return 0;
1353}
1354
1355static int
1356qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
1357                             struct qlink_resp_band_info_get *resp,
1358                             size_t payload_len)
1359{
1360        u16 tlv_type;
1361        size_t tlv_dlen;
1362        const struct qlink_tlv_hdr *tlv;
1363        const struct qlink_channel *qchan;
1364        struct ieee80211_channel *chan;
1365        unsigned int chidx = 0;
1366        u32 qflags;
1367        int ret = -EINVAL;
1368
1369        memset(&band->ht_cap, 0, sizeof(band->ht_cap));
1370        memset(&band->vht_cap, 0, sizeof(band->vht_cap));
1371
1372        if (band->channels) {
1373                if (band->n_channels == resp->num_chans) {
1374                        memset(band->channels, 0,
1375                               sizeof(*band->channels) * band->n_channels);
1376                } else {
1377                        kfree(band->channels);
1378                        band->n_channels = 0;
1379                        band->channels = NULL;
1380                }
1381        }
1382
1383        band->n_channels = resp->num_chans;
1384        if (band->n_channels == 0)
1385                return 0;
1386
1387        if (!band->channels)
1388                band->channels = kcalloc(band->n_channels, sizeof(*chan),
1389                                         GFP_KERNEL);
1390        if (!band->channels) {
1391                band->n_channels = 0;
1392                return -ENOMEM;
1393        }
1394
1395        qlink_for_each_tlv(tlv, resp->info, payload_len) {
1396                tlv_type = le16_to_cpu(tlv->type);
1397                tlv_dlen = le16_to_cpu(tlv->len);
1398
1399                switch (tlv_type) {
1400                case QTN_TLV_ID_CHANNEL:
1401                        if (unlikely(tlv_dlen != sizeof(*qchan))) {
1402                                pr_err("invalid channel TLV len %zu\n",
1403                                       tlv_dlen);
1404                                goto error_ret;
1405                        }
1406
1407                        if (chidx == band->n_channels) {
1408                                pr_err("too many channel TLVs\n");
1409                                goto error_ret;
1410                        }
1411
1412                        qchan = (const struct qlink_channel *)tlv->val;
1413                        chan = &band->channels[chidx++];
1414                        qflags = le32_to_cpu(qchan->flags);
1415
1416                        chan->hw_value = le16_to_cpu(qchan->hw_value);
1417                        chan->band = band->band;
1418                        chan->center_freq = le16_to_cpu(qchan->center_freq);
1419                        chan->max_antenna_gain = (int)qchan->max_antenna_gain;
1420                        chan->max_power = (int)qchan->max_power;
1421                        chan->max_reg_power = (int)qchan->max_reg_power;
1422                        chan->beacon_found = qchan->beacon_found;
1423                        chan->dfs_cac_ms = le32_to_cpu(qchan->dfs_cac_ms);
1424                        chan->flags = 0;
1425
1426                        if (qflags & QLINK_CHAN_DISABLED)
1427                                chan->flags |= IEEE80211_CHAN_DISABLED;
1428
1429                        if (qflags & QLINK_CHAN_NO_IR)
1430                                chan->flags |= IEEE80211_CHAN_NO_IR;
1431
1432                        if (qflags & QLINK_CHAN_NO_HT40PLUS)
1433                                chan->flags |= IEEE80211_CHAN_NO_HT40PLUS;
1434
1435                        if (qflags & QLINK_CHAN_NO_HT40MINUS)
1436                                chan->flags |= IEEE80211_CHAN_NO_HT40MINUS;
1437
1438                        if (qflags & QLINK_CHAN_NO_OFDM)
1439                                chan->flags |= IEEE80211_CHAN_NO_OFDM;
1440
1441                        if (qflags & QLINK_CHAN_NO_80MHZ)
1442                                chan->flags |= IEEE80211_CHAN_NO_80MHZ;
1443
1444                        if (qflags & QLINK_CHAN_NO_160MHZ)
1445                                chan->flags |= IEEE80211_CHAN_NO_160MHZ;
1446
1447                        if (qflags & QLINK_CHAN_INDOOR_ONLY)
1448                                chan->flags |= IEEE80211_CHAN_INDOOR_ONLY;
1449
1450                        if (qflags & QLINK_CHAN_IR_CONCURRENT)
1451                                chan->flags |= IEEE80211_CHAN_IR_CONCURRENT;
1452
1453                        if (qflags & QLINK_CHAN_NO_20MHZ)
1454                                chan->flags |= IEEE80211_CHAN_NO_20MHZ;
1455
1456                        if (qflags & QLINK_CHAN_NO_10MHZ)
1457                                chan->flags |= IEEE80211_CHAN_NO_10MHZ;
1458
1459                        if (qflags & QLINK_CHAN_RADAR) {
1460                                chan->flags |= IEEE80211_CHAN_RADAR;
1461                                chan->dfs_state_entered = jiffies;
1462
1463                                if (qchan->dfs_state == QLINK_DFS_USABLE)
1464                                        chan->dfs_state = NL80211_DFS_USABLE;
1465                                else if (qchan->dfs_state ==
1466                                        QLINK_DFS_AVAILABLE)
1467                                        chan->dfs_state = NL80211_DFS_AVAILABLE;
1468                                else
1469                                        chan->dfs_state =
1470                                                NL80211_DFS_UNAVAILABLE;
1471                        }
1472
1473                        pr_debug("chan=%d flags=%#x max_pow=%d max_reg_pow=%d\n",
1474                                 chan->hw_value, chan->flags, chan->max_power,
1475                                 chan->max_reg_power);
1476                        break;
1477                case WLAN_EID_HT_CAPABILITY:
1478                        if (unlikely(tlv_dlen !=
1479                                     sizeof(struct ieee80211_ht_cap))) {
1480                                pr_err("bad HTCAP TLV len %zu\n", tlv_dlen);
1481                                goto error_ret;
1482                        }
1483
1484                        qtnf_cmd_resp_band_fill_htcap(tlv->val, &band->ht_cap);
1485                        break;
1486                case WLAN_EID_VHT_CAPABILITY:
1487                        if (unlikely(tlv_dlen !=
1488                                     sizeof(struct ieee80211_vht_cap))) {
1489                                pr_err("bad VHTCAP TLV len %zu\n", tlv_dlen);
1490                                goto error_ret;
1491                        }
1492
1493                        qtnf_cmd_resp_band_fill_vhtcap(tlv->val,
1494                                                       &band->vht_cap);
1495                        break;
1496                case QTN_TLV_ID_IFTYPE_DATA:
1497                        ret = qtnf_cmd_band_fill_iftype((const uint8_t *)tlv,
1498                                                        band);
1499                        if (ret)
1500                                goto error_ret;
1501                        break;
1502                default:
1503                        pr_warn("unknown TLV type: %#x\n", tlv_type);
1504                        break;
1505                }
1506        }
1507
1508        if (!qlink_tlv_parsing_ok(tlv, resp->info, payload_len)) {
1509                pr_err("Malformed TLV buffer\n");
1510                goto error_ret;
1511        }
1512
1513        if (band->n_channels != chidx) {
1514                pr_err("channel count mismatch: reported=%d, parsed=%d\n",
1515                       band->n_channels, chidx);
1516                goto error_ret;
1517        }
1518
1519        return 0;
1520
1521error_ret:
1522        kfree(band->channels);
1523        band->channels = NULL;
1524        band->n_channels = 0;
1525
1526        return ret;
1527}
1528
1529int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
1530{
1531        struct sk_buff *cmd_skb, *resp_skb = NULL;
1532        const struct qlink_resp_get_mac_info *resp;
1533        size_t var_data_len = 0;
1534        int ret = 0;
1535
1536        cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
1537                                            QLINK_CMD_MAC_INFO,
1538                                            sizeof(struct qlink_cmd));
1539        if (!cmd_skb)
1540                return -ENOMEM;
1541
1542        qtnf_bus_lock(mac->bus);
1543        ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
1544                                       sizeof(*resp), &var_data_len);
1545        if (ret)
1546                goto out;
1547
1548        resp = (const struct qlink_resp_get_mac_info *)resp_skb->data;
1549        ret = qtnf_cmd_resp_proc_mac_info(mac, resp);
1550        if (ret)
1551                goto out;
1552
1553        ret = qtnf_parse_variable_mac_info(mac, resp, var_data_len);
1554
1555out:
1556        qtnf_bus_unlock(mac->bus);
1557        consume_skb(resp_skb);
1558
1559        return ret;
1560}
1561
1562int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
1563{
1564        struct sk_buff *cmd_skb, *resp_skb = NULL;
1565        const struct qlink_resp_get_hw_info *resp;
1566        size_t info_len = 0;
1567        int ret = 0;
1568
1569        cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1570                                            QLINK_CMD_GET_HW_INFO,
1571                                            sizeof(struct qlink_cmd));
1572        if (!cmd_skb)
1573                return -ENOMEM;
1574
1575        qtnf_bus_lock(bus);
1576        ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
1577                                       sizeof(*resp), &info_len);
1578        if (ret)
1579                goto out;
1580
1581        resp = (const struct qlink_resp_get_hw_info *)resp_skb->data;
1582        ret = qtnf_cmd_resp_proc_hw_info(bus, resp, info_len);
1583
1584out:
1585        qtnf_bus_unlock(bus);
1586        consume_skb(resp_skb);
1587
1588        return ret;
1589}
1590
1591int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
1592                           struct ieee80211_supported_band *band)
1593{
1594        struct sk_buff *cmd_skb, *resp_skb = NULL;
1595        struct qlink_cmd_band_info_get *cmd;
1596        struct qlink_resp_band_info_get *resp;
1597        size_t info_len = 0;
1598        int ret = 0;
1599        u8 qband = qlink_utils_band_cfg2q(band->band);
1600
1601        cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
1602                                            QLINK_CMD_BAND_INFO_GET,
1603                                            sizeof(*cmd));
1604        if (!cmd_skb)
1605                return -ENOMEM;
1606
1607        cmd = (struct qlink_cmd_band_info_get *)cmd_skb->data;
1608        cmd->band = qband;
1609
1610        qtnf_bus_lock(mac->bus);
1611        ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
1612                                       sizeof(*resp), &info_len);
1613        if (ret)
1614                goto out;
1615
1616        resp = (struct qlink_resp_band_info_get *)resp_skb->data;
1617        if (resp->band != qband) {
1618                pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid,
1619                       resp->band, qband);
1620                ret = -EINVAL;
1621                goto out;
1622        }
1623
1624        ret = qtnf_cmd_resp_fill_band_info(band, resp, info_len);
1625
1626out:
1627        qtnf_bus_unlock(mac->bus);
1628        consume_skb(resp_skb);
1629
1630        return ret;
1631}
1632
1633int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
1634{
1635        struct wiphy *wiphy = priv_to_wiphy(mac);
1636        struct sk_buff *cmd_skb;
1637        int ret = 0;
1638
1639        cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
1640                                            QLINK_CMD_PHY_PARAMS_SET,
1641                                            sizeof(struct qlink_cmd));
1642        if (!cmd_skb)
1643                return -ENOMEM;
1644
1645        qtnf_bus_lock(mac->bus);
1646
1647        if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
1648                qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
1649                                         wiphy->frag_threshold);
1650        if (changed & WIPHY_PARAM_RTS_THRESHOLD)
1651                qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH,
1652                                         wiphy->rts_threshold);
1653        if (changed & WIPHY_PARAM_COVERAGE_CLASS)
1654                qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
1655                                         wiphy->coverage_class);
1656
1657        if (changed & WIPHY_PARAM_RETRY_LONG)
1658                qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT,
1659                                         wiphy->retry_long);
1660
1661        if (changed & WIPHY_PARAM_RETRY_SHORT)
1662                qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT,
1663                                         wiphy->retry_short);
1664
1665        ret = qtnf_cmd_send(mac->bus, cmd_skb);
1666
1667        qtnf_bus_unlock(mac->bus);
1668
1669        return ret;
1670}
1671
1672int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
1673{
1674        struct sk_buff *resp_skb = NULL;
1675        struct qlink_resp_init_fw *resp;
1676        struct qlink_cmd_init_fw *cmd;
1677        struct sk_buff *cmd_skb;
1678        size_t info_len = 0;
1679        int ret;
1680
1681        cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1682                                            QLINK_CMD_FW_INIT,
1683                                            sizeof(*cmd));
1684        if (!cmd_skb)
1685                return -ENOMEM;
1686
1687        cmd = (struct qlink_cmd_init_fw *)cmd_skb->data;
1688        cmd->qlink_proto_ver = cpu_to_le32(QLINK_PROTO_VER);
1689
1690        qtnf_bus_lock(bus);
1691        ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
1692                                       sizeof(*resp), &info_len);
1693        qtnf_bus_unlock(bus);
1694
1695        if (ret)
1696                goto out;
1697
1698        resp = (struct qlink_resp_init_fw *)resp_skb->data;
1699        bus->hw_info.ql_proto_ver = le32_to_cpu(resp->qlink_proto_ver);
1700
1701out:
1702        consume_skb(resp_skb);
1703        return ret;
1704}
1705
1706void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus)
1707{
1708        struct sk_buff *cmd_skb;
1709
1710        cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1711                                            QLINK_CMD_FW_DEINIT,
1712                                            sizeof(struct qlink_cmd));
1713        if (!cmd_skb)
1714                return;
1715
1716        qtnf_bus_lock(bus);
1717        qtnf_cmd_send(bus, cmd_skb);
1718        qtnf_bus_unlock(bus);
1719}
1720
1721int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
1722                          const u8 *mac_addr, struct key_params *params)
1723{
1724        struct sk_buff *cmd_skb;
1725        struct qlink_cmd_add_key *cmd;
1726        int ret = 0;
1727
1728        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1729                                            QLINK_CMD_ADD_KEY,
1730                                            sizeof(*cmd));
1731        if (!cmd_skb)
1732                return -ENOMEM;
1733
1734        qtnf_bus_lock(vif->mac->bus);
1735
1736        cmd = (struct qlink_cmd_add_key *)cmd_skb->data;
1737
1738        if (mac_addr)
1739                ether_addr_copy(cmd->addr, mac_addr);
1740        else
1741                eth_broadcast_addr(cmd->addr);
1742
1743        cmd->cipher = cpu_to_le32(params->cipher);
1744        cmd->key_index = key_index;
1745        cmd->pairwise = pairwise;
1746
1747        if (params->key && params->key_len > 0)
1748                qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_KEY,
1749                                         params->key,
1750                                         params->key_len);
1751
1752        if (params->seq && params->seq_len > 0)
1753                qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_SEQ,
1754                                         params->seq,
1755                                         params->seq_len);
1756
1757        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1758
1759        qtnf_bus_unlock(vif->mac->bus);
1760
1761        return ret;
1762}
1763
1764int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
1765                          const u8 *mac_addr)
1766{
1767        struct sk_buff *cmd_skb;
1768        struct qlink_cmd_del_key *cmd;
1769        int ret = 0;
1770
1771        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1772                                            QLINK_CMD_DEL_KEY,
1773                                            sizeof(*cmd));
1774        if (!cmd_skb)
1775                return -ENOMEM;
1776
1777        qtnf_bus_lock(vif->mac->bus);
1778
1779        cmd = (struct qlink_cmd_del_key *)cmd_skb->data;
1780
1781        if (mac_addr)
1782                ether_addr_copy(cmd->addr, mac_addr);
1783        else
1784                eth_broadcast_addr(cmd->addr);
1785
1786        cmd->key_index = key_index;
1787        cmd->pairwise = pairwise;
1788
1789        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1790
1791        qtnf_bus_unlock(vif->mac->bus);
1792
1793        return ret;
1794}
1795
1796int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
1797                                  bool unicast, bool multicast)
1798{
1799        struct sk_buff *cmd_skb;
1800        struct qlink_cmd_set_def_key *cmd;
1801        int ret = 0;
1802
1803        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1804                                            QLINK_CMD_SET_DEFAULT_KEY,
1805                                            sizeof(*cmd));
1806        if (!cmd_skb)
1807                return -ENOMEM;
1808
1809        qtnf_bus_lock(vif->mac->bus);
1810
1811        cmd = (struct qlink_cmd_set_def_key *)cmd_skb->data;
1812        cmd->key_index = key_index;
1813        cmd->unicast = unicast;
1814        cmd->multicast = multicast;
1815
1816        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1817
1818        qtnf_bus_unlock(vif->mac->bus);
1819
1820        return ret;
1821}
1822
1823int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
1824{
1825        struct sk_buff *cmd_skb;
1826        struct qlink_cmd_set_def_mgmt_key *cmd;
1827        int ret = 0;
1828
1829        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1830                                            QLINK_CMD_SET_DEFAULT_MGMT_KEY,
1831                                            sizeof(*cmd));
1832        if (!cmd_skb)
1833                return -ENOMEM;
1834
1835        qtnf_bus_lock(vif->mac->bus);
1836
1837        cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data;
1838        cmd->key_index = key_index;
1839
1840        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1841
1842        qtnf_bus_unlock(vif->mac->bus);
1843
1844        return ret;
1845}
1846
1847static u32 qtnf_encode_sta_flags(u32 flags)
1848{
1849        u32 code = 0;
1850
1851        if (flags & BIT(NL80211_STA_FLAG_AUTHORIZED))
1852                code |= QLINK_STA_FLAG_AUTHORIZED;
1853        if (flags & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
1854                code |= QLINK_STA_FLAG_SHORT_PREAMBLE;
1855        if (flags & BIT(NL80211_STA_FLAG_WME))
1856                code |= QLINK_STA_FLAG_WME;
1857        if (flags & BIT(NL80211_STA_FLAG_MFP))
1858                code |= QLINK_STA_FLAG_MFP;
1859        if (flags & BIT(NL80211_STA_FLAG_AUTHENTICATED))
1860                code |= QLINK_STA_FLAG_AUTHENTICATED;
1861        if (flags & BIT(NL80211_STA_FLAG_TDLS_PEER))
1862                code |= QLINK_STA_FLAG_TDLS_PEER;
1863        if (flags & BIT(NL80211_STA_FLAG_ASSOCIATED))
1864                code |= QLINK_STA_FLAG_ASSOCIATED;
1865        return code;
1866}
1867
1868int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
1869                             struct station_parameters *params)
1870{
1871        struct sk_buff *cmd_skb;
1872        struct qlink_cmd_change_sta *cmd;
1873        int ret = 0;
1874
1875        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1876                                            QLINK_CMD_CHANGE_STA,
1877                                            sizeof(*cmd));
1878        if (!cmd_skb)
1879                return -ENOMEM;
1880
1881        qtnf_bus_lock(vif->mac->bus);
1882
1883        cmd = (struct qlink_cmd_change_sta *)cmd_skb->data;
1884        ether_addr_copy(cmd->sta_addr, mac);
1885        cmd->flag_update.mask =
1886                cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_mask));
1887        cmd->flag_update.value =
1888                cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_set));
1889
1890        switch (vif->wdev.iftype) {
1891        case NL80211_IFTYPE_AP:
1892                cmd->if_type = cpu_to_le16(QLINK_IFTYPE_AP);
1893                break;
1894        case NL80211_IFTYPE_STATION:
1895                cmd->if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
1896                break;
1897        default:
1898                pr_err("unsupported iftype %d\n", vif->wdev.iftype);
1899                dev_kfree_skb(cmd_skb);
1900                ret = -EINVAL;
1901                goto out;
1902        }
1903
1904        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1905
1906out:
1907        qtnf_bus_unlock(vif->mac->bus);
1908
1909        return ret;
1910}
1911
1912int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
1913                          struct station_del_parameters *params)
1914{
1915        struct sk_buff *cmd_skb;
1916        struct qlink_cmd_del_sta *cmd;
1917        int ret = 0;
1918
1919        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1920                                            QLINK_CMD_DEL_STA,
1921                                            sizeof(*cmd));
1922        if (!cmd_skb)
1923                return -ENOMEM;
1924
1925        qtnf_bus_lock(vif->mac->bus);
1926
1927        cmd = (struct qlink_cmd_del_sta *)cmd_skb->data;
1928
1929        if (params->mac)
1930                ether_addr_copy(cmd->sta_addr, params->mac);
1931        else
1932                eth_broadcast_addr(cmd->sta_addr);      /* flush all stations */
1933
1934        cmd->subtype = params->subtype;
1935        cmd->reason_code = cpu_to_le16(params->reason_code);
1936
1937        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1938
1939        qtnf_bus_unlock(vif->mac->bus);
1940
1941        return ret;
1942}
1943
1944static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
1945                                     const struct ieee80211_channel *sc)
1946{
1947        struct qlink_tlv_channel *tlv;
1948        struct qlink_channel *qch;
1949
1950        tlv = skb_put_zero(cmd_skb, sizeof(*tlv));
1951        qch = &tlv->chan;
1952        tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
1953        tlv->hdr.len = cpu_to_le16(sizeof(*qch));
1954
1955        qch->center_freq = cpu_to_le16(sc->center_freq);
1956        qch->hw_value = cpu_to_le16(sc->hw_value);
1957        qch->band = qlink_utils_band_cfg2q(sc->band);
1958        qch->max_power = sc->max_power;
1959        qch->max_reg_power = sc->max_reg_power;
1960        qch->max_antenna_gain = sc->max_antenna_gain;
1961        qch->beacon_found = sc->beacon_found;
1962        qch->dfs_state = qlink_utils_dfs_state_cfg2q(sc->dfs_state);
1963        qch->flags = cpu_to_le32(qlink_utils_chflags_cfg2q(sc->flags));
1964}
1965
1966static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb,
1967                                     const u8 *mac_addr,
1968                                     const u8 *mac_addr_mask)
1969{
1970        struct qlink_random_mac_addr *randmac;
1971        struct qlink_tlv_hdr *hdr =
1972                skb_put(cmd_skb, sizeof(*hdr) + sizeof(*randmac));
1973
1974        hdr->type = cpu_to_le16(QTN_TLV_ID_RANDOM_MAC_ADDR);
1975        hdr->len = cpu_to_le16(sizeof(*randmac));
1976        randmac = (struct qlink_random_mac_addr *)hdr->val;
1977
1978        memcpy(randmac->mac_addr, mac_addr, ETH_ALEN);
1979        memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN);
1980}
1981
1982int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
1983{
1984        struct cfg80211_scan_request *scan_req = mac->scan_req;
1985        u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT;
1986        u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT;
1987        struct wireless_dev *wdev = scan_req->wdev;
1988        struct ieee80211_channel *sc;
1989        struct qlink_cmd_scan *cmd;
1990        struct sk_buff *cmd_skb;
1991        int n_channels = 0;
1992        u64 flags = 0;
1993        int count;
1994        int ret;
1995
1996        cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
1997                                            QLINK_CMD_SCAN,
1998                                            sizeof(*cmd));
1999        if (!cmd_skb)
2000                return -ENOMEM;
2001
2002        cmd = (struct qlink_cmd_scan *)cmd_skb->data;
2003
2004        if (scan_req->duration) {
2005                dwell_active = scan_req->duration;
2006                dwell_passive = scan_req->duration;
2007        } else if (wdev->iftype == NL80211_IFTYPE_STATION &&
2008                   wdev->current_bss) {
2009                /* let device select dwell based on traffic conditions */
2010                dwell_active = QTNF_SCAN_TIME_AUTO;
2011                dwell_passive = QTNF_SCAN_TIME_AUTO;
2012        }
2013
2014        cmd->n_ssids = cpu_to_le16(scan_req->n_ssids);
2015        for (count = 0; count < scan_req->n_ssids; ++count) {
2016                qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID,
2017                                         scan_req->ssids[count].ssid,
2018                                         scan_req->ssids[count].ssid_len);
2019        }
2020
2021        if (scan_req->ie_len != 0)
2022                qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ,
2023                                        scan_req->ie, scan_req->ie_len);
2024
2025        for (count = 0; count < scan_req->n_channels; ++count) {
2026                sc = scan_req->channels[count];
2027                if (sc->flags & IEEE80211_CHAN_DISABLED)
2028                        continue;
2029
2030                pr_debug("[MAC%u] scan chan=%d, freq=%d, flags=%#x\n",
2031                         mac->macid, sc->hw_value, sc->center_freq,
2032                         sc->flags);
2033
2034                qtnf_cmd_channel_tlv_add(cmd_skb, sc);
2035                ++n_channels;
2036        }
2037
2038        if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH)
2039                flags |= QLINK_SCAN_FLAG_FLUSH;
2040
2041        if (scan_req->duration_mandatory)
2042                flags |= QLINK_SCAN_FLAG_DURATION_MANDATORY;
2043
2044        cmd->n_channels = cpu_to_le16(n_channels);
2045        cmd->active_dwell = cpu_to_le16(dwell_active);
2046        cmd->passive_dwell = cpu_to_le16(dwell_passive);
2047        cmd->sample_duration = cpu_to_le16(QTNF_SCAN_SAMPLE_DURATION_DEFAULT);
2048        cmd->flags = cpu_to_le64(flags);
2049
2050        pr_debug("[MAC%u] %s scan dwell active=%u passive=%u duration=%u\n",
2051                 mac->macid,
2052                 scan_req->duration_mandatory ? "mandatory" : "max",
2053                 dwell_active, dwell_passive,
2054                 QTNF_SCAN_SAMPLE_DURATION_DEFAULT);
2055
2056        if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
2057                pr_debug("[MAC%u] scan with random addr=%pM, mask=%pM\n",
2058                         mac->macid,
2059                         scan_req->mac_addr, scan_req->mac_addr_mask);
2060                qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr,
2061                                         scan_req->mac_addr_mask);
2062        }
2063
2064        qtnf_bus_lock(mac->bus);
2065        ret = qtnf_cmd_send(mac->bus, cmd_skb);
2066        qtnf_bus_unlock(mac->bus);
2067
2068        return ret;
2069}
2070
2071int qtnf_cmd_send_connect(struct qtnf_vif *vif,
2072                          struct cfg80211_connect_params *sme)
2073{
2074        struct sk_buff *cmd_skb;
2075        struct qlink_cmd_connect *cmd;
2076        struct qlink_auth_encr *aen;
2077        int ret;
2078        int i;
2079        u32 connect_flags = 0;
2080
2081        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2082                                            QLINK_CMD_CONNECT,
2083                                            sizeof(*cmd));
2084        if (!cmd_skb)
2085                return -ENOMEM;
2086
2087        cmd = (struct qlink_cmd_connect *)cmd_skb->data;
2088
2089        ether_addr_copy(cmd->bssid, vif->bssid);
2090
2091        if (sme->bssid_hint)
2092                ether_addr_copy(cmd->bssid_hint, sme->bssid_hint);
2093        else
2094                eth_zero_addr(cmd->bssid_hint);
2095
2096        if (sme->prev_bssid)
2097                ether_addr_copy(cmd->prev_bssid, sme->prev_bssid);
2098        else
2099                eth_zero_addr(cmd->prev_bssid);
2100
2101        if ((sme->bg_scan_period >= 0) &&
2102            (sme->bg_scan_period <= SHRT_MAX))
2103                cmd->bg_scan_period = cpu_to_le16(sme->bg_scan_period);
2104        else
2105                cmd->bg_scan_period = cpu_to_le16(-1); /* use default value */
2106
2107        if (sme->flags & ASSOC_REQ_DISABLE_HT)
2108                connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
2109        if (sme->flags & ASSOC_REQ_DISABLE_VHT)
2110                connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
2111        if (sme->flags & ASSOC_REQ_USE_RRM)
2112                connect_flags |= QLINK_STA_CONNECT_USE_RRM;
2113
2114        cmd->flags = cpu_to_le32(connect_flags);
2115        memcpy(&cmd->ht_capa, &sme->ht_capa, sizeof(cmd->ht_capa));
2116        memcpy(&cmd->ht_capa_mask, &sme->ht_capa_mask,
2117               sizeof(cmd->ht_capa_mask));
2118        memcpy(&cmd->vht_capa, &sme->vht_capa, sizeof(cmd->vht_capa));
2119        memcpy(&cmd->vht_capa_mask, &sme->vht_capa_mask,
2120               sizeof(cmd->vht_capa_mask));
2121        cmd->pbss = sme->pbss;
2122
2123        aen = &cmd->aen;
2124        aen->auth_type = sme->auth_type;
2125        aen->privacy = !!sme->privacy;
2126        cmd->mfp = sme->mfp;
2127        aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
2128        aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
2129        aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);
2130
2131        for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
2132                aen->ciphers_pairwise[i] =
2133                        cpu_to_le32(sme->crypto.ciphers_pairwise[i]);
2134
2135        aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);
2136
2137        for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
2138                aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]);
2139
2140        aen->control_port = sme->crypto.control_port;
2141        aen->control_port_no_encrypt =
2142                sme->crypto.control_port_no_encrypt;
2143        aen->control_port_ethertype =
2144                cpu_to_le16(be16_to_cpu(sme->crypto.control_port_ethertype));
2145
2146        qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid,
2147                                 sme->ssid_len);
2148
2149        if (sme->ie_len != 0)
2150                qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ,
2151                                        sme->ie, sme->ie_len);
2152
2153        if (sme->channel)
2154                qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel);
2155
2156        qtnf_bus_lock(vif->mac->bus);
2157        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2158        qtnf_bus_unlock(vif->mac->bus);
2159
2160        return ret;
2161}
2162
2163int qtnf_cmd_send_external_auth(struct qtnf_vif *vif,
2164                                struct cfg80211_external_auth_params *auth)
2165{
2166        struct sk_buff *cmd_skb;
2167        struct qlink_cmd_external_auth *cmd;
2168        int ret;
2169
2170        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2171                                            QLINK_CMD_EXTERNAL_AUTH,
2172                                            sizeof(*cmd));
2173        if (!cmd_skb)
2174                return -ENOMEM;
2175
2176        cmd = (struct qlink_cmd_external_auth *)cmd_skb->data;
2177
2178        ether_addr_copy(cmd->peer, auth->bssid);
2179        cmd->status = cpu_to_le16(auth->status);
2180
2181        qtnf_bus_lock(vif->mac->bus);
2182        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2183        qtnf_bus_unlock(vif->mac->bus);
2184
2185        return ret;
2186}
2187
2188int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
2189{
2190        struct sk_buff *cmd_skb;
2191        struct qlink_cmd_disconnect *cmd;
2192        int ret;
2193
2194        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2195                                            QLINK_CMD_DISCONNECT,
2196                                            sizeof(*cmd));
2197        if (!cmd_skb)
2198                return -ENOMEM;
2199
2200        qtnf_bus_lock(vif->mac->bus);
2201
2202        cmd = (struct qlink_cmd_disconnect *)cmd_skb->data;
2203        cmd->reason = cpu_to_le16(reason_code);
2204
2205        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2206
2207        qtnf_bus_unlock(vif->mac->bus);
2208
2209        return ret;
2210}
2211
2212int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
2213{
2214        struct sk_buff *cmd_skb;
2215        struct qlink_cmd_updown *cmd;
2216        int ret;
2217
2218        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2219                                            QLINK_CMD_UPDOWN_INTF,
2220                                            sizeof(*cmd));
2221        if (!cmd_skb)
2222                return -ENOMEM;
2223
2224        cmd = (struct qlink_cmd_updown *)cmd_skb->data;
2225        cmd->if_up = !!up;
2226
2227        qtnf_bus_lock(vif->mac->bus);
2228        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2229        qtnf_bus_unlock(vif->mac->bus);
2230
2231        return ret;
2232}
2233
2234int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req,
2235                        bool slave_radar, bool dfs_offload)
2236{
2237        struct wiphy *wiphy = priv_to_wiphy(mac);
2238        struct qtnf_bus *bus = mac->bus;
2239        struct sk_buff *cmd_skb;
2240        int ret;
2241        struct qlink_cmd_reg_notify *cmd;
2242        enum nl80211_band band;
2243        const struct ieee80211_supported_band *cfg_band;
2244
2245        cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2246                                            QLINK_CMD_REG_NOTIFY,
2247                                            sizeof(*cmd));
2248        if (!cmd_skb)
2249                return -ENOMEM;
2250
2251        cmd = (struct qlink_cmd_reg_notify *)cmd_skb->data;
2252        cmd->alpha2[0] = req->alpha2[0];
2253        cmd->alpha2[1] = req->alpha2[1];
2254
2255        switch (req->initiator) {
2256        case NL80211_REGDOM_SET_BY_CORE:
2257                cmd->initiator = QLINK_REGDOM_SET_BY_CORE;
2258                break;
2259        case NL80211_REGDOM_SET_BY_USER:
2260                cmd->initiator = QLINK_REGDOM_SET_BY_USER;
2261                break;
2262        case NL80211_REGDOM_SET_BY_DRIVER:
2263                cmd->initiator = QLINK_REGDOM_SET_BY_DRIVER;
2264                break;
2265        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
2266                cmd->initiator = QLINK_REGDOM_SET_BY_COUNTRY_IE;
2267                break;
2268        }
2269
2270        switch (req->user_reg_hint_type) {
2271        case NL80211_USER_REG_HINT_USER:
2272                cmd->user_reg_hint_type = QLINK_USER_REG_HINT_USER;
2273                break;
2274        case NL80211_USER_REG_HINT_CELL_BASE:
2275                cmd->user_reg_hint_type = QLINK_USER_REG_HINT_CELL_BASE;
2276                break;
2277        case NL80211_USER_REG_HINT_INDOOR:
2278                cmd->user_reg_hint_type = QLINK_USER_REG_HINT_INDOOR;
2279                break;
2280        }
2281
2282        switch (req->dfs_region) {
2283        case NL80211_DFS_FCC:
2284                cmd->dfs_region = QLINK_DFS_FCC;
2285                break;
2286        case NL80211_DFS_ETSI:
2287                cmd->dfs_region = QLINK_DFS_ETSI;
2288                break;
2289        case NL80211_DFS_JP:
2290                cmd->dfs_region = QLINK_DFS_JP;
2291                break;
2292        default:
2293                cmd->dfs_region = QLINK_DFS_UNSET;
2294                break;
2295        }
2296
2297        cmd->slave_radar = slave_radar;
2298        cmd->dfs_offload = dfs_offload;
2299        cmd->num_channels = 0;
2300
2301        for (band = 0; band < NUM_NL80211_BANDS; band++) {
2302                unsigned int i;
2303
2304                cfg_band = wiphy->bands[band];
2305                if (!cfg_band)
2306                        continue;
2307
2308                cmd->num_channels += cfg_band->n_channels;
2309
2310                for (i = 0; i < cfg_band->n_channels; ++i) {
2311                        qtnf_cmd_channel_tlv_add(cmd_skb,
2312                                                 &cfg_band->channels[i]);
2313                }
2314        }
2315
2316        qtnf_bus_lock(bus);
2317        ret = qtnf_cmd_send(bus, cmd_skb);
2318        qtnf_bus_unlock(bus);
2319
2320        return ret;
2321}
2322
2323static int
2324qtnf_cmd_resp_proc_chan_stat_info(struct survey_info *survey,
2325                                  const u8 *payload, size_t payload_len)
2326{
2327        const struct qlink_chan_stats *stats = NULL;
2328        const struct qlink_tlv_hdr *tlv;
2329        u16 tlv_value_len;
2330        u16 tlv_type;
2331        const u8 *map = NULL;
2332        unsigned int map_len = 0;
2333        unsigned int stats_len = 0;
2334
2335        qlink_for_each_tlv(tlv, payload, payload_len) {
2336                tlv_type = le16_to_cpu(tlv->type);
2337                tlv_value_len = le16_to_cpu(tlv->len);
2338
2339                switch (tlv_type) {
2340                case QTN_TLV_ID_BITMAP:
2341                        map = tlv->val;
2342                        map_len = tlv_value_len;
2343                        break;
2344                case QTN_TLV_ID_CHANNEL_STATS:
2345                        stats = (struct qlink_chan_stats *)tlv->val;
2346                        stats_len = tlv_value_len;
2347                        break;
2348                default:
2349                        pr_info("Unknown TLV type: %#x\n", tlv_type);
2350                        break;
2351                }
2352        }
2353
2354        if (!qlink_tlv_parsing_ok(tlv, payload, payload_len)) {
2355                pr_err("Malformed TLV buffer\n");
2356                return -EINVAL;
2357        }
2358
2359        if (!map || !stats)
2360                return 0;
2361
2362#define qtnf_chan_stat_avail(stat_name, bitn)   \
2363        (qtnf_utils_is_bit_set(map, bitn, map_len) && \
2364         (offsetofend(struct qlink_chan_stats, stat_name) <= stats_len))
2365
2366        if (qtnf_chan_stat_avail(time_on, QLINK_CHAN_STAT_TIME_ON)) {
2367                survey->filled |= SURVEY_INFO_TIME;
2368                survey->time = le64_to_cpu(stats->time_on);
2369        }
2370
2371        if (qtnf_chan_stat_avail(time_tx, QLINK_CHAN_STAT_TIME_TX)) {
2372                survey->filled |= SURVEY_INFO_TIME_TX;
2373                survey->time_tx = le64_to_cpu(stats->time_tx);
2374        }
2375
2376        if (qtnf_chan_stat_avail(time_rx, QLINK_CHAN_STAT_TIME_RX)) {
2377                survey->filled |= SURVEY_INFO_TIME_RX;
2378                survey->time_rx = le64_to_cpu(stats->time_rx);
2379        }
2380
2381        if (qtnf_chan_stat_avail(cca_busy, QLINK_CHAN_STAT_CCA_BUSY)) {
2382                survey->filled |= SURVEY_INFO_TIME_BUSY;
2383                survey->time_busy = le64_to_cpu(stats->cca_busy);
2384        }
2385
2386        if (qtnf_chan_stat_avail(cca_busy_ext, QLINK_CHAN_STAT_CCA_BUSY_EXT)) {
2387                survey->filled |= SURVEY_INFO_TIME_EXT_BUSY;
2388                survey->time_ext_busy = le64_to_cpu(stats->cca_busy_ext);
2389        }
2390
2391        if (qtnf_chan_stat_avail(time_scan, QLINK_CHAN_STAT_TIME_SCAN)) {
2392                survey->filled |= SURVEY_INFO_TIME_SCAN;
2393                survey->time_scan = le64_to_cpu(stats->time_scan);
2394        }
2395
2396        if (qtnf_chan_stat_avail(chan_noise, QLINK_CHAN_STAT_CHAN_NOISE)) {
2397                survey->filled |= SURVEY_INFO_NOISE_DBM;
2398                survey->noise = stats->chan_noise;
2399        }
2400
2401#undef qtnf_chan_stat_avail
2402
2403        return 0;
2404}
2405
2406int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u32 chan_freq,
2407                            struct survey_info *survey)
2408{
2409        struct sk_buff *cmd_skb, *resp_skb = NULL;
2410        struct qlink_cmd_get_chan_stats *cmd;
2411        struct qlink_resp_get_chan_stats *resp;
2412        size_t var_data_len = 0;
2413        int ret = 0;
2414
2415        cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2416                                            QLINK_CMD_CHAN_STATS,
2417                                            sizeof(*cmd));
2418        if (!cmd_skb)
2419                return -ENOMEM;
2420
2421        cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data;
2422        cmd->channel_freq = cpu_to_le32(chan_freq);
2423
2424        qtnf_bus_lock(mac->bus);
2425        ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
2426                                       sizeof(*resp), &var_data_len);
2427        qtnf_bus_unlock(mac->bus);
2428
2429        if (ret)
2430                goto out;
2431
2432        resp = (struct qlink_resp_get_chan_stats *)resp_skb->data;
2433
2434        if (le32_to_cpu(resp->chan_freq) != chan_freq) {
2435                pr_err("[MAC%u] channel stats freq %u != requested %u\n",
2436                       mac->macid, le32_to_cpu(resp->chan_freq), chan_freq);
2437                ret = -EINVAL;
2438                goto out;
2439        }
2440
2441        ret = qtnf_cmd_resp_proc_chan_stat_info(survey, resp->info,
2442                                                var_data_len);
2443
2444out:
2445        consume_skb(resp_skb);
2446
2447        return ret;
2448}
2449
2450int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
2451                              struct cfg80211_csa_settings *params)
2452{
2453        struct qtnf_wmac *mac = vif->mac;
2454        struct qlink_cmd_chan_switch *cmd;
2455        struct sk_buff *cmd_skb;
2456        int ret;
2457        u64 flags = 0;
2458
2459        cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid,
2460                                            QLINK_CMD_CHAN_SWITCH,
2461                                            sizeof(*cmd));
2462        if (!cmd_skb)
2463                return -ENOMEM;
2464
2465        if (params->radar_required)
2466                flags |= QLINK_CHAN_SW_RADAR_REQUIRED;
2467
2468        if (params->block_tx)
2469                flags |= QLINK_CHAN_SW_BLOCK_TX;
2470
2471        cmd = (struct qlink_cmd_chan_switch *)cmd_skb->data;
2472        qlink_chandef_cfg2q(&params->chandef, &cmd->channel);
2473        cmd->flags = cpu_to_le64(flags);
2474        cmd->beacon_count = params->count;
2475
2476        qtnf_bus_lock(mac->bus);
2477        ret = qtnf_cmd_send(mac->bus, cmd_skb);
2478        qtnf_bus_unlock(mac->bus);
2479
2480        return ret;
2481}
2482
2483int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
2484{
2485        struct qtnf_bus *bus = vif->mac->bus;
2486        const struct qlink_resp_channel_get *resp;
2487        struct sk_buff *cmd_skb;
2488        struct sk_buff *resp_skb = NULL;
2489        int ret;
2490
2491        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2492                                            QLINK_CMD_CHAN_GET,
2493                                            sizeof(struct qlink_cmd));
2494        if (!cmd_skb)
2495                return -ENOMEM;
2496
2497        qtnf_bus_lock(bus);
2498        ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
2499                                       sizeof(*resp), NULL);
2500        if (ret)
2501                goto out;
2502
2503        resp = (const struct qlink_resp_channel_get *)resp_skb->data;
2504        qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef);
2505
2506out:
2507        qtnf_bus_unlock(bus);
2508        consume_skb(resp_skb);
2509
2510        return ret;
2511}
2512
2513int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
2514                       const struct cfg80211_chan_def *chdef,
2515                       u32 cac_time_ms)
2516{
2517        struct qtnf_bus *bus = vif->mac->bus;
2518        struct sk_buff *cmd_skb;
2519        struct qlink_cmd_start_cac *cmd;
2520        int ret;
2521
2522        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2523                                            QLINK_CMD_START_CAC,
2524                                            sizeof(*cmd));
2525        if (!cmd_skb)
2526                return -ENOMEM;
2527
2528        cmd = (struct qlink_cmd_start_cac *)cmd_skb->data;
2529        cmd->cac_time_ms = cpu_to_le32(cac_time_ms);
2530        qlink_chandef_cfg2q(chdef, &cmd->chan);
2531
2532        qtnf_bus_lock(bus);
2533        ret = qtnf_cmd_send(bus, cmd_skb);
2534        qtnf_bus_unlock(bus);
2535
2536        return ret;
2537}
2538
2539int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
2540                         const struct cfg80211_acl_data *params)
2541{
2542        struct qtnf_bus *bus = vif->mac->bus;
2543        struct sk_buff *cmd_skb;
2544        struct qlink_tlv_hdr *tlv;
2545        size_t acl_size = struct_size(params, mac_addrs, params->n_acl_entries);
2546        int ret;
2547
2548        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2549                                            QLINK_CMD_SET_MAC_ACL,
2550                                            sizeof(struct qlink_cmd));
2551        if (!cmd_skb)
2552                return -ENOMEM;
2553
2554        tlv = skb_put(cmd_skb, sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN));
2555        tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
2556        tlv->len = cpu_to_le16(acl_size);
2557        qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val);
2558
2559        qtnf_bus_lock(bus);
2560        ret = qtnf_cmd_send(bus, cmd_skb);
2561        qtnf_bus_unlock(bus);
2562
2563        return ret;
2564}
2565
2566int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout)
2567{
2568        struct qtnf_bus *bus = vif->mac->bus;
2569        struct sk_buff *cmd_skb;
2570        struct qlink_cmd_pm_set *cmd;
2571        int ret = 0;
2572
2573        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2574                                            QLINK_CMD_PM_SET, sizeof(*cmd));
2575        if (!cmd_skb)
2576                return -ENOMEM;
2577
2578        cmd = (struct qlink_cmd_pm_set *)cmd_skb->data;
2579        cmd->pm_mode = pm_mode;
2580        cmd->pm_standby_timer = cpu_to_le32(timeout);
2581
2582        qtnf_bus_lock(bus);
2583
2584        ret = qtnf_cmd_send(bus, cmd_skb);
2585
2586        qtnf_bus_unlock(bus);
2587
2588        return ret;
2589}
2590
2591int qtnf_cmd_get_tx_power(const struct qtnf_vif *vif, int *dbm)
2592{
2593        struct qtnf_bus *bus = vif->mac->bus;
2594        const struct qlink_resp_txpwr *resp;
2595        struct sk_buff *resp_skb = NULL;
2596        struct qlink_cmd_txpwr *cmd;
2597        struct sk_buff *cmd_skb;
2598        int ret = 0;
2599
2600        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2601                                            QLINK_CMD_TXPWR, sizeof(*cmd));
2602        if (!cmd_skb)
2603                return -ENOMEM;
2604
2605        cmd = (struct qlink_cmd_txpwr *)cmd_skb->data;
2606        cmd->op_type = QLINK_TXPWR_GET;
2607
2608        qtnf_bus_lock(bus);
2609
2610        ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
2611                                       sizeof(*resp), NULL);
2612        if (ret)
2613                goto out;
2614
2615        resp = (const struct qlink_resp_txpwr *)resp_skb->data;
2616        *dbm = MBM_TO_DBM(le32_to_cpu(resp->txpwr));
2617
2618out:
2619        qtnf_bus_unlock(bus);
2620        consume_skb(resp_skb);
2621
2622        return ret;
2623}
2624
2625int qtnf_cmd_set_tx_power(const struct qtnf_vif *vif,
2626                          enum nl80211_tx_power_setting type, int mbm)
2627{
2628        struct qtnf_bus *bus = vif->mac->bus;
2629        const struct qlink_resp_txpwr *resp;
2630        struct sk_buff *resp_skb = NULL;
2631        struct qlink_cmd_txpwr *cmd;
2632        struct sk_buff *cmd_skb;
2633        int ret = 0;
2634
2635        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2636                                            QLINK_CMD_TXPWR, sizeof(*cmd));
2637        if (!cmd_skb)
2638                return -ENOMEM;
2639
2640        cmd = (struct qlink_cmd_txpwr *)cmd_skb->data;
2641        cmd->op_type = QLINK_TXPWR_SET;
2642        cmd->txpwr_setting = type;
2643        cmd->txpwr = cpu_to_le32(mbm);
2644
2645        qtnf_bus_lock(bus);
2646
2647        ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
2648                                       sizeof(*resp), NULL);
2649
2650        qtnf_bus_unlock(bus);
2651        consume_skb(resp_skb);
2652
2653        return ret;
2654}
2655
2656int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
2657                             const struct cfg80211_wowlan *wowl)
2658{
2659        struct qtnf_bus *bus = vif->mac->bus;
2660        struct sk_buff *cmd_skb;
2661        struct qlink_cmd_wowlan_set *cmd;
2662        u32 triggers = 0;
2663        int count = 0;
2664        int ret = 0;
2665
2666        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2667                                            QLINK_CMD_WOWLAN_SET, sizeof(*cmd));
2668        if (!cmd_skb)
2669                return -ENOMEM;
2670
2671        qtnf_bus_lock(bus);
2672
2673        cmd = (struct qlink_cmd_wowlan_set *)cmd_skb->data;
2674
2675        if (wowl) {
2676                if (wowl->disconnect)
2677                        triggers |=  QLINK_WOWLAN_TRIG_DISCONNECT;
2678
2679                if (wowl->magic_pkt)
2680                        triggers |= QLINK_WOWLAN_TRIG_MAGIC_PKT;
2681
2682                if (wowl->n_patterns && wowl->patterns) {
2683                        triggers |= QLINK_WOWLAN_TRIG_PATTERN_PKT;
2684                        while (count < wowl->n_patterns) {
2685                                qtnf_cmd_skb_put_tlv_arr(cmd_skb,
2686                                        QTN_TLV_ID_WOWLAN_PATTERN,
2687                                        wowl->patterns[count].pattern,
2688                                        wowl->patterns[count].pattern_len);
2689                                count++;
2690                        }
2691                }
2692        }
2693
2694        cmd->triggers = cpu_to_le32(triggers);
2695
2696        ret = qtnf_cmd_send(bus, cmd_skb);
2697
2698        qtnf_bus_unlock(bus);
2699        return ret;
2700}
2701
2702int qtnf_cmd_netdev_changeupper(const struct qtnf_vif *vif, int br_domain)
2703{
2704        struct qtnf_bus *bus = vif->mac->bus;
2705        struct sk_buff *cmd_skb;
2706        struct qlink_cmd_ndev_changeupper *cmd;
2707        int ret;
2708
2709        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2710                                            QLINK_CMD_NDEV_EVENT,
2711                                            sizeof(*cmd));
2712        if (!cmd_skb)
2713                return -ENOMEM;
2714
2715        pr_debug("[VIF%u.%u] set broadcast domain to %d\n",
2716                 vif->mac->macid, vif->vifid, br_domain);
2717
2718        cmd = (struct qlink_cmd_ndev_changeupper *)cmd_skb->data;
2719        cmd->nehdr.event = cpu_to_le16(QLINK_NDEV_EVENT_CHANGEUPPER);
2720        cmd->upper_type = QLINK_NDEV_UPPER_TYPE_BRIDGE;
2721        cmd->br_domain = cpu_to_le32(br_domain);
2722
2723        qtnf_bus_lock(bus);
2724        ret = qtnf_cmd_send(bus, cmd_skb);
2725        qtnf_bus_unlock(bus);
2726
2727        if (ret)
2728                pr_err("[VIF%u.%u] failed to set broadcast domain\n",
2729                       vif->mac->macid, vif->vifid);
2730
2731        return ret;
2732}
2733
2734int qtnf_cmd_send_update_owe(struct qtnf_vif *vif,
2735                             struct cfg80211_update_owe_info *owe)
2736{
2737        struct qlink_cmd_update_owe *cmd;
2738        struct sk_buff *cmd_skb;
2739        int ret;
2740
2741        if (sizeof(*cmd) + owe->ie_len > QTNF_MAX_CMD_BUF_SIZE) {
2742                pr_warn("VIF%u.%u: OWE update IEs too big: %zu\n",
2743                        vif->mac->macid, vif->vifid, owe->ie_len);
2744                return -E2BIG;
2745        }
2746
2747        cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2748                                            QLINK_CMD_UPDATE_OWE,
2749                                            sizeof(*cmd));
2750        if (!cmd_skb)
2751                return -ENOMEM;
2752
2753        cmd = (struct qlink_cmd_update_owe *)cmd_skb->data;
2754        ether_addr_copy(cmd->peer, owe->peer);
2755        cmd->status = cpu_to_le16(owe->status);
2756        if (owe->ie_len && owe->ie)
2757                qtnf_cmd_skb_put_buffer(cmd_skb, owe->ie, owe->ie_len);
2758
2759        qtnf_bus_lock(vif->mac->bus);
2760        ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2761        qtnf_bus_unlock(vif->mac->bus);
2762
2763        return ret;
2764}
2765