root/drivers/net/wireless/quantenna/qtnfmac/commands.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qtnf_cmd_check_reply_header
  2. qtnf_cmd_resp_result_decode
  3. qtnf_cmd_send_with_reply
  4. qtnf_cmd_send
  5. qtnf_cmd_alloc_new_cmdskb
  6. qtnf_cmd_tlv_ie_set_add
  7. qtnf_cmd_start_ap_can_fit
  8. qtnf_cmd_send_start_ap
  9. qtnf_cmd_send_stop_ap
  10. qtnf_cmd_send_register_mgmt
  11. qtnf_cmd_send_frame
  12. qtnf_cmd_send_mgmt_set_appie
  13. qtnf_sta_info_parse_rate
  14. qtnf_sta_info_parse_flags
  15. qtnf_cmd_sta_info_parse
  16. qtnf_cmd_get_sta_info
  17. qtnf_cmd_send_add_change_intf
  18. qtnf_cmd_send_add_intf
  19. qtnf_cmd_send_change_intf_type
  20. qtnf_cmd_send_del_intf
  21. qtnf_cmd_resp_proc_hw_info
  22. qtnf_parse_wowlan_info
  23. qtnf_parse_variable_mac_info
  24. qtnf_cmd_resp_proc_mac_info
  25. qtnf_cmd_resp_band_fill_htcap
  26. qtnf_cmd_resp_band_fill_vhtcap
  27. qtnf_cmd_resp_fill_band_info
  28. qtnf_cmd_resp_proc_phy_params
  29. qtnf_cmd_resp_proc_chan_stat_info
  30. qtnf_cmd_get_mac_info
  31. qtnf_cmd_get_hw_info
  32. qtnf_cmd_band_info_get
  33. qtnf_cmd_send_get_phy_params
  34. qtnf_cmd_send_update_phy_params
  35. qtnf_cmd_send_init_fw
  36. qtnf_cmd_send_deinit_fw
  37. qtnf_cmd_send_add_key
  38. qtnf_cmd_send_del_key
  39. qtnf_cmd_send_set_default_key
  40. qtnf_cmd_send_set_default_mgmt_key
  41. qtnf_encode_sta_flags
  42. qtnf_cmd_send_change_sta
  43. qtnf_cmd_send_del_sta
  44. qtnf_cmd_channel_tlv_add
  45. qtnf_cmd_randmac_tlv_add
  46. qtnf_cmd_scan_set_dwell
  47. qtnf_cmd_send_scan
  48. qtnf_cmd_send_connect
  49. qtnf_cmd_send_external_auth
  50. qtnf_cmd_send_disconnect
  51. qtnf_cmd_send_updown_intf
  52. qtnf_cmd_reg_notify
  53. qtnf_cmd_get_chan_stats
  54. qtnf_cmd_send_chan_switch
  55. qtnf_cmd_get_channel
  56. qtnf_cmd_start_cac
  57. qtnf_cmd_set_mac_acl
  58. qtnf_cmd_send_pm_set
  59. qtnf_cmd_send_wowlan_set

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

/* [<][>][^][v][top][bottom][index][help] */