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