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