Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (c) 2005-2011 Atheros Communications Inc.
0004  * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
0005  * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
0006  */
0007 #include "core.h"
0008 #include "debug.h"
0009 #include "mac.h"
0010 #include "hw.h"
0011 #include "wmi.h"
0012 #include "wmi-ops.h"
0013 #include "wmi-tlv.h"
0014 #include "p2p.h"
0015 #include "testmode.h"
0016 #include <linux/bitfield.h>
0017 
0018 /***************/
0019 /* TLV helpers */
0020 /**************/
0021 
0022 struct wmi_tlv_policy {
0023     size_t min_len;
0024 };
0025 
0026 static const struct wmi_tlv_policy wmi_tlv_policies[] = {
0027     [WMI_TLV_TAG_ARRAY_BYTE]
0028         = { .min_len = 0 },
0029     [WMI_TLV_TAG_ARRAY_UINT32]
0030         = { .min_len = 0 },
0031     [WMI_TLV_TAG_STRUCT_SCAN_EVENT]
0032         = { .min_len = sizeof(struct wmi_scan_event) },
0033     [WMI_TLV_TAG_STRUCT_MGMT_RX_HDR]
0034         = { .min_len = sizeof(struct wmi_tlv_mgmt_rx_ev) },
0035     [WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT]
0036         = { .min_len = sizeof(struct wmi_chan_info_event) },
0037     [WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT]
0038         = { .min_len = sizeof(struct wmi_vdev_start_response_event) },
0039     [WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT]
0040         = { .min_len = sizeof(struct wmi_peer_sta_kickout_event) },
0041     [WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT]
0042         = { .min_len = sizeof(struct wmi_host_swba_event) },
0043     [WMI_TLV_TAG_STRUCT_TIM_INFO]
0044         = { .min_len = sizeof(struct wmi_tim_info) },
0045     [WMI_TLV_TAG_STRUCT_P2P_NOA_INFO]
0046         = { .min_len = sizeof(struct wmi_p2p_noa_info) },
0047     [WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT]
0048         = { .min_len = sizeof(struct wmi_tlv_svc_rdy_ev) },
0049     [WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES]
0050         = { .min_len = sizeof(struct hal_reg_capabilities) },
0051     [WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ]
0052         = { .min_len = sizeof(struct wlan_host_mem_req) },
0053     [WMI_TLV_TAG_STRUCT_READY_EVENT]
0054         = { .min_len = sizeof(struct wmi_tlv_rdy_ev) },
0055     [WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]
0056         = { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
0057     [WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
0058         = { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
0059     [WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
0060         = { .min_len = sizeof(struct wmi_tlv_p2p_noa_ev) },
0061     [WMI_TLV_TAG_STRUCT_ROAM_EVENT]
0062         = { .min_len = sizeof(struct wmi_tlv_roam_ev) },
0063     [WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO]
0064         = { .min_len = sizeof(struct wmi_tlv_wow_event_info) },
0065     [WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT]
0066         = { .min_len = sizeof(struct wmi_tlv_tx_pause_ev) },
0067 };
0068 
0069 static int
0070 ath10k_wmi_tlv_iter(struct ath10k *ar, const void *ptr, size_t len,
0071             int (*iter)(struct ath10k *ar, u16 tag, u16 len,
0072                 const void *ptr, void *data),
0073             void *data)
0074 {
0075     const void *begin = ptr;
0076     const struct wmi_tlv *tlv;
0077     u16 tlv_tag, tlv_len;
0078     int ret;
0079 
0080     while (len > 0) {
0081         if (len < sizeof(*tlv)) {
0082             ath10k_dbg(ar, ATH10K_DBG_WMI,
0083                    "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
0084                    ptr - begin, len, sizeof(*tlv));
0085             return -EINVAL;
0086         }
0087 
0088         tlv = ptr;
0089         tlv_tag = __le16_to_cpu(tlv->tag);
0090         tlv_len = __le16_to_cpu(tlv->len);
0091         ptr += sizeof(*tlv);
0092         len -= sizeof(*tlv);
0093 
0094         if (tlv_len > len) {
0095             ath10k_dbg(ar, ATH10K_DBG_WMI,
0096                    "wmi tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",
0097                    tlv_tag, ptr - begin, len, tlv_len);
0098             return -EINVAL;
0099         }
0100 
0101         if (tlv_tag < ARRAY_SIZE(wmi_tlv_policies) &&
0102             wmi_tlv_policies[tlv_tag].min_len &&
0103             wmi_tlv_policies[tlv_tag].min_len > tlv_len) {
0104             ath10k_dbg(ar, ATH10K_DBG_WMI,
0105                    "wmi tlv parse failure of tag %u at byte %zd (%u bytes is less than min length %zu)\n",
0106                    tlv_tag, ptr - begin, tlv_len,
0107                    wmi_tlv_policies[tlv_tag].min_len);
0108             return -EINVAL;
0109         }
0110 
0111         ret = iter(ar, tlv_tag, tlv_len, ptr, data);
0112         if (ret)
0113             return ret;
0114 
0115         ptr += tlv_len;
0116         len -= tlv_len;
0117     }
0118 
0119     return 0;
0120 }
0121 
0122 static int ath10k_wmi_tlv_iter_parse(struct ath10k *ar, u16 tag, u16 len,
0123                      const void *ptr, void *data)
0124 {
0125     const void **tb = data;
0126 
0127     if (tag < WMI_TLV_TAG_MAX)
0128         tb[tag] = ptr;
0129 
0130     return 0;
0131 }
0132 
0133 static int ath10k_wmi_tlv_parse(struct ath10k *ar, const void **tb,
0134                 const void *ptr, size_t len)
0135 {
0136     return ath10k_wmi_tlv_iter(ar, ptr, len, ath10k_wmi_tlv_iter_parse,
0137                    (void *)tb);
0138 }
0139 
0140 static const void **
0141 ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
0142                size_t len, gfp_t gfp)
0143 {
0144     const void **tb;
0145     int ret;
0146 
0147     tb = kcalloc(WMI_TLV_TAG_MAX, sizeof(*tb), gfp);
0148     if (!tb)
0149         return ERR_PTR(-ENOMEM);
0150 
0151     ret = ath10k_wmi_tlv_parse(ar, tb, ptr, len);
0152     if (ret) {
0153         kfree(tb);
0154         return ERR_PTR(ret);
0155     }
0156 
0157     return tb;
0158 }
0159 
0160 static u16 ath10k_wmi_tlv_len(const void *ptr)
0161 {
0162     return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len);
0163 }
0164 
0165 /**************/
0166 /* TLV events */
0167 /**************/
0168 static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
0169                           struct sk_buff *skb)
0170 {
0171     const void **tb;
0172     const struct wmi_tlv_bcn_tx_status_ev *ev;
0173     struct ath10k_vif *arvif;
0174     u32 vdev_id, tx_status;
0175     int ret;
0176 
0177     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0178     if (IS_ERR(tb)) {
0179         ret = PTR_ERR(tb);
0180         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0181         return ret;
0182     }
0183 
0184     ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT];
0185     if (!ev) {
0186         kfree(tb);
0187         return -EPROTO;
0188     }
0189 
0190     tx_status = __le32_to_cpu(ev->tx_status);
0191     vdev_id = __le32_to_cpu(ev->vdev_id);
0192 
0193     switch (tx_status) {
0194     case WMI_TLV_BCN_TX_STATUS_OK:
0195         break;
0196     case WMI_TLV_BCN_TX_STATUS_XRETRY:
0197     case WMI_TLV_BCN_TX_STATUS_DROP:
0198     case WMI_TLV_BCN_TX_STATUS_FILTERED:
0199         /* FIXME: It's probably worth telling mac80211 to stop the
0200          * interface as it is crippled.
0201          */
0202         ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d",
0203                 vdev_id, tx_status);
0204         break;
0205     }
0206 
0207     arvif = ath10k_get_arvif(ar, vdev_id);
0208     if (arvif && arvif->is_up && arvif->vif->bss_conf.csa_active)
0209         ieee80211_queue_work(ar->hw, &arvif->ap_csa_work);
0210 
0211     kfree(tb);
0212     return 0;
0213 }
0214 
0215 static void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar,
0216                           struct sk_buff *skb)
0217 {
0218     ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n");
0219     complete(&ar->vdev_delete_done);
0220 }
0221 
0222 static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 len,
0223                         const void *ptr, void *data)
0224 {
0225     const struct wmi_tlv_peer_stats_info *stat = ptr;
0226     struct ieee80211_sta *sta;
0227     struct ath10k_sta *arsta;
0228 
0229     if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
0230         return -EPROTO;
0231 
0232     ath10k_dbg(ar, ATH10K_DBG_WMI,
0233            "wmi tlv stats peer addr %pMF rx rate code 0x%x bit rate %d kbps\n",
0234            stat->peer_macaddr.addr,
0235            __le32_to_cpu(stat->last_rx_rate_code),
0236            __le32_to_cpu(stat->last_rx_bitrate_kbps));
0237 
0238     ath10k_dbg(ar, ATH10K_DBG_WMI,
0239            "wmi tlv stats tx rate code 0x%x bit rate %d kbps\n",
0240            __le32_to_cpu(stat->last_tx_rate_code),
0241            __le32_to_cpu(stat->last_tx_bitrate_kbps));
0242 
0243     rcu_read_lock();
0244     sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
0245     if (!sta) {
0246         rcu_read_unlock();
0247         ath10k_warn(ar, "not found station for peer stats\n");
0248         return -EINVAL;
0249     }
0250 
0251     arsta = (struct ath10k_sta *)sta->drv_priv;
0252     arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
0253     arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
0254     arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
0255     arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
0256     rcu_read_unlock();
0257 
0258     return 0;
0259 }
0260 
0261 static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
0262                           struct sk_buff *skb)
0263 {
0264     const void **tb;
0265     const struct wmi_tlv_peer_stats_info_ev *ev;
0266     const void *data;
0267     u32 num_peer_stats;
0268     int ret;
0269 
0270     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0271     if (IS_ERR(tb)) {
0272         ret = PTR_ERR(tb);
0273         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0274         return ret;
0275     }
0276 
0277     ev = tb[WMI_TLV_TAG_STRUCT_PEER_STATS_INFO_EVENT];
0278     data = tb[WMI_TLV_TAG_ARRAY_STRUCT];
0279 
0280     if (!ev || !data) {
0281         kfree(tb);
0282         return -EPROTO;
0283     }
0284 
0285     num_peer_stats = __le32_to_cpu(ev->num_peers);
0286 
0287     ath10k_dbg(ar, ATH10K_DBG_WMI,
0288            "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
0289            __le32_to_cpu(ev->vdev_id),
0290            num_peer_stats,
0291            __le32_to_cpu(ev->more_data));
0292 
0293     ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
0294                   ath10k_wmi_tlv_parse_peer_stats_info, NULL);
0295     if (ret)
0296         ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
0297 
0298     kfree(tb);
0299     return 0;
0300 }
0301 
0302 static void ath10k_wmi_tlv_event_peer_stats_info(struct ath10k *ar,
0303                          struct sk_buff *skb)
0304 {
0305     ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PEER_STATS_INFO_EVENTID\n");
0306     ath10k_wmi_tlv_op_pull_peer_stats_info(ar, skb);
0307     complete(&ar->peer_stats_info_complete);
0308 }
0309 
0310 static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
0311                       struct sk_buff *skb)
0312 {
0313     const void **tb;
0314     const struct wmi_tlv_diag_data_ev *ev;
0315     const struct wmi_tlv_diag_item *item;
0316     const void *data;
0317     int ret, num_items, len;
0318 
0319     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0320     if (IS_ERR(tb)) {
0321         ret = PTR_ERR(tb);
0322         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0323         return ret;
0324     }
0325 
0326     ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT];
0327     data = tb[WMI_TLV_TAG_ARRAY_BYTE];
0328     if (!ev || !data) {
0329         kfree(tb);
0330         return -EPROTO;
0331     }
0332 
0333     num_items = __le32_to_cpu(ev->num_items);
0334     len = ath10k_wmi_tlv_len(data);
0335 
0336     while (num_items--) {
0337         if (len == 0)
0338             break;
0339         if (len < sizeof(*item)) {
0340             ath10k_warn(ar, "failed to parse diag data: can't fit item header\n");
0341             break;
0342         }
0343 
0344         item = data;
0345 
0346         if (len < sizeof(*item) + __le16_to_cpu(item->len)) {
0347             ath10k_warn(ar, "failed to parse diag data: item is too long\n");
0348             break;
0349         }
0350 
0351         trace_ath10k_wmi_diag_container(ar,
0352                         item->type,
0353                         __le32_to_cpu(item->timestamp),
0354                         __le32_to_cpu(item->code),
0355                         __le16_to_cpu(item->len),
0356                         item->payload);
0357 
0358         len -= sizeof(*item);
0359         len -= roundup(__le16_to_cpu(item->len), 4);
0360 
0361         data += sizeof(*item);
0362         data += roundup(__le16_to_cpu(item->len), 4);
0363     }
0364 
0365     if (num_items != -1 || len != 0)
0366         ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n",
0367                 num_items, len);
0368 
0369     kfree(tb);
0370     return 0;
0371 }
0372 
0373 static int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
0374                      struct sk_buff *skb)
0375 {
0376     const void **tb;
0377     const void *data;
0378     int ret, len;
0379 
0380     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0381     if (IS_ERR(tb)) {
0382         ret = PTR_ERR(tb);
0383         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0384         return ret;
0385     }
0386 
0387     data = tb[WMI_TLV_TAG_ARRAY_BYTE];
0388     if (!data) {
0389         kfree(tb);
0390         return -EPROTO;
0391     }
0392     len = ath10k_wmi_tlv_len(data);
0393 
0394     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len);
0395     trace_ath10k_wmi_diag(ar, data, len);
0396 
0397     kfree(tb);
0398     return 0;
0399 }
0400 
0401 static int ath10k_wmi_tlv_event_p2p_noa(struct ath10k *ar,
0402                     struct sk_buff *skb)
0403 {
0404     const void **tb;
0405     const struct wmi_tlv_p2p_noa_ev *ev;
0406     const struct wmi_p2p_noa_info *noa;
0407     int ret, vdev_id;
0408 
0409     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0410     if (IS_ERR(tb)) {
0411         ret = PTR_ERR(tb);
0412         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0413         return ret;
0414     }
0415 
0416     ev = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT];
0417     noa = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO];
0418 
0419     if (!ev || !noa) {
0420         kfree(tb);
0421         return -EPROTO;
0422     }
0423 
0424     vdev_id = __le32_to_cpu(ev->vdev_id);
0425 
0426     ath10k_dbg(ar, ATH10K_DBG_WMI,
0427            "wmi tlv p2p noa vdev_id %i descriptors %u\n",
0428            vdev_id, noa->num_descriptors);
0429 
0430     ath10k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
0431     kfree(tb);
0432     return 0;
0433 }
0434 
0435 static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
0436                      struct sk_buff *skb)
0437 {
0438     const void **tb;
0439     const struct wmi_tlv_tx_pause_ev *ev;
0440     int ret, vdev_id;
0441     u32 pause_id, action, vdev_map, peer_id, tid_map;
0442 
0443     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0444     if (IS_ERR(tb)) {
0445         ret = PTR_ERR(tb);
0446         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0447         return ret;
0448     }
0449 
0450     ev = tb[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT];
0451     if (!ev) {
0452         kfree(tb);
0453         return -EPROTO;
0454     }
0455 
0456     pause_id = __le32_to_cpu(ev->pause_id);
0457     action = __le32_to_cpu(ev->action);
0458     vdev_map = __le32_to_cpu(ev->vdev_map);
0459     peer_id = __le32_to_cpu(ev->peer_id);
0460     tid_map = __le32_to_cpu(ev->tid_map);
0461 
0462     ath10k_dbg(ar, ATH10K_DBG_WMI,
0463            "wmi tlv tx pause pause_id %u action %u vdev_map 0x%08x peer_id %u tid_map 0x%08x\n",
0464            pause_id, action, vdev_map, peer_id, tid_map);
0465 
0466     switch (pause_id) {
0467     case WMI_TLV_TX_PAUSE_ID_MCC:
0468     case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
0469     case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
0470     case WMI_TLV_TX_PAUSE_ID_AP_PS:
0471     case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
0472         for (vdev_id = 0; vdev_map; vdev_id++) {
0473             if (!(vdev_map & BIT(vdev_id)))
0474                 continue;
0475 
0476             vdev_map &= ~BIT(vdev_id);
0477             ath10k_mac_handle_tx_pause_vdev(ar, vdev_id, pause_id,
0478                             action);
0479         }
0480         break;
0481     case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
0482     case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
0483     case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
0484     case WMI_TLV_TX_PAUSE_ID_HOST:
0485         ath10k_dbg(ar, ATH10K_DBG_MAC,
0486                "mac ignoring unsupported tx pause id %d\n",
0487                pause_id);
0488         break;
0489     default:
0490         ath10k_dbg(ar, ATH10K_DBG_MAC,
0491                "mac ignoring unknown tx pause vdev %d\n",
0492                pause_id);
0493         break;
0494     }
0495 
0496     kfree(tb);
0497     return 0;
0498 }
0499 
0500 static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
0501                              struct sk_buff *skb)
0502 {
0503     const struct wmi_tlv_rfkill_state_change_ev *ev;
0504     const void **tb;
0505     bool radio;
0506     int ret;
0507 
0508     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0509     if (IS_ERR(tb)) {
0510         ret = PTR_ERR(tb);
0511         ath10k_warn(ar,
0512                 "failed to parse rfkill state change event: %d\n",
0513                 ret);
0514         return;
0515     }
0516 
0517     ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
0518     if (!ev) {
0519         kfree(tb);
0520         return;
0521     }
0522 
0523     ath10k_dbg(ar, ATH10K_DBG_MAC,
0524            "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
0525            __le32_to_cpu(ev->gpio_pin_num),
0526            __le32_to_cpu(ev->int_type),
0527            __le32_to_cpu(ev->radio_state));
0528 
0529     radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
0530 
0531     spin_lock_bh(&ar->data_lock);
0532 
0533     if (!radio)
0534         ar->hw_rfkill_on = true;
0535 
0536     spin_unlock_bh(&ar->data_lock);
0537 
0538     /* notify cfg80211 radio state change */
0539     ath10k_mac_rfkill_enable_radio(ar, radio);
0540     wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
0541 }
0542 
0543 static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
0544                         struct sk_buff *skb)
0545 {
0546     const struct wmi_tlv_pdev_temperature_event *ev;
0547 
0548     ev = (struct wmi_tlv_pdev_temperature_event *)skb->data;
0549     if (WARN_ON(skb->len < sizeof(*ev)))
0550         return -EPROTO;
0551 
0552     ath10k_thermal_event_temperature(ar, __le32_to_cpu(ev->temperature));
0553     return 0;
0554 }
0555 
0556 static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
0557 {
0558     struct ieee80211_sta *station;
0559     const struct wmi_tlv_tdls_peer_event *ev;
0560     const void **tb;
0561     struct ath10k_vif *arvif;
0562 
0563     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0564     if (IS_ERR(tb)) {
0565         ath10k_warn(ar, "tdls peer failed to parse tlv");
0566         return;
0567     }
0568     ev = tb[WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT];
0569     if (!ev) {
0570         kfree(tb);
0571         ath10k_warn(ar, "tdls peer NULL event");
0572         return;
0573     }
0574 
0575     switch (__le32_to_cpu(ev->peer_reason)) {
0576     case WMI_TDLS_TEARDOWN_REASON_TX:
0577     case WMI_TDLS_TEARDOWN_REASON_RSSI:
0578     case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
0579         rcu_read_lock();
0580         station = ieee80211_find_sta_by_ifaddr(ar->hw,
0581                                ev->peer_macaddr.addr,
0582                                NULL);
0583         if (!station) {
0584             ath10k_warn(ar, "did not find station from tdls peer event");
0585             goto exit;
0586         }
0587         arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
0588         ieee80211_tdls_oper_request(
0589                     arvif->vif, station->addr,
0590                     NL80211_TDLS_TEARDOWN,
0591                     WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
0592                     GFP_ATOMIC
0593                     );
0594         break;
0595     default:
0596         kfree(tb);
0597         return;
0598     }
0599 
0600 exit:
0601     rcu_read_unlock();
0602     kfree(tb);
0603 }
0604 
0605 static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
0606                          struct sk_buff *skb)
0607 {
0608     struct wmi_peer_delete_resp_ev_arg *arg;
0609     struct wmi_tlv *tlv_hdr;
0610 
0611     tlv_hdr = (struct wmi_tlv *)skb->data;
0612     arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value;
0613 
0614     ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id);
0615     ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr);
0616     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n");
0617 
0618     complete(&ar->peer_delete_done);
0619 
0620     return 0;
0621 }
0622 
0623 /***********/
0624 /* TLV ops */
0625 /***********/
0626 
0627 static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
0628 {
0629     struct wmi_cmd_hdr *cmd_hdr;
0630     enum wmi_tlv_event_id id;
0631     bool consumed;
0632 
0633     cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
0634     id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
0635 
0636     if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
0637         goto out;
0638 
0639     trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
0640 
0641     consumed = ath10k_tm_event_wmi(ar, id, skb);
0642 
0643     /* Ready event must be handled normally also in UTF mode so that we
0644      * know the UTF firmware has booted, others we are just bypass WMI
0645      * events to testmode.
0646      */
0647     if (consumed && id != WMI_TLV_READY_EVENTID) {
0648         ath10k_dbg(ar, ATH10K_DBG_WMI,
0649                "wmi tlv testmode consumed 0x%x\n", id);
0650         goto out;
0651     }
0652 
0653     switch (id) {
0654     case WMI_TLV_MGMT_RX_EVENTID:
0655         ath10k_wmi_event_mgmt_rx(ar, skb);
0656         /* mgmt_rx() owns the skb now! */
0657         return;
0658     case WMI_TLV_SCAN_EVENTID:
0659         ath10k_wmi_event_scan(ar, skb);
0660         break;
0661     case WMI_TLV_CHAN_INFO_EVENTID:
0662         ath10k_wmi_event_chan_info(ar, skb);
0663         break;
0664     case WMI_TLV_ECHO_EVENTID:
0665         ath10k_wmi_event_echo(ar, skb);
0666         break;
0667     case WMI_TLV_DEBUG_MESG_EVENTID:
0668         ath10k_wmi_event_debug_mesg(ar, skb);
0669         break;
0670     case WMI_TLV_UPDATE_STATS_EVENTID:
0671         ath10k_wmi_event_update_stats(ar, skb);
0672         break;
0673     case WMI_TLV_PEER_STATS_INFO_EVENTID:
0674         ath10k_wmi_tlv_event_peer_stats_info(ar, skb);
0675         break;
0676     case WMI_TLV_VDEV_START_RESP_EVENTID:
0677         ath10k_wmi_event_vdev_start_resp(ar, skb);
0678         break;
0679     case WMI_TLV_VDEV_STOPPED_EVENTID:
0680         ath10k_wmi_event_vdev_stopped(ar, skb);
0681         break;
0682     case WMI_TLV_VDEV_DELETE_RESP_EVENTID:
0683         ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb);
0684         break;
0685     case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
0686         ath10k_wmi_event_peer_sta_kickout(ar, skb);
0687         break;
0688     case WMI_TLV_HOST_SWBA_EVENTID:
0689         ath10k_wmi_event_host_swba(ar, skb);
0690         break;
0691     case WMI_TLV_TBTTOFFSET_UPDATE_EVENTID:
0692         ath10k_wmi_event_tbttoffset_update(ar, skb);
0693         break;
0694     case WMI_TLV_PHYERR_EVENTID:
0695         ath10k_wmi_event_phyerr(ar, skb);
0696         break;
0697     case WMI_TLV_ROAM_EVENTID:
0698         ath10k_wmi_event_roam(ar, skb);
0699         break;
0700     case WMI_TLV_PROFILE_MATCH:
0701         ath10k_wmi_event_profile_match(ar, skb);
0702         break;
0703     case WMI_TLV_DEBUG_PRINT_EVENTID:
0704         ath10k_wmi_event_debug_print(ar, skb);
0705         break;
0706     case WMI_TLV_PDEV_QVIT_EVENTID:
0707         ath10k_wmi_event_pdev_qvit(ar, skb);
0708         break;
0709     case WMI_TLV_WLAN_PROFILE_DATA_EVENTID:
0710         ath10k_wmi_event_wlan_profile_data(ar, skb);
0711         break;
0712     case WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID:
0713         ath10k_wmi_event_rtt_measurement_report(ar, skb);
0714         break;
0715     case WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID:
0716         ath10k_wmi_event_tsf_measurement_report(ar, skb);
0717         break;
0718     case WMI_TLV_RTT_ERROR_REPORT_EVENTID:
0719         ath10k_wmi_event_rtt_error_report(ar, skb);
0720         break;
0721     case WMI_TLV_WOW_WAKEUP_HOST_EVENTID:
0722         ath10k_wmi_event_wow_wakeup_host(ar, skb);
0723         break;
0724     case WMI_TLV_DCS_INTERFERENCE_EVENTID:
0725         ath10k_wmi_event_dcs_interference(ar, skb);
0726         break;
0727     case WMI_TLV_PDEV_TPC_CONFIG_EVENTID:
0728         ath10k_wmi_event_pdev_tpc_config(ar, skb);
0729         break;
0730     case WMI_TLV_PDEV_FTM_INTG_EVENTID:
0731         ath10k_wmi_event_pdev_ftm_intg(ar, skb);
0732         break;
0733     case WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID:
0734         ath10k_wmi_event_gtk_offload_status(ar, skb);
0735         break;
0736     case WMI_TLV_GTK_REKEY_FAIL_EVENTID:
0737         ath10k_wmi_event_gtk_rekey_fail(ar, skb);
0738         break;
0739     case WMI_TLV_TX_DELBA_COMPLETE_EVENTID:
0740         ath10k_wmi_event_delba_complete(ar, skb);
0741         break;
0742     case WMI_TLV_TX_ADDBA_COMPLETE_EVENTID:
0743         ath10k_wmi_event_addba_complete(ar, skb);
0744         break;
0745     case WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID:
0746         ath10k_wmi_event_vdev_install_key_complete(ar, skb);
0747         break;
0748     case WMI_TLV_SERVICE_READY_EVENTID:
0749         ath10k_wmi_event_service_ready(ar, skb);
0750         return;
0751     case WMI_TLV_READY_EVENTID:
0752         ath10k_wmi_event_ready(ar, skb);
0753         break;
0754     case WMI_TLV_SERVICE_AVAILABLE_EVENTID:
0755         ath10k_wmi_event_service_available(ar, skb);
0756         break;
0757     case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID:
0758         ath10k_wmi_tlv_event_bcn_tx_status(ar, skb);
0759         break;
0760     case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID:
0761         ath10k_wmi_tlv_event_diag_data(ar, skb);
0762         break;
0763     case WMI_TLV_DIAG_EVENTID:
0764         ath10k_wmi_tlv_event_diag(ar, skb);
0765         break;
0766     case WMI_TLV_P2P_NOA_EVENTID:
0767         ath10k_wmi_tlv_event_p2p_noa(ar, skb);
0768         break;
0769     case WMI_TLV_TX_PAUSE_EVENTID:
0770         ath10k_wmi_tlv_event_tx_pause(ar, skb);
0771         break;
0772     case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
0773         ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
0774         break;
0775     case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
0776         ath10k_wmi_tlv_event_temperature(ar, skb);
0777         break;
0778     case WMI_TLV_TDLS_PEER_EVENTID:
0779         ath10k_wmi_event_tdls_peer(ar, skb);
0780         break;
0781     case WMI_TLV_PEER_DELETE_RESP_EVENTID:
0782         ath10k_wmi_tlv_event_peer_delete_resp(ar, skb);
0783         break;
0784     case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
0785         ath10k_wmi_event_mgmt_tx_compl(ar, skb);
0786         break;
0787     case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID:
0788         ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb);
0789         break;
0790     default:
0791         ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id);
0792         break;
0793     }
0794 
0795 out:
0796     dev_kfree_skb(skb);
0797 }
0798 
0799 static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
0800                       struct sk_buff *skb,
0801                       struct wmi_scan_ev_arg *arg)
0802 {
0803     const void **tb;
0804     const struct wmi_scan_event *ev;
0805     int ret;
0806 
0807     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0808     if (IS_ERR(tb)) {
0809         ret = PTR_ERR(tb);
0810         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0811         return ret;
0812     }
0813 
0814     ev = tb[WMI_TLV_TAG_STRUCT_SCAN_EVENT];
0815     if (!ev) {
0816         kfree(tb);
0817         return -EPROTO;
0818     }
0819 
0820     arg->event_type = ev->event_type;
0821     arg->reason = ev->reason;
0822     arg->channel_freq = ev->channel_freq;
0823     arg->scan_req_id = ev->scan_req_id;
0824     arg->scan_id = ev->scan_id;
0825     arg->vdev_id = ev->vdev_id;
0826 
0827     kfree(tb);
0828     return 0;
0829 }
0830 
0831 static int
0832 ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
0833                     struct wmi_tlv_mgmt_tx_compl_ev_arg *arg)
0834 {
0835     const void **tb;
0836     const struct wmi_tlv_mgmt_tx_compl_ev *ev;
0837     int ret;
0838 
0839     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0840     if (IS_ERR(tb)) {
0841         ret = PTR_ERR(tb);
0842         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0843         return ret;
0844     }
0845 
0846     ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
0847 
0848     arg->desc_id = ev->desc_id;
0849     arg->status = ev->status;
0850     arg->pdev_id = ev->pdev_id;
0851     arg->ppdu_id = ev->ppdu_id;
0852 
0853     if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
0854         arg->ack_rssi = ev->ack_rssi;
0855 
0856     kfree(tb);
0857     return 0;
0858 }
0859 
0860 struct wmi_tlv_tx_bundle_compl_parse {
0861     const __le32 *num_reports;
0862     const __le32 *desc_ids;
0863     const __le32 *status;
0864     const __le32 *ppdu_ids;
0865     const __le32 *ack_rssi;
0866     bool desc_ids_done;
0867     bool status_done;
0868     bool ppdu_ids_done;
0869     bool ack_rssi_done;
0870 };
0871 
0872 static int
0873 ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len,
0874                       const void *ptr, void *data)
0875 {
0876     struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data;
0877 
0878     switch (tag) {
0879     case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT:
0880         bundle_tx_compl->num_reports = ptr;
0881         break;
0882     case WMI_TLV_TAG_ARRAY_UINT32:
0883         if (!bundle_tx_compl->desc_ids_done) {
0884             bundle_tx_compl->desc_ids_done = true;
0885             bundle_tx_compl->desc_ids = ptr;
0886         } else if (!bundle_tx_compl->status_done) {
0887             bundle_tx_compl->status_done = true;
0888             bundle_tx_compl->status = ptr;
0889         } else if (!bundle_tx_compl->ppdu_ids_done) {
0890             bundle_tx_compl->ppdu_ids_done = true;
0891             bundle_tx_compl->ppdu_ids = ptr;
0892         } else if (!bundle_tx_compl->ack_rssi_done) {
0893             bundle_tx_compl->ack_rssi_done = true;
0894             bundle_tx_compl->ack_rssi = ptr;
0895         }
0896         break;
0897     default:
0898         break;
0899     }
0900     return 0;
0901 }
0902 
0903 static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
0904                 struct ath10k *ar, struct sk_buff *skb,
0905                 struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
0906 {
0907     struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { };
0908     int ret;
0909 
0910     ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
0911                   ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse,
0912                   &bundle_tx_compl);
0913     if (ret) {
0914         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0915         return ret;
0916     }
0917 
0918     if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids ||
0919         !bundle_tx_compl.status)
0920         return -EPROTO;
0921 
0922     arg->num_reports = *bundle_tx_compl.num_reports;
0923     arg->desc_ids = bundle_tx_compl.desc_ids;
0924     arg->status = bundle_tx_compl.status;
0925     arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
0926 
0927     if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
0928         arg->ack_rssi = bundle_tx_compl.ack_rssi;
0929 
0930     return 0;
0931 }
0932 
0933 static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
0934                          struct sk_buff *skb,
0935                          struct wmi_mgmt_rx_ev_arg *arg)
0936 {
0937     const void **tb;
0938     const struct wmi_tlv_mgmt_rx_ev *ev;
0939     const u8 *frame;
0940     u32 msdu_len;
0941     int ret, i;
0942 
0943     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0944     if (IS_ERR(tb)) {
0945         ret = PTR_ERR(tb);
0946         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0947         return ret;
0948     }
0949 
0950     ev = tb[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR];
0951     frame = tb[WMI_TLV_TAG_ARRAY_BYTE];
0952 
0953     if (!ev || !frame) {
0954         kfree(tb);
0955         return -EPROTO;
0956     }
0957 
0958     arg->channel = ev->channel;
0959     arg->buf_len = ev->buf_len;
0960     arg->status = ev->status;
0961     arg->snr = ev->snr;
0962     arg->phy_mode = ev->phy_mode;
0963     arg->rate = ev->rate;
0964 
0965     for (i = 0; i < ARRAY_SIZE(ev->rssi); i++)
0966         arg->rssi[i] = ev->rssi[i];
0967 
0968     msdu_len = __le32_to_cpu(arg->buf_len);
0969 
0970     if (skb->len < (frame - skb->data) + msdu_len) {
0971         kfree(tb);
0972         return -EPROTO;
0973     }
0974 
0975     /* shift the sk_buff to point to `frame` */
0976     skb_trim(skb, 0);
0977     skb_put(skb, frame - skb->data);
0978     skb_pull(skb, frame - skb->data);
0979     skb_put(skb, msdu_len);
0980 
0981     kfree(tb);
0982     return 0;
0983 }
0984 
0985 static int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar,
0986                          struct sk_buff *skb,
0987                          struct wmi_ch_info_ev_arg *arg)
0988 {
0989     const void **tb;
0990     const struct wmi_tlv_chan_info_event *ev;
0991     int ret;
0992 
0993     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
0994     if (IS_ERR(tb)) {
0995         ret = PTR_ERR(tb);
0996         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
0997         return ret;
0998     }
0999 
1000     ev = tb[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT];
1001     if (!ev) {
1002         kfree(tb);
1003         return -EPROTO;
1004     }
1005 
1006     arg->err_code = ev->err_code;
1007     arg->freq = ev->freq;
1008     arg->cmd_flags = ev->cmd_flags;
1009     arg->noise_floor = ev->noise_floor;
1010     arg->rx_clear_count = ev->rx_clear_count;
1011     arg->cycle_count = ev->cycle_count;
1012     if (test_bit(ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL,
1013              ar->running_fw->fw_file.fw_features))
1014         arg->mac_clk_mhz = ev->mac_clk_mhz;
1015 
1016     kfree(tb);
1017     return 0;
1018 }
1019 
1020 static int
1021 ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
1022                      struct wmi_vdev_start_ev_arg *arg)
1023 {
1024     const void **tb;
1025     const struct wmi_vdev_start_response_event *ev;
1026     int ret;
1027 
1028     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1029     if (IS_ERR(tb)) {
1030         ret = PTR_ERR(tb);
1031         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1032         return ret;
1033     }
1034 
1035     ev = tb[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT];
1036     if (!ev) {
1037         kfree(tb);
1038         return -EPROTO;
1039     }
1040 
1041     skb_pull(skb, sizeof(*ev));
1042     arg->vdev_id = ev->vdev_id;
1043     arg->req_id = ev->req_id;
1044     arg->resp_type = ev->resp_type;
1045     arg->status = ev->status;
1046 
1047     kfree(tb);
1048     return 0;
1049 }
1050 
1051 static int ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k *ar,
1052                            struct sk_buff *skb,
1053                            struct wmi_peer_kick_ev_arg *arg)
1054 {
1055     const void **tb;
1056     const struct wmi_peer_sta_kickout_event *ev;
1057     int ret;
1058 
1059     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1060     if (IS_ERR(tb)) {
1061         ret = PTR_ERR(tb);
1062         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1063         return ret;
1064     }
1065 
1066     ev = tb[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT];
1067     if (!ev) {
1068         kfree(tb);
1069         return -EPROTO;
1070     }
1071 
1072     arg->mac_addr = ev->peer_macaddr.addr;
1073 
1074     kfree(tb);
1075     return 0;
1076 }
1077 
1078 struct wmi_tlv_swba_parse {
1079     const struct wmi_host_swba_event *ev;
1080     bool tim_done;
1081     bool noa_done;
1082     size_t n_tim;
1083     size_t n_noa;
1084     struct wmi_swba_ev_arg *arg;
1085 };
1086 
1087 static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
1088                      const void *ptr, void *data)
1089 {
1090     struct wmi_tlv_swba_parse *swba = data;
1091     struct wmi_tim_info_arg *tim_info_arg;
1092     const struct wmi_tim_info *tim_info_ev = ptr;
1093 
1094     if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO)
1095         return -EPROTO;
1096 
1097     if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info))
1098         return -ENOBUFS;
1099 
1100     if (__le32_to_cpu(tim_info_ev->tim_len) >
1101          sizeof(tim_info_ev->tim_bitmap)) {
1102         ath10k_warn(ar, "refusing to parse invalid swba structure\n");
1103         return -EPROTO;
1104     }
1105 
1106     tim_info_arg = &swba->arg->tim_info[swba->n_tim];
1107     tim_info_arg->tim_len = tim_info_ev->tim_len;
1108     tim_info_arg->tim_mcast = tim_info_ev->tim_mcast;
1109     tim_info_arg->tim_bitmap = tim_info_ev->tim_bitmap;
1110     tim_info_arg->tim_changed = tim_info_ev->tim_changed;
1111     tim_info_arg->tim_num_ps_pending = tim_info_ev->tim_num_ps_pending;
1112 
1113     swba->n_tim++;
1114 
1115     return 0;
1116 }
1117 
1118 static int ath10k_wmi_tlv_swba_noa_parse(struct ath10k *ar, u16 tag, u16 len,
1119                      const void *ptr, void *data)
1120 {
1121     struct wmi_tlv_swba_parse *swba = data;
1122 
1123     if (tag != WMI_TLV_TAG_STRUCT_P2P_NOA_INFO)
1124         return -EPROTO;
1125 
1126     if (swba->n_noa >= ARRAY_SIZE(swba->arg->noa_info))
1127         return -ENOBUFS;
1128 
1129     swba->arg->noa_info[swba->n_noa++] = ptr;
1130     return 0;
1131 }
1132 
1133 static int ath10k_wmi_tlv_swba_parse(struct ath10k *ar, u16 tag, u16 len,
1134                      const void *ptr, void *data)
1135 {
1136     struct wmi_tlv_swba_parse *swba = data;
1137     int ret;
1138 
1139     switch (tag) {
1140     case WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT:
1141         swba->ev = ptr;
1142         break;
1143     case WMI_TLV_TAG_ARRAY_STRUCT:
1144         if (!swba->tim_done) {
1145             swba->tim_done = true;
1146             ret = ath10k_wmi_tlv_iter(ar, ptr, len,
1147                           ath10k_wmi_tlv_swba_tim_parse,
1148                           swba);
1149             if (ret)
1150                 return ret;
1151         } else if (!swba->noa_done) {
1152             swba->noa_done = true;
1153             ret = ath10k_wmi_tlv_iter(ar, ptr, len,
1154                           ath10k_wmi_tlv_swba_noa_parse,
1155                           swba);
1156             if (ret)
1157                 return ret;
1158         }
1159         break;
1160     default:
1161         break;
1162     }
1163     return 0;
1164 }
1165 
1166 static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
1167                       struct sk_buff *skb,
1168                       struct wmi_swba_ev_arg *arg)
1169 {
1170     struct wmi_tlv_swba_parse swba = { .arg = arg };
1171     u32 map;
1172     size_t n_vdevs;
1173     int ret;
1174 
1175     ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1176                   ath10k_wmi_tlv_swba_parse, &swba);
1177     if (ret) {
1178         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1179         return ret;
1180     }
1181 
1182     if (!swba.ev)
1183         return -EPROTO;
1184 
1185     arg->vdev_map = swba.ev->vdev_map;
1186 
1187     for (map = __le32_to_cpu(arg->vdev_map), n_vdevs = 0; map; map >>= 1)
1188         if (map & BIT(0))
1189             n_vdevs++;
1190 
1191     if (n_vdevs != swba.n_tim ||
1192         n_vdevs != swba.n_noa)
1193         return -EPROTO;
1194 
1195     return 0;
1196 }
1197 
1198 static int ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k *ar,
1199                         struct sk_buff *skb,
1200                         struct wmi_phyerr_hdr_arg *arg)
1201 {
1202     const void **tb;
1203     const struct wmi_tlv_phyerr_ev *ev;
1204     const void *phyerrs;
1205     int ret;
1206 
1207     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1208     if (IS_ERR(tb)) {
1209         ret = PTR_ERR(tb);
1210         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1211         return ret;
1212     }
1213 
1214     ev = tb[WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR];
1215     phyerrs = tb[WMI_TLV_TAG_ARRAY_BYTE];
1216 
1217     if (!ev || !phyerrs) {
1218         kfree(tb);
1219         return -EPROTO;
1220     }
1221 
1222     arg->num_phyerrs  = __le32_to_cpu(ev->num_phyerrs);
1223     arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
1224     arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
1225     arg->buf_len = __le32_to_cpu(ev->buf_len);
1226     arg->phyerrs = phyerrs;
1227 
1228     kfree(tb);
1229     return 0;
1230 }
1231 
1232 #define WMI_TLV_ABI_VER_NS0 0x5F414351
1233 #define WMI_TLV_ABI_VER_NS1 0x00004C4D
1234 #define WMI_TLV_ABI_VER_NS2 0x00000000
1235 #define WMI_TLV_ABI_VER_NS3 0x00000000
1236 
1237 #define WMI_TLV_ABI_VER0_MAJOR 1
1238 #define WMI_TLV_ABI_VER0_MINOR 0
1239 #define WMI_TLV_ABI_VER0 ((((WMI_TLV_ABI_VER0_MAJOR) << 24) & 0xFF000000) | \
1240               (((WMI_TLV_ABI_VER0_MINOR) <<  0) & 0x00FFFFFF))
1241 #define WMI_TLV_ABI_VER1 53
1242 
1243 static int
1244 ath10k_wmi_tlv_parse_mem_reqs(struct ath10k *ar, u16 tag, u16 len,
1245                   const void *ptr, void *data)
1246 {
1247     struct wmi_svc_rdy_ev_arg *arg = data;
1248     int i;
1249 
1250     if (tag != WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ)
1251         return -EPROTO;
1252 
1253     for (i = 0; i < ARRAY_SIZE(arg->mem_reqs); i++) {
1254         if (!arg->mem_reqs[i]) {
1255             arg->mem_reqs[i] = ptr;
1256             return 0;
1257         }
1258     }
1259 
1260     return -ENOMEM;
1261 }
1262 
1263 struct wmi_tlv_svc_rdy_parse {
1264     const struct hal_reg_capabilities *reg;
1265     const struct wmi_tlv_svc_rdy_ev *ev;
1266     const __le32 *svc_bmap;
1267     const struct wlan_host_mem_req *mem_reqs;
1268     bool svc_bmap_done;
1269     bool dbs_hw_mode_done;
1270 };
1271 
1272 static int ath10k_wmi_tlv_svc_rdy_parse(struct ath10k *ar, u16 tag, u16 len,
1273                     const void *ptr, void *data)
1274 {
1275     struct wmi_tlv_svc_rdy_parse *svc_rdy = data;
1276 
1277     switch (tag) {
1278     case WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT:
1279         svc_rdy->ev = ptr;
1280         break;
1281     case WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES:
1282         svc_rdy->reg = ptr;
1283         break;
1284     case WMI_TLV_TAG_ARRAY_STRUCT:
1285         svc_rdy->mem_reqs = ptr;
1286         break;
1287     case WMI_TLV_TAG_ARRAY_UINT32:
1288         if (!svc_rdy->svc_bmap_done) {
1289             svc_rdy->svc_bmap_done = true;
1290             svc_rdy->svc_bmap = ptr;
1291         } else if (!svc_rdy->dbs_hw_mode_done) {
1292             svc_rdy->dbs_hw_mode_done = true;
1293         }
1294         break;
1295     default:
1296         break;
1297     }
1298     return 0;
1299 }
1300 
1301 static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
1302                          struct sk_buff *skb,
1303                          struct wmi_svc_rdy_ev_arg *arg)
1304 {
1305     const struct hal_reg_capabilities *reg;
1306     const struct wmi_tlv_svc_rdy_ev *ev;
1307     const __le32 *svc_bmap;
1308     const struct wlan_host_mem_req *mem_reqs;
1309     struct wmi_tlv_svc_rdy_parse svc_rdy = { };
1310     int ret;
1311 
1312     ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1313                   ath10k_wmi_tlv_svc_rdy_parse, &svc_rdy);
1314     if (ret) {
1315         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1316         return ret;
1317     }
1318 
1319     ev = svc_rdy.ev;
1320     reg = svc_rdy.reg;
1321     svc_bmap = svc_rdy.svc_bmap;
1322     mem_reqs = svc_rdy.mem_reqs;
1323 
1324     if (!ev || !reg || !svc_bmap || !mem_reqs)
1325         return -EPROTO;
1326 
1327     /* This is an internal ABI compatibility check for WMI TLV so check it
1328      * here instead of the generic WMI code.
1329      */
1330     ath10k_dbg(ar, ATH10K_DBG_WMI,
1331            "wmi tlv abi 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x\n",
1332            __le32_to_cpu(ev->abi.abi_ver0), WMI_TLV_ABI_VER0,
1333            __le32_to_cpu(ev->abi.abi_ver_ns0), WMI_TLV_ABI_VER_NS0,
1334            __le32_to_cpu(ev->abi.abi_ver_ns1), WMI_TLV_ABI_VER_NS1,
1335            __le32_to_cpu(ev->abi.abi_ver_ns2), WMI_TLV_ABI_VER_NS2,
1336            __le32_to_cpu(ev->abi.abi_ver_ns3), WMI_TLV_ABI_VER_NS3);
1337 
1338     if (__le32_to_cpu(ev->abi.abi_ver0) != WMI_TLV_ABI_VER0 ||
1339         __le32_to_cpu(ev->abi.abi_ver_ns0) != WMI_TLV_ABI_VER_NS0 ||
1340         __le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 ||
1341         __le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 ||
1342         __le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) {
1343         return -ENOTSUPP;
1344     }
1345 
1346     arg->min_tx_power = ev->hw_min_tx_power;
1347     arg->max_tx_power = ev->hw_max_tx_power;
1348     arg->ht_cap = ev->ht_cap_info;
1349     arg->vht_cap = ev->vht_cap_info;
1350     arg->vht_supp_mcs = ev->vht_supp_mcs;
1351     arg->sw_ver0 = ev->abi.abi_ver0;
1352     arg->sw_ver1 = ev->abi.abi_ver1;
1353     arg->fw_build = ev->fw_build_vers;
1354     arg->phy_capab = ev->phy_capability;
1355     arg->num_rf_chains = ev->num_rf_chains;
1356     arg->eeprom_rd = reg->eeprom_rd;
1357     arg->low_2ghz_chan = reg->low_2ghz_chan;
1358     arg->high_2ghz_chan = reg->high_2ghz_chan;
1359     arg->low_5ghz_chan = reg->low_5ghz_chan;
1360     arg->high_5ghz_chan = reg->high_5ghz_chan;
1361     arg->num_mem_reqs = ev->num_mem_reqs;
1362     arg->service_map = svc_bmap;
1363     arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
1364     arg->sys_cap_info = ev->sys_cap_info;
1365 
1366     ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
1367                   ath10k_wmi_tlv_parse_mem_reqs, arg);
1368     if (ret) {
1369         ath10k_warn(ar, "failed to parse mem_reqs tlv: %d\n", ret);
1370         return ret;
1371     }
1372 
1373     return 0;
1374 }
1375 
1376 static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
1377                      struct sk_buff *skb,
1378                      struct wmi_rdy_ev_arg *arg)
1379 {
1380     const void **tb;
1381     const struct wmi_tlv_rdy_ev *ev;
1382     int ret;
1383 
1384     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1385     if (IS_ERR(tb)) {
1386         ret = PTR_ERR(tb);
1387         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1388         return ret;
1389     }
1390 
1391     ev = tb[WMI_TLV_TAG_STRUCT_READY_EVENT];
1392     if (!ev) {
1393         kfree(tb);
1394         return -EPROTO;
1395     }
1396 
1397     arg->sw_version = ev->abi.abi_ver0;
1398     arg->abi_version = ev->abi.abi_ver1;
1399     arg->status = ev->status;
1400     arg->mac_addr = ev->mac_addr.addr;
1401 
1402     kfree(tb);
1403     return 0;
1404 }
1405 
1406 static int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len,
1407                       const void *ptr, void *data)
1408 {
1409     struct wmi_svc_avail_ev_arg *arg = data;
1410 
1411     switch (tag) {
1412     case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT:
1413         arg->service_map_ext_valid = true;
1414         arg->service_map_ext_len = *(__le32 *)ptr;
1415         arg->service_map_ext = ptr + sizeof(__le32);
1416         return 0;
1417     default:
1418         break;
1419     }
1420 
1421     return 0;
1422 }
1423 
1424 static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar,
1425                         struct sk_buff *skb,
1426                         struct wmi_svc_avail_ev_arg *arg)
1427 {
1428     int ret;
1429 
1430     ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1431                   ath10k_wmi_tlv_svc_avail_parse, arg);
1432 
1433     if (ret) {
1434         ath10k_warn(ar, "failed to parse svc_avail tlv: %d\n", ret);
1435         return ret;
1436     }
1437 
1438     return 0;
1439 }
1440 
1441 static void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
1442                        struct ath10k_fw_stats_vdev *dst)
1443 {
1444     int i;
1445 
1446     dst->vdev_id = __le32_to_cpu(src->vdev_id);
1447     dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
1448     dst->data_snr = __le32_to_cpu(src->data_snr);
1449     dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
1450     dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
1451     dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
1452     dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
1453     dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
1454     dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
1455 
1456     for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
1457         dst->num_tx_frames[i] =
1458             __le32_to_cpu(src->num_tx_frames[i]);
1459 
1460     for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
1461         dst->num_tx_frames_retries[i] =
1462             __le32_to_cpu(src->num_tx_frames_retries[i]);
1463 
1464     for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
1465         dst->num_tx_frames_failures[i] =
1466             __le32_to_cpu(src->num_tx_frames_failures[i]);
1467 
1468     for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
1469         dst->tx_rate_history[i] =
1470             __le32_to_cpu(src->tx_rate_history[i]);
1471 
1472     for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
1473         dst->beacon_rssi_history[i] =
1474             __le32_to_cpu(src->beacon_rssi_history[i]);
1475 }
1476 
1477 static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
1478                        struct sk_buff *skb,
1479                        struct ath10k_fw_stats *stats)
1480 {
1481     const void **tb;
1482     const struct wmi_tlv_stats_ev *ev;
1483     u32 num_peer_stats_extd;
1484     const void *data;
1485     u32 num_pdev_stats;
1486     u32 num_vdev_stats;
1487     u32 num_peer_stats;
1488     u32 num_bcnflt_stats;
1489     u32 num_chan_stats;
1490     size_t data_len;
1491     u32 stats_id;
1492     int ret;
1493     int i;
1494 
1495     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1496     if (IS_ERR(tb)) {
1497         ret = PTR_ERR(tb);
1498         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1499         return ret;
1500     }
1501 
1502     ev = tb[WMI_TLV_TAG_STRUCT_STATS_EVENT];
1503     data = tb[WMI_TLV_TAG_ARRAY_BYTE];
1504 
1505     if (!ev || !data) {
1506         kfree(tb);
1507         return -EPROTO;
1508     }
1509 
1510     data_len = ath10k_wmi_tlv_len(data);
1511     num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
1512     num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
1513     num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
1514     num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
1515     num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
1516     stats_id = __le32_to_cpu(ev->stats_id);
1517     num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd);
1518 
1519     ath10k_dbg(ar, ATH10K_DBG_WMI,
1520            "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n",
1521            num_pdev_stats, num_vdev_stats, num_peer_stats,
1522            num_bcnflt_stats, num_chan_stats, num_peer_stats_extd);
1523 
1524     for (i = 0; i < num_pdev_stats; i++) {
1525         const struct wmi_pdev_stats *src;
1526         struct ath10k_fw_stats_pdev *dst;
1527 
1528         src = data;
1529         if (data_len < sizeof(*src)) {
1530             kfree(tb);
1531             return -EPROTO;
1532         }
1533 
1534         data += sizeof(*src);
1535         data_len -= sizeof(*src);
1536 
1537         dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1538         if (!dst)
1539             continue;
1540 
1541         ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
1542         ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
1543         ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
1544         list_add_tail(&dst->list, &stats->pdevs);
1545     }
1546 
1547     for (i = 0; i < num_vdev_stats; i++) {
1548         const struct wmi_tlv_vdev_stats *src;
1549         struct ath10k_fw_stats_vdev *dst;
1550 
1551         src = data;
1552         if (data_len < sizeof(*src)) {
1553             kfree(tb);
1554             return -EPROTO;
1555         }
1556 
1557         data += sizeof(*src);
1558         data_len -= sizeof(*src);
1559 
1560         dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1561         if (!dst)
1562             continue;
1563 
1564         ath10k_wmi_tlv_pull_vdev_stats(src, dst);
1565         list_add_tail(&dst->list, &stats->vdevs);
1566     }
1567 
1568     for (i = 0; i < num_peer_stats; i++) {
1569         const struct wmi_10x_peer_stats *src;
1570         struct ath10k_fw_stats_peer *dst;
1571 
1572         src = data;
1573         if (data_len < sizeof(*src)) {
1574             kfree(tb);
1575             return -EPROTO;
1576         }
1577 
1578         data += sizeof(*src);
1579         data_len -= sizeof(*src);
1580 
1581         dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1582         if (!dst)
1583             continue;
1584 
1585         ath10k_wmi_pull_peer_stats(&src->old, dst);
1586         dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
1587 
1588         if (stats_id & WMI_TLV_STAT_PEER_EXTD) {
1589             const struct wmi_tlv_peer_stats_extd *extd;
1590             unsigned long rx_duration_high;
1591 
1592             extd = data + sizeof(*src) * (num_peer_stats - i - 1)
1593                    + sizeof(*extd) * i;
1594 
1595             dst->rx_duration = __le32_to_cpu(extd->rx_duration);
1596             rx_duration_high = __le32_to_cpu
1597                         (extd->rx_duration_high);
1598 
1599             if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT,
1600                      &rx_duration_high)) {
1601                 rx_duration_high =
1602                     FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK,
1603                           rx_duration_high);
1604                 dst->rx_duration |= (u64)rx_duration_high <<
1605                             WMI_TLV_PEER_RX_DURATION_SHIFT;
1606             }
1607         }
1608 
1609         list_add_tail(&dst->list, &stats->peers);
1610     }
1611 
1612     kfree(tb);
1613     return 0;
1614 }
1615 
1616 static int ath10k_wmi_tlv_op_pull_roam_ev(struct ath10k *ar,
1617                       struct sk_buff *skb,
1618                       struct wmi_roam_ev_arg *arg)
1619 {
1620     const void **tb;
1621     const struct wmi_tlv_roam_ev *ev;
1622     int ret;
1623 
1624     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1625     if (IS_ERR(tb)) {
1626         ret = PTR_ERR(tb);
1627         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1628         return ret;
1629     }
1630 
1631     ev = tb[WMI_TLV_TAG_STRUCT_ROAM_EVENT];
1632     if (!ev) {
1633         kfree(tb);
1634         return -EPROTO;
1635     }
1636 
1637     arg->vdev_id = ev->vdev_id;
1638     arg->reason = ev->reason;
1639     arg->rssi = ev->rssi;
1640 
1641     kfree(tb);
1642     return 0;
1643 }
1644 
1645 static int
1646 ath10k_wmi_tlv_op_pull_wow_ev(struct ath10k *ar, struct sk_buff *skb,
1647                   struct wmi_wow_ev_arg *arg)
1648 {
1649     const void **tb;
1650     const struct wmi_tlv_wow_event_info *ev;
1651     int ret;
1652 
1653     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1654     if (IS_ERR(tb)) {
1655         ret = PTR_ERR(tb);
1656         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1657         return ret;
1658     }
1659 
1660     ev = tb[WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO];
1661     if (!ev) {
1662         kfree(tb);
1663         return -EPROTO;
1664     }
1665 
1666     arg->vdev_id = __le32_to_cpu(ev->vdev_id);
1667     arg->flag = __le32_to_cpu(ev->flag);
1668     arg->wake_reason = __le32_to_cpu(ev->wake_reason);
1669     arg->data_len = __le32_to_cpu(ev->data_len);
1670 
1671     kfree(tb);
1672     return 0;
1673 }
1674 
1675 static int ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k *ar,
1676                       struct sk_buff *skb,
1677                       struct wmi_echo_ev_arg *arg)
1678 {
1679     const void **tb;
1680     const struct wmi_echo_event *ev;
1681     int ret;
1682 
1683     tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1684     if (IS_ERR(tb)) {
1685         ret = PTR_ERR(tb);
1686         ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1687         return ret;
1688     }
1689 
1690     ev = tb[WMI_TLV_TAG_STRUCT_ECHO_EVENT];
1691     if (!ev) {
1692         kfree(tb);
1693         return -EPROTO;
1694     }
1695 
1696     arg->value = ev->value;
1697 
1698     kfree(tb);
1699     return 0;
1700 }
1701 
1702 static struct sk_buff *
1703 ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
1704 {
1705     struct wmi_tlv_pdev_suspend *cmd;
1706     struct wmi_tlv *tlv;
1707     struct sk_buff *skb;
1708 
1709     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1710     if (!skb)
1711         return ERR_PTR(-ENOMEM);
1712 
1713     tlv = (void *)skb->data;
1714     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD);
1715     tlv->len = __cpu_to_le16(sizeof(*cmd));
1716     cmd = (void *)tlv->value;
1717     cmd->opt = __cpu_to_le32(opt);
1718 
1719     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev suspend\n");
1720     return skb;
1721 }
1722 
1723 static struct sk_buff *
1724 ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k *ar)
1725 {
1726     struct wmi_tlv_resume_cmd *cmd;
1727     struct wmi_tlv *tlv;
1728     struct sk_buff *skb;
1729 
1730     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1731     if (!skb)
1732         return ERR_PTR(-ENOMEM);
1733 
1734     tlv = (void *)skb->data;
1735     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD);
1736     tlv->len = __cpu_to_le16(sizeof(*cmd));
1737     cmd = (void *)tlv->value;
1738     cmd->reserved = __cpu_to_le32(0);
1739 
1740     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev resume\n");
1741     return skb;
1742 }
1743 
1744 static struct sk_buff *
1745 ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
1746                   u16 rd, u16 rd2g, u16 rd5g,
1747                   u16 ctl2g, u16 ctl5g,
1748                   enum wmi_dfs_region dfs_reg)
1749 {
1750     struct wmi_tlv_pdev_set_rd_cmd *cmd;
1751     struct wmi_tlv *tlv;
1752     struct sk_buff *skb;
1753 
1754     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1755     if (!skb)
1756         return ERR_PTR(-ENOMEM);
1757 
1758     tlv = (void *)skb->data;
1759     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD);
1760     tlv->len = __cpu_to_le16(sizeof(*cmd));
1761     cmd = (void *)tlv->value;
1762     cmd->regd = __cpu_to_le32(rd);
1763     cmd->regd_2ghz = __cpu_to_le32(rd2g);
1764     cmd->regd_5ghz = __cpu_to_le32(rd5g);
1765     cmd->conform_limit_2ghz = __cpu_to_le32(ctl2g);
1766     cmd->conform_limit_5ghz = __cpu_to_le32(ctl5g);
1767 
1768     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
1769     return skb;
1770 }
1771 
1772 static enum wmi_txbf_conf ath10k_wmi_tlv_txbf_conf_scheme(struct ath10k *ar)
1773 {
1774     return WMI_TXBF_CONF_AFTER_ASSOC;
1775 }
1776 
1777 static struct sk_buff *
1778 ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
1779                      u32 param_value)
1780 {
1781     struct wmi_tlv_pdev_set_param_cmd *cmd;
1782     struct wmi_tlv *tlv;
1783     struct sk_buff *skb;
1784 
1785     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1786     if (!skb)
1787         return ERR_PTR(-ENOMEM);
1788 
1789     tlv = (void *)skb->data;
1790     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD);
1791     tlv->len = __cpu_to_le16(sizeof(*cmd));
1792     cmd = (void *)tlv->value;
1793     cmd->param_id = __cpu_to_le32(param_id);
1794     cmd->param_value = __cpu_to_le32(param_value);
1795 
1796     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n",
1797            param_id, param_value);
1798     return skb;
1799 }
1800 
1801 static void
1802 ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
1803 {
1804     struct host_memory_chunk_tlv *chunk;
1805     struct wmi_tlv *tlv;
1806     dma_addr_t paddr;
1807     int i;
1808     __le16 tlv_len, tlv_tag;
1809 
1810     tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK);
1811     tlv_len = __cpu_to_le16(sizeof(*chunk));
1812     for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
1813         tlv = host_mem_chunks;
1814         tlv->tag = tlv_tag;
1815         tlv->len = tlv_len;
1816         chunk = (void *)tlv->value;
1817 
1818         chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
1819         chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
1820         chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
1821 
1822         if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
1823                  ar->wmi.svc_map)) {
1824             paddr = ar->wmi.mem_chunks[i].paddr;
1825             chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr));
1826         }
1827 
1828         ath10k_dbg(ar, ATH10K_DBG_WMI,
1829                "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
1830                i,
1831                ar->wmi.mem_chunks[i].len,
1832                (unsigned long long)ar->wmi.mem_chunks[i].paddr,
1833                ar->wmi.mem_chunks[i].req_id);
1834 
1835         host_mem_chunks += sizeof(*tlv);
1836         host_mem_chunks += sizeof(*chunk);
1837     }
1838 }
1839 
1840 static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
1841 {
1842     struct sk_buff *skb;
1843     struct wmi_tlv *tlv;
1844     struct wmi_tlv_init_cmd *cmd;
1845     struct wmi_tlv_resource_config *cfg;
1846     void *chunks;
1847     size_t len, chunks_len;
1848     void *ptr;
1849 
1850     chunks_len = ar->wmi.num_mem_chunks *
1851              (sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv));
1852     len = (sizeof(*tlv) + sizeof(*cmd)) +
1853           (sizeof(*tlv) + sizeof(*cfg)) +
1854           (sizeof(*tlv) + chunks_len);
1855 
1856     skb = ath10k_wmi_alloc_skb(ar, len);
1857     if (!skb)
1858         return ERR_PTR(-ENOMEM);
1859 
1860     ptr = skb->data;
1861 
1862     tlv = ptr;
1863     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_INIT_CMD);
1864     tlv->len = __cpu_to_le16(sizeof(*cmd));
1865     cmd = (void *)tlv->value;
1866     ptr += sizeof(*tlv);
1867     ptr += sizeof(*cmd);
1868 
1869     tlv = ptr;
1870     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG);
1871     tlv->len = __cpu_to_le16(sizeof(*cfg));
1872     cfg = (void *)tlv->value;
1873     ptr += sizeof(*tlv);
1874     ptr += sizeof(*cfg);
1875 
1876     tlv = ptr;
1877     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
1878     tlv->len = __cpu_to_le16(chunks_len);
1879     chunks = (void *)tlv->value;
1880 
1881     ptr += sizeof(*tlv);
1882     ptr += chunks_len;
1883 
1884     cmd->abi.abi_ver0 = __cpu_to_le32(WMI_TLV_ABI_VER0);
1885     cmd->abi.abi_ver1 = __cpu_to_le32(WMI_TLV_ABI_VER1);
1886     cmd->abi.abi_ver_ns0 = __cpu_to_le32(WMI_TLV_ABI_VER_NS0);
1887     cmd->abi.abi_ver_ns1 = __cpu_to_le32(WMI_TLV_ABI_VER_NS1);
1888     cmd->abi.abi_ver_ns2 = __cpu_to_le32(WMI_TLV_ABI_VER_NS2);
1889     cmd->abi.abi_ver_ns3 = __cpu_to_le32(WMI_TLV_ABI_VER_NS3);
1890     cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
1891 
1892     cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1893 
1894     if (ar->hw_params.num_peers)
1895         cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers);
1896     else
1897         cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
1898     cfg->ast_skid_limit = __cpu_to_le32(ar->hw_params.ast_skid_limit);
1899     cfg->num_wds_entries = __cpu_to_le32(ar->hw_params.num_wds_entries);
1900 
1901     if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
1902         cfg->num_offload_peers = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1903         cfg->num_offload_reorder_bufs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1904     } else {
1905         cfg->num_offload_peers = __cpu_to_le32(0);
1906         cfg->num_offload_reorder_bufs = __cpu_to_le32(0);
1907     }
1908 
1909     cfg->num_peer_keys = __cpu_to_le32(2);
1910     if (ar->hw_params.num_peers)
1911         cfg->num_tids = __cpu_to_le32(ar->hw_params.num_peers * 2);
1912     else
1913         cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
1914     cfg->tx_chain_mask = __cpu_to_le32(0x7);
1915     cfg->rx_chain_mask = __cpu_to_le32(0x7);
1916     cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
1917     cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64);
1918     cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64);
1919     cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28);
1920     cfg->rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
1921     cfg->scan_max_pending_reqs = __cpu_to_le32(4);
1922     cfg->bmiss_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1923     cfg->roam_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1924     cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8);
1925     cfg->num_mcast_groups = __cpu_to_le32(0);
1926     cfg->num_mcast_table_elems = __cpu_to_le32(0);
1927     cfg->mcast2ucast_mode = __cpu_to_le32(0);
1928     cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
1929     cfg->dma_burst_size = __cpu_to_le32(0);
1930     cfg->mac_aggr_delim = __cpu_to_le32(0);
1931     cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
1932     cfg->vow_config = __cpu_to_le32(0);
1933     cfg->gtk_offload_max_vdev = __cpu_to_le32(2);
1934     cfg->num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx);
1935     cfg->max_frag_entries = __cpu_to_le32(2);
1936     cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS);
1937     cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
1938     cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2);
1939     cfg->num_multicast_filter_entries = __cpu_to_le32(5);
1940     cfg->num_wow_filters = __cpu_to_le32(ar->wow.max_num_patterns);
1941     cfg->num_keep_alive_pattern = __cpu_to_le32(6);
1942     cfg->keep_alive_pattern_size = __cpu_to_le32(0);
1943     cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1);
1944     cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1);
1945     cfg->wmi_send_separate = __cpu_to_le32(0);
1946     cfg->num_ocb_vdevs = __cpu_to_le32(0);
1947     cfg->num_ocb_channels = __cpu_to_le32(0);
1948     cfg->num_ocb_schedules = __cpu_to_le32(0);
1949     cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL);
1950 
1951     if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
1952         cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
1953 
1954     ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks);
1955 
1956     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
1957     return skb;
1958 }
1959 
1960 static struct sk_buff *
1961 ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
1962                  const struct wmi_start_scan_arg *arg)
1963 {
1964     struct wmi_tlv_start_scan_cmd *cmd;
1965     struct wmi_tlv *tlv;
1966     struct sk_buff *skb;
1967     size_t len, chan_len, ssid_len, bssid_len, ie_len;
1968     __le32 *chans;
1969     struct wmi_ssid *ssids;
1970     struct wmi_mac_addr *addrs;
1971     void *ptr;
1972     int i, ret;
1973 
1974     ret = ath10k_wmi_start_scan_verify(arg);
1975     if (ret)
1976         return ERR_PTR(ret);
1977 
1978     chan_len = arg->n_channels * sizeof(__le32);
1979     ssid_len = arg->n_ssids * sizeof(struct wmi_ssid);
1980     bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr);
1981     ie_len = roundup(arg->ie_len, 4);
1982     len = (sizeof(*tlv) + sizeof(*cmd)) +
1983           sizeof(*tlv) + chan_len +
1984           sizeof(*tlv) + ssid_len +
1985           sizeof(*tlv) + bssid_len +
1986           sizeof(*tlv) + ie_len;
1987 
1988     skb = ath10k_wmi_alloc_skb(ar, len);
1989     if (!skb)
1990         return ERR_PTR(-ENOMEM);
1991 
1992     ptr = (void *)skb->data;
1993     tlv = ptr;
1994     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_START_SCAN_CMD);
1995     tlv->len = __cpu_to_le16(sizeof(*cmd));
1996     cmd = (void *)tlv->value;
1997 
1998     ath10k_wmi_put_start_scan_common(&cmd->common, arg);
1999     cmd->burst_duration_ms = __cpu_to_le32(arg->burst_duration_ms);
2000     cmd->num_channels = __cpu_to_le32(arg->n_channels);
2001     cmd->num_ssids = __cpu_to_le32(arg->n_ssids);
2002     cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
2003     cmd->ie_len = __cpu_to_le32(arg->ie_len);
2004     cmd->num_probes = __cpu_to_le32(3);
2005     ether_addr_copy(cmd->mac_addr.addr, arg->mac_addr.addr);
2006     ether_addr_copy(cmd->mac_mask.addr, arg->mac_mask.addr);
2007 
2008     /* FIXME: There are some scan flag inconsistencies across firmwares,
2009      * e.g. WMI-TLV inverts the logic behind the following flag.
2010      */
2011     cmd->common.scan_ctrl_flags ^= __cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);
2012 
2013     ptr += sizeof(*tlv);
2014     ptr += sizeof(*cmd);
2015 
2016     tlv = ptr;
2017     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
2018     tlv->len = __cpu_to_le16(chan_len);
2019     chans = (void *)tlv->value;
2020     for (i = 0; i < arg->n_channels; i++)
2021         chans[i] = __cpu_to_le32(arg->channels[i]);
2022 
2023     ptr += sizeof(*tlv);
2024     ptr += chan_len;
2025 
2026     tlv = ptr;
2027     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
2028     tlv->len = __cpu_to_le16(ssid_len);
2029     ssids = (void *)tlv->value;
2030     for (i = 0; i < arg->n_ssids; i++) {
2031         ssids[i].ssid_len = __cpu_to_le32(arg->ssids[i].len);
2032         memcpy(ssids[i].ssid, arg->ssids[i].ssid, arg->ssids[i].len);
2033     }
2034 
2035     ptr += sizeof(*tlv);
2036     ptr += ssid_len;
2037 
2038     tlv = ptr;
2039     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
2040     tlv->len = __cpu_to_le16(bssid_len);
2041     addrs = (void *)tlv->value;
2042     for (i = 0; i < arg->n_bssids; i++)
2043         ether_addr_copy(addrs[i].addr, arg->bssids[i].bssid);
2044 
2045     ptr += sizeof(*tlv);
2046     ptr += bssid_len;
2047 
2048     tlv = ptr;
2049     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2050     tlv->len = __cpu_to_le16(ie_len);
2051     memcpy(tlv->value, arg->ie, arg->ie_len);
2052 
2053     ptr += sizeof(*tlv);
2054     ptr += ie_len;
2055 
2056     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start scan\n");
2057     return skb;
2058 }
2059 
2060 static struct sk_buff *
2061 ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar,
2062                 const struct wmi_stop_scan_arg *arg)
2063 {
2064     struct wmi_stop_scan_cmd *cmd;
2065     struct wmi_tlv *tlv;
2066     struct sk_buff *skb;
2067     u32 scan_id;
2068     u32 req_id;
2069 
2070     if (arg->req_id > 0xFFF)
2071         return ERR_PTR(-EINVAL);
2072     if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
2073         return ERR_PTR(-EINVAL);
2074 
2075     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2076     if (!skb)
2077         return ERR_PTR(-ENOMEM);
2078 
2079     scan_id = arg->u.scan_id;
2080     scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
2081 
2082     req_id = arg->req_id;
2083     req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
2084 
2085     tlv = (void *)skb->data;
2086     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD);
2087     tlv->len = __cpu_to_le16(sizeof(*cmd));
2088     cmd = (void *)tlv->value;
2089     cmd->req_type = __cpu_to_le32(arg->req_type);
2090     cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id);
2091     cmd->scan_id = __cpu_to_le32(scan_id);
2092     cmd->scan_req_id = __cpu_to_le32(req_id);
2093 
2094     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop scan\n");
2095     return skb;
2096 }
2097 
2098 static int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar,
2099                           enum wmi_vdev_subtype subtype)
2100 {
2101     switch (subtype) {
2102     case WMI_VDEV_SUBTYPE_NONE:
2103         return WMI_TLV_VDEV_SUBTYPE_NONE;
2104     case WMI_VDEV_SUBTYPE_P2P_DEVICE:
2105         return WMI_TLV_VDEV_SUBTYPE_P2P_DEV;
2106     case WMI_VDEV_SUBTYPE_P2P_CLIENT:
2107         return WMI_TLV_VDEV_SUBTYPE_P2P_CLI;
2108     case WMI_VDEV_SUBTYPE_P2P_GO:
2109         return WMI_TLV_VDEV_SUBTYPE_P2P_GO;
2110     case WMI_VDEV_SUBTYPE_PROXY_STA:
2111         return WMI_TLV_VDEV_SUBTYPE_PROXY_STA;
2112     case WMI_VDEV_SUBTYPE_MESH_11S:
2113         return WMI_TLV_VDEV_SUBTYPE_MESH_11S;
2114     case WMI_VDEV_SUBTYPE_MESH_NON_11S:
2115         return -ENOTSUPP;
2116     }
2117     return -ENOTSUPP;
2118 }
2119 
2120 static struct sk_buff *
2121 ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar,
2122                   u32 vdev_id,
2123                   enum wmi_vdev_type vdev_type,
2124                   enum wmi_vdev_subtype vdev_subtype,
2125                   const u8 mac_addr[ETH_ALEN])
2126 {
2127     struct wmi_vdev_create_cmd *cmd;
2128     struct wmi_tlv *tlv;
2129     struct sk_buff *skb;
2130 
2131     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2132     if (!skb)
2133         return ERR_PTR(-ENOMEM);
2134 
2135     tlv = (void *)skb->data;
2136     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD);
2137     tlv->len = __cpu_to_le16(sizeof(*cmd));
2138     cmd = (void *)tlv->value;
2139     cmd->vdev_id = __cpu_to_le32(vdev_id);
2140     cmd->vdev_type = __cpu_to_le32(vdev_type);
2141     cmd->vdev_subtype = __cpu_to_le32(vdev_subtype);
2142     ether_addr_copy(cmd->vdev_macaddr.addr, mac_addr);
2143 
2144     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev create\n");
2145     return skb;
2146 }
2147 
2148 static struct sk_buff *
2149 ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
2150 {
2151     struct wmi_vdev_delete_cmd *cmd;
2152     struct wmi_tlv *tlv;
2153     struct sk_buff *skb;
2154 
2155     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2156     if (!skb)
2157         return ERR_PTR(-ENOMEM);
2158 
2159     tlv = (void *)skb->data;
2160     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD);
2161     tlv->len = __cpu_to_le16(sizeof(*cmd));
2162     cmd = (void *)tlv->value;
2163     cmd->vdev_id = __cpu_to_le32(vdev_id);
2164 
2165     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev delete\n");
2166     return skb;
2167 }
2168 
2169 static struct sk_buff *
2170 ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
2171                  const struct wmi_vdev_start_request_arg *arg,
2172                  bool restart)
2173 {
2174     struct wmi_tlv_vdev_start_cmd *cmd;
2175     struct wmi_channel *ch;
2176     struct wmi_tlv *tlv;
2177     struct sk_buff *skb;
2178     size_t len;
2179     void *ptr;
2180     u32 flags = 0;
2181 
2182     if (WARN_ON(arg->hidden_ssid && !arg->ssid))
2183         return ERR_PTR(-EINVAL);
2184     if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
2185         return ERR_PTR(-EINVAL);
2186 
2187     len = (sizeof(*tlv) + sizeof(*cmd)) +
2188           (sizeof(*tlv) + sizeof(*ch)) +
2189           (sizeof(*tlv) + 0);
2190     skb = ath10k_wmi_alloc_skb(ar, len);
2191     if (!skb)
2192         return ERR_PTR(-ENOMEM);
2193 
2194     if (arg->hidden_ssid)
2195         flags |= WMI_VDEV_START_HIDDEN_SSID;
2196     if (arg->pmf_enabled)
2197         flags |= WMI_VDEV_START_PMF_ENABLED;
2198 
2199     ptr = (void *)skb->data;
2200 
2201     tlv = ptr;
2202     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD);
2203     tlv->len = __cpu_to_le16(sizeof(*cmd));
2204     cmd = (void *)tlv->value;
2205     cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2206     cmd->bcn_intval = __cpu_to_le32(arg->bcn_intval);
2207     cmd->dtim_period = __cpu_to_le32(arg->dtim_period);
2208     cmd->flags = __cpu_to_le32(flags);
2209     cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate);
2210     cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power);
2211     cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack);
2212 
2213     if (arg->ssid) {
2214         cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len);
2215         memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
2216     }
2217 
2218     ptr += sizeof(*tlv);
2219     ptr += sizeof(*cmd);
2220 
2221     tlv = ptr;
2222     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
2223     tlv->len = __cpu_to_le16(sizeof(*ch));
2224     ch = (void *)tlv->value;
2225     ath10k_wmi_put_wmi_channel(ar, ch, &arg->channel);
2226 
2227     ptr += sizeof(*tlv);
2228     ptr += sizeof(*ch);
2229 
2230     tlv = ptr;
2231     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2232     tlv->len = 0;
2233 
2234     /* Note: This is a nested TLV containing:
2235      * [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
2236      */
2237 
2238     ptr += sizeof(*tlv);
2239     ptr += 0;
2240 
2241     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev start\n");
2242     return skb;
2243 }
2244 
2245 static struct sk_buff *
2246 ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
2247 {
2248     struct wmi_vdev_stop_cmd *cmd;
2249     struct wmi_tlv *tlv;
2250     struct sk_buff *skb;
2251 
2252     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2253     if (!skb)
2254         return ERR_PTR(-ENOMEM);
2255 
2256     tlv = (void *)skb->data;
2257     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD);
2258     tlv->len = __cpu_to_le16(sizeof(*cmd));
2259     cmd = (void *)tlv->value;
2260     cmd->vdev_id = __cpu_to_le32(vdev_id);
2261 
2262     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev stop\n");
2263     return skb;
2264 }
2265 
2266 static struct sk_buff *
2267 ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
2268                   const u8 *bssid)
2269 
2270 {
2271     struct wmi_vdev_up_cmd *cmd;
2272     struct wmi_tlv *tlv;
2273     struct sk_buff *skb;
2274 
2275     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2276     if (!skb)
2277         return ERR_PTR(-ENOMEM);
2278 
2279     tlv = (void *)skb->data;
2280     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_UP_CMD);
2281     tlv->len = __cpu_to_le16(sizeof(*cmd));
2282     cmd = (void *)tlv->value;
2283     cmd->vdev_id = __cpu_to_le32(vdev_id);
2284     cmd->vdev_assoc_id = __cpu_to_le32(aid);
2285     ether_addr_copy(cmd->vdev_bssid.addr, bssid);
2286 
2287     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev up\n");
2288     return skb;
2289 }
2290 
2291 static struct sk_buff *
2292 ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
2293 {
2294     struct wmi_vdev_down_cmd *cmd;
2295     struct wmi_tlv *tlv;
2296     struct sk_buff *skb;
2297 
2298     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2299     if (!skb)
2300         return ERR_PTR(-ENOMEM);
2301 
2302     tlv = (void *)skb->data;
2303     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD);
2304     tlv->len = __cpu_to_le16(sizeof(*cmd));
2305     cmd = (void *)tlv->value;
2306     cmd->vdev_id = __cpu_to_le32(vdev_id);
2307 
2308     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev down\n");
2309     return skb;
2310 }
2311 
2312 static struct sk_buff *
2313 ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
2314                      u32 param_id, u32 param_value)
2315 {
2316     struct wmi_vdev_set_param_cmd *cmd;
2317     struct wmi_tlv *tlv;
2318     struct sk_buff *skb;
2319 
2320     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2321     if (!skb)
2322         return ERR_PTR(-ENOMEM);
2323 
2324     tlv = (void *)skb->data;
2325     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD);
2326     tlv->len = __cpu_to_le16(sizeof(*cmd));
2327     cmd = (void *)tlv->value;
2328     cmd->vdev_id = __cpu_to_le32(vdev_id);
2329     cmd->param_id = __cpu_to_le32(param_id);
2330     cmd->param_value = __cpu_to_le32(param_value);
2331 
2332     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n",
2333            vdev_id, param_id, param_value);
2334     return skb;
2335 }
2336 
2337 static struct sk_buff *
2338 ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
2339                        const struct wmi_vdev_install_key_arg *arg)
2340 {
2341     struct wmi_vdev_install_key_cmd *cmd;
2342     struct wmi_tlv *tlv;
2343     struct sk_buff *skb;
2344     size_t len;
2345     void *ptr;
2346 
2347     if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
2348         arg->key_data)
2349         return ERR_PTR(-EINVAL);
2350     if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
2351         !arg->key_data)
2352         return ERR_PTR(-EINVAL);
2353 
2354     len = sizeof(*tlv) + sizeof(*cmd) +
2355           sizeof(*tlv) + roundup(arg->key_len, sizeof(__le32));
2356     skb = ath10k_wmi_alloc_skb(ar, len);
2357     if (!skb)
2358         return ERR_PTR(-ENOMEM);
2359 
2360     ptr = (void *)skb->data;
2361     tlv = ptr;
2362     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD);
2363     tlv->len = __cpu_to_le16(sizeof(*cmd));
2364     cmd = (void *)tlv->value;
2365     cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2366     cmd->key_idx = __cpu_to_le32(arg->key_idx);
2367     cmd->key_flags = __cpu_to_le32(arg->key_flags);
2368     cmd->key_cipher = __cpu_to_le32(arg->key_cipher);
2369     cmd->key_len = __cpu_to_le32(arg->key_len);
2370     cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len);
2371     cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
2372 
2373     if (arg->macaddr)
2374         ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
2375 
2376     ptr += sizeof(*tlv);
2377     ptr += sizeof(*cmd);
2378 
2379     tlv = ptr;
2380     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2381     tlv->len = __cpu_to_le16(roundup(arg->key_len, sizeof(__le32)));
2382     if (arg->key_data)
2383         memcpy(tlv->value, arg->key_data, arg->key_len);
2384 
2385     ptr += sizeof(*tlv);
2386     ptr += roundup(arg->key_len, sizeof(__le32));
2387 
2388     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev install key\n");
2389     return skb;
2390 }
2391 
2392 static void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr,
2393                      const struct wmi_sta_uapsd_auto_trig_arg *arg)
2394 {
2395     struct wmi_sta_uapsd_auto_trig_param *ac;
2396     struct wmi_tlv *tlv;
2397 
2398     tlv = ptr;
2399     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM);
2400     tlv->len = __cpu_to_le16(sizeof(*ac));
2401     ac = (void *)tlv->value;
2402 
2403     ac->wmm_ac = __cpu_to_le32(arg->wmm_ac);
2404     ac->user_priority = __cpu_to_le32(arg->user_priority);
2405     ac->service_interval = __cpu_to_le32(arg->service_interval);
2406     ac->suspend_interval = __cpu_to_le32(arg->suspend_interval);
2407     ac->delay_interval = __cpu_to_le32(arg->delay_interval);
2408 
2409     ath10k_dbg(ar, ATH10K_DBG_WMI,
2410            "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n",
2411            ac->wmm_ac, ac->user_priority, ac->service_interval,
2412            ac->suspend_interval, ac->delay_interval);
2413 
2414     return ptr + sizeof(*tlv) + sizeof(*ac);
2415 }
2416 
2417 static struct sk_buff *
2418 ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id,
2419                      const u8 peer_addr[ETH_ALEN],
2420                      const struct wmi_sta_uapsd_auto_trig_arg *args,
2421                      u32 num_ac)
2422 {
2423     struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd;
2424     struct wmi_sta_uapsd_auto_trig_param *ac;
2425     struct wmi_tlv *tlv;
2426     struct sk_buff *skb;
2427     size_t len;
2428     size_t ac_tlv_len;
2429     void *ptr;
2430     int i;
2431 
2432     ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac));
2433     len = sizeof(*tlv) + sizeof(*cmd) +
2434           sizeof(*tlv) + ac_tlv_len;
2435     skb = ath10k_wmi_alloc_skb(ar, len);
2436     if (!skb)
2437         return ERR_PTR(-ENOMEM);
2438 
2439     ptr = (void *)skb->data;
2440     tlv = ptr;
2441     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD);
2442     tlv->len = __cpu_to_le16(sizeof(*cmd));
2443     cmd = (void *)tlv->value;
2444     cmd->vdev_id = __cpu_to_le32(vdev_id);
2445     cmd->num_ac = __cpu_to_le32(num_ac);
2446     ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2447 
2448     ptr += sizeof(*tlv);
2449     ptr += sizeof(*cmd);
2450 
2451     tlv = ptr;
2452     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2453     tlv->len = __cpu_to_le16(ac_tlv_len);
2454     ac = (void *)tlv->value;
2455 
2456     ptr += sizeof(*tlv);
2457     for (i = 0; i < num_ac; i++)
2458         ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]);
2459 
2460     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n");
2461     return skb;
2462 }
2463 
2464 static void *ath10k_wmi_tlv_put_wmm(void *ptr,
2465                     const struct wmi_wmm_params_arg *arg)
2466 {
2467     struct wmi_wmm_params *wmm;
2468     struct wmi_tlv *tlv;
2469 
2470     tlv = ptr;
2471     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS);
2472     tlv->len = __cpu_to_le16(sizeof(*wmm));
2473     wmm = (void *)tlv->value;
2474     ath10k_wmi_set_wmm_param(wmm, arg);
2475 
2476     return ptr + sizeof(*tlv) + sizeof(*wmm);
2477 }
2478 
2479 static struct sk_buff *
2480 ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
2481                     const struct wmi_wmm_params_all_arg *arg)
2482 {
2483     struct wmi_tlv_vdev_set_wmm_cmd *cmd;
2484     struct wmi_tlv *tlv;
2485     struct sk_buff *skb;
2486     size_t len;
2487     void *ptr;
2488 
2489     len = sizeof(*tlv) + sizeof(*cmd);
2490     skb = ath10k_wmi_alloc_skb(ar, len);
2491     if (!skb)
2492         return ERR_PTR(-ENOMEM);
2493 
2494     ptr = (void *)skb->data;
2495     tlv = ptr;
2496     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD);
2497     tlv->len = __cpu_to_le16(sizeof(*cmd));
2498     cmd = (void *)tlv->value;
2499     cmd->vdev_id = __cpu_to_le32(vdev_id);
2500 
2501     ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[0].params, &arg->ac_be);
2502     ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[1].params, &arg->ac_bk);
2503     ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[2].params, &arg->ac_vi);
2504     ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[3].params, &arg->ac_vo);
2505 
2506     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n");
2507     return skb;
2508 }
2509 
2510 static struct sk_buff *
2511 ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar,
2512                     const struct wmi_sta_keepalive_arg *arg)
2513 {
2514     struct wmi_tlv_sta_keepalive_cmd *cmd;
2515     struct wmi_sta_keepalive_arp_resp *arp;
2516     struct sk_buff *skb;
2517     struct wmi_tlv *tlv;
2518     void *ptr;
2519     size_t len;
2520 
2521     len = sizeof(*tlv) + sizeof(*cmd) +
2522           sizeof(*tlv) + sizeof(*arp);
2523     skb = ath10k_wmi_alloc_skb(ar, len);
2524     if (!skb)
2525         return ERR_PTR(-ENOMEM);
2526 
2527     ptr = (void *)skb->data;
2528     tlv = ptr;
2529     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD);
2530     tlv->len = __cpu_to_le16(sizeof(*cmd));
2531     cmd = (void *)tlv->value;
2532     cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2533     cmd->enabled = __cpu_to_le32(arg->enabled);
2534     cmd->method = __cpu_to_le32(arg->method);
2535     cmd->interval = __cpu_to_le32(arg->interval);
2536 
2537     ptr += sizeof(*tlv);
2538     ptr += sizeof(*cmd);
2539 
2540     tlv = ptr;
2541     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE);
2542     tlv->len = __cpu_to_le16(sizeof(*arp));
2543     arp = (void *)tlv->value;
2544 
2545     arp->src_ip4_addr = arg->src_ip4_addr;
2546     arp->dest_ip4_addr = arg->dest_ip4_addr;
2547     ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
2548 
2549     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d interval %d\n",
2550            arg->vdev_id, arg->enabled, arg->method, arg->interval);
2551     return skb;
2552 }
2553 
2554 static struct sk_buff *
2555 ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
2556                   const u8 peer_addr[ETH_ALEN],
2557                   enum wmi_peer_type peer_type)
2558 {
2559     struct wmi_tlv_peer_create_cmd *cmd;
2560     struct wmi_tlv *tlv;
2561     struct sk_buff *skb;
2562 
2563     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2564     if (!skb)
2565         return ERR_PTR(-ENOMEM);
2566 
2567     tlv = (void *)skb->data;
2568     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD);
2569     tlv->len = __cpu_to_le16(sizeof(*cmd));
2570     cmd = (void *)tlv->value;
2571     cmd->vdev_id = __cpu_to_le32(vdev_id);
2572     cmd->peer_type = __cpu_to_le32(peer_type);
2573     ether_addr_copy(cmd->peer_addr.addr, peer_addr);
2574 
2575     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer create\n");
2576     return skb;
2577 }
2578 
2579 static struct sk_buff *
2580 ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
2581                   const u8 peer_addr[ETH_ALEN])
2582 {
2583     struct wmi_peer_delete_cmd *cmd;
2584     struct wmi_tlv *tlv;
2585     struct sk_buff *skb;
2586 
2587     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2588     if (!skb)
2589         return ERR_PTR(-ENOMEM);
2590 
2591     tlv = (void *)skb->data;
2592     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD);
2593     tlv->len = __cpu_to_le16(sizeof(*cmd));
2594     cmd = (void *)tlv->value;
2595     cmd->vdev_id = __cpu_to_le32(vdev_id);
2596     ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2597 
2598     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete\n");
2599     return skb;
2600 }
2601 
2602 static struct sk_buff *
2603 ath10k_wmi_tlv_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
2604                  const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
2605 {
2606     struct wmi_peer_flush_tids_cmd *cmd;
2607     struct wmi_tlv *tlv;
2608     struct sk_buff *skb;
2609 
2610     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2611     if (!skb)
2612         return ERR_PTR(-ENOMEM);
2613 
2614     tlv = (void *)skb->data;
2615     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD);
2616     tlv->len = __cpu_to_le16(sizeof(*cmd));
2617     cmd = (void *)tlv->value;
2618     cmd->vdev_id = __cpu_to_le32(vdev_id);
2619     cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
2620     ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2621 
2622     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer flush\n");
2623     return skb;
2624 }
2625 
2626 static struct sk_buff *
2627 ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
2628                      const u8 *peer_addr,
2629                      enum wmi_peer_param param_id,
2630                      u32 param_value)
2631 {
2632     struct wmi_peer_set_param_cmd *cmd;
2633     struct wmi_tlv *tlv;
2634     struct sk_buff *skb;
2635 
2636     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2637     if (!skb)
2638         return ERR_PTR(-ENOMEM);
2639 
2640     tlv = (void *)skb->data;
2641     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD);
2642     tlv->len = __cpu_to_le16(sizeof(*cmd));
2643     cmd = (void *)tlv->value;
2644     cmd->vdev_id = __cpu_to_le32(vdev_id);
2645     cmd->param_id = __cpu_to_le32(param_id);
2646     cmd->param_value = __cpu_to_le32(param_value);
2647     ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2648 
2649     ath10k_dbg(ar, ATH10K_DBG_WMI,
2650            "wmi tlv vdev %d peer %pM set param %d value 0x%x\n",
2651            vdev_id, peer_addr, param_id, param_value);
2652     return skb;
2653 }
2654 
2655 static struct sk_buff *
2656 ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k *ar,
2657                  const struct wmi_peer_assoc_complete_arg *arg)
2658 {
2659     struct wmi_tlv_peer_assoc_cmd *cmd;
2660     struct wmi_vht_rate_set *vht_rate;
2661     struct wmi_tlv *tlv;
2662     struct sk_buff *skb;
2663     size_t len, legacy_rate_len, ht_rate_len;
2664     void *ptr;
2665 
2666     if (arg->peer_mpdu_density > 16)
2667         return ERR_PTR(-EINVAL);
2668     if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
2669         return ERR_PTR(-EINVAL);
2670     if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
2671         return ERR_PTR(-EINVAL);
2672 
2673     legacy_rate_len = roundup(arg->peer_legacy_rates.num_rates,
2674                   sizeof(__le32));
2675     ht_rate_len = roundup(arg->peer_ht_rates.num_rates, sizeof(__le32));
2676     len = (sizeof(*tlv) + sizeof(*cmd)) +
2677           (sizeof(*tlv) + legacy_rate_len) +
2678           (sizeof(*tlv) + ht_rate_len) +
2679           (sizeof(*tlv) + sizeof(*vht_rate));
2680     skb = ath10k_wmi_alloc_skb(ar, len);
2681     if (!skb)
2682         return ERR_PTR(-ENOMEM);
2683 
2684     ptr = (void *)skb->data;
2685     tlv = ptr;
2686     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD);
2687     tlv->len = __cpu_to_le16(sizeof(*cmd));
2688     cmd = (void *)tlv->value;
2689 
2690     cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2691     cmd->new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
2692     cmd->assoc_id = __cpu_to_le32(arg->peer_aid);
2693     cmd->flags = __cpu_to_le32(arg->peer_flags);
2694     cmd->caps = __cpu_to_le32(arg->peer_caps);
2695     cmd->listen_intval = __cpu_to_le32(arg->peer_listen_intval);
2696     cmd->ht_caps = __cpu_to_le32(arg->peer_ht_caps);
2697     cmd->max_mpdu = __cpu_to_le32(arg->peer_max_mpdu);
2698     cmd->mpdu_density = __cpu_to_le32(arg->peer_mpdu_density);
2699     cmd->rate_caps = __cpu_to_le32(arg->peer_rate_caps);
2700     cmd->nss = __cpu_to_le32(arg->peer_num_spatial_streams);
2701     cmd->vht_caps = __cpu_to_le32(arg->peer_vht_caps);
2702     cmd->phy_mode = __cpu_to_le32(arg->peer_phymode);
2703     cmd->num_legacy_rates = __cpu_to_le32(arg->peer_legacy_rates.num_rates);
2704     cmd->num_ht_rates = __cpu_to_le32(arg->peer_ht_rates.num_rates);
2705     ether_addr_copy(cmd->mac_addr.addr, arg->addr);
2706 
2707     ptr += sizeof(*tlv);
2708     ptr += sizeof(*cmd);
2709 
2710     tlv = ptr;
2711     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2712     tlv->len = __cpu_to_le16(legacy_rate_len);
2713     memcpy(tlv->value, arg->peer_legacy_rates.rates,
2714            arg->peer_legacy_rates.num_rates);
2715 
2716     ptr += sizeof(*tlv);
2717     ptr += legacy_rate_len;
2718 
2719     tlv = ptr;
2720     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2721     tlv->len = __cpu_to_le16(ht_rate_len);
2722     memcpy(tlv->value, arg->peer_ht_rates.rates,
2723            arg->peer_ht_rates.num_rates);
2724 
2725     ptr += sizeof(*tlv);
2726     ptr += ht_rate_len;
2727 
2728     tlv = ptr;
2729     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VHT_RATE_SET);
2730     tlv->len = __cpu_to_le16(sizeof(*vht_rate));
2731     vht_rate = (void *)tlv->value;
2732 
2733     vht_rate->rx_max_rate = __cpu_to_le32(arg->peer_vht_rates.rx_max_rate);
2734     vht_rate->rx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set);
2735     vht_rate->tx_max_rate = __cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
2736     vht_rate->tx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
2737 
2738     ptr += sizeof(*tlv);
2739     ptr += sizeof(*vht_rate);
2740 
2741     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer assoc\n");
2742     return skb;
2743 }
2744 
2745 static struct sk_buff *
2746 ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
2747                  enum wmi_sta_ps_mode psmode)
2748 {
2749     struct wmi_sta_powersave_mode_cmd *cmd;
2750     struct wmi_tlv *tlv;
2751     struct sk_buff *skb;
2752 
2753     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2754     if (!skb)
2755         return ERR_PTR(-ENOMEM);
2756 
2757     tlv = (void *)skb->data;
2758     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD);
2759     tlv->len = __cpu_to_le16(sizeof(*cmd));
2760     cmd = (void *)tlv->value;
2761     cmd->vdev_id = __cpu_to_le32(vdev_id);
2762     cmd->sta_ps_mode = __cpu_to_le32(psmode);
2763 
2764     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set psmode\n");
2765     return skb;
2766 }
2767 
2768 static struct sk_buff *
2769 ath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
2770                  enum wmi_sta_powersave_param param_id,
2771                  u32 param_value)
2772 {
2773     struct wmi_sta_powersave_param_cmd *cmd;
2774     struct wmi_tlv *tlv;
2775     struct sk_buff *skb;
2776 
2777     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2778     if (!skb)
2779         return ERR_PTR(-ENOMEM);
2780 
2781     tlv = (void *)skb->data;
2782     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD);
2783     tlv->len = __cpu_to_le16(sizeof(*cmd));
2784     cmd = (void *)tlv->value;
2785     cmd->vdev_id = __cpu_to_le32(vdev_id);
2786     cmd->param_id = __cpu_to_le32(param_id);
2787     cmd->param_value = __cpu_to_le32(param_value);
2788 
2789     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set sta ps\n");
2790     return skb;
2791 }
2792 
2793 static struct sk_buff *
2794 ath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
2795                 enum wmi_ap_ps_peer_param param_id, u32 value)
2796 {
2797     struct wmi_ap_ps_peer_cmd *cmd;
2798     struct wmi_tlv *tlv;
2799     struct sk_buff *skb;
2800 
2801     if (!mac)
2802         return ERR_PTR(-EINVAL);
2803 
2804     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2805     if (!skb)
2806         return ERR_PTR(-ENOMEM);
2807 
2808     tlv = (void *)skb->data;
2809     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD);
2810     tlv->len = __cpu_to_le16(sizeof(*cmd));
2811     cmd = (void *)tlv->value;
2812     cmd->vdev_id = __cpu_to_le32(vdev_id);
2813     cmd->param_id = __cpu_to_le32(param_id);
2814     cmd->param_value = __cpu_to_le32(value);
2815     ether_addr_copy(cmd->peer_macaddr.addr, mac);
2816 
2817     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv ap ps param\n");
2818     return skb;
2819 }
2820 
2821 static struct sk_buff *
2822 ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
2823                      const struct wmi_scan_chan_list_arg *arg)
2824 {
2825     struct wmi_tlv_scan_chan_list_cmd *cmd;
2826     struct wmi_channel *ci;
2827     struct wmi_channel_arg *ch;
2828     struct wmi_tlv *tlv;
2829     struct sk_buff *skb;
2830     size_t chans_len, len;
2831     int i;
2832     void *ptr, *chans;
2833 
2834     chans_len = arg->n_channels * (sizeof(*tlv) + sizeof(*ci));
2835     len = (sizeof(*tlv) + sizeof(*cmd)) +
2836           (sizeof(*tlv) + chans_len);
2837 
2838     skb = ath10k_wmi_alloc_skb(ar, len);
2839     if (!skb)
2840         return ERR_PTR(-ENOMEM);
2841 
2842     ptr = (void *)skb->data;
2843     tlv = ptr;
2844     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD);
2845     tlv->len = __cpu_to_le16(sizeof(*cmd));
2846     cmd = (void *)tlv->value;
2847     cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
2848 
2849     ptr += sizeof(*tlv);
2850     ptr += sizeof(*cmd);
2851 
2852     tlv = ptr;
2853     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2854     tlv->len = __cpu_to_le16(chans_len);
2855     chans = (void *)tlv->value;
2856 
2857     for (i = 0; i < arg->n_channels; i++) {
2858         ch = &arg->channels[i];
2859 
2860         tlv = chans;
2861         tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
2862         tlv->len = __cpu_to_le16(sizeof(*ci));
2863         ci = (void *)tlv->value;
2864 
2865         ath10k_wmi_put_wmi_channel(ar, ci, ch);
2866 
2867         chans += sizeof(*tlv);
2868         chans += sizeof(*ci);
2869     }
2870 
2871     ptr += sizeof(*tlv);
2872     ptr += chans_len;
2873 
2874     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan chan list\n");
2875     return skb;
2876 }
2877 
2878 static struct sk_buff *
2879 ath10k_wmi_tlv_op_gen_scan_prob_req_oui(struct ath10k *ar, u32 prob_req_oui)
2880 {
2881     struct wmi_scan_prob_req_oui_cmd *cmd;
2882     struct wmi_tlv *tlv;
2883     struct sk_buff *skb;
2884 
2885     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2886     if (!skb)
2887         return ERR_PTR(-ENOMEM);
2888 
2889     tlv = (void *)skb->data;
2890     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_PROB_REQ_OUI_CMD);
2891     tlv->len = __cpu_to_le16(sizeof(*cmd));
2892     cmd = (void *)tlv->value;
2893     cmd->prob_req_oui = __cpu_to_le32(prob_req_oui);
2894 
2895     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan prob req oui\n");
2896     return skb;
2897 }
2898 
2899 static struct sk_buff *
2900 ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
2901                  const void *bcn, size_t bcn_len,
2902                  u32 bcn_paddr, bool dtim_zero,
2903                  bool deliver_cab)
2904 
2905 {
2906     struct wmi_bcn_tx_ref_cmd *cmd;
2907     struct wmi_tlv *tlv;
2908     struct sk_buff *skb;
2909     struct ieee80211_hdr *hdr;
2910     u16 fc;
2911 
2912     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2913     if (!skb)
2914         return ERR_PTR(-ENOMEM);
2915 
2916     hdr = (struct ieee80211_hdr *)bcn;
2917     fc = le16_to_cpu(hdr->frame_control);
2918 
2919     tlv = (void *)skb->data;
2920     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD);
2921     tlv->len = __cpu_to_le16(sizeof(*cmd));
2922     cmd = (void *)tlv->value;
2923     cmd->vdev_id = __cpu_to_le32(vdev_id);
2924     cmd->data_len = __cpu_to_le32(bcn_len);
2925     cmd->data_ptr = __cpu_to_le32(bcn_paddr);
2926     cmd->msdu_id = 0;
2927     cmd->frame_control = __cpu_to_le32(fc);
2928     cmd->flags = 0;
2929 
2930     if (dtim_zero)
2931         cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
2932 
2933     if (deliver_cab)
2934         cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
2935 
2936     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n");
2937     return skb;
2938 }
2939 
2940 static struct sk_buff *
2941 ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
2942                    const struct wmi_wmm_params_all_arg *arg)
2943 {
2944     struct wmi_tlv_pdev_set_wmm_cmd *cmd;
2945     struct wmi_wmm_params *wmm;
2946     struct wmi_tlv *tlv;
2947     struct sk_buff *skb;
2948     size_t len;
2949     void *ptr;
2950 
2951     len = (sizeof(*tlv) + sizeof(*cmd)) +
2952           (4 * (sizeof(*tlv) + sizeof(*wmm)));
2953     skb = ath10k_wmi_alloc_skb(ar, len);
2954     if (!skb)
2955         return ERR_PTR(-ENOMEM);
2956 
2957     ptr = (void *)skb->data;
2958 
2959     tlv = ptr;
2960     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD);
2961     tlv->len = __cpu_to_le16(sizeof(*cmd));
2962     cmd = (void *)tlv->value;
2963 
2964     /* nothing to set here */
2965 
2966     ptr += sizeof(*tlv);
2967     ptr += sizeof(*cmd);
2968 
2969     ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be);
2970     ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk);
2971     ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi);
2972     ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo);
2973 
2974     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set wmm\n");
2975     return skb;
2976 }
2977 
2978 static struct sk_buff *
2979 ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
2980 {
2981     struct wmi_request_stats_cmd *cmd;
2982     struct wmi_tlv *tlv;
2983     struct sk_buff *skb;
2984 
2985     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2986     if (!skb)
2987         return ERR_PTR(-ENOMEM);
2988 
2989     tlv = (void *)skb->data;
2990     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
2991     tlv->len = __cpu_to_le16(sizeof(*cmd));
2992     cmd = (void *)tlv->value;
2993     cmd->stats_id = __cpu_to_le32(stats_mask);
2994 
2995     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
2996     return skb;
2997 }
2998 
2999 static struct sk_buff *
3000 ath10k_wmi_tlv_op_gen_request_peer_stats_info(struct ath10k *ar,
3001                           u32 vdev_id,
3002                           enum wmi_peer_stats_info_request_type type,
3003                           u8 *addr,
3004                           u32 reset)
3005 {
3006     struct wmi_tlv_request_peer_stats_info *cmd;
3007     struct wmi_tlv *tlv;
3008     struct sk_buff *skb;
3009 
3010     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3011     if (!skb)
3012         return ERR_PTR(-ENOMEM);
3013 
3014     tlv = (void *)skb->data;
3015     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_PEER_STATS_INFO_CMD);
3016     tlv->len = __cpu_to_le16(sizeof(*cmd));
3017     cmd = (void *)tlv->value;
3018     cmd->vdev_id = __cpu_to_le32(vdev_id);
3019     cmd->request_type = __cpu_to_le32(type);
3020 
3021     if (type == WMI_REQUEST_ONE_PEER_STATS_INFO)
3022         ether_addr_copy(cmd->peer_macaddr.addr, addr);
3023 
3024     cmd->reset_after_request = __cpu_to_le32(reset);
3025     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request peer stats info\n");
3026     return skb;
3027 }
3028 
3029 static int
3030 ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
3031                        struct sk_buff *msdu)
3032 {
3033     struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
3034     struct ath10k_wmi *wmi = &ar->wmi;
3035 
3036     idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
3037 
3038     return 0;
3039 }
3040 
3041 static int
3042 ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
3043                  dma_addr_t paddr)
3044 {
3045     struct ath10k_wmi *wmi = &ar->wmi;
3046     struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
3047     int ret;
3048 
3049     pkt_addr = kmalloc(sizeof(*pkt_addr), GFP_ATOMIC);
3050     if (!pkt_addr)
3051         return -ENOMEM;
3052 
3053     pkt_addr->vaddr = skb;
3054     pkt_addr->paddr = paddr;
3055 
3056     spin_lock_bh(&ar->data_lock);
3057     ret = idr_alloc(&wmi->mgmt_pending_tx, pkt_addr, 0,
3058             wmi->mgmt_max_num_pending_tx, GFP_ATOMIC);
3059     spin_unlock_bh(&ar->data_lock);
3060 
3061     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx alloc msdu_id ret %d\n", ret);
3062     return ret;
3063 }
3064 
3065 static struct sk_buff *
3066 ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
3067                    dma_addr_t paddr)
3068 {
3069     struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
3070     struct wmi_tlv_mgmt_tx_cmd *cmd;
3071     struct ieee80211_hdr *hdr;
3072     struct ath10k_vif *arvif;
3073     u32 buf_len = msdu->len;
3074     struct wmi_tlv *tlv;
3075     struct sk_buff *skb;
3076     int len, desc_id;
3077     u32 vdev_id;
3078     void *ptr;
3079 
3080     if (!cb->vif)
3081         return ERR_PTR(-EINVAL);
3082 
3083     hdr = (struct ieee80211_hdr *)msdu->data;
3084     arvif = (void *)cb->vif->drv_priv;
3085     vdev_id = arvif->vdev_id;
3086 
3087     if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
3088              (!(ieee80211_is_nullfunc(hdr->frame_control) ||
3089              ieee80211_is_qos_nullfunc(hdr->frame_control)))))
3090         return ERR_PTR(-EINVAL);
3091 
3092     len = sizeof(*cmd) + 2 * sizeof(*tlv);
3093 
3094     if ((ieee80211_is_action(hdr->frame_control) ||
3095          ieee80211_is_deauth(hdr->frame_control) ||
3096          ieee80211_is_disassoc(hdr->frame_control)) &&
3097          ieee80211_has_protected(hdr->frame_control)) {
3098         skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
3099         buf_len += IEEE80211_CCMP_MIC_LEN;
3100     }
3101 
3102     buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN);
3103     buf_len = round_up(buf_len, 4);
3104 
3105     len += buf_len;
3106     len = round_up(len, 4);
3107     skb = ath10k_wmi_alloc_skb(ar, len);
3108     if (!skb)
3109         return ERR_PTR(-ENOMEM);
3110 
3111     desc_id = ath10k_wmi_mgmt_tx_alloc_msdu_id(ar, msdu, paddr);
3112     if (desc_id < 0)
3113         goto err_free_skb;
3114 
3115     cb->msdu_id = desc_id;
3116 
3117     ptr = (void *)skb->data;
3118     tlv = ptr;
3119     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
3120     tlv->len = __cpu_to_le16(sizeof(*cmd));
3121     cmd = (void *)tlv->value;
3122     cmd->vdev_id = __cpu_to_le32(vdev_id);
3123     cmd->desc_id = __cpu_to_le32(desc_id);
3124     cmd->chanfreq = 0;
3125     cmd->buf_len = __cpu_to_le32(buf_len);
3126     cmd->frame_len = __cpu_to_le32(msdu->len);
3127     cmd->paddr = __cpu_to_le64(paddr);
3128 
3129     ptr += sizeof(*tlv);
3130     ptr += sizeof(*cmd);
3131 
3132     tlv = ptr;
3133     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3134     tlv->len = __cpu_to_le16(buf_len);
3135 
3136     ptr += sizeof(*tlv);
3137     memcpy(ptr, msdu->data, buf_len);
3138 
3139     return skb;
3140 
3141 err_free_skb:
3142     dev_kfree_skb(skb);
3143     return ERR_PTR(desc_id);
3144 }
3145 
3146 static struct sk_buff *
3147 ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
3148                     enum wmi_force_fw_hang_type type,
3149                     u32 delay_ms)
3150 {
3151     struct wmi_force_fw_hang_cmd *cmd;
3152     struct wmi_tlv *tlv;
3153     struct sk_buff *skb;
3154 
3155     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3156     if (!skb)
3157         return ERR_PTR(-ENOMEM);
3158 
3159     tlv = (void *)skb->data;
3160     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD);
3161     tlv->len = __cpu_to_le16(sizeof(*cmd));
3162     cmd = (void *)tlv->value;
3163     cmd->type = __cpu_to_le32(type);
3164     cmd->delay_ms = __cpu_to_le32(delay_ms);
3165 
3166     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv force fw hang\n");
3167     return skb;
3168 }
3169 
3170 static struct sk_buff *
3171 ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u64 module_enable,
3172                  u32 log_level)
3173 {
3174     struct wmi_tlv_dbglog_cmd *cmd;
3175     struct wmi_tlv *tlv;
3176     struct sk_buff *skb;
3177     size_t len, bmap_len;
3178     u32 value;
3179     void *ptr;
3180 
3181     if (module_enable) {
3182         value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
3183                 module_enable,
3184                 WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE);
3185     } else {
3186         value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
3187                 WMI_TLV_DBGLOG_ALL_MODULES,
3188                 WMI_TLV_DBGLOG_LOG_LEVEL_WARN);
3189     }
3190 
3191     bmap_len = 0;
3192     len = sizeof(*tlv) + sizeof(*cmd) + sizeof(*tlv) + bmap_len;
3193     skb = ath10k_wmi_alloc_skb(ar, len);
3194     if (!skb)
3195         return ERR_PTR(-ENOMEM);
3196 
3197     ptr = (void *)skb->data;
3198 
3199     tlv = ptr;
3200     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD);
3201     tlv->len = __cpu_to_le16(sizeof(*cmd));
3202     cmd = (void *)tlv->value;
3203     cmd->param = __cpu_to_le32(WMI_TLV_DBGLOG_PARAM_LOG_LEVEL);
3204     cmd->value = __cpu_to_le32(value);
3205 
3206     ptr += sizeof(*tlv);
3207     ptr += sizeof(*cmd);
3208 
3209     tlv = ptr;
3210     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3211     tlv->len = __cpu_to_le16(bmap_len);
3212 
3213     /* nothing to do here */
3214 
3215     ptr += sizeof(*tlv);
3216     ptr += sizeof(bmap_len);
3217 
3218     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv dbglog value 0x%08x\n", value);
3219     return skb;
3220 }
3221 
3222 static struct sk_buff *
3223 ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
3224 {
3225     struct wmi_tlv_pktlog_enable *cmd;
3226     struct wmi_tlv *tlv;
3227     struct sk_buff *skb;
3228     void *ptr;
3229     size_t len;
3230 
3231     len = sizeof(*tlv) + sizeof(*cmd);
3232     skb = ath10k_wmi_alloc_skb(ar, len);
3233     if (!skb)
3234         return ERR_PTR(-ENOMEM);
3235 
3236     ptr = (void *)skb->data;
3237     tlv = ptr;
3238     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD);
3239     tlv->len = __cpu_to_le16(sizeof(*cmd));
3240     cmd = (void *)tlv->value;
3241     cmd->filter = __cpu_to_le32(filter);
3242 
3243     ptr += sizeof(*tlv);
3244     ptr += sizeof(*cmd);
3245 
3246     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog enable filter 0x%08x\n",
3247            filter);
3248     return skb;
3249 }
3250 
3251 static struct sk_buff *
3252 ath10k_wmi_tlv_op_gen_pdev_get_temperature(struct ath10k *ar)
3253 {
3254     struct wmi_tlv_pdev_get_temp_cmd *cmd;
3255     struct wmi_tlv *tlv;
3256     struct sk_buff *skb;
3257 
3258     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3259     if (!skb)
3260         return ERR_PTR(-ENOMEM);
3261 
3262     tlv = (void *)skb->data;
3263     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_GET_TEMPERATURE_CMD);
3264     tlv->len = __cpu_to_le16(sizeof(*cmd));
3265     cmd = (void *)tlv->value;
3266     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev get temperature tlv\n");
3267     return skb;
3268 }
3269 
3270 static struct sk_buff *
3271 ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar)
3272 {
3273     struct wmi_tlv_pktlog_disable *cmd;
3274     struct wmi_tlv *tlv;
3275     struct sk_buff *skb;
3276     void *ptr;
3277     size_t len;
3278 
3279     len = sizeof(*tlv) + sizeof(*cmd);
3280     skb = ath10k_wmi_alloc_skb(ar, len);
3281     if (!skb)
3282         return ERR_PTR(-ENOMEM);
3283 
3284     ptr = (void *)skb->data;
3285     tlv = ptr;
3286     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD);
3287     tlv->len = __cpu_to_le16(sizeof(*cmd));
3288     cmd = (void *)tlv->value;
3289 
3290     ptr += sizeof(*tlv);
3291     ptr += sizeof(*cmd);
3292 
3293     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog disable\n");
3294     return skb;
3295 }
3296 
3297 static struct sk_buff *
3298 ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id,
3299                    u32 tim_ie_offset, struct sk_buff *bcn,
3300                    u32 prb_caps, u32 prb_erp, void *prb_ies,
3301                    size_t prb_ies_len)
3302 {
3303     struct wmi_tlv_bcn_tmpl_cmd *cmd;
3304     struct wmi_tlv_bcn_prb_info *info;
3305     struct wmi_tlv *tlv;
3306     struct sk_buff *skb;
3307     void *ptr;
3308     size_t len;
3309 
3310     if (WARN_ON(prb_ies_len > 0 && !prb_ies))
3311         return ERR_PTR(-EINVAL);
3312 
3313     len = sizeof(*tlv) + sizeof(*cmd) +
3314           sizeof(*tlv) + sizeof(*info) + prb_ies_len +
3315           sizeof(*tlv) + roundup(bcn->len, 4);
3316     skb = ath10k_wmi_alloc_skb(ar, len);
3317     if (!skb)
3318         return ERR_PTR(-ENOMEM);
3319 
3320     ptr = (void *)skb->data;
3321     tlv = ptr;
3322     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD);
3323     tlv->len = __cpu_to_le16(sizeof(*cmd));
3324     cmd = (void *)tlv->value;
3325     cmd->vdev_id = __cpu_to_le32(vdev_id);
3326     cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset);
3327     cmd->buf_len = __cpu_to_le32(bcn->len);
3328 
3329     ptr += sizeof(*tlv);
3330     ptr += sizeof(*cmd);
3331 
3332     /* FIXME: prb_ies_len should be probably aligned to 4byte boundary but
3333      * then it is then impossible to pass original ie len.
3334      * This chunk is not used yet so if setting probe resp template yields
3335      * problems with beaconing or crashes firmware look here.
3336      */
3337     tlv = ptr;
3338     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
3339     tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len);
3340     info = (void *)tlv->value;
3341     info->caps = __cpu_to_le32(prb_caps);
3342     info->erp = __cpu_to_le32(prb_erp);
3343     memcpy(info->ies, prb_ies, prb_ies_len);
3344 
3345     ptr += sizeof(*tlv);
3346     ptr += sizeof(*info);
3347     ptr += prb_ies_len;
3348 
3349     tlv = ptr;
3350     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3351     tlv->len = __cpu_to_le16(roundup(bcn->len, 4));
3352     memcpy(tlv->value, bcn->data, bcn->len);
3353 
3354     /* FIXME: Adjust TSF? */
3355 
3356     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n",
3357            vdev_id);
3358     return skb;
3359 }
3360 
3361 static struct sk_buff *
3362 ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id,
3363                    struct sk_buff *prb)
3364 {
3365     struct wmi_tlv_prb_tmpl_cmd *cmd;
3366     struct wmi_tlv_bcn_prb_info *info;
3367     struct wmi_tlv *tlv;
3368     struct sk_buff *skb;
3369     void *ptr;
3370     size_t len;
3371 
3372     len = sizeof(*tlv) + sizeof(*cmd) +
3373           sizeof(*tlv) + sizeof(*info) +
3374           sizeof(*tlv) + roundup(prb->len, 4);
3375     skb = ath10k_wmi_alloc_skb(ar, len);
3376     if (!skb)
3377         return ERR_PTR(-ENOMEM);
3378 
3379     ptr = (void *)skb->data;
3380     tlv = ptr;
3381     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD);
3382     tlv->len = __cpu_to_le16(sizeof(*cmd));
3383     cmd = (void *)tlv->value;
3384     cmd->vdev_id = __cpu_to_le32(vdev_id);
3385     cmd->buf_len = __cpu_to_le32(prb->len);
3386 
3387     ptr += sizeof(*tlv);
3388     ptr += sizeof(*cmd);
3389 
3390     tlv = ptr;
3391     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
3392     tlv->len = __cpu_to_le16(sizeof(*info));
3393     info = (void *)tlv->value;
3394     info->caps = 0;
3395     info->erp = 0;
3396 
3397     ptr += sizeof(*tlv);
3398     ptr += sizeof(*info);
3399 
3400     tlv = ptr;
3401     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3402     tlv->len = __cpu_to_le16(roundup(prb->len, 4));
3403     memcpy(tlv->value, prb->data, prb->len);
3404 
3405     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n",
3406            vdev_id);
3407     return skb;
3408 }
3409 
3410 static struct sk_buff *
3411 ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id,
3412                     const u8 *p2p_ie)
3413 {
3414     struct wmi_tlv_p2p_go_bcn_ie *cmd;
3415     struct wmi_tlv *tlv;
3416     struct sk_buff *skb;
3417     void *ptr;
3418     size_t len;
3419 
3420     len = sizeof(*tlv) + sizeof(*cmd) +
3421           sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4);
3422     skb = ath10k_wmi_alloc_skb(ar, len);
3423     if (!skb)
3424         return ERR_PTR(-ENOMEM);
3425 
3426     ptr = (void *)skb->data;
3427     tlv = ptr;
3428     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE);
3429     tlv->len = __cpu_to_le16(sizeof(*cmd));
3430     cmd = (void *)tlv->value;
3431     cmd->vdev_id = __cpu_to_le32(vdev_id);
3432     cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2);
3433 
3434     ptr += sizeof(*tlv);
3435     ptr += sizeof(*cmd);
3436 
3437     tlv = ptr;
3438     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3439     tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4));
3440     memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2);
3441 
3442     ptr += sizeof(*tlv);
3443     ptr += roundup(p2p_ie[1] + 2, 4);
3444 
3445     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n",
3446            vdev_id);
3447     return skb;
3448 }
3449 
3450 static struct sk_buff *
3451 ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
3452                        enum wmi_tdls_state state)
3453 {
3454     struct wmi_tdls_set_state_cmd *cmd;
3455     struct wmi_tlv *tlv;
3456     struct sk_buff *skb;
3457     void *ptr;
3458     size_t len;
3459     /* Set to options from wmi_tlv_tdls_options,
3460      * for now none of them are enabled.
3461      */
3462     u32 options = 0;
3463 
3464     if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
3465         options |=  WMI_TLV_TDLS_BUFFER_STA_EN;
3466 
3467     /* WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL means firm will handle TDLS
3468      * link inactivity detecting logic.
3469      */
3470     if (state == WMI_TDLS_ENABLE_ACTIVE)
3471         state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
3472 
3473     len = sizeof(*tlv) + sizeof(*cmd);
3474     skb = ath10k_wmi_alloc_skb(ar, len);
3475     if (!skb)
3476         return ERR_PTR(-ENOMEM);
3477 
3478     ptr = (void *)skb->data;
3479     tlv = ptr;
3480     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_SET_STATE_CMD);
3481     tlv->len = __cpu_to_le16(sizeof(*cmd));
3482 
3483     cmd = (void *)tlv->value;
3484     cmd->vdev_id = __cpu_to_le32(vdev_id);
3485     cmd->state = __cpu_to_le32(state);
3486     cmd->notification_interval_ms = __cpu_to_le32(5000);
3487     cmd->tx_discovery_threshold = __cpu_to_le32(100);
3488     cmd->tx_teardown_threshold = __cpu_to_le32(5);
3489     cmd->rssi_teardown_threshold = __cpu_to_le32(-75);
3490     cmd->rssi_delta = __cpu_to_le32(-20);
3491     cmd->tdls_options = __cpu_to_le32(options);
3492     cmd->tdls_peer_traffic_ind_window = __cpu_to_le32(2);
3493     cmd->tdls_peer_traffic_response_timeout_ms = __cpu_to_le32(5000);
3494     cmd->tdls_puapsd_mask = __cpu_to_le32(0xf);
3495     cmd->tdls_puapsd_inactivity_time_ms = __cpu_to_le32(0);
3496     cmd->tdls_puapsd_rx_frame_threshold = __cpu_to_le32(10);
3497 
3498     ptr += sizeof(*tlv);
3499     ptr += sizeof(*cmd);
3500 
3501     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv update fw tdls state %d for vdev %i\n",
3502            state, vdev_id);
3503     return skb;
3504 }
3505 
3506 static u32 ath10k_wmi_tlv_prepare_peer_qos(u8 uapsd_queues, u8 sp)
3507 {
3508     u32 peer_qos = 0;
3509 
3510     if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
3511         peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VO;
3512     if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
3513         peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VI;
3514     if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
3515         peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BK;
3516     if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
3517         peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BE;
3518 
3519     peer_qos |= SM(sp, WMI_TLV_TDLS_PEER_SP);
3520 
3521     return peer_qos;
3522 }
3523 
3524 static struct sk_buff *
3525 ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar,
3526                        const struct wmi_tdls_peer_update_cmd_arg *arg,
3527                        const struct wmi_tdls_peer_capab_arg *cap,
3528                        const struct wmi_channel_arg *chan_arg)
3529 {
3530     struct wmi_tdls_peer_update_cmd *cmd;
3531     struct wmi_tdls_peer_capab *peer_cap;
3532     struct wmi_channel *chan;
3533     struct wmi_tlv *tlv;
3534     struct sk_buff *skb;
3535     u32 peer_qos;
3536     void *ptr;
3537     int len;
3538     int i;
3539 
3540     len = sizeof(*tlv) + sizeof(*cmd) +
3541           sizeof(*tlv) + sizeof(*peer_cap) +
3542           sizeof(*tlv) + cap->peer_chan_len * sizeof(*chan);
3543 
3544     skb = ath10k_wmi_alloc_skb(ar, len);
3545     if (!skb)
3546         return ERR_PTR(-ENOMEM);
3547 
3548     ptr = (void *)skb->data;
3549     tlv = ptr;
3550     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_UPDATE_CMD);
3551     tlv->len = __cpu_to_le16(sizeof(*cmd));
3552 
3553     cmd = (void *)tlv->value;
3554     cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
3555     ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
3556     cmd->peer_state = __cpu_to_le32(arg->peer_state);
3557 
3558     ptr += sizeof(*tlv);
3559     ptr += sizeof(*cmd);
3560 
3561     tlv = ptr;
3562     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_CAPABILITIES);
3563     tlv->len = __cpu_to_le16(sizeof(*peer_cap));
3564     peer_cap = (void *)tlv->value;
3565     peer_qos = ath10k_wmi_tlv_prepare_peer_qos(cap->peer_uapsd_queues,
3566                            cap->peer_max_sp);
3567     peer_cap->peer_qos = __cpu_to_le32(peer_qos);
3568     peer_cap->buff_sta_support = __cpu_to_le32(cap->buff_sta_support);
3569     peer_cap->off_chan_support = __cpu_to_le32(cap->off_chan_support);
3570     peer_cap->peer_curr_operclass = __cpu_to_le32(cap->peer_curr_operclass);
3571     peer_cap->self_curr_operclass = __cpu_to_le32(cap->self_curr_operclass);
3572     peer_cap->peer_chan_len = __cpu_to_le32(cap->peer_chan_len);
3573     peer_cap->peer_operclass_len = __cpu_to_le32(cap->peer_operclass_len);
3574 
3575     for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++)
3576         peer_cap->peer_operclass[i] = cap->peer_operclass[i];
3577 
3578     peer_cap->is_peer_responder = __cpu_to_le32(cap->is_peer_responder);
3579     peer_cap->pref_offchan_num = __cpu_to_le32(cap->pref_offchan_num);
3580     peer_cap->pref_offchan_bw = __cpu_to_le32(cap->pref_offchan_bw);
3581 
3582     ptr += sizeof(*tlv);
3583     ptr += sizeof(*peer_cap);
3584 
3585     tlv = ptr;
3586     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3587     tlv->len = __cpu_to_le16(cap->peer_chan_len * sizeof(*chan));
3588 
3589     ptr += sizeof(*tlv);
3590 
3591     for (i = 0; i < cap->peer_chan_len; i++) {
3592         tlv = ptr;
3593         tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
3594         tlv->len = __cpu_to_le16(sizeof(*chan));
3595         chan = (void *)tlv->value;
3596         ath10k_wmi_put_wmi_channel(ar, chan, &chan_arg[i]);
3597 
3598         ptr += sizeof(*tlv);
3599         ptr += sizeof(*chan);
3600     }
3601 
3602     ath10k_dbg(ar, ATH10K_DBG_WMI,
3603            "wmi tlv tdls peer update vdev %i state %d n_chans %u\n",
3604            arg->vdev_id, arg->peer_state, cap->peer_chan_len);
3605     return skb;
3606 }
3607 
3608 static struct sk_buff *
3609 ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period,
3610                       u32 duration, u32 next_offset,
3611                       u32 enabled)
3612 {
3613     struct wmi_tlv_set_quiet_cmd *cmd;
3614     struct wmi_tlv *tlv;
3615     struct sk_buff *skb;
3616 
3617     skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3618     if (!skb)
3619         return ERR_PTR(-ENOMEM);
3620 
3621     tlv = (void *)skb->data;
3622     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_QUIET_CMD);
3623     tlv->len = __cpu_to_le16(sizeof(*cmd));
3624     cmd = (void *)tlv->value;
3625 
3626     /* vdev_id is not in use, set to 0 */
3627     cmd->vdev_id = __cpu_to_le32(0);
3628     cmd->period = __cpu_to_le32(period);
3629     cmd->duration = __cpu_to_le32(duration);
3630     cmd->next_start = __cpu_to_le32(next_offset);
3631     cmd->enabled = __cpu_to_le32(enabled);
3632 
3633     ath10k_dbg(ar, ATH10K_DBG_WMI,
3634            "wmi tlv quiet param: period %u duration %u enabled %d\n",
3635            period, duration, enabled);
3636     return skb;
3637 }
3638 
3639 static struct sk_buff *
3640 ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar)
3641 {
3642     struct wmi_tlv_wow_enable_cmd *cmd;
3643     struct wmi_tlv *tlv;
3644     struct sk_buff *skb;
3645     size_t len;
3646 
3647     len = sizeof(*tlv) + sizeof(*cmd);
3648     skb = ath10k_wmi_alloc_skb(ar, len);
3649     if (!skb)
3650         return ERR_PTR(-ENOMEM);
3651 
3652     tlv = (struct wmi_tlv *)skb->data;
3653     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ENABLE_CMD);
3654     tlv->len = __cpu_to_le16(sizeof(*cmd));
3655     cmd = (void *)tlv->value;
3656 
3657     cmd->enable = __cpu_to_le32(1);
3658     if (!ar->bus_param.link_can_suspend)
3659         cmd->pause_iface_config = __cpu_to_le32(WOW_IFACE_PAUSE_DISABLED);
3660 
3661     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow enable\n");
3662     return skb;
3663 }
3664 
3665 static struct sk_buff *
3666 ath10k_wmi_tlv_op_gen_wow_add_wakeup_event(struct ath10k *ar,
3667                        u32 vdev_id,
3668                        enum wmi_wow_wakeup_event event,
3669                        u32 enable)
3670 {
3671     struct wmi_tlv_wow_add_del_event_cmd *cmd;
3672     struct wmi_tlv *tlv;
3673     struct sk_buff *skb;
3674     size_t len;
3675 
3676     len = sizeof(*tlv) + sizeof(*cmd);
3677     skb = ath10k_wmi_alloc_skb(ar, len);
3678     if (!skb)
3679         return ERR_PTR(-ENOMEM);
3680 
3681     tlv = (struct wmi_tlv *)skb->data;
3682     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_DEL_EVT_CMD);
3683     tlv->len = __cpu_to_le16(sizeof(*cmd));
3684     cmd = (void *)tlv->value;
3685 
3686     cmd->vdev_id = __cpu_to_le32(vdev_id);
3687     cmd->is_add = __cpu_to_le32(enable);
3688     cmd->event_bitmap = __cpu_to_le32(1 << event);
3689 
3690     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
3691            wow_wakeup_event(event), enable, vdev_id);
3692     return skb;
3693 }
3694 
3695 static struct sk_buff *
3696 ath10k_wmi_tlv_gen_wow_host_wakeup_ind(struct ath10k *ar)
3697 {
3698     struct wmi_tlv_wow_host_wakeup_ind *cmd;
3699     struct wmi_tlv *tlv;
3700     struct sk_buff *skb;
3701     size_t len;
3702 
3703     len = sizeof(*tlv) + sizeof(*cmd);
3704     skb = ath10k_wmi_alloc_skb(ar, len);
3705     if (!skb)
3706         return ERR_PTR(-ENOMEM);
3707 
3708     tlv = (struct wmi_tlv *)skb->data;
3709     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_HOSTWAKEUP_FROM_SLEEP_CMD);
3710     tlv->len = __cpu_to_le16(sizeof(*cmd));
3711     cmd = (void *)tlv->value;
3712 
3713     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
3714     return skb;
3715 }
3716 
3717 static struct sk_buff *
3718 ath10k_wmi_tlv_op_gen_wow_add_pattern(struct ath10k *ar, u32 vdev_id,
3719                       u32 pattern_id, const u8 *pattern,
3720                       const u8 *bitmask, int pattern_len,
3721                       int pattern_offset)
3722 {
3723     struct wmi_tlv_wow_add_pattern_cmd *cmd;
3724     struct wmi_tlv_wow_bitmap_pattern *bitmap;
3725     struct wmi_tlv *tlv;
3726     struct sk_buff *skb;
3727     void *ptr;
3728     size_t len;
3729 
3730     len = sizeof(*tlv) + sizeof(*cmd) +
3731           sizeof(*tlv) +            /* array struct */
3732           sizeof(*tlv) + sizeof(*bitmap) +  /* bitmap */
3733           sizeof(*tlv) +            /* empty ipv4 sync */
3734           sizeof(*tlv) +            /* empty ipv6 sync */
3735           sizeof(*tlv) +            /* empty magic */
3736           sizeof(*tlv) +            /* empty info timeout */
3737           sizeof(*tlv) + sizeof(u32);   /* ratelimit interval */
3738 
3739     skb = ath10k_wmi_alloc_skb(ar, len);
3740     if (!skb)
3741         return ERR_PTR(-ENOMEM);
3742 
3743     /* cmd */
3744     ptr = (void *)skb->data;
3745     tlv = ptr;
3746     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_PATTERN_CMD);
3747     tlv->len = __cpu_to_le16(sizeof(*cmd));
3748     cmd = (void *)tlv->value;
3749 
3750     cmd->vdev_id = __cpu_to_le32(vdev_id);
3751     cmd->pattern_id = __cpu_to_le32(pattern_id);
3752     cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
3753 
3754     ptr += sizeof(*tlv);
3755     ptr += sizeof(*cmd);
3756 
3757     /* bitmap */
3758     tlv = ptr;
3759     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3760     tlv->len = __cpu_to_le16(sizeof(*tlv) + sizeof(*bitmap));
3761 
3762     ptr += sizeof(*tlv);
3763 
3764     tlv = ptr;
3765     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_BITMAP_PATTERN_T);
3766     tlv->len = __cpu_to_le16(sizeof(*bitmap));
3767     bitmap = (void *)tlv->value;
3768 
3769     memcpy(bitmap->patternbuf, pattern, pattern_len);
3770     memcpy(bitmap->bitmaskbuf, bitmask, pattern_len);
3771     bitmap->pattern_offset = __cpu_to_le32(pattern_offset);
3772     bitmap->pattern_len = __cpu_to_le32(pattern_len);
3773     bitmap->bitmask_len = __cpu_to_le32(pattern_len);
3774     bitmap->pattern_id = __cpu_to_le32(pattern_id);
3775 
3776     ptr += sizeof(*tlv);
3777     ptr += sizeof(*bitmap);
3778 
3779     /* ipv4 sync */
3780     tlv = ptr;
3781     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3782     tlv->len = __cpu_to_le16(0);
3783 
3784     ptr += sizeof(*tlv);
3785 
3786     /* ipv6 sync */
3787     tlv = ptr;
3788     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3789     tlv->len = __cpu_to_le16(0);
3790 
3791     ptr += sizeof(*tlv);
3792 
3793     /* magic */
3794     tlv = ptr;
3795     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3796     tlv->len = __cpu_to_le16(0);
3797 
3798     ptr += sizeof(*tlv);
3799 
3800     /* pattern info timeout */
3801     tlv = ptr;
3802     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3803     tlv->len = __cpu_to_le16(0);
3804 
3805     ptr += sizeof(*tlv);
3806 
3807     /* ratelimit interval */
3808     tlv = ptr;
3809     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3810     tlv->len = __cpu_to_le16(sizeof(u32));
3811 
3812     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d, pattern_offset %d\n",
3813            vdev_id, pattern_id, pattern_offset);
3814     return skb;
3815 }
3816 
3817 static struct sk_buff *
3818 ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
3819                       u32 pattern_id)
3820 {
3821     struct wmi_tlv_wow_del_pattern_cmd *cmd;
3822     struct wmi_tlv *tlv;
3823     struct sk_buff *skb;
3824     size_t len;
3825 
3826     len = sizeof(*tlv) + sizeof(*cmd);
3827     skb = ath10k_wmi_alloc_skb(ar, len);
3828     if (!skb)
3829         return ERR_PTR(-ENOMEM);
3830 
3831     tlv = (struct wmi_tlv *)skb->data;
3832     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_DEL_PATTERN_CMD);
3833     tlv->len = __cpu_to_le16(sizeof(*cmd));
3834     cmd = (void *)tlv->value;
3835 
3836     cmd->vdev_id = __cpu_to_le32(vdev_id);
3837     cmd->pattern_id = __cpu_to_le32(pattern_id);
3838     cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
3839 
3840     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
3841            vdev_id, pattern_id);
3842     return skb;
3843 }
3844 
3845 /* Request FW to start PNO operation */
3846 static struct sk_buff *
3847 ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
3848                        u32 vdev_id,
3849                        struct wmi_pno_scan_req *pno)
3850 {
3851     struct nlo_configured_parameters *nlo_list;
3852     struct wmi_tlv_wow_nlo_config_cmd *cmd;
3853     struct wmi_tlv *tlv;
3854     struct sk_buff *skb;
3855     __le32 *channel_list;
3856     u16 tlv_len;
3857     size_t len;
3858     void *ptr;
3859     u32 i;
3860 
3861     len = sizeof(*tlv) + sizeof(*cmd) +
3862           sizeof(*tlv) +
3863           /* TLV place holder for array of structures
3864            * nlo_configured_parameters(nlo_list)
3865            */
3866           sizeof(*tlv);
3867           /* TLV place holder for array of uint32 channel_list */
3868 
3869     len += sizeof(u32) * min_t(u8, pno->a_networks[0].channel_count,
3870                    WMI_NLO_MAX_CHAN);
3871     len += sizeof(struct nlo_configured_parameters) *
3872                 min_t(u8, pno->uc_networks_count, WMI_NLO_MAX_SSIDS);
3873 
3874     skb = ath10k_wmi_alloc_skb(ar, len);
3875     if (!skb)
3876         return ERR_PTR(-ENOMEM);
3877 
3878     ptr = (void *)skb->data;
3879     tlv = ptr;
3880     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
3881     tlv->len = __cpu_to_le16(sizeof(*cmd));
3882     cmd = (void *)tlv->value;
3883 
3884     /* wmi_tlv_wow_nlo_config_cmd parameters*/
3885     cmd->vdev_id = __cpu_to_le32(pno->vdev_id);
3886     cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);
3887 
3888     /* current FW does not support min-max range for dwell time */
3889     cmd->active_dwell_time = __cpu_to_le32(pno->active_max_time);
3890     cmd->passive_dwell_time = __cpu_to_le32(pno->passive_max_time);
3891 
3892     if (pno->do_passive_scan)
3893         cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);
3894 
3895     /* copy scan interval */
3896     cmd->fast_scan_period = __cpu_to_le32(pno->fast_scan_period);
3897     cmd->slow_scan_period = __cpu_to_le32(pno->slow_scan_period);
3898     cmd->fast_scan_max_cycles = __cpu_to_le32(pno->fast_scan_max_cycles);
3899     cmd->delay_start_time = __cpu_to_le32(pno->delay_start_time);
3900 
3901     if (pno->enable_pno_scan_randomization) {
3902         cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |
3903                 WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);
3904         ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);
3905         ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);
3906     }
3907 
3908     ptr += sizeof(*tlv);
3909     ptr += sizeof(*cmd);
3910 
3911     /* nlo_configured_parameters(nlo_list) */
3912     cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
3913                            WMI_NLO_MAX_SSIDS));
3914     tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
3915         sizeof(struct nlo_configured_parameters);
3916 
3917     tlv = ptr;
3918     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3919     tlv->len = __cpu_to_le16(tlv_len);
3920 
3921     ptr += sizeof(*tlv);
3922     nlo_list = ptr;
3923     for (i = 0; i < __le32_to_cpu(cmd->no_of_ssids); i++) {
3924         tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);
3925         tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3926         tlv->len = __cpu_to_le16(sizeof(struct nlo_configured_parameters) -
3927                      sizeof(*tlv));
3928 
3929         /* copy ssid and it's length */
3930         nlo_list[i].ssid.valid = __cpu_to_le32(true);
3931         nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len;
3932         memcpy(nlo_list[i].ssid.ssid.ssid,
3933                pno->a_networks[i].ssid.ssid,
3934                __le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));
3935 
3936         /* copy rssi threshold */
3937         if (pno->a_networks[i].rssi_threshold &&
3938             pno->a_networks[i].rssi_threshold > -300) {
3939             nlo_list[i].rssi_cond.valid = __cpu_to_le32(true);
3940             nlo_list[i].rssi_cond.rssi =
3941                 __cpu_to_le32(pno->a_networks[i].rssi_threshold);
3942         }
3943 
3944         nlo_list[i].bcast_nw_type.valid = __cpu_to_le32(true);
3945         nlo_list[i].bcast_nw_type.bcast_nw_type =
3946             __cpu_to_le32(pno->a_networks[i].bcast_nw_type);
3947     }
3948 
3949     ptr += __le32_to_cpu(cmd->no_of_ssids) * sizeof(struct nlo_configured_parameters);
3950 
3951     /* copy channel info */
3952     cmd->num_of_channels = __cpu_to_le32(min_t(u8,
3953                            pno->a_networks[0].channel_count,
3954                            WMI_NLO_MAX_CHAN));
3955 
3956     tlv = ptr;
3957     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3958     tlv->len = __cpu_to_le16(__le32_to_cpu(cmd->num_of_channels) *
3959                  sizeof(u_int32_t));
3960     ptr += sizeof(*tlv);
3961 
3962     channel_list = (__le32 *)ptr;
3963     for (i = 0; i < __le32_to_cpu(cmd->num_of_channels); i++)
3964         channel_list[i] = __cpu_to_le32(pno->a_networks[0].channels[i]);
3965 
3966     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
3967            vdev_id);
3968 
3969     return skb;
3970 }
3971 
3972 /* Request FW to stop ongoing PNO operation */
3973 static struct sk_buff *ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k *ar,
3974                                  u32 vdev_id)
3975 {
3976     struct wmi_tlv_wow_nlo_config_cmd *cmd;
3977     struct wmi_tlv *tlv;
3978     struct sk_buff *skb;
3979     void *ptr;
3980     size_t len;
3981 
3982     len = sizeof(*tlv) + sizeof(*cmd) +
3983           sizeof(*tlv) +
3984           /* TLV place holder for array of structures
3985            * nlo_configured_parameters(nlo_list)
3986            */
3987           sizeof(*tlv);
3988           /* TLV place holder for array of uint32 channel_list */
3989     skb = ath10k_wmi_alloc_skb(ar, len);
3990     if (!skb)
3991         return ERR_PTR(-ENOMEM);
3992 
3993     ptr = (void *)skb->data;
3994     tlv = ptr;
3995     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
3996     tlv->len = __cpu_to_le16(sizeof(*cmd));
3997     cmd = (void *)tlv->value;
3998 
3999     cmd->vdev_id = __cpu_to_le32(vdev_id);
4000     cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_STOP);
4001 
4002     ptr += sizeof(*tlv);
4003     ptr += sizeof(*cmd);
4004 
4005     /* nlo_configured_parameters(nlo_list) */
4006     tlv = ptr;
4007     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4008     tlv->len = __cpu_to_le16(0);
4009 
4010     ptr += sizeof(*tlv);
4011 
4012     /* channel list */
4013     tlv = ptr;
4014     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
4015     tlv->len = __cpu_to_le16(0);
4016 
4017     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop pno config vdev_id %d\n", vdev_id);
4018     return skb;
4019 }
4020 
4021 static struct sk_buff *
4022 ath10k_wmi_tlv_op_gen_config_pno(struct ath10k *ar, u32 vdev_id,
4023                  struct wmi_pno_scan_req *pno_scan)
4024 {
4025     if (pno_scan->enable)
4026         return ath10k_wmi_tlv_op_gen_config_pno_start(ar, vdev_id, pno_scan);
4027     else
4028         return ath10k_wmi_tlv_op_gen_config_pno_stop(ar, vdev_id);
4029 }
4030 
4031 static struct sk_buff *
4032 ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
4033 {
4034     struct wmi_tlv_adaptive_qcs *cmd;
4035     struct wmi_tlv *tlv;
4036     struct sk_buff *skb;
4037     void *ptr;
4038     size_t len;
4039 
4040     len = sizeof(*tlv) + sizeof(*cmd);
4041     skb = ath10k_wmi_alloc_skb(ar, len);
4042     if (!skb)
4043         return ERR_PTR(-ENOMEM);
4044 
4045     ptr = (void *)skb->data;
4046     tlv = ptr;
4047     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESMGR_ADAPTIVE_OCS_CMD);
4048     tlv->len = __cpu_to_le16(sizeof(*cmd));
4049     cmd = (void *)tlv->value;
4050     cmd->enable = __cpu_to_le32(enable ? 1 : 0);
4051 
4052     ptr += sizeof(*tlv);
4053     ptr += sizeof(*cmd);
4054 
4055     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv adaptive qcs %d\n", enable);
4056     return skb;
4057 }
4058 
4059 static struct sk_buff *
4060 ath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value)
4061 {
4062     struct wmi_echo_cmd *cmd;
4063     struct wmi_tlv *tlv;
4064     struct sk_buff *skb;
4065     void *ptr;
4066     size_t len;
4067 
4068     len = sizeof(*tlv) + sizeof(*cmd);
4069     skb = ath10k_wmi_alloc_skb(ar, len);
4070     if (!skb)
4071         return ERR_PTR(-ENOMEM);
4072 
4073     ptr = (void *)skb->data;
4074     tlv = ptr;
4075     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_ECHO_CMD);
4076     tlv->len = __cpu_to_le16(sizeof(*cmd));
4077     cmd = (void *)tlv->value;
4078     cmd->value = cpu_to_le32(value);
4079 
4080     ptr += sizeof(*tlv);
4081     ptr += sizeof(*cmd);
4082 
4083     ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv echo value 0x%08x\n", value);
4084     return skb;
4085 }
4086 
4087 static struct sk_buff *
4088 ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k *ar,
4089                      const struct wmi_vdev_spectral_conf_arg *arg)
4090 {
4091     struct wmi_vdev_spectral_conf_cmd *cmd;
4092     struct sk_buff *skb;
4093     struct wmi_tlv *tlv;
4094     void *ptr;
4095     size_t len;
4096 
4097     len = sizeof(*tlv) + sizeof(*cmd);
4098     skb = ath10k_wmi_alloc_skb(ar, len);
4099     if (!skb)
4100         return ERR_PTR(-ENOMEM);
4101 
4102     ptr = (void *)skb->data;
4103     tlv = ptr;
4104     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD);
4105     tlv->len = __cpu_to_le16(sizeof(*cmd));
4106     cmd = (void *)tlv->value;
4107     cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
4108     cmd->scan_count = __cpu_to_le32(arg->scan_count);
4109     cmd->scan_period = __cpu_to_le32(arg->scan_period);
4110     cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
4111     cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
4112     cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
4113     cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
4114     cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
4115     cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
4116     cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
4117     cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
4118     cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
4119     cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
4120     cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
4121     cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
4122     cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
4123     cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
4124     cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
4125     cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
4126 
4127     return skb;
4128 }
4129 
4130 static struct sk_buff *
4131 ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
4132                        u32 trigger, u32 enable)
4133 {
4134     struct wmi_vdev_spectral_enable_cmd *cmd;
4135     struct sk_buff *skb;
4136     struct wmi_tlv *tlv;
4137     void *ptr;
4138     size_t len;
4139 
4140     len = sizeof(*tlv) + sizeof(*cmd);
4141     skb = ath10k_wmi_alloc_skb(ar, len);
4142     if (!skb)
4143         return ERR_PTR(-ENOMEM);
4144 
4145     ptr = (void *)skb->data;
4146     tlv = ptr;
4147     tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD);
4148     tlv->len = __cpu_to_le16(sizeof(*cmd));
4149     cmd = (void *)tlv->value;
4150     cmd->vdev_id = __cpu_to_le32(vdev_id);
4151     cmd->trigger_cmd = __cpu_to_le32(trigger);
4152     cmd->enable_cmd = __cpu_to_le32(enable);
4153 
4154     return skb;
4155 }
4156 
4157 /****************/
4158 /* TLV mappings */
4159 /****************/
4160 
4161 static struct wmi_cmd_map wmi_tlv_cmd_map = {
4162     .init_cmdid = WMI_TLV_INIT_CMDID,
4163     .start_scan_cmdid = WMI_TLV_START_SCAN_CMDID,
4164     .stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
4165     .scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
4166     .scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
4167     .scan_prob_req_oui_cmdid = WMI_TLV_SCAN_PROB_REQ_OUI_CMDID,
4168     .pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
4169     .pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
4170     .pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
4171     .pdev_pktlog_enable_cmdid = WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID,
4172     .pdev_pktlog_disable_cmdid = WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID,
4173     .pdev_set_wmm_params_cmdid = WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID,
4174     .pdev_set_ht_cap_ie_cmdid = WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID,
4175     .pdev_set_vht_cap_ie_cmdid = WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID,
4176     .pdev_set_dscp_tid_map_cmdid = WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID,
4177     .pdev_set_quiet_mode_cmdid = WMI_TLV_PDEV_SET_QUIET_MODE_CMDID,
4178     .pdev_green_ap_ps_enable_cmdid = WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID,
4179     .pdev_get_tpc_config_cmdid = WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID,
4180     .pdev_set_base_macaddr_cmdid = WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID,
4181     .vdev_create_cmdid = WMI_TLV_VDEV_CREATE_CMDID,
4182     .vdev_delete_cmdid = WMI_TLV_VDEV_DELETE_CMDID,
4183     .vdev_start_request_cmdid = WMI_TLV_VDEV_START_REQUEST_CMDID,
4184     .vdev_restart_request_cmdid = WMI_TLV_VDEV_RESTART_REQUEST_CMDID,
4185     .vdev_up_cmdid = WMI_TLV_VDEV_UP_CMDID,
4186     .vdev_stop_cmdid = WMI_TLV_VDEV_STOP_CMDID,
4187     .vdev_down_cmdid = WMI_TLV_VDEV_DOWN_CMDID,
4188     .vdev_set_param_cmdid = WMI_TLV_VDEV_SET_PARAM_CMDID,
4189     .vdev_install_key_cmdid = WMI_TLV_VDEV_INSTALL_KEY_CMDID,
4190     .peer_create_cmdid = WMI_TLV_PEER_CREATE_CMDID,
4191     .peer_delete_cmdid = WMI_TLV_PEER_DELETE_CMDID,
4192     .peer_flush_tids_cmdid = WMI_TLV_PEER_FLUSH_TIDS_CMDID,
4193     .peer_set_param_cmdid = WMI_TLV_PEER_SET_PARAM_CMDID,
4194     .peer_assoc_cmdid = WMI_TLV_PEER_ASSOC_CMDID,
4195     .peer_add_wds_entry_cmdid = WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID,
4196     .peer_remove_wds_entry_cmdid = WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID,
4197     .peer_mcast_group_cmdid = WMI_TLV_PEER_MCAST_GROUP_CMDID,
4198     .bcn_tx_cmdid = WMI_TLV_BCN_TX_CMDID,
4199     .pdev_send_bcn_cmdid = WMI_TLV_PDEV_SEND_BCN_CMDID,
4200     .bcn_tmpl_cmdid = WMI_TLV_BCN_TMPL_CMDID,
4201     .bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID,
4202     .prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
4203     .mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID,
4204     .mgmt_tx_send_cmdid = WMI_TLV_MGMT_TX_SEND_CMD,
4205     .prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID,
4206     .addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID,
4207     .addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID,
4208     .addba_status_cmdid = WMI_TLV_ADDBA_STATUS_CMDID,
4209     .delba_send_cmdid = WMI_TLV_DELBA_SEND_CMDID,
4210     .addba_set_resp_cmdid = WMI_TLV_ADDBA_SET_RESP_CMDID,
4211     .send_singleamsdu_cmdid = WMI_TLV_SEND_SINGLEAMSDU_CMDID,
4212     .sta_powersave_mode_cmdid = WMI_TLV_STA_POWERSAVE_MODE_CMDID,
4213     .sta_powersave_param_cmdid = WMI_TLV_STA_POWERSAVE_PARAM_CMDID,
4214     .sta_mimo_ps_mode_cmdid = WMI_TLV_STA_MIMO_PS_MODE_CMDID,
4215     .pdev_dfs_enable_cmdid = WMI_TLV_PDEV_DFS_ENABLE_CMDID,
4216     .pdev_dfs_disable_cmdid = WMI_TLV_PDEV_DFS_DISABLE_CMDID,
4217     .roam_scan_mode = WMI_TLV_ROAM_SCAN_MODE,
4218     .roam_scan_rssi_threshold = WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD,
4219     .roam_scan_period = WMI_TLV_ROAM_SCAN_PERIOD,
4220     .roam_scan_rssi_change_threshold =
4221                 WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
4222     .roam_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
4223     .ofl_scan_add_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
4224     .ofl_scan_remove_ap_profile = WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE,
4225     .ofl_scan_period = WMI_TLV_OFL_SCAN_PERIOD,
4226     .p2p_dev_set_device_info = WMI_TLV_P2P_DEV_SET_DEVICE_INFO,
4227     .p2p_dev_set_discoverability = WMI_TLV_P2P_DEV_SET_DISCOVERABILITY,
4228     .p2p_go_set_beacon_ie = WMI_TLV_P2P_GO_SET_BEACON_IE,
4229     .p2p_go_set_probe_resp_ie = WMI_TLV_P2P_GO_SET_PROBE_RESP_IE,
4230     .p2p_set_vendor_ie_data_cmdid = WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID,
4231     .ap_ps_peer_param_cmdid = WMI_TLV_AP_PS_PEER_PARAM_CMDID,
4232     .ap_ps_peer_uapsd_coex_cmdid = WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID,
4233     .peer_rate_retry_sched_cmdid = WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID,
4234     .wlan_profile_trigger_cmdid = WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID,
4235     .wlan_profile_set_hist_intvl_cmdid =
4236                 WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
4237     .wlan_profile_get_profile_data_cmdid =
4238                 WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
4239     .wlan_profile_enable_profile_id_cmdid =
4240                 WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
4241     .wlan_profile_list_profile_id_cmdid =
4242                 WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
4243     .pdev_suspend_cmdid = WMI_TLV_PDEV_SUSPEND_CMDID,
4244     .pdev_resume_cmdid = WMI_TLV_PDEV_RESUME_CMDID,
4245     .add_bcn_filter_cmdid = WMI_TLV_ADD_BCN_FILTER_CMDID,
4246     .rmv_bcn_filter_cmdid = WMI_TLV_RMV_BCN_FILTER_CMDID,
4247     .wow_add_wake_pattern_cmdid = WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID,
4248     .wow_del_wake_pattern_cmdid = WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID,
4249     .wow_enable_disable_wake_event_cmdid =
4250                 WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
4251     .wow_enable_cmdid = WMI_TLV_WOW_ENABLE_CMDID,
4252     .wow_hostwakeup_from_sleep_cmdid =
4253                 WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
4254     .rtt_measreq_cmdid = WMI_TLV_RTT_MEASREQ_CMDID,
4255     .rtt_tsf_cmdid = WMI_TLV_RTT_TSF_CMDID,
4256     .vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID,
4257     .vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID,
4258     .request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID,
4259     .request_peer_stats_info_cmdid = WMI_TLV_REQUEST_PEER_STATS_INFO_CMDID,
4260     .set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID,
4261     .network_list_offload_config_cmdid =
4262                 WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID,
4263     .gtk_offload_cmdid = WMI_TLV_GTK_OFFLOAD_CMDID,
4264     .csa_offload_enable_cmdid = WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID,
4265     .csa_offload_chanswitch_cmdid = WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID,
4266     .chatter_set_mode_cmdid = WMI_TLV_CHATTER_SET_MODE_CMDID,
4267     .peer_tid_addba_cmdid = WMI_TLV_PEER_TID_ADDBA_CMDID,
4268     .peer_tid_delba_cmdid = WMI_TLV_PEER_TID_DELBA_CMDID,
4269     .sta_dtim_ps_method_cmdid = WMI_TLV_STA_DTIM_PS_METHOD_CMDID,
4270     .sta_uapsd_auto_trig_cmdid = WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID,
4271     .sta_keepalive_cmd = WMI_TLV_STA_KEEPALIVE_CMDID,
4272     .echo_cmdid = WMI_TLV_ECHO_CMDID,
4273     .pdev_utf_cmdid = WMI_TLV_PDEV_UTF_CMDID,
4274     .dbglog_cfg_cmdid = WMI_TLV_DBGLOG_CFG_CMDID,
4275     .pdev_qvit_cmdid = WMI_TLV_PDEV_QVIT_CMDID,
4276     .pdev_ftm_intg_cmdid = WMI_TLV_PDEV_FTM_INTG_CMDID,
4277     .vdev_set_keepalive_cmdid = WMI_TLV_VDEV_SET_KEEPALIVE_CMDID,
4278     .vdev_get_keepalive_cmdid = WMI_TLV_VDEV_GET_KEEPALIVE_CMDID,
4279     .force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID,
4280     .gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID,
4281     .gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID,
4282     .pdev_get_temperature_cmdid = WMI_TLV_PDEV_GET_TEMPERATURE_CMDID,
4283     .vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
4284     .tdls_set_state_cmdid = WMI_TLV_TDLS_SET_STATE_CMDID,
4285     .tdls_peer_update_cmdid = WMI_TLV_TDLS_PEER_UPDATE_CMDID,
4286     .adaptive_qcs_cmdid = WMI_TLV_RESMGR_ADAPTIVE_OCS_CMDID,
4287     .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
4288     .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
4289     .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
4290     .wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
4291     .wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
4292     .wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
4293     .wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
4294     .peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
4295     .peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
4296     .rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
4297     .oem_req_cmdid = WMI_CMD_UNSUPPORTED,
4298     .nan_cmdid = WMI_CMD_UNSUPPORTED,
4299     .vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
4300     .qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
4301     .pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
4302     .pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
4303     .peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
4304     .peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
4305     .peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
4306     .pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
4307     .pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
4308     .pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
4309     .pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
4310     .pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
4311     .pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
4312     .tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
4313     .fwtest_cmdid = WMI_CMD_UNSUPPORTED,
4314     .vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
4315     .peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
4316     .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
4317     .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
4318     .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
4319 };
4320 
4321 static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
4322     .tx_chain_mask = WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK,
4323     .rx_chain_mask = WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK,
4324     .txpower_limit2g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G,
4325     .txpower_limit5g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G,
4326     .txpower_scale = WMI_TLV_PDEV_PARAM_TXPOWER_SCALE,
4327     .beacon_gen_mode = WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE,
4328     .beacon_tx_mode = WMI_TLV_PDEV_PARAM_BEACON_TX_MODE,
4329     .resmgr_offchan_mode = WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
4330     .protection_mode = WMI_TLV_PDEV_PARAM_PROTECTION_MODE,
4331     .dynamic_bw = WMI_TLV_PDEV_PARAM_DYNAMIC_BW,
4332     .non_agg_sw_retry_th = WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
4333     .agg_sw_retry_th = WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH,
4334     .sta_kickout_th = WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH,
4335     .ac_aggrsize_scaling = WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING,
4336     .ltr_enable = WMI_TLV_PDEV_PARAM_LTR_ENABLE,
4337     .ltr_ac_latency_be = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE,
4338     .ltr_ac_latency_bk = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK,
4339     .ltr_ac_latency_vi = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI,
4340     .ltr_ac_latency_vo = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO,
4341     .ltr_ac_latency_timeout = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
4342     .ltr_sleep_override = WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
4343     .ltr_rx_override = WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE,
4344     .ltr_tx_activity_timeout = WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
4345     .l1ss_enable = WMI_TLV_PDEV_PARAM_L1SS_ENABLE,
4346     .dsleep_enable = WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE,
4347     .pcielp_txbuf_flush = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
4348     .pcielp_txbuf_watermark = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
4349     .pcielp_txbuf_tmo_en = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
4350     .pcielp_txbuf_tmo_value = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
4351     .pdev_stats_update_period = WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
4352     .vdev_stats_update_period = WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
4353     .peer_stats_update_period = WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
4354     .bcnflt_stats_update_period =
4355                 WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
4356     .pmf_qos = WMI_TLV_PDEV_PARAM_PMF_QOS,
4357     .arp_ac_override = WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE,
4358     .dcs = WMI_TLV_PDEV_PARAM_DCS,
4359     .ani_enable = WMI_TLV_PDEV_PARAM_ANI_ENABLE,
4360     .ani_poll_period = WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD,
4361     .ani_listen_period = WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD,
4362     .ani_ofdm_level = WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL,
4363     .ani_cck_level = WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL,
4364     .dyntxchain = WMI_TLV_PDEV_PARAM_DYNTXCHAIN,
4365     .proxy_sta = WMI_TLV_PDEV_PARAM_PROXY_STA,
4366     .idle_ps_config = WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG,
4367     .power_gating_sleep = WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP,
4368     .fast_channel_reset = WMI_TLV_PDEV_PARAM_UNSUPPORTED,
4369     .burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR,
4370     .burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE,
4371     .cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
4372     .aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
4373     .rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4374     .smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
4375     .igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
4376     .igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
4377     .antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
4378     .rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
4379     .set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
4380     .proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4381     .set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4382     .set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
4383     .remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
4384     .peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
4385     .igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
4386     .block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
4387     .set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4388     .set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4389     .set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4390     .txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4391     .set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4392     .set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4393     .en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
4394     .mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
4395     .noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
4396     .noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
4397     .dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
4398     .set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
4399     .atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
4400     .atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
4401     .ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
4402     .mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
4403     .sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
4404     .signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
4405     .signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
4406     .enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
4407     .enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
4408     .cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
4409     .rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
4410     .pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
4411     .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
4412     .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
4413     .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
4414     .rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
4415     .rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
4416     .peer_stats_info_enable = WMI_TLV_PDEV_PARAM_PEER_STATS_INFO_ENABLE,
4417 };
4418 
4419 static struct wmi_peer_param_map wmi_tlv_peer_param_map = {
4420     .smps_state = WMI_TLV_PEER_SMPS_STATE,
4421     .ampdu = WMI_TLV_PEER_AMPDU,
4422     .authorize = WMI_TLV_PEER_AUTHORIZE,
4423     .chan_width = WMI_TLV_PEER_CHAN_WIDTH,
4424     .nss = WMI_TLV_PEER_NSS,
4425     .use_4addr = WMI_TLV_PEER_USE_4ADDR,
4426     .membership = WMI_TLV_PEER_MEMBERSHIP,
4427     .user_pos = WMI_TLV_PEER_USERPOS,
4428     .crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED,
4429     .tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR,
4430     .set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S,
4431     .ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH,
4432     .phymode = WMI_TLV_PEER_PHYMODE,
4433     .use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR,
4434     .dummy_var = WMI_TLV_PEER_DUMMY_VAR,
4435 };
4436 
4437 static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
4438     .rts_threshold = WMI_TLV_VDEV_PARAM_RTS_THRESHOLD,
4439     .fragmentation_threshold = WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
4440     .beacon_interval = WMI_TLV_VDEV_PARAM_BEACON_INTERVAL,
4441     .listen_interval = WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL,
4442     .multicast_rate = WMI_TLV_VDEV_PARAM_MULTICAST_RATE,
4443     .mgmt_tx_rate = WMI_TLV_VDEV_PARAM_MGMT_TX_RATE,
4444     .slot_time = WMI_TLV_VDEV_PARAM_SLOT_TIME,
4445     .preamble = WMI_TLV_VDEV_PARAM_PREAMBLE,
4446     .swba_time = WMI_TLV_VDEV_PARAM_SWBA_TIME,
4447     .wmi_vdev_stats_update_period = WMI_TLV_VDEV_STATS_UPDATE_PERIOD,
4448     .wmi_vdev_pwrsave_ageout_time = WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME,
4449     .wmi_vdev_host_swba_interval = WMI_TLV_VDEV_HOST_SWBA_INTERVAL,
4450     .dtim_period = WMI_TLV_VDEV_PARAM_DTIM_PERIOD,
4451     .wmi_vdev_oc_scheduler_air_time_limit =
4452                 WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
4453     .wds = WMI_TLV_VDEV_PARAM_WDS,
4454     .atim_window = WMI_TLV_VDEV_PARAM_ATIM_WINDOW,
4455     .bmiss_count_max = WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX,
4456     .bmiss_first_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT,
4457     .bmiss_final_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT,
4458     .feature_wmm = WMI_TLV_VDEV_PARAM_FEATURE_WMM,
4459     .chwidth = WMI_TLV_VDEV_PARAM_CHWIDTH,
4460     .chextoffset = WMI_TLV_VDEV_PARAM_CHEXTOFFSET,
4461     .disable_htprotection = WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION,
4462     .sta_quickkickout = WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT,
4463     .mgmt_rate = WMI_TLV_VDEV_PARAM_MGMT_RATE,
4464     .protection_mode = WMI_TLV_VDEV_PARAM_PROTECTION_MODE,
4465     .fixed_rate = WMI_TLV_VDEV_PARAM_FIXED_RATE,
4466     .sgi = WMI_TLV_VDEV_PARAM_SGI,
4467     .ldpc = WMI_TLV_VDEV_PARAM_LDPC,
4468     .tx_stbc = WMI_TLV_VDEV_PARAM_TX_STBC,
4469     .rx_stbc = WMI_TLV_VDEV_PARAM_RX_STBC,
4470     .intra_bss_fwd = WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD,
4471     .def_keyid = WMI_TLV_VDEV_PARAM_DEF_KEYID,
4472     .nss = WMI_TLV_VDEV_PARAM_NSS,
4473     .bcast_data_rate = WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE,
4474     .mcast_data_rate = WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE,
4475     .mcast_indicate = WMI_TLV_VDEV_PARAM_MCAST_INDICATE,
4476     .dhcp_indicate = WMI_TLV_VDEV_PARAM_DHCP_INDICATE,
4477     .unknown_dest_indicate = WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
4478     .ap_keepalive_min_idle_inactive_time_secs =
4479         WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
4480     .ap_keepalive_max_idle_inactive_time_secs =
4481         WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
4482     .ap_keepalive_max_unresponsive_time_secs =
4483         WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
4484     .ap_enable_nawds = WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS,
4485     .mcast2ucast_set = WMI_TLV_VDEV_PARAM_UNSUPPORTED,
4486     .enable_rtscts = WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS,
4487     .txbf = WMI_TLV_VDEV_PARAM_TXBF,
4488     .packet_powersave = WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE,
4489     .drop_unencry = WMI_TLV_VDEV_PARAM_DROP_UNENCRY,
4490     .tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
4491     .ap_detect_out_of_sync_sleeping_sta_time_secs =
4492                     WMI_TLV_VDEV_PARAM_UNSUPPORTED,
4493     .rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
4494     .cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
4495     .mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
4496     .rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
4497     .vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
4498     .vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
4499     .early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
4500     .early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
4501     .early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
4502     .early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
4503     .early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
4504     .early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
4505     .proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
4506     .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
4507     .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
4508     .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
4509 };
4510 
4511 static const struct wmi_ops wmi_tlv_ops = {
4512     .rx = ath10k_wmi_tlv_op_rx,
4513     .map_svc = wmi_tlv_svc_map,
4514     .map_svc_ext = wmi_tlv_svc_map_ext,
4515 
4516     .pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
4517     .pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
4518     .pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev,
4519     .pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev,
4520     .pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
4521     .pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
4522     .pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
4523     .pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
4524     .pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
4525     .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
4526     .pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
4527     .pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
4528     .pull_svc_avail = ath10k_wmi_tlv_op_pull_svc_avail,
4529     .pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
4530     .pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
4531     .pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
4532     .pull_echo_ev = ath10k_wmi_tlv_op_pull_echo_ev,
4533     .get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
4534 
4535     .gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
4536     .gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
4537     .gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
4538     .gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
4539     .gen_init = ath10k_wmi_tlv_op_gen_init,
4540     .gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
4541     .gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
4542     .gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
4543     .gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
4544     .gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
4545     .gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
4546     .gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
4547     .gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
4548     .gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
4549     .gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
4550     .gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
4551     .gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
4552     .gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
4553     .gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
4554     .gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
4555     .gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
4556     .gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
4557     .gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
4558     .gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
4559     .gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
4560     .gen_scan_prob_req_oui = ath10k_wmi_tlv_op_gen_scan_prob_req_oui,
4561     .gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
4562     .gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
4563     .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
4564     .gen_request_peer_stats_info = ath10k_wmi_tlv_op_gen_request_peer_stats_info,
4565     .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
4566     /* .gen_mgmt_tx = not implemented; HTT is used */
4567     .gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send,
4568     .cleanup_mgmt_tx_send = ath10k_wmi_tlv_op_cleanup_mgmt_tx_send,
4569     .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
4570     .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
4571     .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
4572     .gen_pdev_set_quiet_mode = ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode,
4573     .gen_pdev_get_temperature = ath10k_wmi_tlv_op_gen_pdev_get_temperature,
4574     /* .gen_addba_clear_resp not implemented */
4575     /* .gen_addba_send not implemented */
4576     /* .gen_addba_set_resp not implemented */
4577     /* .gen_delba_send not implemented */
4578     .gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
4579     .gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
4580     .gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
4581     .gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
4582     .gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
4583     .gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
4584     .gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
4585     .gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
4586     .gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
4587     .gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
4588     .gen_wow_config_pno = ath10k_wmi_tlv_op_gen_config_pno,
4589     .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
4590     .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
4591     .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
4592     .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
4593     .get_vdev_subtype = ath10k_wmi_tlv_op_get_vdev_subtype,
4594     .gen_echo = ath10k_wmi_tlv_op_gen_echo,
4595     .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
4596     .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
4597 };
4598 
4599 static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
4600     .auth = WMI_TLV_PEER_AUTH,
4601     .qos = WMI_TLV_PEER_QOS,
4602     .need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
4603     .need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
4604     .apsd = WMI_TLV_PEER_APSD,
4605     .ht = WMI_TLV_PEER_HT,
4606     .bw40 = WMI_TLV_PEER_40MHZ,
4607     .stbc = WMI_TLV_PEER_STBC,
4608     .ldbc = WMI_TLV_PEER_LDPC,
4609     .dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
4610     .static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
4611     .spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
4612     .vht = WMI_TLV_PEER_VHT,
4613     .bw80 = WMI_TLV_PEER_80MHZ,
4614     .pmf = WMI_TLV_PEER_PMF,
4615     .bw160 = WMI_TLV_PEER_160MHZ,
4616 };
4617 
4618 /************/
4619 /* TLV init */
4620 /************/
4621 
4622 void ath10k_wmi_tlv_attach(struct ath10k *ar)
4623 {
4624     ar->wmi.cmd = &wmi_tlv_cmd_map;
4625     ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
4626     ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
4627     ar->wmi.peer_param = &wmi_tlv_peer_param_map;
4628     ar->wmi.ops = &wmi_tlv_ops;
4629     ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
4630 }