162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2005-2011 Atheros Communications Inc.
462306a36Sopenharmony_ci * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
562306a36Sopenharmony_ci * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include "core.h"
862306a36Sopenharmony_ci#include "debug.h"
962306a36Sopenharmony_ci#include "mac.h"
1062306a36Sopenharmony_ci#include "hw.h"
1162306a36Sopenharmony_ci#include "wmi.h"
1262306a36Sopenharmony_ci#include "wmi-ops.h"
1362306a36Sopenharmony_ci#include "wmi-tlv.h"
1462306a36Sopenharmony_ci#include "p2p.h"
1562306a36Sopenharmony_ci#include "testmode.h"
1662306a36Sopenharmony_ci#include <linux/bitfield.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/***************/
1962306a36Sopenharmony_ci/* TLV helpers */
2062306a36Sopenharmony_ci/**************/
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct wmi_tlv_policy {
2362306a36Sopenharmony_ci	size_t min_len;
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic const struct wmi_tlv_policy wmi_tlv_policies[] = {
2762306a36Sopenharmony_ci	[WMI_TLV_TAG_ARRAY_BYTE]
2862306a36Sopenharmony_ci		= { .min_len = 0 },
2962306a36Sopenharmony_ci	[WMI_TLV_TAG_ARRAY_UINT32]
3062306a36Sopenharmony_ci		= { .min_len = 0 },
3162306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_SCAN_EVENT]
3262306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_scan_event) },
3362306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR]
3462306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_mgmt_rx_ev) },
3562306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT]
3662306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_chan_info_event) },
3762306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT]
3862306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_vdev_start_response_event) },
3962306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT]
4062306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_peer_sta_kickout_event) },
4162306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT]
4262306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_host_swba_event) },
4362306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_TIM_INFO]
4462306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tim_info) },
4562306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO]
4662306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_p2p_noa_info) },
4762306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT]
4862306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_svc_rdy_ev) },
4962306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES]
5062306a36Sopenharmony_ci		= { .min_len = sizeof(struct hal_reg_capabilities) },
5162306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ]
5262306a36Sopenharmony_ci		= { .min_len = sizeof(struct wlan_host_mem_req) },
5362306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_READY_EVENT]
5462306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_rdy_ev) },
5562306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]
5662306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
5762306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
5862306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
5962306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
6062306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_p2p_noa_ev) },
6162306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_ROAM_EVENT]
6262306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_roam_ev) },
6362306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO]
6462306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_wow_event_info) },
6562306a36Sopenharmony_ci	[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT]
6662306a36Sopenharmony_ci		= { .min_len = sizeof(struct wmi_tlv_tx_pause_ev) },
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic int
7062306a36Sopenharmony_ciath10k_wmi_tlv_iter(struct ath10k *ar, const void *ptr, size_t len,
7162306a36Sopenharmony_ci		    int (*iter)(struct ath10k *ar, u16 tag, u16 len,
7262306a36Sopenharmony_ci				const void *ptr, void *data),
7362306a36Sopenharmony_ci		    void *data)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	const void *begin = ptr;
7662306a36Sopenharmony_ci	const struct wmi_tlv *tlv;
7762306a36Sopenharmony_ci	u16 tlv_tag, tlv_len;
7862306a36Sopenharmony_ci	int ret;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	while (len > 0) {
8162306a36Sopenharmony_ci		if (len < sizeof(*tlv)) {
8262306a36Sopenharmony_ci			ath10k_dbg(ar, ATH10K_DBG_WMI,
8362306a36Sopenharmony_ci				   "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
8462306a36Sopenharmony_ci				   ptr - begin, len, sizeof(*tlv));
8562306a36Sopenharmony_ci			return -EINVAL;
8662306a36Sopenharmony_ci		}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci		tlv = ptr;
8962306a36Sopenharmony_ci		tlv_tag = __le16_to_cpu(tlv->tag);
9062306a36Sopenharmony_ci		tlv_len = __le16_to_cpu(tlv->len);
9162306a36Sopenharmony_ci		ptr += sizeof(*tlv);
9262306a36Sopenharmony_ci		len -= sizeof(*tlv);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci		if (tlv_len > len) {
9562306a36Sopenharmony_ci			ath10k_dbg(ar, ATH10K_DBG_WMI,
9662306a36Sopenharmony_ci				   "wmi tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",
9762306a36Sopenharmony_ci				   tlv_tag, ptr - begin, len, tlv_len);
9862306a36Sopenharmony_ci			return -EINVAL;
9962306a36Sopenharmony_ci		}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci		if (tlv_tag < ARRAY_SIZE(wmi_tlv_policies) &&
10262306a36Sopenharmony_ci		    wmi_tlv_policies[tlv_tag].min_len &&
10362306a36Sopenharmony_ci		    wmi_tlv_policies[tlv_tag].min_len > tlv_len) {
10462306a36Sopenharmony_ci			ath10k_dbg(ar, ATH10K_DBG_WMI,
10562306a36Sopenharmony_ci				   "wmi tlv parse failure of tag %u at byte %zd (%u bytes is less than min length %zu)\n",
10662306a36Sopenharmony_ci				   tlv_tag, ptr - begin, tlv_len,
10762306a36Sopenharmony_ci				   wmi_tlv_policies[tlv_tag].min_len);
10862306a36Sopenharmony_ci			return -EINVAL;
10962306a36Sopenharmony_ci		}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		ret = iter(ar, tlv_tag, tlv_len, ptr, data);
11262306a36Sopenharmony_ci		if (ret)
11362306a36Sopenharmony_ci			return ret;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci		ptr += tlv_len;
11662306a36Sopenharmony_ci		len -= tlv_len;
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	return 0;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic int ath10k_wmi_tlv_iter_parse(struct ath10k *ar, u16 tag, u16 len,
12362306a36Sopenharmony_ci				     const void *ptr, void *data)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	const void **tb = data;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (tag < WMI_TLV_TAG_MAX)
12862306a36Sopenharmony_ci		tb[tag] = ptr;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	return 0;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic int ath10k_wmi_tlv_parse(struct ath10k *ar, const void **tb,
13462306a36Sopenharmony_ci				const void *ptr, size_t len)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	return ath10k_wmi_tlv_iter(ar, ptr, len, ath10k_wmi_tlv_iter_parse,
13762306a36Sopenharmony_ci				   (void *)tb);
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic const void **
14162306a36Sopenharmony_ciath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
14262306a36Sopenharmony_ci			   size_t len, gfp_t gfp)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	const void **tb;
14562306a36Sopenharmony_ci	int ret;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	tb = kcalloc(WMI_TLV_TAG_MAX, sizeof(*tb), gfp);
14862306a36Sopenharmony_ci	if (!tb)
14962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	ret = ath10k_wmi_tlv_parse(ar, tb, ptr, len);
15262306a36Sopenharmony_ci	if (ret) {
15362306a36Sopenharmony_ci		kfree(tb);
15462306a36Sopenharmony_ci		return ERR_PTR(ret);
15562306a36Sopenharmony_ci	}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	return tb;
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic u16 ath10k_wmi_tlv_len(const void *ptr)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/**************/
16662306a36Sopenharmony_ci/* TLV events */
16762306a36Sopenharmony_ci/**************/
16862306a36Sopenharmony_cistatic int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
16962306a36Sopenharmony_ci					      struct sk_buff *skb)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	const void **tb;
17262306a36Sopenharmony_ci	const struct wmi_tlv_bcn_tx_status_ev *ev;
17362306a36Sopenharmony_ci	struct ath10k_vif *arvif;
17462306a36Sopenharmony_ci	u32 vdev_id, tx_status;
17562306a36Sopenharmony_ci	int ret;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
17862306a36Sopenharmony_ci	if (IS_ERR(tb)) {
17962306a36Sopenharmony_ci		ret = PTR_ERR(tb);
18062306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
18162306a36Sopenharmony_ci		return ret;
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT];
18562306a36Sopenharmony_ci	if (!ev) {
18662306a36Sopenharmony_ci		kfree(tb);
18762306a36Sopenharmony_ci		return -EPROTO;
18862306a36Sopenharmony_ci	}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	tx_status = __le32_to_cpu(ev->tx_status);
19162306a36Sopenharmony_ci	vdev_id = __le32_to_cpu(ev->vdev_id);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	switch (tx_status) {
19462306a36Sopenharmony_ci	case WMI_TLV_BCN_TX_STATUS_OK:
19562306a36Sopenharmony_ci		break;
19662306a36Sopenharmony_ci	case WMI_TLV_BCN_TX_STATUS_XRETRY:
19762306a36Sopenharmony_ci	case WMI_TLV_BCN_TX_STATUS_DROP:
19862306a36Sopenharmony_ci	case WMI_TLV_BCN_TX_STATUS_FILTERED:
19962306a36Sopenharmony_ci		/* FIXME: It's probably worth telling mac80211 to stop the
20062306a36Sopenharmony_ci		 * interface as it is crippled.
20162306a36Sopenharmony_ci		 */
20262306a36Sopenharmony_ci		ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d",
20362306a36Sopenharmony_ci			    vdev_id, tx_status);
20462306a36Sopenharmony_ci		break;
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	arvif = ath10k_get_arvif(ar, vdev_id);
20862306a36Sopenharmony_ci	if (arvif && arvif->is_up && arvif->vif->bss_conf.csa_active)
20962306a36Sopenharmony_ci		ieee80211_queue_work(ar->hw, &arvif->ap_csa_work);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	kfree(tb);
21262306a36Sopenharmony_ci	return 0;
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistatic void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar,
21662306a36Sopenharmony_ci						  struct sk_buff *skb)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n");
21962306a36Sopenharmony_ci	complete(&ar->vdev_delete_done);
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 len,
22362306a36Sopenharmony_ci						const void *ptr, void *data)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	const struct wmi_tlv_peer_stats_info *stat = ptr;
22662306a36Sopenharmony_ci	struct ieee80211_sta *sta;
22762306a36Sopenharmony_ci	struct ath10k_sta *arsta;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
23062306a36Sopenharmony_ci		return -EPROTO;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
23362306a36Sopenharmony_ci		   "wmi tlv stats peer addr %pMF rx rate code 0x%x bit rate %d kbps\n",
23462306a36Sopenharmony_ci		   stat->peer_macaddr.addr,
23562306a36Sopenharmony_ci		   __le32_to_cpu(stat->last_rx_rate_code),
23662306a36Sopenharmony_ci		   __le32_to_cpu(stat->last_rx_bitrate_kbps));
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
23962306a36Sopenharmony_ci		   "wmi tlv stats tx rate code 0x%x bit rate %d kbps\n",
24062306a36Sopenharmony_ci		   __le32_to_cpu(stat->last_tx_rate_code),
24162306a36Sopenharmony_ci		   __le32_to_cpu(stat->last_tx_bitrate_kbps));
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	rcu_read_lock();
24462306a36Sopenharmony_ci	sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
24562306a36Sopenharmony_ci	if (!sta) {
24662306a36Sopenharmony_ci		rcu_read_unlock();
24762306a36Sopenharmony_ci		ath10k_warn(ar, "not found station for peer stats\n");
24862306a36Sopenharmony_ci		return -EINVAL;
24962306a36Sopenharmony_ci	}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	arsta = (struct ath10k_sta *)sta->drv_priv;
25262306a36Sopenharmony_ci	arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
25362306a36Sopenharmony_ci	arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
25462306a36Sopenharmony_ci	arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
25562306a36Sopenharmony_ci	arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
25662306a36Sopenharmony_ci	rcu_read_unlock();
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	return 0;
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
26262306a36Sopenharmony_ci						  struct sk_buff *skb)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	const void **tb;
26562306a36Sopenharmony_ci	const struct wmi_tlv_peer_stats_info_ev *ev;
26662306a36Sopenharmony_ci	const void *data;
26762306a36Sopenharmony_ci	u32 num_peer_stats;
26862306a36Sopenharmony_ci	int ret;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
27162306a36Sopenharmony_ci	if (IS_ERR(tb)) {
27262306a36Sopenharmony_ci		ret = PTR_ERR(tb);
27362306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
27462306a36Sopenharmony_ci		return ret;
27562306a36Sopenharmony_ci	}
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STATS_INFO_EVENT];
27862306a36Sopenharmony_ci	data = tb[WMI_TLV_TAG_ARRAY_STRUCT];
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	if (!ev || !data) {
28162306a36Sopenharmony_ci		kfree(tb);
28262306a36Sopenharmony_ci		return -EPROTO;
28362306a36Sopenharmony_ci	}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	num_peer_stats = __le32_to_cpu(ev->num_peers);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
28862306a36Sopenharmony_ci		   "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
28962306a36Sopenharmony_ci		   __le32_to_cpu(ev->vdev_id),
29062306a36Sopenharmony_ci		   num_peer_stats,
29162306a36Sopenharmony_ci		   __le32_to_cpu(ev->more_data));
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
29462306a36Sopenharmony_ci				  ath10k_wmi_tlv_parse_peer_stats_info, NULL);
29562306a36Sopenharmony_ci	if (ret)
29662306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	kfree(tb);
29962306a36Sopenharmony_ci	return 0;
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistatic void ath10k_wmi_tlv_event_peer_stats_info(struct ath10k *ar,
30362306a36Sopenharmony_ci						 struct sk_buff *skb)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PEER_STATS_INFO_EVENTID\n");
30662306a36Sopenharmony_ci	ath10k_wmi_tlv_op_pull_peer_stats_info(ar, skb);
30762306a36Sopenharmony_ci	complete(&ar->peer_stats_info_complete);
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
31162306a36Sopenharmony_ci					  struct sk_buff *skb)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	const void **tb;
31462306a36Sopenharmony_ci	const struct wmi_tlv_diag_data_ev *ev;
31562306a36Sopenharmony_ci	const struct wmi_tlv_diag_item *item;
31662306a36Sopenharmony_ci	const void *data;
31762306a36Sopenharmony_ci	int ret, num_items, len;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
32062306a36Sopenharmony_ci	if (IS_ERR(tb)) {
32162306a36Sopenharmony_ci		ret = PTR_ERR(tb);
32262306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
32362306a36Sopenharmony_ci		return ret;
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT];
32762306a36Sopenharmony_ci	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
32862306a36Sopenharmony_ci	if (!ev || !data) {
32962306a36Sopenharmony_ci		kfree(tb);
33062306a36Sopenharmony_ci		return -EPROTO;
33162306a36Sopenharmony_ci	}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	num_items = __le32_to_cpu(ev->num_items);
33462306a36Sopenharmony_ci	len = ath10k_wmi_tlv_len(data);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	while (num_items--) {
33762306a36Sopenharmony_ci		if (len == 0)
33862306a36Sopenharmony_ci			break;
33962306a36Sopenharmony_ci		if (len < sizeof(*item)) {
34062306a36Sopenharmony_ci			ath10k_warn(ar, "failed to parse diag data: can't fit item header\n");
34162306a36Sopenharmony_ci			break;
34262306a36Sopenharmony_ci		}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci		item = data;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci		if (len < sizeof(*item) + __le16_to_cpu(item->len)) {
34762306a36Sopenharmony_ci			ath10k_warn(ar, "failed to parse diag data: item is too long\n");
34862306a36Sopenharmony_ci			break;
34962306a36Sopenharmony_ci		}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci		trace_ath10k_wmi_diag_container(ar,
35262306a36Sopenharmony_ci						item->type,
35362306a36Sopenharmony_ci						__le32_to_cpu(item->timestamp),
35462306a36Sopenharmony_ci						__le32_to_cpu(item->code),
35562306a36Sopenharmony_ci						__le16_to_cpu(item->len),
35662306a36Sopenharmony_ci						item->payload);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci		len -= sizeof(*item);
35962306a36Sopenharmony_ci		len -= roundup(__le16_to_cpu(item->len), 4);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci		data += sizeof(*item);
36262306a36Sopenharmony_ci		data += roundup(__le16_to_cpu(item->len), 4);
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	if (num_items != -1 || len != 0)
36662306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n",
36762306a36Sopenharmony_ci			    num_items, len);
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	kfree(tb);
37062306a36Sopenharmony_ci	return 0;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
37462306a36Sopenharmony_ci				     struct sk_buff *skb)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	const void **tb;
37762306a36Sopenharmony_ci	const void *data;
37862306a36Sopenharmony_ci	int ret, len;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
38162306a36Sopenharmony_ci	if (IS_ERR(tb)) {
38262306a36Sopenharmony_ci		ret = PTR_ERR(tb);
38362306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
38462306a36Sopenharmony_ci		return ret;
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
38862306a36Sopenharmony_ci	if (!data) {
38962306a36Sopenharmony_ci		kfree(tb);
39062306a36Sopenharmony_ci		return -EPROTO;
39162306a36Sopenharmony_ci	}
39262306a36Sopenharmony_ci	len = ath10k_wmi_tlv_len(data);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len);
39562306a36Sopenharmony_ci	trace_ath10k_wmi_diag(ar, data, len);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	kfree(tb);
39862306a36Sopenharmony_ci	return 0;
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic int ath10k_wmi_tlv_event_p2p_noa(struct ath10k *ar,
40262306a36Sopenharmony_ci					struct sk_buff *skb)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	const void **tb;
40562306a36Sopenharmony_ci	const struct wmi_tlv_p2p_noa_ev *ev;
40662306a36Sopenharmony_ci	const struct wmi_p2p_noa_info *noa;
40762306a36Sopenharmony_ci	int ret, vdev_id;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
41062306a36Sopenharmony_ci	if (IS_ERR(tb)) {
41162306a36Sopenharmony_ci		ret = PTR_ERR(tb);
41262306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
41362306a36Sopenharmony_ci		return ret;
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT];
41762306a36Sopenharmony_ci	noa = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO];
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	if (!ev || !noa) {
42062306a36Sopenharmony_ci		kfree(tb);
42162306a36Sopenharmony_ci		return -EPROTO;
42262306a36Sopenharmony_ci	}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	vdev_id = __le32_to_cpu(ev->vdev_id);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
42762306a36Sopenharmony_ci		   "wmi tlv p2p noa vdev_id %i descriptors %u\n",
42862306a36Sopenharmony_ci		   vdev_id, noa->num_descriptors);
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	ath10k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
43162306a36Sopenharmony_ci	kfree(tb);
43262306a36Sopenharmony_ci	return 0;
43362306a36Sopenharmony_ci}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_cistatic int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
43662306a36Sopenharmony_ci					 struct sk_buff *skb)
43762306a36Sopenharmony_ci{
43862306a36Sopenharmony_ci	const void **tb;
43962306a36Sopenharmony_ci	const struct wmi_tlv_tx_pause_ev *ev;
44062306a36Sopenharmony_ci	int ret, vdev_id;
44162306a36Sopenharmony_ci	u32 pause_id, action, vdev_map, peer_id, tid_map;
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
44462306a36Sopenharmony_ci	if (IS_ERR(tb)) {
44562306a36Sopenharmony_ci		ret = PTR_ERR(tb);
44662306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
44762306a36Sopenharmony_ci		return ret;
44862306a36Sopenharmony_ci	}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT];
45162306a36Sopenharmony_ci	if (!ev) {
45262306a36Sopenharmony_ci		kfree(tb);
45362306a36Sopenharmony_ci		return -EPROTO;
45462306a36Sopenharmony_ci	}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	pause_id = __le32_to_cpu(ev->pause_id);
45762306a36Sopenharmony_ci	action = __le32_to_cpu(ev->action);
45862306a36Sopenharmony_ci	vdev_map = __le32_to_cpu(ev->vdev_map);
45962306a36Sopenharmony_ci	peer_id = __le32_to_cpu(ev->peer_id);
46062306a36Sopenharmony_ci	tid_map = __le32_to_cpu(ev->tid_map);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
46362306a36Sopenharmony_ci		   "wmi tlv tx pause pause_id %u action %u vdev_map 0x%08x peer_id %u tid_map 0x%08x\n",
46462306a36Sopenharmony_ci		   pause_id, action, vdev_map, peer_id, tid_map);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	switch (pause_id) {
46762306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_MCC:
46862306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
46962306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
47062306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_AP_PS:
47162306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
47262306a36Sopenharmony_ci		for (vdev_id = 0; vdev_map; vdev_id++) {
47362306a36Sopenharmony_ci			if (!(vdev_map & BIT(vdev_id)))
47462306a36Sopenharmony_ci				continue;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci			vdev_map &= ~BIT(vdev_id);
47762306a36Sopenharmony_ci			ath10k_mac_handle_tx_pause_vdev(ar, vdev_id, pause_id,
47862306a36Sopenharmony_ci							action);
47962306a36Sopenharmony_ci		}
48062306a36Sopenharmony_ci		break;
48162306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
48262306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
48362306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
48462306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_ID_HOST:
48562306a36Sopenharmony_ci		ath10k_dbg(ar, ATH10K_DBG_MAC,
48662306a36Sopenharmony_ci			   "mac ignoring unsupported tx pause id %d\n",
48762306a36Sopenharmony_ci			   pause_id);
48862306a36Sopenharmony_ci		break;
48962306a36Sopenharmony_ci	default:
49062306a36Sopenharmony_ci		ath10k_dbg(ar, ATH10K_DBG_MAC,
49162306a36Sopenharmony_ci			   "mac ignoring unknown tx pause vdev %d\n",
49262306a36Sopenharmony_ci			   pause_id);
49362306a36Sopenharmony_ci		break;
49462306a36Sopenharmony_ci	}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	kfree(tb);
49762306a36Sopenharmony_ci	return 0;
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_cistatic void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
50162306a36Sopenharmony_ci						     struct sk_buff *skb)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	const struct wmi_tlv_rfkill_state_change_ev *ev;
50462306a36Sopenharmony_ci	const void **tb;
50562306a36Sopenharmony_ci	bool radio;
50662306a36Sopenharmony_ci	int ret;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
50962306a36Sopenharmony_ci	if (IS_ERR(tb)) {
51062306a36Sopenharmony_ci		ret = PTR_ERR(tb);
51162306a36Sopenharmony_ci		ath10k_warn(ar,
51262306a36Sopenharmony_ci			    "failed to parse rfkill state change event: %d\n",
51362306a36Sopenharmony_ci			    ret);
51462306a36Sopenharmony_ci		return;
51562306a36Sopenharmony_ci	}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
51862306a36Sopenharmony_ci	if (!ev) {
51962306a36Sopenharmony_ci		kfree(tb);
52062306a36Sopenharmony_ci		return;
52162306a36Sopenharmony_ci	}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_MAC,
52462306a36Sopenharmony_ci		   "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
52562306a36Sopenharmony_ci		   __le32_to_cpu(ev->gpio_pin_num),
52662306a36Sopenharmony_ci		   __le32_to_cpu(ev->int_type),
52762306a36Sopenharmony_ci		   __le32_to_cpu(ev->radio_state));
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	spin_lock_bh(&ar->data_lock);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (!radio)
53462306a36Sopenharmony_ci		ar->hw_rfkill_on = true;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	spin_unlock_bh(&ar->data_lock);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	/* notify cfg80211 radio state change */
53962306a36Sopenharmony_ci	ath10k_mac_rfkill_enable_radio(ar, radio);
54062306a36Sopenharmony_ci	wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_cistatic int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
54462306a36Sopenharmony_ci					    struct sk_buff *skb)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	const struct wmi_tlv_pdev_temperature_event *ev;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	ev = (struct wmi_tlv_pdev_temperature_event *)skb->data;
54962306a36Sopenharmony_ci	if (WARN_ON(skb->len < sizeof(*ev)))
55062306a36Sopenharmony_ci		return -EPROTO;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	ath10k_thermal_event_temperature(ar, __le32_to_cpu(ev->temperature));
55362306a36Sopenharmony_ci	return 0;
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_cistatic void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	struct ieee80211_sta *station;
55962306a36Sopenharmony_ci	const struct wmi_tlv_tdls_peer_event *ev;
56062306a36Sopenharmony_ci	const void **tb;
56162306a36Sopenharmony_ci	struct ath10k_vif *arvif;
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
56462306a36Sopenharmony_ci	if (IS_ERR(tb)) {
56562306a36Sopenharmony_ci		ath10k_warn(ar, "tdls peer failed to parse tlv");
56662306a36Sopenharmony_ci		return;
56762306a36Sopenharmony_ci	}
56862306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT];
56962306a36Sopenharmony_ci	if (!ev) {
57062306a36Sopenharmony_ci		kfree(tb);
57162306a36Sopenharmony_ci		ath10k_warn(ar, "tdls peer NULL event");
57262306a36Sopenharmony_ci		return;
57362306a36Sopenharmony_ci	}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	switch (__le32_to_cpu(ev->peer_reason)) {
57662306a36Sopenharmony_ci	case WMI_TDLS_TEARDOWN_REASON_TX:
57762306a36Sopenharmony_ci	case WMI_TDLS_TEARDOWN_REASON_RSSI:
57862306a36Sopenharmony_ci	case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
57962306a36Sopenharmony_ci		rcu_read_lock();
58062306a36Sopenharmony_ci		station = ieee80211_find_sta_by_ifaddr(ar->hw,
58162306a36Sopenharmony_ci						       ev->peer_macaddr.addr,
58262306a36Sopenharmony_ci						       NULL);
58362306a36Sopenharmony_ci		if (!station) {
58462306a36Sopenharmony_ci			ath10k_warn(ar, "did not find station from tdls peer event");
58562306a36Sopenharmony_ci			goto exit;
58662306a36Sopenharmony_ci		}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci		arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
58962306a36Sopenharmony_ci		if (!arvif) {
59062306a36Sopenharmony_ci			ath10k_warn(ar, "no vif for vdev_id %d found",
59162306a36Sopenharmony_ci				    __le32_to_cpu(ev->vdev_id));
59262306a36Sopenharmony_ci			goto exit;
59362306a36Sopenharmony_ci		}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci		ieee80211_tdls_oper_request(
59662306a36Sopenharmony_ci					arvif->vif, station->addr,
59762306a36Sopenharmony_ci					NL80211_TDLS_TEARDOWN,
59862306a36Sopenharmony_ci					WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
59962306a36Sopenharmony_ci					GFP_ATOMIC
60062306a36Sopenharmony_ci					);
60162306a36Sopenharmony_ci		break;
60262306a36Sopenharmony_ci	default:
60362306a36Sopenharmony_ci		kfree(tb);
60462306a36Sopenharmony_ci		return;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ciexit:
60862306a36Sopenharmony_ci	rcu_read_unlock();
60962306a36Sopenharmony_ci	kfree(tb);
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
61362306a36Sopenharmony_ci						 struct sk_buff *skb)
61462306a36Sopenharmony_ci{
61562306a36Sopenharmony_ci	struct wmi_peer_delete_resp_ev_arg *arg;
61662306a36Sopenharmony_ci	struct wmi_tlv *tlv_hdr;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	tlv_hdr = (struct wmi_tlv *)skb->data;
61962306a36Sopenharmony_ci	arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id);
62262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr);
62362306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n");
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	complete(&ar->peer_delete_done);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	return 0;
62862306a36Sopenharmony_ci}
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci/***********/
63162306a36Sopenharmony_ci/* TLV ops */
63262306a36Sopenharmony_ci/***********/
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_cistatic void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
63562306a36Sopenharmony_ci{
63662306a36Sopenharmony_ci	struct wmi_cmd_hdr *cmd_hdr;
63762306a36Sopenharmony_ci	enum wmi_tlv_event_id id;
63862306a36Sopenharmony_ci	bool consumed;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
64162306a36Sopenharmony_ci	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
64462306a36Sopenharmony_ci		goto out;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	consumed = ath10k_tm_event_wmi(ar, id, skb);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	/* Ready event must be handled normally also in UTF mode so that we
65162306a36Sopenharmony_ci	 * know the UTF firmware has booted, others we are just bypass WMI
65262306a36Sopenharmony_ci	 * events to testmode.
65362306a36Sopenharmony_ci	 */
65462306a36Sopenharmony_ci	if (consumed && id != WMI_TLV_READY_EVENTID) {
65562306a36Sopenharmony_ci		ath10k_dbg(ar, ATH10K_DBG_WMI,
65662306a36Sopenharmony_ci			   "wmi tlv testmode consumed 0x%x\n", id);
65762306a36Sopenharmony_ci		goto out;
65862306a36Sopenharmony_ci	}
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	switch (id) {
66162306a36Sopenharmony_ci	case WMI_TLV_MGMT_RX_EVENTID:
66262306a36Sopenharmony_ci		ath10k_wmi_event_mgmt_rx(ar, skb);
66362306a36Sopenharmony_ci		/* mgmt_rx() owns the skb now! */
66462306a36Sopenharmony_ci		return;
66562306a36Sopenharmony_ci	case WMI_TLV_SCAN_EVENTID:
66662306a36Sopenharmony_ci		ath10k_wmi_event_scan(ar, skb);
66762306a36Sopenharmony_ci		break;
66862306a36Sopenharmony_ci	case WMI_TLV_CHAN_INFO_EVENTID:
66962306a36Sopenharmony_ci		ath10k_wmi_event_chan_info(ar, skb);
67062306a36Sopenharmony_ci		break;
67162306a36Sopenharmony_ci	case WMI_TLV_ECHO_EVENTID:
67262306a36Sopenharmony_ci		ath10k_wmi_event_echo(ar, skb);
67362306a36Sopenharmony_ci		break;
67462306a36Sopenharmony_ci	case WMI_TLV_DEBUG_MESG_EVENTID:
67562306a36Sopenharmony_ci		ath10k_wmi_event_debug_mesg(ar, skb);
67662306a36Sopenharmony_ci		break;
67762306a36Sopenharmony_ci	case WMI_TLV_UPDATE_STATS_EVENTID:
67862306a36Sopenharmony_ci		ath10k_wmi_event_update_stats(ar, skb);
67962306a36Sopenharmony_ci		break;
68062306a36Sopenharmony_ci	case WMI_TLV_PEER_STATS_INFO_EVENTID:
68162306a36Sopenharmony_ci		ath10k_wmi_tlv_event_peer_stats_info(ar, skb);
68262306a36Sopenharmony_ci		break;
68362306a36Sopenharmony_ci	case WMI_TLV_VDEV_START_RESP_EVENTID:
68462306a36Sopenharmony_ci		ath10k_wmi_event_vdev_start_resp(ar, skb);
68562306a36Sopenharmony_ci		break;
68662306a36Sopenharmony_ci	case WMI_TLV_VDEV_STOPPED_EVENTID:
68762306a36Sopenharmony_ci		ath10k_wmi_event_vdev_stopped(ar, skb);
68862306a36Sopenharmony_ci		break;
68962306a36Sopenharmony_ci	case WMI_TLV_VDEV_DELETE_RESP_EVENTID:
69062306a36Sopenharmony_ci		ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb);
69162306a36Sopenharmony_ci		break;
69262306a36Sopenharmony_ci	case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
69362306a36Sopenharmony_ci		ath10k_wmi_event_peer_sta_kickout(ar, skb);
69462306a36Sopenharmony_ci		break;
69562306a36Sopenharmony_ci	case WMI_TLV_HOST_SWBA_EVENTID:
69662306a36Sopenharmony_ci		ath10k_wmi_event_host_swba(ar, skb);
69762306a36Sopenharmony_ci		break;
69862306a36Sopenharmony_ci	case WMI_TLV_TBTTOFFSET_UPDATE_EVENTID:
69962306a36Sopenharmony_ci		ath10k_wmi_event_tbttoffset_update(ar, skb);
70062306a36Sopenharmony_ci		break;
70162306a36Sopenharmony_ci	case WMI_TLV_PHYERR_EVENTID:
70262306a36Sopenharmony_ci		ath10k_wmi_event_phyerr(ar, skb);
70362306a36Sopenharmony_ci		break;
70462306a36Sopenharmony_ci	case WMI_TLV_ROAM_EVENTID:
70562306a36Sopenharmony_ci		ath10k_wmi_event_roam(ar, skb);
70662306a36Sopenharmony_ci		break;
70762306a36Sopenharmony_ci	case WMI_TLV_PROFILE_MATCH:
70862306a36Sopenharmony_ci		ath10k_wmi_event_profile_match(ar, skb);
70962306a36Sopenharmony_ci		break;
71062306a36Sopenharmony_ci	case WMI_TLV_DEBUG_PRINT_EVENTID:
71162306a36Sopenharmony_ci		ath10k_wmi_event_debug_print(ar, skb);
71262306a36Sopenharmony_ci		break;
71362306a36Sopenharmony_ci	case WMI_TLV_PDEV_QVIT_EVENTID:
71462306a36Sopenharmony_ci		ath10k_wmi_event_pdev_qvit(ar, skb);
71562306a36Sopenharmony_ci		break;
71662306a36Sopenharmony_ci	case WMI_TLV_WLAN_PROFILE_DATA_EVENTID:
71762306a36Sopenharmony_ci		ath10k_wmi_event_wlan_profile_data(ar, skb);
71862306a36Sopenharmony_ci		break;
71962306a36Sopenharmony_ci	case WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID:
72062306a36Sopenharmony_ci		ath10k_wmi_event_rtt_measurement_report(ar, skb);
72162306a36Sopenharmony_ci		break;
72262306a36Sopenharmony_ci	case WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID:
72362306a36Sopenharmony_ci		ath10k_wmi_event_tsf_measurement_report(ar, skb);
72462306a36Sopenharmony_ci		break;
72562306a36Sopenharmony_ci	case WMI_TLV_RTT_ERROR_REPORT_EVENTID:
72662306a36Sopenharmony_ci		ath10k_wmi_event_rtt_error_report(ar, skb);
72762306a36Sopenharmony_ci		break;
72862306a36Sopenharmony_ci	case WMI_TLV_WOW_WAKEUP_HOST_EVENTID:
72962306a36Sopenharmony_ci		ath10k_wmi_event_wow_wakeup_host(ar, skb);
73062306a36Sopenharmony_ci		break;
73162306a36Sopenharmony_ci	case WMI_TLV_DCS_INTERFERENCE_EVENTID:
73262306a36Sopenharmony_ci		ath10k_wmi_event_dcs_interference(ar, skb);
73362306a36Sopenharmony_ci		break;
73462306a36Sopenharmony_ci	case WMI_TLV_PDEV_TPC_CONFIG_EVENTID:
73562306a36Sopenharmony_ci		ath10k_wmi_event_pdev_tpc_config(ar, skb);
73662306a36Sopenharmony_ci		break;
73762306a36Sopenharmony_ci	case WMI_TLV_PDEV_FTM_INTG_EVENTID:
73862306a36Sopenharmony_ci		ath10k_wmi_event_pdev_ftm_intg(ar, skb);
73962306a36Sopenharmony_ci		break;
74062306a36Sopenharmony_ci	case WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID:
74162306a36Sopenharmony_ci		ath10k_wmi_event_gtk_offload_status(ar, skb);
74262306a36Sopenharmony_ci		break;
74362306a36Sopenharmony_ci	case WMI_TLV_GTK_REKEY_FAIL_EVENTID:
74462306a36Sopenharmony_ci		ath10k_wmi_event_gtk_rekey_fail(ar, skb);
74562306a36Sopenharmony_ci		break;
74662306a36Sopenharmony_ci	case WMI_TLV_TX_DELBA_COMPLETE_EVENTID:
74762306a36Sopenharmony_ci		ath10k_wmi_event_delba_complete(ar, skb);
74862306a36Sopenharmony_ci		break;
74962306a36Sopenharmony_ci	case WMI_TLV_TX_ADDBA_COMPLETE_EVENTID:
75062306a36Sopenharmony_ci		ath10k_wmi_event_addba_complete(ar, skb);
75162306a36Sopenharmony_ci		break;
75262306a36Sopenharmony_ci	case WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID:
75362306a36Sopenharmony_ci		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
75462306a36Sopenharmony_ci		break;
75562306a36Sopenharmony_ci	case WMI_TLV_SERVICE_READY_EVENTID:
75662306a36Sopenharmony_ci		ath10k_wmi_event_service_ready(ar, skb);
75762306a36Sopenharmony_ci		return;
75862306a36Sopenharmony_ci	case WMI_TLV_READY_EVENTID:
75962306a36Sopenharmony_ci		ath10k_wmi_event_ready(ar, skb);
76062306a36Sopenharmony_ci		break;
76162306a36Sopenharmony_ci	case WMI_TLV_SERVICE_AVAILABLE_EVENTID:
76262306a36Sopenharmony_ci		ath10k_wmi_event_service_available(ar, skb);
76362306a36Sopenharmony_ci		break;
76462306a36Sopenharmony_ci	case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID:
76562306a36Sopenharmony_ci		ath10k_wmi_tlv_event_bcn_tx_status(ar, skb);
76662306a36Sopenharmony_ci		break;
76762306a36Sopenharmony_ci	case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID:
76862306a36Sopenharmony_ci		ath10k_wmi_tlv_event_diag_data(ar, skb);
76962306a36Sopenharmony_ci		break;
77062306a36Sopenharmony_ci	case WMI_TLV_DIAG_EVENTID:
77162306a36Sopenharmony_ci		ath10k_wmi_tlv_event_diag(ar, skb);
77262306a36Sopenharmony_ci		break;
77362306a36Sopenharmony_ci	case WMI_TLV_P2P_NOA_EVENTID:
77462306a36Sopenharmony_ci		ath10k_wmi_tlv_event_p2p_noa(ar, skb);
77562306a36Sopenharmony_ci		break;
77662306a36Sopenharmony_ci	case WMI_TLV_TX_PAUSE_EVENTID:
77762306a36Sopenharmony_ci		ath10k_wmi_tlv_event_tx_pause(ar, skb);
77862306a36Sopenharmony_ci		break;
77962306a36Sopenharmony_ci	case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
78062306a36Sopenharmony_ci		ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
78162306a36Sopenharmony_ci		break;
78262306a36Sopenharmony_ci	case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
78362306a36Sopenharmony_ci		ath10k_wmi_tlv_event_temperature(ar, skb);
78462306a36Sopenharmony_ci		break;
78562306a36Sopenharmony_ci	case WMI_TLV_TDLS_PEER_EVENTID:
78662306a36Sopenharmony_ci		ath10k_wmi_event_tdls_peer(ar, skb);
78762306a36Sopenharmony_ci		break;
78862306a36Sopenharmony_ci	case WMI_TLV_PEER_DELETE_RESP_EVENTID:
78962306a36Sopenharmony_ci		ath10k_wmi_tlv_event_peer_delete_resp(ar, skb);
79062306a36Sopenharmony_ci		break;
79162306a36Sopenharmony_ci	case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
79262306a36Sopenharmony_ci		ath10k_wmi_event_mgmt_tx_compl(ar, skb);
79362306a36Sopenharmony_ci		break;
79462306a36Sopenharmony_ci	case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID:
79562306a36Sopenharmony_ci		ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb);
79662306a36Sopenharmony_ci		break;
79762306a36Sopenharmony_ci	default:
79862306a36Sopenharmony_ci		ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id);
79962306a36Sopenharmony_ci		break;
80062306a36Sopenharmony_ci	}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ciout:
80362306a36Sopenharmony_ci	dev_kfree_skb(skb);
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
80762306a36Sopenharmony_ci					  struct sk_buff *skb,
80862306a36Sopenharmony_ci					  struct wmi_scan_ev_arg *arg)
80962306a36Sopenharmony_ci{
81062306a36Sopenharmony_ci	const void **tb;
81162306a36Sopenharmony_ci	const struct wmi_scan_event *ev;
81262306a36Sopenharmony_ci	int ret;
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
81562306a36Sopenharmony_ci	if (IS_ERR(tb)) {
81662306a36Sopenharmony_ci		ret = PTR_ERR(tb);
81762306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
81862306a36Sopenharmony_ci		return ret;
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_SCAN_EVENT];
82262306a36Sopenharmony_ci	if (!ev) {
82362306a36Sopenharmony_ci		kfree(tb);
82462306a36Sopenharmony_ci		return -EPROTO;
82562306a36Sopenharmony_ci	}
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	arg->event_type = ev->event_type;
82862306a36Sopenharmony_ci	arg->reason = ev->reason;
82962306a36Sopenharmony_ci	arg->channel_freq = ev->channel_freq;
83062306a36Sopenharmony_ci	arg->scan_req_id = ev->scan_req_id;
83162306a36Sopenharmony_ci	arg->scan_id = ev->scan_id;
83262306a36Sopenharmony_ci	arg->vdev_id = ev->vdev_id;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	kfree(tb);
83562306a36Sopenharmony_ci	return 0;
83662306a36Sopenharmony_ci}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_cistatic int
83962306a36Sopenharmony_ciath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
84062306a36Sopenharmony_ci					struct wmi_tlv_mgmt_tx_compl_ev_arg *arg)
84162306a36Sopenharmony_ci{
84262306a36Sopenharmony_ci	const void **tb;
84362306a36Sopenharmony_ci	const struct wmi_tlv_mgmt_tx_compl_ev *ev;
84462306a36Sopenharmony_ci	int ret;
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
84762306a36Sopenharmony_ci	if (IS_ERR(tb)) {
84862306a36Sopenharmony_ci		ret = PTR_ERR(tb);
84962306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
85062306a36Sopenharmony_ci		return ret;
85162306a36Sopenharmony_ci	}
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
85462306a36Sopenharmony_ci	if (!ev) {
85562306a36Sopenharmony_ci		kfree(tb);
85662306a36Sopenharmony_ci		return -EPROTO;
85762306a36Sopenharmony_ci	}
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	arg->desc_id = ev->desc_id;
86062306a36Sopenharmony_ci	arg->status = ev->status;
86162306a36Sopenharmony_ci	arg->pdev_id = ev->pdev_id;
86262306a36Sopenharmony_ci	arg->ppdu_id = ev->ppdu_id;
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
86562306a36Sopenharmony_ci		arg->ack_rssi = ev->ack_rssi;
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	kfree(tb);
86862306a36Sopenharmony_ci	return 0;
86962306a36Sopenharmony_ci}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_cistruct wmi_tlv_tx_bundle_compl_parse {
87262306a36Sopenharmony_ci	const __le32 *num_reports;
87362306a36Sopenharmony_ci	const __le32 *desc_ids;
87462306a36Sopenharmony_ci	const __le32 *status;
87562306a36Sopenharmony_ci	const __le32 *ppdu_ids;
87662306a36Sopenharmony_ci	const __le32 *ack_rssi;
87762306a36Sopenharmony_ci	bool desc_ids_done;
87862306a36Sopenharmony_ci	bool status_done;
87962306a36Sopenharmony_ci	bool ppdu_ids_done;
88062306a36Sopenharmony_ci	bool ack_rssi_done;
88162306a36Sopenharmony_ci};
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_cistatic int
88462306a36Sopenharmony_ciath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len,
88562306a36Sopenharmony_ci					  const void *ptr, void *data)
88662306a36Sopenharmony_ci{
88762306a36Sopenharmony_ci	struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	switch (tag) {
89062306a36Sopenharmony_ci	case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT:
89162306a36Sopenharmony_ci		bundle_tx_compl->num_reports = ptr;
89262306a36Sopenharmony_ci		break;
89362306a36Sopenharmony_ci	case WMI_TLV_TAG_ARRAY_UINT32:
89462306a36Sopenharmony_ci		if (!bundle_tx_compl->desc_ids_done) {
89562306a36Sopenharmony_ci			bundle_tx_compl->desc_ids_done = true;
89662306a36Sopenharmony_ci			bundle_tx_compl->desc_ids = ptr;
89762306a36Sopenharmony_ci		} else if (!bundle_tx_compl->status_done) {
89862306a36Sopenharmony_ci			bundle_tx_compl->status_done = true;
89962306a36Sopenharmony_ci			bundle_tx_compl->status = ptr;
90062306a36Sopenharmony_ci		} else if (!bundle_tx_compl->ppdu_ids_done) {
90162306a36Sopenharmony_ci			bundle_tx_compl->ppdu_ids_done = true;
90262306a36Sopenharmony_ci			bundle_tx_compl->ppdu_ids = ptr;
90362306a36Sopenharmony_ci		} else if (!bundle_tx_compl->ack_rssi_done) {
90462306a36Sopenharmony_ci			bundle_tx_compl->ack_rssi_done = true;
90562306a36Sopenharmony_ci			bundle_tx_compl->ack_rssi = ptr;
90662306a36Sopenharmony_ci		}
90762306a36Sopenharmony_ci		break;
90862306a36Sopenharmony_ci	default:
90962306a36Sopenharmony_ci		break;
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci	return 0;
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
91562306a36Sopenharmony_ci				struct ath10k *ar, struct sk_buff *skb,
91662306a36Sopenharmony_ci				struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { };
91962306a36Sopenharmony_ci	int ret;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
92262306a36Sopenharmony_ci				  ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse,
92362306a36Sopenharmony_ci				  &bundle_tx_compl);
92462306a36Sopenharmony_ci	if (ret) {
92562306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
92662306a36Sopenharmony_ci		return ret;
92762306a36Sopenharmony_ci	}
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids ||
93062306a36Sopenharmony_ci	    !bundle_tx_compl.status)
93162306a36Sopenharmony_ci		return -EPROTO;
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	arg->num_reports = *bundle_tx_compl.num_reports;
93462306a36Sopenharmony_ci	arg->desc_ids = bundle_tx_compl.desc_ids;
93562306a36Sopenharmony_ci	arg->status = bundle_tx_compl.status;
93662306a36Sopenharmony_ci	arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
93962306a36Sopenharmony_ci		arg->ack_rssi = bundle_tx_compl.ack_rssi;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	return 0;
94262306a36Sopenharmony_ci}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
94562306a36Sopenharmony_ci					     struct sk_buff *skb,
94662306a36Sopenharmony_ci					     struct wmi_mgmt_rx_ev_arg *arg)
94762306a36Sopenharmony_ci{
94862306a36Sopenharmony_ci	const void **tb;
94962306a36Sopenharmony_ci	const struct wmi_tlv_mgmt_rx_ev *ev;
95062306a36Sopenharmony_ci	const u8 *frame;
95162306a36Sopenharmony_ci	u32 msdu_len;
95262306a36Sopenharmony_ci	int ret, i;
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
95562306a36Sopenharmony_ci	if (IS_ERR(tb)) {
95662306a36Sopenharmony_ci		ret = PTR_ERR(tb);
95762306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
95862306a36Sopenharmony_ci		return ret;
95962306a36Sopenharmony_ci	}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR];
96262306a36Sopenharmony_ci	frame = tb[WMI_TLV_TAG_ARRAY_BYTE];
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	if (!ev || !frame) {
96562306a36Sopenharmony_ci		kfree(tb);
96662306a36Sopenharmony_ci		return -EPROTO;
96762306a36Sopenharmony_ci	}
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	arg->channel = ev->channel;
97062306a36Sopenharmony_ci	arg->buf_len = ev->buf_len;
97162306a36Sopenharmony_ci	arg->status = ev->status;
97262306a36Sopenharmony_ci	arg->snr = ev->snr;
97362306a36Sopenharmony_ci	arg->phy_mode = ev->phy_mode;
97462306a36Sopenharmony_ci	arg->rate = ev->rate;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ev->rssi); i++)
97762306a36Sopenharmony_ci		arg->rssi[i] = ev->rssi[i];
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	msdu_len = __le32_to_cpu(arg->buf_len);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	if (skb->len < (frame - skb->data) + msdu_len) {
98262306a36Sopenharmony_ci		kfree(tb);
98362306a36Sopenharmony_ci		return -EPROTO;
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	/* shift the sk_buff to point to `frame` */
98762306a36Sopenharmony_ci	skb_trim(skb, 0);
98862306a36Sopenharmony_ci	skb_put(skb, frame - skb->data);
98962306a36Sopenharmony_ci	skb_pull(skb, frame - skb->data);
99062306a36Sopenharmony_ci	skb_put(skb, msdu_len);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	kfree(tb);
99362306a36Sopenharmony_ci	return 0;
99462306a36Sopenharmony_ci}
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar,
99762306a36Sopenharmony_ci					     struct sk_buff *skb,
99862306a36Sopenharmony_ci					     struct wmi_ch_info_ev_arg *arg)
99962306a36Sopenharmony_ci{
100062306a36Sopenharmony_ci	const void **tb;
100162306a36Sopenharmony_ci	const struct wmi_tlv_chan_info_event *ev;
100262306a36Sopenharmony_ci	int ret;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
100562306a36Sopenharmony_ci	if (IS_ERR(tb)) {
100662306a36Sopenharmony_ci		ret = PTR_ERR(tb);
100762306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
100862306a36Sopenharmony_ci		return ret;
100962306a36Sopenharmony_ci	}
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT];
101262306a36Sopenharmony_ci	if (!ev) {
101362306a36Sopenharmony_ci		kfree(tb);
101462306a36Sopenharmony_ci		return -EPROTO;
101562306a36Sopenharmony_ci	}
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	arg->err_code = ev->err_code;
101862306a36Sopenharmony_ci	arg->freq = ev->freq;
101962306a36Sopenharmony_ci	arg->cmd_flags = ev->cmd_flags;
102062306a36Sopenharmony_ci	arg->noise_floor = ev->noise_floor;
102162306a36Sopenharmony_ci	arg->rx_clear_count = ev->rx_clear_count;
102262306a36Sopenharmony_ci	arg->cycle_count = ev->cycle_count;
102362306a36Sopenharmony_ci	if (test_bit(ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL,
102462306a36Sopenharmony_ci		     ar->running_fw->fw_file.fw_features))
102562306a36Sopenharmony_ci		arg->mac_clk_mhz = ev->mac_clk_mhz;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	kfree(tb);
102862306a36Sopenharmony_ci	return 0;
102962306a36Sopenharmony_ci}
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_cistatic int
103262306a36Sopenharmony_ciath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
103362306a36Sopenharmony_ci				     struct wmi_vdev_start_ev_arg *arg)
103462306a36Sopenharmony_ci{
103562306a36Sopenharmony_ci	const void **tb;
103662306a36Sopenharmony_ci	const struct wmi_vdev_start_response_event *ev;
103762306a36Sopenharmony_ci	int ret;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
104062306a36Sopenharmony_ci	if (IS_ERR(tb)) {
104162306a36Sopenharmony_ci		ret = PTR_ERR(tb);
104262306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
104362306a36Sopenharmony_ci		return ret;
104462306a36Sopenharmony_ci	}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT];
104762306a36Sopenharmony_ci	if (!ev) {
104862306a36Sopenharmony_ci		kfree(tb);
104962306a36Sopenharmony_ci		return -EPROTO;
105062306a36Sopenharmony_ci	}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	skb_pull(skb, sizeof(*ev));
105362306a36Sopenharmony_ci	arg->vdev_id = ev->vdev_id;
105462306a36Sopenharmony_ci	arg->req_id = ev->req_id;
105562306a36Sopenharmony_ci	arg->resp_type = ev->resp_type;
105662306a36Sopenharmony_ci	arg->status = ev->status;
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	kfree(tb);
105962306a36Sopenharmony_ci	return 0;
106062306a36Sopenharmony_ci}
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k *ar,
106362306a36Sopenharmony_ci					       struct sk_buff *skb,
106462306a36Sopenharmony_ci					       struct wmi_peer_kick_ev_arg *arg)
106562306a36Sopenharmony_ci{
106662306a36Sopenharmony_ci	const void **tb;
106762306a36Sopenharmony_ci	const struct wmi_peer_sta_kickout_event *ev;
106862306a36Sopenharmony_ci	int ret;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
107162306a36Sopenharmony_ci	if (IS_ERR(tb)) {
107262306a36Sopenharmony_ci		ret = PTR_ERR(tb);
107362306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
107462306a36Sopenharmony_ci		return ret;
107562306a36Sopenharmony_ci	}
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT];
107862306a36Sopenharmony_ci	if (!ev) {
107962306a36Sopenharmony_ci		kfree(tb);
108062306a36Sopenharmony_ci		return -EPROTO;
108162306a36Sopenharmony_ci	}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	arg->mac_addr = ev->peer_macaddr.addr;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	kfree(tb);
108662306a36Sopenharmony_ci	return 0;
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_cistruct wmi_tlv_swba_parse {
109062306a36Sopenharmony_ci	const struct wmi_host_swba_event *ev;
109162306a36Sopenharmony_ci	bool tim_done;
109262306a36Sopenharmony_ci	bool noa_done;
109362306a36Sopenharmony_ci	size_t n_tim;
109462306a36Sopenharmony_ci	size_t n_noa;
109562306a36Sopenharmony_ci	struct wmi_swba_ev_arg *arg;
109662306a36Sopenharmony_ci};
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_cistatic int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
109962306a36Sopenharmony_ci					 const void *ptr, void *data)
110062306a36Sopenharmony_ci{
110162306a36Sopenharmony_ci	struct wmi_tlv_swba_parse *swba = data;
110262306a36Sopenharmony_ci	struct wmi_tim_info_arg *tim_info_arg;
110362306a36Sopenharmony_ci	const struct wmi_tim_info *tim_info_ev = ptr;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO)
110662306a36Sopenharmony_ci		return -EPROTO;
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info))
110962306a36Sopenharmony_ci		return -ENOBUFS;
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	if (__le32_to_cpu(tim_info_ev->tim_len) >
111262306a36Sopenharmony_ci	     sizeof(tim_info_ev->tim_bitmap)) {
111362306a36Sopenharmony_ci		ath10k_warn(ar, "refusing to parse invalid swba structure\n");
111462306a36Sopenharmony_ci		return -EPROTO;
111562306a36Sopenharmony_ci	}
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	tim_info_arg = &swba->arg->tim_info[swba->n_tim];
111862306a36Sopenharmony_ci	tim_info_arg->tim_len = tim_info_ev->tim_len;
111962306a36Sopenharmony_ci	tim_info_arg->tim_mcast = tim_info_ev->tim_mcast;
112062306a36Sopenharmony_ci	tim_info_arg->tim_bitmap = tim_info_ev->tim_bitmap;
112162306a36Sopenharmony_ci	tim_info_arg->tim_changed = tim_info_ev->tim_changed;
112262306a36Sopenharmony_ci	tim_info_arg->tim_num_ps_pending = tim_info_ev->tim_num_ps_pending;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	swba->n_tim++;
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	return 0;
112762306a36Sopenharmony_ci}
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_cistatic int ath10k_wmi_tlv_swba_noa_parse(struct ath10k *ar, u16 tag, u16 len,
113062306a36Sopenharmony_ci					 const void *ptr, void *data)
113162306a36Sopenharmony_ci{
113262306a36Sopenharmony_ci	struct wmi_tlv_swba_parse *swba = data;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	if (tag != WMI_TLV_TAG_STRUCT_P2P_NOA_INFO)
113562306a36Sopenharmony_ci		return -EPROTO;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	if (swba->n_noa >= ARRAY_SIZE(swba->arg->noa_info))
113862306a36Sopenharmony_ci		return -ENOBUFS;
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	swba->arg->noa_info[swba->n_noa++] = ptr;
114162306a36Sopenharmony_ci	return 0;
114262306a36Sopenharmony_ci}
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_cistatic int ath10k_wmi_tlv_swba_parse(struct ath10k *ar, u16 tag, u16 len,
114562306a36Sopenharmony_ci				     const void *ptr, void *data)
114662306a36Sopenharmony_ci{
114762306a36Sopenharmony_ci	struct wmi_tlv_swba_parse *swba = data;
114862306a36Sopenharmony_ci	int ret;
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	switch (tag) {
115162306a36Sopenharmony_ci	case WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT:
115262306a36Sopenharmony_ci		swba->ev = ptr;
115362306a36Sopenharmony_ci		break;
115462306a36Sopenharmony_ci	case WMI_TLV_TAG_ARRAY_STRUCT:
115562306a36Sopenharmony_ci		if (!swba->tim_done) {
115662306a36Sopenharmony_ci			swba->tim_done = true;
115762306a36Sopenharmony_ci			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
115862306a36Sopenharmony_ci						  ath10k_wmi_tlv_swba_tim_parse,
115962306a36Sopenharmony_ci						  swba);
116062306a36Sopenharmony_ci			if (ret)
116162306a36Sopenharmony_ci				return ret;
116262306a36Sopenharmony_ci		} else if (!swba->noa_done) {
116362306a36Sopenharmony_ci			swba->noa_done = true;
116462306a36Sopenharmony_ci			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
116562306a36Sopenharmony_ci						  ath10k_wmi_tlv_swba_noa_parse,
116662306a36Sopenharmony_ci						  swba);
116762306a36Sopenharmony_ci			if (ret)
116862306a36Sopenharmony_ci				return ret;
116962306a36Sopenharmony_ci		}
117062306a36Sopenharmony_ci		break;
117162306a36Sopenharmony_ci	default:
117262306a36Sopenharmony_ci		break;
117362306a36Sopenharmony_ci	}
117462306a36Sopenharmony_ci	return 0;
117562306a36Sopenharmony_ci}
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
117862306a36Sopenharmony_ci					  struct sk_buff *skb,
117962306a36Sopenharmony_ci					  struct wmi_swba_ev_arg *arg)
118062306a36Sopenharmony_ci{
118162306a36Sopenharmony_ci	struct wmi_tlv_swba_parse swba = { .arg = arg };
118262306a36Sopenharmony_ci	u32 map;
118362306a36Sopenharmony_ci	size_t n_vdevs;
118462306a36Sopenharmony_ci	int ret;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
118762306a36Sopenharmony_ci				  ath10k_wmi_tlv_swba_parse, &swba);
118862306a36Sopenharmony_ci	if (ret) {
118962306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
119062306a36Sopenharmony_ci		return ret;
119162306a36Sopenharmony_ci	}
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	if (!swba.ev)
119462306a36Sopenharmony_ci		return -EPROTO;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	arg->vdev_map = swba.ev->vdev_map;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	for (map = __le32_to_cpu(arg->vdev_map), n_vdevs = 0; map; map >>= 1)
119962306a36Sopenharmony_ci		if (map & BIT(0))
120062306a36Sopenharmony_ci			n_vdevs++;
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	if (n_vdevs != swba.n_tim ||
120362306a36Sopenharmony_ci	    n_vdevs != swba.n_noa)
120462306a36Sopenharmony_ci		return -EPROTO;
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	return 0;
120762306a36Sopenharmony_ci}
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k *ar,
121062306a36Sopenharmony_ci						struct sk_buff *skb,
121162306a36Sopenharmony_ci						struct wmi_phyerr_hdr_arg *arg)
121262306a36Sopenharmony_ci{
121362306a36Sopenharmony_ci	const void **tb;
121462306a36Sopenharmony_ci	const struct wmi_tlv_phyerr_ev *ev;
121562306a36Sopenharmony_ci	const void *phyerrs;
121662306a36Sopenharmony_ci	int ret;
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
121962306a36Sopenharmony_ci	if (IS_ERR(tb)) {
122062306a36Sopenharmony_ci		ret = PTR_ERR(tb);
122162306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
122262306a36Sopenharmony_ci		return ret;
122362306a36Sopenharmony_ci	}
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR];
122662306a36Sopenharmony_ci	phyerrs = tb[WMI_TLV_TAG_ARRAY_BYTE];
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci	if (!ev || !phyerrs) {
122962306a36Sopenharmony_ci		kfree(tb);
123062306a36Sopenharmony_ci		return -EPROTO;
123162306a36Sopenharmony_ci	}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	arg->num_phyerrs  = __le32_to_cpu(ev->num_phyerrs);
123462306a36Sopenharmony_ci	arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
123562306a36Sopenharmony_ci	arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
123662306a36Sopenharmony_ci	arg->buf_len = __le32_to_cpu(ev->buf_len);
123762306a36Sopenharmony_ci	arg->phyerrs = phyerrs;
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	kfree(tb);
124062306a36Sopenharmony_ci	return 0;
124162306a36Sopenharmony_ci}
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci#define WMI_TLV_ABI_VER_NS0 0x5F414351
124462306a36Sopenharmony_ci#define WMI_TLV_ABI_VER_NS1 0x00004C4D
124562306a36Sopenharmony_ci#define WMI_TLV_ABI_VER_NS2 0x00000000
124662306a36Sopenharmony_ci#define WMI_TLV_ABI_VER_NS3 0x00000000
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci#define WMI_TLV_ABI_VER0_MAJOR 1
124962306a36Sopenharmony_ci#define WMI_TLV_ABI_VER0_MINOR 0
125062306a36Sopenharmony_ci#define WMI_TLV_ABI_VER0 ((((WMI_TLV_ABI_VER0_MAJOR) << 24) & 0xFF000000) | \
125162306a36Sopenharmony_ci			  (((WMI_TLV_ABI_VER0_MINOR) <<  0) & 0x00FFFFFF))
125262306a36Sopenharmony_ci#define WMI_TLV_ABI_VER1 53
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_cistatic int
125562306a36Sopenharmony_ciath10k_wmi_tlv_parse_mem_reqs(struct ath10k *ar, u16 tag, u16 len,
125662306a36Sopenharmony_ci			      const void *ptr, void *data)
125762306a36Sopenharmony_ci{
125862306a36Sopenharmony_ci	struct wmi_svc_rdy_ev_arg *arg = data;
125962306a36Sopenharmony_ci	int i;
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	if (tag != WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ)
126262306a36Sopenharmony_ci		return -EPROTO;
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(arg->mem_reqs); i++) {
126562306a36Sopenharmony_ci		if (!arg->mem_reqs[i]) {
126662306a36Sopenharmony_ci			arg->mem_reqs[i] = ptr;
126762306a36Sopenharmony_ci			return 0;
126862306a36Sopenharmony_ci		}
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	return -ENOMEM;
127262306a36Sopenharmony_ci}
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_cistruct wmi_tlv_svc_rdy_parse {
127562306a36Sopenharmony_ci	const struct hal_reg_capabilities *reg;
127662306a36Sopenharmony_ci	const struct wmi_tlv_svc_rdy_ev *ev;
127762306a36Sopenharmony_ci	const __le32 *svc_bmap;
127862306a36Sopenharmony_ci	const struct wlan_host_mem_req *mem_reqs;
127962306a36Sopenharmony_ci	bool svc_bmap_done;
128062306a36Sopenharmony_ci	bool dbs_hw_mode_done;
128162306a36Sopenharmony_ci};
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic int ath10k_wmi_tlv_svc_rdy_parse(struct ath10k *ar, u16 tag, u16 len,
128462306a36Sopenharmony_ci					const void *ptr, void *data)
128562306a36Sopenharmony_ci{
128662306a36Sopenharmony_ci	struct wmi_tlv_svc_rdy_parse *svc_rdy = data;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	switch (tag) {
128962306a36Sopenharmony_ci	case WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT:
129062306a36Sopenharmony_ci		svc_rdy->ev = ptr;
129162306a36Sopenharmony_ci		break;
129262306a36Sopenharmony_ci	case WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES:
129362306a36Sopenharmony_ci		svc_rdy->reg = ptr;
129462306a36Sopenharmony_ci		break;
129562306a36Sopenharmony_ci	case WMI_TLV_TAG_ARRAY_STRUCT:
129662306a36Sopenharmony_ci		svc_rdy->mem_reqs = ptr;
129762306a36Sopenharmony_ci		break;
129862306a36Sopenharmony_ci	case WMI_TLV_TAG_ARRAY_UINT32:
129962306a36Sopenharmony_ci		if (!svc_rdy->svc_bmap_done) {
130062306a36Sopenharmony_ci			svc_rdy->svc_bmap_done = true;
130162306a36Sopenharmony_ci			svc_rdy->svc_bmap = ptr;
130262306a36Sopenharmony_ci		} else if (!svc_rdy->dbs_hw_mode_done) {
130362306a36Sopenharmony_ci			svc_rdy->dbs_hw_mode_done = true;
130462306a36Sopenharmony_ci		}
130562306a36Sopenharmony_ci		break;
130662306a36Sopenharmony_ci	default:
130762306a36Sopenharmony_ci		break;
130862306a36Sopenharmony_ci	}
130962306a36Sopenharmony_ci	return 0;
131062306a36Sopenharmony_ci}
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
131362306a36Sopenharmony_ci					     struct sk_buff *skb,
131462306a36Sopenharmony_ci					     struct wmi_svc_rdy_ev_arg *arg)
131562306a36Sopenharmony_ci{
131662306a36Sopenharmony_ci	const struct hal_reg_capabilities *reg;
131762306a36Sopenharmony_ci	const struct wmi_tlv_svc_rdy_ev *ev;
131862306a36Sopenharmony_ci	const __le32 *svc_bmap;
131962306a36Sopenharmony_ci	const struct wlan_host_mem_req *mem_reqs;
132062306a36Sopenharmony_ci	struct wmi_tlv_svc_rdy_parse svc_rdy = { };
132162306a36Sopenharmony_ci	int ret;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
132462306a36Sopenharmony_ci				  ath10k_wmi_tlv_svc_rdy_parse, &svc_rdy);
132562306a36Sopenharmony_ci	if (ret) {
132662306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
132762306a36Sopenharmony_ci		return ret;
132862306a36Sopenharmony_ci	}
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	ev = svc_rdy.ev;
133162306a36Sopenharmony_ci	reg = svc_rdy.reg;
133262306a36Sopenharmony_ci	svc_bmap = svc_rdy.svc_bmap;
133362306a36Sopenharmony_ci	mem_reqs = svc_rdy.mem_reqs;
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	if (!ev || !reg || !svc_bmap || !mem_reqs)
133662306a36Sopenharmony_ci		return -EPROTO;
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	/* This is an internal ABI compatibility check for WMI TLV so check it
133962306a36Sopenharmony_ci	 * here instead of the generic WMI code.
134062306a36Sopenharmony_ci	 */
134162306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
134262306a36Sopenharmony_ci		   "wmi tlv abi 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x\n",
134362306a36Sopenharmony_ci		   __le32_to_cpu(ev->abi.abi_ver0), WMI_TLV_ABI_VER0,
134462306a36Sopenharmony_ci		   __le32_to_cpu(ev->abi.abi_ver_ns0), WMI_TLV_ABI_VER_NS0,
134562306a36Sopenharmony_ci		   __le32_to_cpu(ev->abi.abi_ver_ns1), WMI_TLV_ABI_VER_NS1,
134662306a36Sopenharmony_ci		   __le32_to_cpu(ev->abi.abi_ver_ns2), WMI_TLV_ABI_VER_NS2,
134762306a36Sopenharmony_ci		   __le32_to_cpu(ev->abi.abi_ver_ns3), WMI_TLV_ABI_VER_NS3);
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	if (__le32_to_cpu(ev->abi.abi_ver0) != WMI_TLV_ABI_VER0 ||
135062306a36Sopenharmony_ci	    __le32_to_cpu(ev->abi.abi_ver_ns0) != WMI_TLV_ABI_VER_NS0 ||
135162306a36Sopenharmony_ci	    __le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 ||
135262306a36Sopenharmony_ci	    __le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 ||
135362306a36Sopenharmony_ci	    __le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) {
135462306a36Sopenharmony_ci		return -ENOTSUPP;
135562306a36Sopenharmony_ci	}
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	arg->min_tx_power = ev->hw_min_tx_power;
135862306a36Sopenharmony_ci	arg->max_tx_power = ev->hw_max_tx_power;
135962306a36Sopenharmony_ci	arg->ht_cap = ev->ht_cap_info;
136062306a36Sopenharmony_ci	arg->vht_cap = ev->vht_cap_info;
136162306a36Sopenharmony_ci	arg->vht_supp_mcs = ev->vht_supp_mcs;
136262306a36Sopenharmony_ci	arg->sw_ver0 = ev->abi.abi_ver0;
136362306a36Sopenharmony_ci	arg->sw_ver1 = ev->abi.abi_ver1;
136462306a36Sopenharmony_ci	arg->fw_build = ev->fw_build_vers;
136562306a36Sopenharmony_ci	arg->phy_capab = ev->phy_capability;
136662306a36Sopenharmony_ci	arg->num_rf_chains = ev->num_rf_chains;
136762306a36Sopenharmony_ci	arg->eeprom_rd = reg->eeprom_rd;
136862306a36Sopenharmony_ci	arg->low_2ghz_chan = reg->low_2ghz_chan;
136962306a36Sopenharmony_ci	arg->high_2ghz_chan = reg->high_2ghz_chan;
137062306a36Sopenharmony_ci	arg->low_5ghz_chan = reg->low_5ghz_chan;
137162306a36Sopenharmony_ci	arg->high_5ghz_chan = reg->high_5ghz_chan;
137262306a36Sopenharmony_ci	arg->num_mem_reqs = ev->num_mem_reqs;
137362306a36Sopenharmony_ci	arg->service_map = svc_bmap;
137462306a36Sopenharmony_ci	arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
137562306a36Sopenharmony_ci	arg->sys_cap_info = ev->sys_cap_info;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
137862306a36Sopenharmony_ci				  ath10k_wmi_tlv_parse_mem_reqs, arg);
137962306a36Sopenharmony_ci	if (ret) {
138062306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse mem_reqs tlv: %d\n", ret);
138162306a36Sopenharmony_ci		return ret;
138262306a36Sopenharmony_ci	}
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	return 0;
138562306a36Sopenharmony_ci}
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
138862306a36Sopenharmony_ci					 struct sk_buff *skb,
138962306a36Sopenharmony_ci					 struct wmi_rdy_ev_arg *arg)
139062306a36Sopenharmony_ci{
139162306a36Sopenharmony_ci	const void **tb;
139262306a36Sopenharmony_ci	const struct wmi_tlv_rdy_ev *ev;
139362306a36Sopenharmony_ci	int ret;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
139662306a36Sopenharmony_ci	if (IS_ERR(tb)) {
139762306a36Sopenharmony_ci		ret = PTR_ERR(tb);
139862306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
139962306a36Sopenharmony_ci		return ret;
140062306a36Sopenharmony_ci	}
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_READY_EVENT];
140362306a36Sopenharmony_ci	if (!ev) {
140462306a36Sopenharmony_ci		kfree(tb);
140562306a36Sopenharmony_ci		return -EPROTO;
140662306a36Sopenharmony_ci	}
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	arg->sw_version = ev->abi.abi_ver0;
140962306a36Sopenharmony_ci	arg->abi_version = ev->abi.abi_ver1;
141062306a36Sopenharmony_ci	arg->status = ev->status;
141162306a36Sopenharmony_ci	arg->mac_addr = ev->mac_addr.addr;
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	kfree(tb);
141462306a36Sopenharmony_ci	return 0;
141562306a36Sopenharmony_ci}
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_cistatic int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len,
141862306a36Sopenharmony_ci					  const void *ptr, void *data)
141962306a36Sopenharmony_ci{
142062306a36Sopenharmony_ci	struct wmi_svc_avail_ev_arg *arg = data;
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	switch (tag) {
142362306a36Sopenharmony_ci	case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT:
142462306a36Sopenharmony_ci		arg->service_map_ext_valid = true;
142562306a36Sopenharmony_ci		arg->service_map_ext_len = *(__le32 *)ptr;
142662306a36Sopenharmony_ci		arg->service_map_ext = ptr + sizeof(__le32);
142762306a36Sopenharmony_ci		return 0;
142862306a36Sopenharmony_ci	default:
142962306a36Sopenharmony_ci		break;
143062306a36Sopenharmony_ci	}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	return 0;
143362306a36Sopenharmony_ci}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar,
143662306a36Sopenharmony_ci					    struct sk_buff *skb,
143762306a36Sopenharmony_ci					    struct wmi_svc_avail_ev_arg *arg)
143862306a36Sopenharmony_ci{
143962306a36Sopenharmony_ci	int ret;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
144262306a36Sopenharmony_ci				  ath10k_wmi_tlv_svc_avail_parse, arg);
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	if (ret) {
144562306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse svc_avail tlv: %d\n", ret);
144662306a36Sopenharmony_ci		return ret;
144762306a36Sopenharmony_ci	}
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	return 0;
145062306a36Sopenharmony_ci}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_cistatic void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
145362306a36Sopenharmony_ci					   struct ath10k_fw_stats_vdev *dst)
145462306a36Sopenharmony_ci{
145562306a36Sopenharmony_ci	int i;
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	dst->vdev_id = __le32_to_cpu(src->vdev_id);
145862306a36Sopenharmony_ci	dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
145962306a36Sopenharmony_ci	dst->data_snr = __le32_to_cpu(src->data_snr);
146062306a36Sopenharmony_ci	dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
146162306a36Sopenharmony_ci	dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
146262306a36Sopenharmony_ci	dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
146362306a36Sopenharmony_ci	dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
146462306a36Sopenharmony_ci	dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
146562306a36Sopenharmony_ci	dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
146862306a36Sopenharmony_ci		dst->num_tx_frames[i] =
146962306a36Sopenharmony_ci			__le32_to_cpu(src->num_tx_frames[i]);
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
147262306a36Sopenharmony_ci		dst->num_tx_frames_retries[i] =
147362306a36Sopenharmony_ci			__le32_to_cpu(src->num_tx_frames_retries[i]);
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
147662306a36Sopenharmony_ci		dst->num_tx_frames_failures[i] =
147762306a36Sopenharmony_ci			__le32_to_cpu(src->num_tx_frames_failures[i]);
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
148062306a36Sopenharmony_ci		dst->tx_rate_history[i] =
148162306a36Sopenharmony_ci			__le32_to_cpu(src->tx_rate_history[i]);
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
148462306a36Sopenharmony_ci		dst->beacon_rssi_history[i] =
148562306a36Sopenharmony_ci			__le32_to_cpu(src->beacon_rssi_history[i]);
148662306a36Sopenharmony_ci}
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
148962306a36Sopenharmony_ci					   struct sk_buff *skb,
149062306a36Sopenharmony_ci					   struct ath10k_fw_stats *stats)
149162306a36Sopenharmony_ci{
149262306a36Sopenharmony_ci	const void **tb;
149362306a36Sopenharmony_ci	const struct wmi_tlv_stats_ev *ev;
149462306a36Sopenharmony_ci	u32 num_peer_stats_extd;
149562306a36Sopenharmony_ci	const void *data;
149662306a36Sopenharmony_ci	u32 num_pdev_stats;
149762306a36Sopenharmony_ci	u32 num_vdev_stats;
149862306a36Sopenharmony_ci	u32 num_peer_stats;
149962306a36Sopenharmony_ci	u32 num_bcnflt_stats;
150062306a36Sopenharmony_ci	u32 num_chan_stats;
150162306a36Sopenharmony_ci	size_t data_len;
150262306a36Sopenharmony_ci	u32 stats_id;
150362306a36Sopenharmony_ci	int ret;
150462306a36Sopenharmony_ci	int i;
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
150762306a36Sopenharmony_ci	if (IS_ERR(tb)) {
150862306a36Sopenharmony_ci		ret = PTR_ERR(tb);
150962306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
151062306a36Sopenharmony_ci		return ret;
151162306a36Sopenharmony_ci	}
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_STATS_EVENT];
151462306a36Sopenharmony_ci	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	if (!ev || !data) {
151762306a36Sopenharmony_ci		kfree(tb);
151862306a36Sopenharmony_ci		return -EPROTO;
151962306a36Sopenharmony_ci	}
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	data_len = ath10k_wmi_tlv_len(data);
152262306a36Sopenharmony_ci	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
152362306a36Sopenharmony_ci	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
152462306a36Sopenharmony_ci	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
152562306a36Sopenharmony_ci	num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
152662306a36Sopenharmony_ci	num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
152762306a36Sopenharmony_ci	stats_id = __le32_to_cpu(ev->stats_id);
152862306a36Sopenharmony_ci	num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd);
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
153162306a36Sopenharmony_ci		   "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n",
153262306a36Sopenharmony_ci		   num_pdev_stats, num_vdev_stats, num_peer_stats,
153362306a36Sopenharmony_ci		   num_bcnflt_stats, num_chan_stats, num_peer_stats_extd);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	for (i = 0; i < num_pdev_stats; i++) {
153662306a36Sopenharmony_ci		const struct wmi_pdev_stats *src;
153762306a36Sopenharmony_ci		struct ath10k_fw_stats_pdev *dst;
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci		src = data;
154062306a36Sopenharmony_ci		if (data_len < sizeof(*src)) {
154162306a36Sopenharmony_ci			kfree(tb);
154262306a36Sopenharmony_ci			return -EPROTO;
154362306a36Sopenharmony_ci		}
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci		data += sizeof(*src);
154662306a36Sopenharmony_ci		data_len -= sizeof(*src);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
154962306a36Sopenharmony_ci		if (!dst)
155062306a36Sopenharmony_ci			continue;
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
155362306a36Sopenharmony_ci		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
155462306a36Sopenharmony_ci		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
155562306a36Sopenharmony_ci		list_add_tail(&dst->list, &stats->pdevs);
155662306a36Sopenharmony_ci	}
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	for (i = 0; i < num_vdev_stats; i++) {
155962306a36Sopenharmony_ci		const struct wmi_tlv_vdev_stats *src;
156062306a36Sopenharmony_ci		struct ath10k_fw_stats_vdev *dst;
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci		src = data;
156362306a36Sopenharmony_ci		if (data_len < sizeof(*src)) {
156462306a36Sopenharmony_ci			kfree(tb);
156562306a36Sopenharmony_ci			return -EPROTO;
156662306a36Sopenharmony_ci		}
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci		data += sizeof(*src);
156962306a36Sopenharmony_ci		data_len -= sizeof(*src);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
157262306a36Sopenharmony_ci		if (!dst)
157362306a36Sopenharmony_ci			continue;
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci		ath10k_wmi_tlv_pull_vdev_stats(src, dst);
157662306a36Sopenharmony_ci		list_add_tail(&dst->list, &stats->vdevs);
157762306a36Sopenharmony_ci	}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	for (i = 0; i < num_peer_stats; i++) {
158062306a36Sopenharmony_ci		const struct wmi_10x_peer_stats *src;
158162306a36Sopenharmony_ci		struct ath10k_fw_stats_peer *dst;
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci		src = data;
158462306a36Sopenharmony_ci		if (data_len < sizeof(*src)) {
158562306a36Sopenharmony_ci			kfree(tb);
158662306a36Sopenharmony_ci			return -EPROTO;
158762306a36Sopenharmony_ci		}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci		data += sizeof(*src);
159062306a36Sopenharmony_ci		data_len -= sizeof(*src);
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
159362306a36Sopenharmony_ci		if (!dst)
159462306a36Sopenharmony_ci			continue;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci		ath10k_wmi_pull_peer_stats(&src->old, dst);
159762306a36Sopenharmony_ci		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci		if (stats_id & WMI_TLV_STAT_PEER_EXTD) {
160062306a36Sopenharmony_ci			const struct wmi_tlv_peer_stats_extd *extd;
160162306a36Sopenharmony_ci			unsigned long rx_duration_high;
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci			extd = data + sizeof(*src) * (num_peer_stats - i - 1)
160462306a36Sopenharmony_ci			       + sizeof(*extd) * i;
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci			dst->rx_duration = __le32_to_cpu(extd->rx_duration);
160762306a36Sopenharmony_ci			rx_duration_high = __le32_to_cpu
160862306a36Sopenharmony_ci						(extd->rx_duration_high);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci			if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT,
161162306a36Sopenharmony_ci				     &rx_duration_high)) {
161262306a36Sopenharmony_ci				rx_duration_high =
161362306a36Sopenharmony_ci					FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK,
161462306a36Sopenharmony_ci						  rx_duration_high);
161562306a36Sopenharmony_ci				dst->rx_duration |= (u64)rx_duration_high <<
161662306a36Sopenharmony_ci						    WMI_TLV_PEER_RX_DURATION_SHIFT;
161762306a36Sopenharmony_ci			}
161862306a36Sopenharmony_ci		}
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci		list_add_tail(&dst->list, &stats->peers);
162162306a36Sopenharmony_ci	}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	kfree(tb);
162462306a36Sopenharmony_ci	return 0;
162562306a36Sopenharmony_ci}
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_roam_ev(struct ath10k *ar,
162862306a36Sopenharmony_ci					  struct sk_buff *skb,
162962306a36Sopenharmony_ci					  struct wmi_roam_ev_arg *arg)
163062306a36Sopenharmony_ci{
163162306a36Sopenharmony_ci	const void **tb;
163262306a36Sopenharmony_ci	const struct wmi_tlv_roam_ev *ev;
163362306a36Sopenharmony_ci	int ret;
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
163662306a36Sopenharmony_ci	if (IS_ERR(tb)) {
163762306a36Sopenharmony_ci		ret = PTR_ERR(tb);
163862306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
163962306a36Sopenharmony_ci		return ret;
164062306a36Sopenharmony_ci	}
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_ROAM_EVENT];
164362306a36Sopenharmony_ci	if (!ev) {
164462306a36Sopenharmony_ci		kfree(tb);
164562306a36Sopenharmony_ci		return -EPROTO;
164662306a36Sopenharmony_ci	}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	arg->vdev_id = ev->vdev_id;
164962306a36Sopenharmony_ci	arg->reason = ev->reason;
165062306a36Sopenharmony_ci	arg->rssi = ev->rssi;
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	kfree(tb);
165362306a36Sopenharmony_ci	return 0;
165462306a36Sopenharmony_ci}
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_cistatic int
165762306a36Sopenharmony_ciath10k_wmi_tlv_op_pull_wow_ev(struct ath10k *ar, struct sk_buff *skb,
165862306a36Sopenharmony_ci			      struct wmi_wow_ev_arg *arg)
165962306a36Sopenharmony_ci{
166062306a36Sopenharmony_ci	const void **tb;
166162306a36Sopenharmony_ci	const struct wmi_tlv_wow_event_info *ev;
166262306a36Sopenharmony_ci	int ret;
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
166562306a36Sopenharmony_ci	if (IS_ERR(tb)) {
166662306a36Sopenharmony_ci		ret = PTR_ERR(tb);
166762306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
166862306a36Sopenharmony_ci		return ret;
166962306a36Sopenharmony_ci	}
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO];
167262306a36Sopenharmony_ci	if (!ev) {
167362306a36Sopenharmony_ci		kfree(tb);
167462306a36Sopenharmony_ci		return -EPROTO;
167562306a36Sopenharmony_ci	}
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	arg->vdev_id = __le32_to_cpu(ev->vdev_id);
167862306a36Sopenharmony_ci	arg->flag = __le32_to_cpu(ev->flag);
167962306a36Sopenharmony_ci	arg->wake_reason = __le32_to_cpu(ev->wake_reason);
168062306a36Sopenharmony_ci	arg->data_len = __le32_to_cpu(ev->data_len);
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	kfree(tb);
168362306a36Sopenharmony_ci	return 0;
168462306a36Sopenharmony_ci}
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k *ar,
168762306a36Sopenharmony_ci					  struct sk_buff *skb,
168862306a36Sopenharmony_ci					  struct wmi_echo_ev_arg *arg)
168962306a36Sopenharmony_ci{
169062306a36Sopenharmony_ci	const void **tb;
169162306a36Sopenharmony_ci	const struct wmi_echo_event *ev;
169262306a36Sopenharmony_ci	int ret;
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
169562306a36Sopenharmony_ci	if (IS_ERR(tb)) {
169662306a36Sopenharmony_ci		ret = PTR_ERR(tb);
169762306a36Sopenharmony_ci		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
169862306a36Sopenharmony_ci		return ret;
169962306a36Sopenharmony_ci	}
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	ev = tb[WMI_TLV_TAG_STRUCT_ECHO_EVENT];
170262306a36Sopenharmony_ci	if (!ev) {
170362306a36Sopenharmony_ci		kfree(tb);
170462306a36Sopenharmony_ci		return -EPROTO;
170562306a36Sopenharmony_ci	}
170662306a36Sopenharmony_ci
170762306a36Sopenharmony_ci	arg->value = ev->value;
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	kfree(tb);
171062306a36Sopenharmony_ci	return 0;
171162306a36Sopenharmony_ci}
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_cistatic struct sk_buff *
171462306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
171562306a36Sopenharmony_ci{
171662306a36Sopenharmony_ci	struct wmi_tlv_pdev_suspend *cmd;
171762306a36Sopenharmony_ci	struct wmi_tlv *tlv;
171862306a36Sopenharmony_ci	struct sk_buff *skb;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
172162306a36Sopenharmony_ci	if (!skb)
172262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	tlv = (void *)skb->data;
172562306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD);
172662306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
172762306a36Sopenharmony_ci	cmd = (void *)tlv->value;
172862306a36Sopenharmony_ci	cmd->opt = __cpu_to_le32(opt);
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev suspend\n");
173162306a36Sopenharmony_ci	return skb;
173262306a36Sopenharmony_ci}
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_cistatic struct sk_buff *
173562306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k *ar)
173662306a36Sopenharmony_ci{
173762306a36Sopenharmony_ci	struct wmi_tlv_resume_cmd *cmd;
173862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
173962306a36Sopenharmony_ci	struct sk_buff *skb;
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
174262306a36Sopenharmony_ci	if (!skb)
174362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	tlv = (void *)skb->data;
174662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD);
174762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
174862306a36Sopenharmony_ci	cmd = (void *)tlv->value;
174962306a36Sopenharmony_ci	cmd->reserved = __cpu_to_le32(0);
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev resume\n");
175262306a36Sopenharmony_ci	return skb;
175362306a36Sopenharmony_ci}
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_cistatic struct sk_buff *
175662306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
175762306a36Sopenharmony_ci				  u16 rd, u16 rd2g, u16 rd5g,
175862306a36Sopenharmony_ci				  u16 ctl2g, u16 ctl5g,
175962306a36Sopenharmony_ci				  enum wmi_dfs_region dfs_reg)
176062306a36Sopenharmony_ci{
176162306a36Sopenharmony_ci	struct wmi_tlv_pdev_set_rd_cmd *cmd;
176262306a36Sopenharmony_ci	struct wmi_tlv *tlv;
176362306a36Sopenharmony_ci	struct sk_buff *skb;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
176662306a36Sopenharmony_ci	if (!skb)
176762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	tlv = (void *)skb->data;
177062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD);
177162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
177262306a36Sopenharmony_ci	cmd = (void *)tlv->value;
177362306a36Sopenharmony_ci	cmd->regd = __cpu_to_le32(rd);
177462306a36Sopenharmony_ci	cmd->regd_2ghz = __cpu_to_le32(rd2g);
177562306a36Sopenharmony_ci	cmd->regd_5ghz = __cpu_to_le32(rd5g);
177662306a36Sopenharmony_ci	cmd->conform_limit_2ghz = __cpu_to_le32(ctl2g);
177762306a36Sopenharmony_ci	cmd->conform_limit_5ghz = __cpu_to_le32(ctl5g);
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
178062306a36Sopenharmony_ci	return skb;
178162306a36Sopenharmony_ci}
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_cistatic enum wmi_txbf_conf ath10k_wmi_tlv_txbf_conf_scheme(struct ath10k *ar)
178462306a36Sopenharmony_ci{
178562306a36Sopenharmony_ci	return WMI_TXBF_CONF_AFTER_ASSOC;
178662306a36Sopenharmony_ci}
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_cistatic struct sk_buff *
178962306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
179062306a36Sopenharmony_ci				     u32 param_value)
179162306a36Sopenharmony_ci{
179262306a36Sopenharmony_ci	struct wmi_tlv_pdev_set_param_cmd *cmd;
179362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
179462306a36Sopenharmony_ci	struct sk_buff *skb;
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
179762306a36Sopenharmony_ci	if (!skb)
179862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	tlv = (void *)skb->data;
180162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD);
180262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
180362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
180462306a36Sopenharmony_ci	cmd->param_id = __cpu_to_le32(param_id);
180562306a36Sopenharmony_ci	cmd->param_value = __cpu_to_le32(param_value);
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n",
180862306a36Sopenharmony_ci		   param_id, param_value);
180962306a36Sopenharmony_ci	return skb;
181062306a36Sopenharmony_ci}
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_cistatic void
181362306a36Sopenharmony_ciath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
181462306a36Sopenharmony_ci{
181562306a36Sopenharmony_ci	struct host_memory_chunk_tlv *chunk;
181662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
181762306a36Sopenharmony_ci	dma_addr_t paddr;
181862306a36Sopenharmony_ci	int i;
181962306a36Sopenharmony_ci	__le16 tlv_len, tlv_tag;
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK);
182262306a36Sopenharmony_ci	tlv_len = __cpu_to_le16(sizeof(*chunk));
182362306a36Sopenharmony_ci	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
182462306a36Sopenharmony_ci		tlv = host_mem_chunks;
182562306a36Sopenharmony_ci		tlv->tag = tlv_tag;
182662306a36Sopenharmony_ci		tlv->len = tlv_len;
182762306a36Sopenharmony_ci		chunk = (void *)tlv->value;
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci		chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
183062306a36Sopenharmony_ci		chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
183162306a36Sopenharmony_ci		chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci		if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
183462306a36Sopenharmony_ci			     ar->wmi.svc_map)) {
183562306a36Sopenharmony_ci			paddr = ar->wmi.mem_chunks[i].paddr;
183662306a36Sopenharmony_ci			chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr));
183762306a36Sopenharmony_ci		}
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci		ath10k_dbg(ar, ATH10K_DBG_WMI,
184062306a36Sopenharmony_ci			   "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
184162306a36Sopenharmony_ci			   i,
184262306a36Sopenharmony_ci			   ar->wmi.mem_chunks[i].len,
184362306a36Sopenharmony_ci			   (unsigned long long)ar->wmi.mem_chunks[i].paddr,
184462306a36Sopenharmony_ci			   ar->wmi.mem_chunks[i].req_id);
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci		host_mem_chunks += sizeof(*tlv);
184762306a36Sopenharmony_ci		host_mem_chunks += sizeof(*chunk);
184862306a36Sopenharmony_ci	}
184962306a36Sopenharmony_ci}
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_cistatic struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
185262306a36Sopenharmony_ci{
185362306a36Sopenharmony_ci	struct sk_buff *skb;
185462306a36Sopenharmony_ci	struct wmi_tlv *tlv;
185562306a36Sopenharmony_ci	struct wmi_tlv_init_cmd *cmd;
185662306a36Sopenharmony_ci	struct wmi_tlv_resource_config *cfg;
185762306a36Sopenharmony_ci	void *chunks;
185862306a36Sopenharmony_ci	size_t len, chunks_len;
185962306a36Sopenharmony_ci	void *ptr;
186062306a36Sopenharmony_ci
186162306a36Sopenharmony_ci	chunks_len = ar->wmi.num_mem_chunks *
186262306a36Sopenharmony_ci		     (sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv));
186362306a36Sopenharmony_ci	len = (sizeof(*tlv) + sizeof(*cmd)) +
186462306a36Sopenharmony_ci	      (sizeof(*tlv) + sizeof(*cfg)) +
186562306a36Sopenharmony_ci	      (sizeof(*tlv) + chunks_len);
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
186862306a36Sopenharmony_ci	if (!skb)
186962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	ptr = skb->data;
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci	tlv = ptr;
187462306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_INIT_CMD);
187562306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
187662306a36Sopenharmony_ci	cmd = (void *)tlv->value;
187762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
187862306a36Sopenharmony_ci	ptr += sizeof(*cmd);
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	tlv = ptr;
188162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG);
188262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cfg));
188362306a36Sopenharmony_ci	cfg = (void *)tlv->value;
188462306a36Sopenharmony_ci	ptr += sizeof(*tlv);
188562306a36Sopenharmony_ci	ptr += sizeof(*cfg);
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	tlv = ptr;
188862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
188962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(chunks_len);
189062306a36Sopenharmony_ci	chunks = (void *)tlv->value;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	ptr += sizeof(*tlv);
189362306a36Sopenharmony_ci	ptr += chunks_len;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	cmd->abi.abi_ver0 = __cpu_to_le32(WMI_TLV_ABI_VER0);
189662306a36Sopenharmony_ci	cmd->abi.abi_ver1 = __cpu_to_le32(WMI_TLV_ABI_VER1);
189762306a36Sopenharmony_ci	cmd->abi.abi_ver_ns0 = __cpu_to_le32(WMI_TLV_ABI_VER_NS0);
189862306a36Sopenharmony_ci	cmd->abi.abi_ver_ns1 = __cpu_to_le32(WMI_TLV_ABI_VER_NS1);
189962306a36Sopenharmony_ci	cmd->abi.abi_ver_ns2 = __cpu_to_le32(WMI_TLV_ABI_VER_NS2);
190062306a36Sopenharmony_ci	cmd->abi.abi_ver_ns3 = __cpu_to_le32(WMI_TLV_ABI_VER_NS3);
190162306a36Sopenharmony_ci	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	if (ar->hw_params.num_peers)
190662306a36Sopenharmony_ci		cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers);
190762306a36Sopenharmony_ci	else
190862306a36Sopenharmony_ci		cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
190962306a36Sopenharmony_ci	cfg->ast_skid_limit = __cpu_to_le32(ar->hw_params.ast_skid_limit);
191062306a36Sopenharmony_ci	cfg->num_wds_entries = __cpu_to_le32(ar->hw_params.num_wds_entries);
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
191362306a36Sopenharmony_ci		cfg->num_offload_peers = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
191462306a36Sopenharmony_ci		cfg->num_offload_reorder_bufs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
191562306a36Sopenharmony_ci	} else {
191662306a36Sopenharmony_ci		cfg->num_offload_peers = __cpu_to_le32(0);
191762306a36Sopenharmony_ci		cfg->num_offload_reorder_bufs = __cpu_to_le32(0);
191862306a36Sopenharmony_ci	}
191962306a36Sopenharmony_ci
192062306a36Sopenharmony_ci	cfg->num_peer_keys = __cpu_to_le32(2);
192162306a36Sopenharmony_ci	if (ar->hw_params.num_peers)
192262306a36Sopenharmony_ci		cfg->num_tids = __cpu_to_le32(ar->hw_params.num_peers * 2);
192362306a36Sopenharmony_ci	else
192462306a36Sopenharmony_ci		cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
192562306a36Sopenharmony_ci	cfg->tx_chain_mask = __cpu_to_le32(0x7);
192662306a36Sopenharmony_ci	cfg->rx_chain_mask = __cpu_to_le32(0x7);
192762306a36Sopenharmony_ci	cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
192862306a36Sopenharmony_ci	cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64);
192962306a36Sopenharmony_ci	cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64);
193062306a36Sopenharmony_ci	cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28);
193162306a36Sopenharmony_ci	cfg->rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
193262306a36Sopenharmony_ci	cfg->scan_max_pending_reqs = __cpu_to_le32(4);
193362306a36Sopenharmony_ci	cfg->bmiss_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
193462306a36Sopenharmony_ci	cfg->roam_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
193562306a36Sopenharmony_ci	cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8);
193662306a36Sopenharmony_ci	cfg->num_mcast_groups = __cpu_to_le32(0);
193762306a36Sopenharmony_ci	cfg->num_mcast_table_elems = __cpu_to_le32(0);
193862306a36Sopenharmony_ci	cfg->mcast2ucast_mode = __cpu_to_le32(0);
193962306a36Sopenharmony_ci	cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
194062306a36Sopenharmony_ci	cfg->dma_burst_size = __cpu_to_le32(0);
194162306a36Sopenharmony_ci	cfg->mac_aggr_delim = __cpu_to_le32(0);
194262306a36Sopenharmony_ci	cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
194362306a36Sopenharmony_ci	cfg->vow_config = __cpu_to_le32(0);
194462306a36Sopenharmony_ci	cfg->gtk_offload_max_vdev = __cpu_to_le32(2);
194562306a36Sopenharmony_ci	cfg->num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx);
194662306a36Sopenharmony_ci	cfg->max_frag_entries = __cpu_to_le32(2);
194762306a36Sopenharmony_ci	cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS);
194862306a36Sopenharmony_ci	cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
194962306a36Sopenharmony_ci	cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2);
195062306a36Sopenharmony_ci	cfg->num_multicast_filter_entries = __cpu_to_le32(5);
195162306a36Sopenharmony_ci	cfg->num_wow_filters = __cpu_to_le32(ar->wow.max_num_patterns);
195262306a36Sopenharmony_ci	cfg->num_keep_alive_pattern = __cpu_to_le32(6);
195362306a36Sopenharmony_ci	cfg->keep_alive_pattern_size = __cpu_to_le32(0);
195462306a36Sopenharmony_ci	cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1);
195562306a36Sopenharmony_ci	cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1);
195662306a36Sopenharmony_ci	cfg->wmi_send_separate = __cpu_to_le32(0);
195762306a36Sopenharmony_ci	cfg->num_ocb_vdevs = __cpu_to_le32(0);
195862306a36Sopenharmony_ci	cfg->num_ocb_channels = __cpu_to_le32(0);
195962306a36Sopenharmony_ci	cfg->num_ocb_schedules = __cpu_to_le32(0);
196062306a36Sopenharmony_ci	cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL);
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
196362306a36Sopenharmony_ci		cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci	ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks);
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
196862306a36Sopenharmony_ci	return skb;
196962306a36Sopenharmony_ci}
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_cistatic struct sk_buff *
197262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
197362306a36Sopenharmony_ci				 const struct wmi_start_scan_arg *arg)
197462306a36Sopenharmony_ci{
197562306a36Sopenharmony_ci	struct wmi_tlv_start_scan_cmd *cmd;
197662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
197762306a36Sopenharmony_ci	struct sk_buff *skb;
197862306a36Sopenharmony_ci	size_t len, chan_len, ssid_len, bssid_len, ie_len;
197962306a36Sopenharmony_ci	__le32 *chans;
198062306a36Sopenharmony_ci	struct wmi_ssid *ssids;
198162306a36Sopenharmony_ci	struct wmi_mac_addr *addrs;
198262306a36Sopenharmony_ci	void *ptr;
198362306a36Sopenharmony_ci	int i, ret;
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	ret = ath10k_wmi_start_scan_verify(arg);
198662306a36Sopenharmony_ci	if (ret)
198762306a36Sopenharmony_ci		return ERR_PTR(ret);
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	chan_len = arg->n_channels * sizeof(__le32);
199062306a36Sopenharmony_ci	ssid_len = arg->n_ssids * sizeof(struct wmi_ssid);
199162306a36Sopenharmony_ci	bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr);
199262306a36Sopenharmony_ci	ie_len = roundup(arg->ie_len, 4);
199362306a36Sopenharmony_ci	len = (sizeof(*tlv) + sizeof(*cmd)) +
199462306a36Sopenharmony_ci	      sizeof(*tlv) + chan_len +
199562306a36Sopenharmony_ci	      sizeof(*tlv) + ssid_len +
199662306a36Sopenharmony_ci	      sizeof(*tlv) + bssid_len +
199762306a36Sopenharmony_ci	      sizeof(*tlv) + ie_len;
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
200062306a36Sopenharmony_ci	if (!skb)
200162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci	ptr = (void *)skb->data;
200462306a36Sopenharmony_ci	tlv = ptr;
200562306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_START_SCAN_CMD);
200662306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
200762306a36Sopenharmony_ci	cmd = (void *)tlv->value;
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
201062306a36Sopenharmony_ci	cmd->burst_duration_ms = __cpu_to_le32(arg->burst_duration_ms);
201162306a36Sopenharmony_ci	cmd->num_channels = __cpu_to_le32(arg->n_channels);
201262306a36Sopenharmony_ci	cmd->num_ssids = __cpu_to_le32(arg->n_ssids);
201362306a36Sopenharmony_ci	cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
201462306a36Sopenharmony_ci	cmd->ie_len = __cpu_to_le32(arg->ie_len);
201562306a36Sopenharmony_ci	cmd->num_probes = __cpu_to_le32(3);
201662306a36Sopenharmony_ci	ether_addr_copy(cmd->mac_addr.addr, arg->mac_addr.addr);
201762306a36Sopenharmony_ci	ether_addr_copy(cmd->mac_mask.addr, arg->mac_mask.addr);
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci	/* FIXME: There are some scan flag inconsistencies across firmwares,
202062306a36Sopenharmony_ci	 * e.g. WMI-TLV inverts the logic behind the following flag.
202162306a36Sopenharmony_ci	 */
202262306a36Sopenharmony_ci	cmd->common.scan_ctrl_flags ^= __cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci	ptr += sizeof(*tlv);
202562306a36Sopenharmony_ci	ptr += sizeof(*cmd);
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	tlv = ptr;
202862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
202962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(chan_len);
203062306a36Sopenharmony_ci	chans = (void *)tlv->value;
203162306a36Sopenharmony_ci	for (i = 0; i < arg->n_channels; i++)
203262306a36Sopenharmony_ci		chans[i] = __cpu_to_le32(arg->channels[i]);
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ci	ptr += sizeof(*tlv);
203562306a36Sopenharmony_ci	ptr += chan_len;
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_ci	tlv = ptr;
203862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
203962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(ssid_len);
204062306a36Sopenharmony_ci	ssids = (void *)tlv->value;
204162306a36Sopenharmony_ci	for (i = 0; i < arg->n_ssids; i++) {
204262306a36Sopenharmony_ci		ssids[i].ssid_len = __cpu_to_le32(arg->ssids[i].len);
204362306a36Sopenharmony_ci		memcpy(ssids[i].ssid, arg->ssids[i].ssid, arg->ssids[i].len);
204462306a36Sopenharmony_ci	}
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_ci	ptr += sizeof(*tlv);
204762306a36Sopenharmony_ci	ptr += ssid_len;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	tlv = ptr;
205062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
205162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(bssid_len);
205262306a36Sopenharmony_ci	addrs = (void *)tlv->value;
205362306a36Sopenharmony_ci	for (i = 0; i < arg->n_bssids; i++)
205462306a36Sopenharmony_ci		ether_addr_copy(addrs[i].addr, arg->bssids[i].bssid);
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci	ptr += sizeof(*tlv);
205762306a36Sopenharmony_ci	ptr += bssid_len;
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_ci	tlv = ptr;
206062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
206162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(ie_len);
206262306a36Sopenharmony_ci	memcpy(tlv->value, arg->ie, arg->ie_len);
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	ptr += sizeof(*tlv);
206562306a36Sopenharmony_ci	ptr += ie_len;
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start scan\n");
206862306a36Sopenharmony_ci	return skb;
206962306a36Sopenharmony_ci}
207062306a36Sopenharmony_ci
207162306a36Sopenharmony_cistatic struct sk_buff *
207262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar,
207362306a36Sopenharmony_ci				const struct wmi_stop_scan_arg *arg)
207462306a36Sopenharmony_ci{
207562306a36Sopenharmony_ci	struct wmi_stop_scan_cmd *cmd;
207662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
207762306a36Sopenharmony_ci	struct sk_buff *skb;
207862306a36Sopenharmony_ci	u32 scan_id;
207962306a36Sopenharmony_ci	u32 req_id;
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	if (arg->req_id > 0xFFF)
208262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
208362306a36Sopenharmony_ci	if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
208462306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
208762306a36Sopenharmony_ci	if (!skb)
208862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	scan_id = arg->u.scan_id;
209162306a36Sopenharmony_ci	scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci	req_id = arg->req_id;
209462306a36Sopenharmony_ci	req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_ci	tlv = (void *)skb->data;
209762306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD);
209862306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
209962306a36Sopenharmony_ci	cmd = (void *)tlv->value;
210062306a36Sopenharmony_ci	cmd->req_type = __cpu_to_le32(arg->req_type);
210162306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id);
210262306a36Sopenharmony_ci	cmd->scan_id = __cpu_to_le32(scan_id);
210362306a36Sopenharmony_ci	cmd->scan_req_id = __cpu_to_le32(req_id);
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop scan\n");
210662306a36Sopenharmony_ci	return skb;
210762306a36Sopenharmony_ci}
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_cistatic int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar,
211062306a36Sopenharmony_ci					      enum wmi_vdev_subtype subtype)
211162306a36Sopenharmony_ci{
211262306a36Sopenharmony_ci	switch (subtype) {
211362306a36Sopenharmony_ci	case WMI_VDEV_SUBTYPE_NONE:
211462306a36Sopenharmony_ci		return WMI_TLV_VDEV_SUBTYPE_NONE;
211562306a36Sopenharmony_ci	case WMI_VDEV_SUBTYPE_P2P_DEVICE:
211662306a36Sopenharmony_ci		return WMI_TLV_VDEV_SUBTYPE_P2P_DEV;
211762306a36Sopenharmony_ci	case WMI_VDEV_SUBTYPE_P2P_CLIENT:
211862306a36Sopenharmony_ci		return WMI_TLV_VDEV_SUBTYPE_P2P_CLI;
211962306a36Sopenharmony_ci	case WMI_VDEV_SUBTYPE_P2P_GO:
212062306a36Sopenharmony_ci		return WMI_TLV_VDEV_SUBTYPE_P2P_GO;
212162306a36Sopenharmony_ci	case WMI_VDEV_SUBTYPE_PROXY_STA:
212262306a36Sopenharmony_ci		return WMI_TLV_VDEV_SUBTYPE_PROXY_STA;
212362306a36Sopenharmony_ci	case WMI_VDEV_SUBTYPE_MESH_11S:
212462306a36Sopenharmony_ci		return WMI_TLV_VDEV_SUBTYPE_MESH_11S;
212562306a36Sopenharmony_ci	case WMI_VDEV_SUBTYPE_MESH_NON_11S:
212662306a36Sopenharmony_ci		return -ENOTSUPP;
212762306a36Sopenharmony_ci	}
212862306a36Sopenharmony_ci	return -ENOTSUPP;
212962306a36Sopenharmony_ci}
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_cistatic struct sk_buff *
213262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar,
213362306a36Sopenharmony_ci				  u32 vdev_id,
213462306a36Sopenharmony_ci				  enum wmi_vdev_type vdev_type,
213562306a36Sopenharmony_ci				  enum wmi_vdev_subtype vdev_subtype,
213662306a36Sopenharmony_ci				  const u8 mac_addr[ETH_ALEN])
213762306a36Sopenharmony_ci{
213862306a36Sopenharmony_ci	struct wmi_vdev_create_cmd *cmd;
213962306a36Sopenharmony_ci	struct wmi_tlv *tlv;
214062306a36Sopenharmony_ci	struct sk_buff *skb;
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
214362306a36Sopenharmony_ci	if (!skb)
214462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci	tlv = (void *)skb->data;
214762306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD);
214862306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
214962306a36Sopenharmony_ci	cmd = (void *)tlv->value;
215062306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
215162306a36Sopenharmony_ci	cmd->vdev_type = __cpu_to_le32(vdev_type);
215262306a36Sopenharmony_ci	cmd->vdev_subtype = __cpu_to_le32(vdev_subtype);
215362306a36Sopenharmony_ci	ether_addr_copy(cmd->vdev_macaddr.addr, mac_addr);
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev create\n");
215662306a36Sopenharmony_ci	return skb;
215762306a36Sopenharmony_ci}
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_cistatic struct sk_buff *
216062306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
216162306a36Sopenharmony_ci{
216262306a36Sopenharmony_ci	struct wmi_vdev_delete_cmd *cmd;
216362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
216462306a36Sopenharmony_ci	struct sk_buff *skb;
216562306a36Sopenharmony_ci
216662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
216762306a36Sopenharmony_ci	if (!skb)
216862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	tlv = (void *)skb->data;
217162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD);
217262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
217362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
217462306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
217562306a36Sopenharmony_ci
217662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev delete\n");
217762306a36Sopenharmony_ci	return skb;
217862306a36Sopenharmony_ci}
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_cistatic struct sk_buff *
218162306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
218262306a36Sopenharmony_ci				 const struct wmi_vdev_start_request_arg *arg,
218362306a36Sopenharmony_ci				 bool restart)
218462306a36Sopenharmony_ci{
218562306a36Sopenharmony_ci	struct wmi_tlv_vdev_start_cmd *cmd;
218662306a36Sopenharmony_ci	struct wmi_channel *ch;
218762306a36Sopenharmony_ci	struct wmi_tlv *tlv;
218862306a36Sopenharmony_ci	struct sk_buff *skb;
218962306a36Sopenharmony_ci	size_t len;
219062306a36Sopenharmony_ci	void *ptr;
219162306a36Sopenharmony_ci	u32 flags = 0;
219262306a36Sopenharmony_ci
219362306a36Sopenharmony_ci	if (WARN_ON(arg->hidden_ssid && !arg->ssid))
219462306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
219562306a36Sopenharmony_ci	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
219662306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	len = (sizeof(*tlv) + sizeof(*cmd)) +
219962306a36Sopenharmony_ci	      (sizeof(*tlv) + sizeof(*ch)) +
220062306a36Sopenharmony_ci	      (sizeof(*tlv) + 0);
220162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
220262306a36Sopenharmony_ci	if (!skb)
220362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci	if (arg->hidden_ssid)
220662306a36Sopenharmony_ci		flags |= WMI_VDEV_START_HIDDEN_SSID;
220762306a36Sopenharmony_ci	if (arg->pmf_enabled)
220862306a36Sopenharmony_ci		flags |= WMI_VDEV_START_PMF_ENABLED;
220962306a36Sopenharmony_ci
221062306a36Sopenharmony_ci	ptr = (void *)skb->data;
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	tlv = ptr;
221362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD);
221462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
221562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
221662306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
221762306a36Sopenharmony_ci	cmd->bcn_intval = __cpu_to_le32(arg->bcn_intval);
221862306a36Sopenharmony_ci	cmd->dtim_period = __cpu_to_le32(arg->dtim_period);
221962306a36Sopenharmony_ci	cmd->flags = __cpu_to_le32(flags);
222062306a36Sopenharmony_ci	cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate);
222162306a36Sopenharmony_ci	cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power);
222262306a36Sopenharmony_ci	cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack);
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ci	if (arg->ssid) {
222562306a36Sopenharmony_ci		cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len);
222662306a36Sopenharmony_ci		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
222762306a36Sopenharmony_ci	}
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
223062306a36Sopenharmony_ci	ptr += sizeof(*cmd);
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_ci	tlv = ptr;
223362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
223462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*ch));
223562306a36Sopenharmony_ci	ch = (void *)tlv->value;
223662306a36Sopenharmony_ci	ath10k_wmi_put_wmi_channel(ar, ch, &arg->channel);
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci	ptr += sizeof(*tlv);
223962306a36Sopenharmony_ci	ptr += sizeof(*ch);
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	tlv = ptr;
224262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
224362306a36Sopenharmony_ci	tlv->len = 0;
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	/* Note: This is a nested TLV containing:
224662306a36Sopenharmony_ci	 * [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
224762306a36Sopenharmony_ci	 */
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
225062306a36Sopenharmony_ci	ptr += 0;
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev start\n");
225362306a36Sopenharmony_ci	return skb;
225462306a36Sopenharmony_ci}
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_cistatic struct sk_buff *
225762306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
225862306a36Sopenharmony_ci{
225962306a36Sopenharmony_ci	struct wmi_vdev_stop_cmd *cmd;
226062306a36Sopenharmony_ci	struct wmi_tlv *tlv;
226162306a36Sopenharmony_ci	struct sk_buff *skb;
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
226462306a36Sopenharmony_ci	if (!skb)
226562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	tlv = (void *)skb->data;
226862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD);
226962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
227062306a36Sopenharmony_ci	cmd = (void *)tlv->value;
227162306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev stop\n");
227462306a36Sopenharmony_ci	return skb;
227562306a36Sopenharmony_ci}
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_cistatic struct sk_buff *
227862306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
227962306a36Sopenharmony_ci			      const u8 *bssid)
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci{
228262306a36Sopenharmony_ci	struct wmi_vdev_up_cmd *cmd;
228362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
228462306a36Sopenharmony_ci	struct sk_buff *skb;
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
228762306a36Sopenharmony_ci	if (!skb)
228862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci	tlv = (void *)skb->data;
229162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_UP_CMD);
229262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
229362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
229462306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
229562306a36Sopenharmony_ci	cmd->vdev_assoc_id = __cpu_to_le32(aid);
229662306a36Sopenharmony_ci	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev up\n");
229962306a36Sopenharmony_ci	return skb;
230062306a36Sopenharmony_ci}
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_cistatic struct sk_buff *
230362306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
230462306a36Sopenharmony_ci{
230562306a36Sopenharmony_ci	struct wmi_vdev_down_cmd *cmd;
230662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
230762306a36Sopenharmony_ci	struct sk_buff *skb;
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
231062306a36Sopenharmony_ci	if (!skb)
231162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_ci	tlv = (void *)skb->data;
231462306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD);
231562306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
231662306a36Sopenharmony_ci	cmd = (void *)tlv->value;
231762306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev down\n");
232062306a36Sopenharmony_ci	return skb;
232162306a36Sopenharmony_ci}
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_cistatic struct sk_buff *
232462306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
232562306a36Sopenharmony_ci				     u32 param_id, u32 param_value)
232662306a36Sopenharmony_ci{
232762306a36Sopenharmony_ci	struct wmi_vdev_set_param_cmd *cmd;
232862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
232962306a36Sopenharmony_ci	struct sk_buff *skb;
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
233262306a36Sopenharmony_ci	if (!skb)
233362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ci	tlv = (void *)skb->data;
233662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD);
233762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
233862306a36Sopenharmony_ci	cmd = (void *)tlv->value;
233962306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
234062306a36Sopenharmony_ci	cmd->param_id = __cpu_to_le32(param_id);
234162306a36Sopenharmony_ci	cmd->param_value = __cpu_to_le32(param_value);
234262306a36Sopenharmony_ci
234362306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n",
234462306a36Sopenharmony_ci		   vdev_id, param_id, param_value);
234562306a36Sopenharmony_ci	return skb;
234662306a36Sopenharmony_ci}
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_cistatic struct sk_buff *
234962306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
235062306a36Sopenharmony_ci				       const struct wmi_vdev_install_key_arg *arg)
235162306a36Sopenharmony_ci{
235262306a36Sopenharmony_ci	struct wmi_vdev_install_key_cmd *cmd;
235362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
235462306a36Sopenharmony_ci	struct sk_buff *skb;
235562306a36Sopenharmony_ci	size_t len;
235662306a36Sopenharmony_ci	void *ptr;
235762306a36Sopenharmony_ci
235862306a36Sopenharmony_ci	if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
235962306a36Sopenharmony_ci	    arg->key_data)
236062306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
236162306a36Sopenharmony_ci	if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
236262306a36Sopenharmony_ci	    !arg->key_data)
236362306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
236462306a36Sopenharmony_ci
236562306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
236662306a36Sopenharmony_ci	      sizeof(*tlv) + roundup(arg->key_len, sizeof(__le32));
236762306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
236862306a36Sopenharmony_ci	if (!skb)
236962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	ptr = (void *)skb->data;
237262306a36Sopenharmony_ci	tlv = ptr;
237362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD);
237462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
237562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
237662306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
237762306a36Sopenharmony_ci	cmd->key_idx = __cpu_to_le32(arg->key_idx);
237862306a36Sopenharmony_ci	cmd->key_flags = __cpu_to_le32(arg->key_flags);
237962306a36Sopenharmony_ci	cmd->key_cipher = __cpu_to_le32(arg->key_cipher);
238062306a36Sopenharmony_ci	cmd->key_len = __cpu_to_le32(arg->key_len);
238162306a36Sopenharmony_ci	cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len);
238262306a36Sopenharmony_ci	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	if (arg->macaddr)
238562306a36Sopenharmony_ci		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
238862306a36Sopenharmony_ci	ptr += sizeof(*cmd);
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	tlv = ptr;
239162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
239262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(roundup(arg->key_len, sizeof(__le32)));
239362306a36Sopenharmony_ci	if (arg->key_data)
239462306a36Sopenharmony_ci		memcpy(tlv->value, arg->key_data, arg->key_len);
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci	ptr += sizeof(*tlv);
239762306a36Sopenharmony_ci	ptr += roundup(arg->key_len, sizeof(__le32));
239862306a36Sopenharmony_ci
239962306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev install key\n");
240062306a36Sopenharmony_ci	return skb;
240162306a36Sopenharmony_ci}
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_cistatic void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr,
240462306a36Sopenharmony_ci					 const struct wmi_sta_uapsd_auto_trig_arg *arg)
240562306a36Sopenharmony_ci{
240662306a36Sopenharmony_ci	struct wmi_sta_uapsd_auto_trig_param *ac;
240762306a36Sopenharmony_ci	struct wmi_tlv *tlv;
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	tlv = ptr;
241062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM);
241162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*ac));
241262306a36Sopenharmony_ci	ac = (void *)tlv->value;
241362306a36Sopenharmony_ci
241462306a36Sopenharmony_ci	ac->wmm_ac = __cpu_to_le32(arg->wmm_ac);
241562306a36Sopenharmony_ci	ac->user_priority = __cpu_to_le32(arg->user_priority);
241662306a36Sopenharmony_ci	ac->service_interval = __cpu_to_le32(arg->service_interval);
241762306a36Sopenharmony_ci	ac->suspend_interval = __cpu_to_le32(arg->suspend_interval);
241862306a36Sopenharmony_ci	ac->delay_interval = __cpu_to_le32(arg->delay_interval);
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
242162306a36Sopenharmony_ci		   "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n",
242262306a36Sopenharmony_ci		   ac->wmm_ac, ac->user_priority, ac->service_interval,
242362306a36Sopenharmony_ci		   ac->suspend_interval, ac->delay_interval);
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_ci	return ptr + sizeof(*tlv) + sizeof(*ac);
242662306a36Sopenharmony_ci}
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_cistatic struct sk_buff *
242962306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id,
243062306a36Sopenharmony_ci				     const u8 peer_addr[ETH_ALEN],
243162306a36Sopenharmony_ci				     const struct wmi_sta_uapsd_auto_trig_arg *args,
243262306a36Sopenharmony_ci				     u32 num_ac)
243362306a36Sopenharmony_ci{
243462306a36Sopenharmony_ci	struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd;
243562306a36Sopenharmony_ci	struct wmi_sta_uapsd_auto_trig_param *ac;
243662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
243762306a36Sopenharmony_ci	struct sk_buff *skb;
243862306a36Sopenharmony_ci	size_t len;
243962306a36Sopenharmony_ci	size_t ac_tlv_len;
244062306a36Sopenharmony_ci	void *ptr;
244162306a36Sopenharmony_ci	int i;
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_ci	ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac));
244462306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
244562306a36Sopenharmony_ci	      sizeof(*tlv) + ac_tlv_len;
244662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
244762306a36Sopenharmony_ci	if (!skb)
244862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	ptr = (void *)skb->data;
245162306a36Sopenharmony_ci	tlv = ptr;
245262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD);
245362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
245462306a36Sopenharmony_ci	cmd = (void *)tlv->value;
245562306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
245662306a36Sopenharmony_ci	cmd->num_ac = __cpu_to_le32(num_ac);
245762306a36Sopenharmony_ci	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
246062306a36Sopenharmony_ci	ptr += sizeof(*cmd);
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci	tlv = ptr;
246362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
246462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(ac_tlv_len);
246562306a36Sopenharmony_ci	ac = (void *)tlv->value;
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
246862306a36Sopenharmony_ci	for (i = 0; i < num_ac; i++)
246962306a36Sopenharmony_ci		ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]);
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n");
247262306a36Sopenharmony_ci	return skb;
247362306a36Sopenharmony_ci}
247462306a36Sopenharmony_ci
247562306a36Sopenharmony_cistatic void *ath10k_wmi_tlv_put_wmm(void *ptr,
247662306a36Sopenharmony_ci				    const struct wmi_wmm_params_arg *arg)
247762306a36Sopenharmony_ci{
247862306a36Sopenharmony_ci	struct wmi_wmm_params *wmm;
247962306a36Sopenharmony_ci	struct wmi_tlv *tlv;
248062306a36Sopenharmony_ci
248162306a36Sopenharmony_ci	tlv = ptr;
248262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS);
248362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*wmm));
248462306a36Sopenharmony_ci	wmm = (void *)tlv->value;
248562306a36Sopenharmony_ci	ath10k_wmi_set_wmm_param(wmm, arg);
248662306a36Sopenharmony_ci
248762306a36Sopenharmony_ci	return ptr + sizeof(*tlv) + sizeof(*wmm);
248862306a36Sopenharmony_ci}
248962306a36Sopenharmony_ci
249062306a36Sopenharmony_cistatic struct sk_buff *
249162306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
249262306a36Sopenharmony_ci				    const struct wmi_wmm_params_all_arg *arg)
249362306a36Sopenharmony_ci{
249462306a36Sopenharmony_ci	struct wmi_tlv_vdev_set_wmm_cmd *cmd;
249562306a36Sopenharmony_ci	struct wmi_tlv *tlv;
249662306a36Sopenharmony_ci	struct sk_buff *skb;
249762306a36Sopenharmony_ci	size_t len;
249862306a36Sopenharmony_ci	void *ptr;
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
250162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
250262306a36Sopenharmony_ci	if (!skb)
250362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
250462306a36Sopenharmony_ci
250562306a36Sopenharmony_ci	ptr = (void *)skb->data;
250662306a36Sopenharmony_ci	tlv = ptr;
250762306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD);
250862306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
250962306a36Sopenharmony_ci	cmd = (void *)tlv->value;
251062306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[0].params, &arg->ac_be);
251362306a36Sopenharmony_ci	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[1].params, &arg->ac_bk);
251462306a36Sopenharmony_ci	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[2].params, &arg->ac_vi);
251562306a36Sopenharmony_ci	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[3].params, &arg->ac_vo);
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n");
251862306a36Sopenharmony_ci	return skb;
251962306a36Sopenharmony_ci}
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_cistatic struct sk_buff *
252262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar,
252362306a36Sopenharmony_ci				    const struct wmi_sta_keepalive_arg *arg)
252462306a36Sopenharmony_ci{
252562306a36Sopenharmony_ci	struct wmi_tlv_sta_keepalive_cmd *cmd;
252662306a36Sopenharmony_ci	struct wmi_sta_keepalive_arp_resp *arp;
252762306a36Sopenharmony_ci	struct sk_buff *skb;
252862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
252962306a36Sopenharmony_ci	void *ptr;
253062306a36Sopenharmony_ci	size_t len;
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
253362306a36Sopenharmony_ci	      sizeof(*tlv) + sizeof(*arp);
253462306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
253562306a36Sopenharmony_ci	if (!skb)
253662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
253762306a36Sopenharmony_ci
253862306a36Sopenharmony_ci	ptr = (void *)skb->data;
253962306a36Sopenharmony_ci	tlv = ptr;
254062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD);
254162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
254262306a36Sopenharmony_ci	cmd = (void *)tlv->value;
254362306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
254462306a36Sopenharmony_ci	cmd->enabled = __cpu_to_le32(arg->enabled);
254562306a36Sopenharmony_ci	cmd->method = __cpu_to_le32(arg->method);
254662306a36Sopenharmony_ci	cmd->interval = __cpu_to_le32(arg->interval);
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	ptr += sizeof(*tlv);
254962306a36Sopenharmony_ci	ptr += sizeof(*cmd);
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci	tlv = ptr;
255262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE);
255362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*arp));
255462306a36Sopenharmony_ci	arp = (void *)tlv->value;
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_ci	arp->src_ip4_addr = arg->src_ip4_addr;
255762306a36Sopenharmony_ci	arp->dest_ip4_addr = arg->dest_ip4_addr;
255862306a36Sopenharmony_ci	ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
255962306a36Sopenharmony_ci
256062306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d interval %d\n",
256162306a36Sopenharmony_ci		   arg->vdev_id, arg->enabled, arg->method, arg->interval);
256262306a36Sopenharmony_ci	return skb;
256362306a36Sopenharmony_ci}
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_cistatic struct sk_buff *
256662306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
256762306a36Sopenharmony_ci				  const u8 peer_addr[ETH_ALEN],
256862306a36Sopenharmony_ci				  enum wmi_peer_type peer_type)
256962306a36Sopenharmony_ci{
257062306a36Sopenharmony_ci	struct wmi_tlv_peer_create_cmd *cmd;
257162306a36Sopenharmony_ci	struct wmi_tlv *tlv;
257262306a36Sopenharmony_ci	struct sk_buff *skb;
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
257562306a36Sopenharmony_ci	if (!skb)
257662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci	tlv = (void *)skb->data;
257962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD);
258062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
258162306a36Sopenharmony_ci	cmd = (void *)tlv->value;
258262306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
258362306a36Sopenharmony_ci	cmd->peer_type = __cpu_to_le32(peer_type);
258462306a36Sopenharmony_ci	ether_addr_copy(cmd->peer_addr.addr, peer_addr);
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer create\n");
258762306a36Sopenharmony_ci	return skb;
258862306a36Sopenharmony_ci}
258962306a36Sopenharmony_ci
259062306a36Sopenharmony_cistatic struct sk_buff *
259162306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
259262306a36Sopenharmony_ci				  const u8 peer_addr[ETH_ALEN])
259362306a36Sopenharmony_ci{
259462306a36Sopenharmony_ci	struct wmi_peer_delete_cmd *cmd;
259562306a36Sopenharmony_ci	struct wmi_tlv *tlv;
259662306a36Sopenharmony_ci	struct sk_buff *skb;
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
259962306a36Sopenharmony_ci	if (!skb)
260062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
260162306a36Sopenharmony_ci
260262306a36Sopenharmony_ci	tlv = (void *)skb->data;
260362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD);
260462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
260562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
260662306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
260762306a36Sopenharmony_ci	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete\n");
261062306a36Sopenharmony_ci	return skb;
261162306a36Sopenharmony_ci}
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_cistatic struct sk_buff *
261462306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
261562306a36Sopenharmony_ci				 const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
261662306a36Sopenharmony_ci{
261762306a36Sopenharmony_ci	struct wmi_peer_flush_tids_cmd *cmd;
261862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
261962306a36Sopenharmony_ci	struct sk_buff *skb;
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
262262306a36Sopenharmony_ci	if (!skb)
262362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
262462306a36Sopenharmony_ci
262562306a36Sopenharmony_ci	tlv = (void *)skb->data;
262662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD);
262762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
262862306a36Sopenharmony_ci	cmd = (void *)tlv->value;
262962306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
263062306a36Sopenharmony_ci	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
263162306a36Sopenharmony_ci	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer flush\n");
263462306a36Sopenharmony_ci	return skb;
263562306a36Sopenharmony_ci}
263662306a36Sopenharmony_ci
263762306a36Sopenharmony_cistatic struct sk_buff *
263862306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
263962306a36Sopenharmony_ci				     const u8 *peer_addr,
264062306a36Sopenharmony_ci				     enum wmi_peer_param param_id,
264162306a36Sopenharmony_ci				     u32 param_value)
264262306a36Sopenharmony_ci{
264362306a36Sopenharmony_ci	struct wmi_peer_set_param_cmd *cmd;
264462306a36Sopenharmony_ci	struct wmi_tlv *tlv;
264562306a36Sopenharmony_ci	struct sk_buff *skb;
264662306a36Sopenharmony_ci
264762306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
264862306a36Sopenharmony_ci	if (!skb)
264962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci	tlv = (void *)skb->data;
265262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD);
265362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
265462306a36Sopenharmony_ci	cmd = (void *)tlv->value;
265562306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
265662306a36Sopenharmony_ci	cmd->param_id = __cpu_to_le32(param_id);
265762306a36Sopenharmony_ci	cmd->param_value = __cpu_to_le32(param_value);
265862306a36Sopenharmony_ci	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
266162306a36Sopenharmony_ci		   "wmi tlv vdev %d peer %pM set param %d value 0x%x\n",
266262306a36Sopenharmony_ci		   vdev_id, peer_addr, param_id, param_value);
266362306a36Sopenharmony_ci	return skb;
266462306a36Sopenharmony_ci}
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_cistatic struct sk_buff *
266762306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k *ar,
266862306a36Sopenharmony_ci				 const struct wmi_peer_assoc_complete_arg *arg)
266962306a36Sopenharmony_ci{
267062306a36Sopenharmony_ci	struct wmi_tlv_peer_assoc_cmd *cmd;
267162306a36Sopenharmony_ci	struct wmi_vht_rate_set *vht_rate;
267262306a36Sopenharmony_ci	struct wmi_tlv *tlv;
267362306a36Sopenharmony_ci	struct sk_buff *skb;
267462306a36Sopenharmony_ci	size_t len, legacy_rate_len, ht_rate_len;
267562306a36Sopenharmony_ci	void *ptr;
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci	if (arg->peer_mpdu_density > 16)
267862306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
267962306a36Sopenharmony_ci	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
268062306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
268162306a36Sopenharmony_ci	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
268262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	legacy_rate_len = roundup(arg->peer_legacy_rates.num_rates,
268562306a36Sopenharmony_ci				  sizeof(__le32));
268662306a36Sopenharmony_ci	ht_rate_len = roundup(arg->peer_ht_rates.num_rates, sizeof(__le32));
268762306a36Sopenharmony_ci	len = (sizeof(*tlv) + sizeof(*cmd)) +
268862306a36Sopenharmony_ci	      (sizeof(*tlv) + legacy_rate_len) +
268962306a36Sopenharmony_ci	      (sizeof(*tlv) + ht_rate_len) +
269062306a36Sopenharmony_ci	      (sizeof(*tlv) + sizeof(*vht_rate));
269162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
269262306a36Sopenharmony_ci	if (!skb)
269362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
269462306a36Sopenharmony_ci
269562306a36Sopenharmony_ci	ptr = (void *)skb->data;
269662306a36Sopenharmony_ci	tlv = ptr;
269762306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD);
269862306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
269962306a36Sopenharmony_ci	cmd = (void *)tlv->value;
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
270262306a36Sopenharmony_ci	cmd->new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
270362306a36Sopenharmony_ci	cmd->assoc_id = __cpu_to_le32(arg->peer_aid);
270462306a36Sopenharmony_ci	cmd->flags = __cpu_to_le32(arg->peer_flags);
270562306a36Sopenharmony_ci	cmd->caps = __cpu_to_le32(arg->peer_caps);
270662306a36Sopenharmony_ci	cmd->listen_intval = __cpu_to_le32(arg->peer_listen_intval);
270762306a36Sopenharmony_ci	cmd->ht_caps = __cpu_to_le32(arg->peer_ht_caps);
270862306a36Sopenharmony_ci	cmd->max_mpdu = __cpu_to_le32(arg->peer_max_mpdu);
270962306a36Sopenharmony_ci	cmd->mpdu_density = __cpu_to_le32(arg->peer_mpdu_density);
271062306a36Sopenharmony_ci	cmd->rate_caps = __cpu_to_le32(arg->peer_rate_caps);
271162306a36Sopenharmony_ci	cmd->nss = __cpu_to_le32(arg->peer_num_spatial_streams);
271262306a36Sopenharmony_ci	cmd->vht_caps = __cpu_to_le32(arg->peer_vht_caps);
271362306a36Sopenharmony_ci	cmd->phy_mode = __cpu_to_le32(arg->peer_phymode);
271462306a36Sopenharmony_ci	cmd->num_legacy_rates = __cpu_to_le32(arg->peer_legacy_rates.num_rates);
271562306a36Sopenharmony_ci	cmd->num_ht_rates = __cpu_to_le32(arg->peer_ht_rates.num_rates);
271662306a36Sopenharmony_ci	ether_addr_copy(cmd->mac_addr.addr, arg->addr);
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci	ptr += sizeof(*tlv);
271962306a36Sopenharmony_ci	ptr += sizeof(*cmd);
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_ci	tlv = ptr;
272262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
272362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(legacy_rate_len);
272462306a36Sopenharmony_ci	memcpy(tlv->value, arg->peer_legacy_rates.rates,
272562306a36Sopenharmony_ci	       arg->peer_legacy_rates.num_rates);
272662306a36Sopenharmony_ci
272762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
272862306a36Sopenharmony_ci	ptr += legacy_rate_len;
272962306a36Sopenharmony_ci
273062306a36Sopenharmony_ci	tlv = ptr;
273162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
273262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(ht_rate_len);
273362306a36Sopenharmony_ci	memcpy(tlv->value, arg->peer_ht_rates.rates,
273462306a36Sopenharmony_ci	       arg->peer_ht_rates.num_rates);
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	ptr += sizeof(*tlv);
273762306a36Sopenharmony_ci	ptr += ht_rate_len;
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci	tlv = ptr;
274062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VHT_RATE_SET);
274162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*vht_rate));
274262306a36Sopenharmony_ci	vht_rate = (void *)tlv->value;
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_ci	vht_rate->rx_max_rate = __cpu_to_le32(arg->peer_vht_rates.rx_max_rate);
274562306a36Sopenharmony_ci	vht_rate->rx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set);
274662306a36Sopenharmony_ci	vht_rate->tx_max_rate = __cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
274762306a36Sopenharmony_ci	vht_rate->tx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
275062306a36Sopenharmony_ci	ptr += sizeof(*vht_rate);
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer assoc\n");
275362306a36Sopenharmony_ci	return skb;
275462306a36Sopenharmony_ci}
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_cistatic struct sk_buff *
275762306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
275862306a36Sopenharmony_ci				 enum wmi_sta_ps_mode psmode)
275962306a36Sopenharmony_ci{
276062306a36Sopenharmony_ci	struct wmi_sta_powersave_mode_cmd *cmd;
276162306a36Sopenharmony_ci	struct wmi_tlv *tlv;
276262306a36Sopenharmony_ci	struct sk_buff *skb;
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
276562306a36Sopenharmony_ci	if (!skb)
276662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
276762306a36Sopenharmony_ci
276862306a36Sopenharmony_ci	tlv = (void *)skb->data;
276962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD);
277062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
277162306a36Sopenharmony_ci	cmd = (void *)tlv->value;
277262306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
277362306a36Sopenharmony_ci	cmd->sta_ps_mode = __cpu_to_le32(psmode);
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set psmode\n");
277662306a36Sopenharmony_ci	return skb;
277762306a36Sopenharmony_ci}
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_cistatic struct sk_buff *
278062306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
278162306a36Sopenharmony_ci				 enum wmi_sta_powersave_param param_id,
278262306a36Sopenharmony_ci				 u32 param_value)
278362306a36Sopenharmony_ci{
278462306a36Sopenharmony_ci	struct wmi_sta_powersave_param_cmd *cmd;
278562306a36Sopenharmony_ci	struct wmi_tlv *tlv;
278662306a36Sopenharmony_ci	struct sk_buff *skb;
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
278962306a36Sopenharmony_ci	if (!skb)
279062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
279162306a36Sopenharmony_ci
279262306a36Sopenharmony_ci	tlv = (void *)skb->data;
279362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD);
279462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
279562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
279662306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
279762306a36Sopenharmony_ci	cmd->param_id = __cpu_to_le32(param_id);
279862306a36Sopenharmony_ci	cmd->param_value = __cpu_to_le32(param_value);
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set sta ps\n");
280162306a36Sopenharmony_ci	return skb;
280262306a36Sopenharmony_ci}
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_cistatic struct sk_buff *
280562306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
280662306a36Sopenharmony_ci				enum wmi_ap_ps_peer_param param_id, u32 value)
280762306a36Sopenharmony_ci{
280862306a36Sopenharmony_ci	struct wmi_ap_ps_peer_cmd *cmd;
280962306a36Sopenharmony_ci	struct wmi_tlv *tlv;
281062306a36Sopenharmony_ci	struct sk_buff *skb;
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci	if (!mac)
281362306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
281662306a36Sopenharmony_ci	if (!skb)
281762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
281862306a36Sopenharmony_ci
281962306a36Sopenharmony_ci	tlv = (void *)skb->data;
282062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD);
282162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
282262306a36Sopenharmony_ci	cmd = (void *)tlv->value;
282362306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
282462306a36Sopenharmony_ci	cmd->param_id = __cpu_to_le32(param_id);
282562306a36Sopenharmony_ci	cmd->param_value = __cpu_to_le32(value);
282662306a36Sopenharmony_ci	ether_addr_copy(cmd->peer_macaddr.addr, mac);
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv ap ps param\n");
282962306a36Sopenharmony_ci	return skb;
283062306a36Sopenharmony_ci}
283162306a36Sopenharmony_ci
283262306a36Sopenharmony_cistatic struct sk_buff *
283362306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
283462306a36Sopenharmony_ci				     const struct wmi_scan_chan_list_arg *arg)
283562306a36Sopenharmony_ci{
283662306a36Sopenharmony_ci	struct wmi_tlv_scan_chan_list_cmd *cmd;
283762306a36Sopenharmony_ci	struct wmi_channel *ci;
283862306a36Sopenharmony_ci	struct wmi_channel_arg *ch;
283962306a36Sopenharmony_ci	struct wmi_tlv *tlv;
284062306a36Sopenharmony_ci	struct sk_buff *skb;
284162306a36Sopenharmony_ci	size_t chans_len, len;
284262306a36Sopenharmony_ci	int i;
284362306a36Sopenharmony_ci	void *ptr, *chans;
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci	chans_len = arg->n_channels * (sizeof(*tlv) + sizeof(*ci));
284662306a36Sopenharmony_ci	len = (sizeof(*tlv) + sizeof(*cmd)) +
284762306a36Sopenharmony_ci	      (sizeof(*tlv) + chans_len);
284862306a36Sopenharmony_ci
284962306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
285062306a36Sopenharmony_ci	if (!skb)
285162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	ptr = (void *)skb->data;
285462306a36Sopenharmony_ci	tlv = ptr;
285562306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD);
285662306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
285762306a36Sopenharmony_ci	cmd = (void *)tlv->value;
285862306a36Sopenharmony_ci	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci	ptr += sizeof(*tlv);
286162306a36Sopenharmony_ci	ptr += sizeof(*cmd);
286262306a36Sopenharmony_ci
286362306a36Sopenharmony_ci	tlv = ptr;
286462306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
286562306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(chans_len);
286662306a36Sopenharmony_ci	chans = (void *)tlv->value;
286762306a36Sopenharmony_ci
286862306a36Sopenharmony_ci	for (i = 0; i < arg->n_channels; i++) {
286962306a36Sopenharmony_ci		ch = &arg->channels[i];
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci		tlv = chans;
287262306a36Sopenharmony_ci		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
287362306a36Sopenharmony_ci		tlv->len = __cpu_to_le16(sizeof(*ci));
287462306a36Sopenharmony_ci		ci = (void *)tlv->value;
287562306a36Sopenharmony_ci
287662306a36Sopenharmony_ci		ath10k_wmi_put_wmi_channel(ar, ci, ch);
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci		chans += sizeof(*tlv);
287962306a36Sopenharmony_ci		chans += sizeof(*ci);
288062306a36Sopenharmony_ci	}
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_ci	ptr += sizeof(*tlv);
288362306a36Sopenharmony_ci	ptr += chans_len;
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan chan list\n");
288662306a36Sopenharmony_ci	return skb;
288762306a36Sopenharmony_ci}
288862306a36Sopenharmony_ci
288962306a36Sopenharmony_cistatic struct sk_buff *
289062306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_scan_prob_req_oui(struct ath10k *ar, u32 prob_req_oui)
289162306a36Sopenharmony_ci{
289262306a36Sopenharmony_ci	struct wmi_scan_prob_req_oui_cmd *cmd;
289362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
289462306a36Sopenharmony_ci	struct sk_buff *skb;
289562306a36Sopenharmony_ci
289662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
289762306a36Sopenharmony_ci	if (!skb)
289862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci	tlv = (void *)skb->data;
290162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_PROB_REQ_OUI_CMD);
290262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
290362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
290462306a36Sopenharmony_ci	cmd->prob_req_oui = __cpu_to_le32(prob_req_oui);
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan prob req oui\n");
290762306a36Sopenharmony_ci	return skb;
290862306a36Sopenharmony_ci}
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_cistatic struct sk_buff *
291162306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
291262306a36Sopenharmony_ci				 const void *bcn, size_t bcn_len,
291362306a36Sopenharmony_ci				 u32 bcn_paddr, bool dtim_zero,
291462306a36Sopenharmony_ci				 bool deliver_cab)
291562306a36Sopenharmony_ci
291662306a36Sopenharmony_ci{
291762306a36Sopenharmony_ci	struct wmi_bcn_tx_ref_cmd *cmd;
291862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
291962306a36Sopenharmony_ci	struct sk_buff *skb;
292062306a36Sopenharmony_ci	struct ieee80211_hdr *hdr;
292162306a36Sopenharmony_ci	u16 fc;
292262306a36Sopenharmony_ci
292362306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
292462306a36Sopenharmony_ci	if (!skb)
292562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
292662306a36Sopenharmony_ci
292762306a36Sopenharmony_ci	hdr = (struct ieee80211_hdr *)bcn;
292862306a36Sopenharmony_ci	fc = le16_to_cpu(hdr->frame_control);
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_ci	tlv = (void *)skb->data;
293162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD);
293262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
293362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
293462306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
293562306a36Sopenharmony_ci	cmd->data_len = __cpu_to_le32(bcn_len);
293662306a36Sopenharmony_ci	cmd->data_ptr = __cpu_to_le32(bcn_paddr);
293762306a36Sopenharmony_ci	cmd->msdu_id = 0;
293862306a36Sopenharmony_ci	cmd->frame_control = __cpu_to_le32(fc);
293962306a36Sopenharmony_ci	cmd->flags = 0;
294062306a36Sopenharmony_ci
294162306a36Sopenharmony_ci	if (dtim_zero)
294262306a36Sopenharmony_ci		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
294362306a36Sopenharmony_ci
294462306a36Sopenharmony_ci	if (deliver_cab)
294562306a36Sopenharmony_ci		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n");
294862306a36Sopenharmony_ci	return skb;
294962306a36Sopenharmony_ci}
295062306a36Sopenharmony_ci
295162306a36Sopenharmony_cistatic struct sk_buff *
295262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
295362306a36Sopenharmony_ci				   const struct wmi_wmm_params_all_arg *arg)
295462306a36Sopenharmony_ci{
295562306a36Sopenharmony_ci	struct wmi_tlv_pdev_set_wmm_cmd *cmd;
295662306a36Sopenharmony_ci	struct wmi_wmm_params *wmm;
295762306a36Sopenharmony_ci	struct wmi_tlv *tlv;
295862306a36Sopenharmony_ci	struct sk_buff *skb;
295962306a36Sopenharmony_ci	size_t len;
296062306a36Sopenharmony_ci	void *ptr;
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_ci	len = (sizeof(*tlv) + sizeof(*cmd)) +
296362306a36Sopenharmony_ci	      (4 * (sizeof(*tlv) + sizeof(*wmm)));
296462306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
296562306a36Sopenharmony_ci	if (!skb)
296662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_ci	ptr = (void *)skb->data;
296962306a36Sopenharmony_ci
297062306a36Sopenharmony_ci	tlv = ptr;
297162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD);
297262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
297362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci	/* nothing to set here */
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
297862306a36Sopenharmony_ci	ptr += sizeof(*cmd);
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_ci	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be);
298162306a36Sopenharmony_ci	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk);
298262306a36Sopenharmony_ci	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi);
298362306a36Sopenharmony_ci	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo);
298462306a36Sopenharmony_ci
298562306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set wmm\n");
298662306a36Sopenharmony_ci	return skb;
298762306a36Sopenharmony_ci}
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_cistatic struct sk_buff *
299062306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
299162306a36Sopenharmony_ci{
299262306a36Sopenharmony_ci	struct wmi_request_stats_cmd *cmd;
299362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
299462306a36Sopenharmony_ci	struct sk_buff *skb;
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
299762306a36Sopenharmony_ci	if (!skb)
299862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ci	tlv = (void *)skb->data;
300162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
300262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
300362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
300462306a36Sopenharmony_ci	cmd->stats_id = __cpu_to_le32(stats_mask);
300562306a36Sopenharmony_ci
300662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
300762306a36Sopenharmony_ci	return skb;
300862306a36Sopenharmony_ci}
300962306a36Sopenharmony_ci
301062306a36Sopenharmony_cistatic struct sk_buff *
301162306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_request_peer_stats_info(struct ath10k *ar,
301262306a36Sopenharmony_ci					      u32 vdev_id,
301362306a36Sopenharmony_ci					      enum wmi_peer_stats_info_request_type type,
301462306a36Sopenharmony_ci					      u8 *addr,
301562306a36Sopenharmony_ci					      u32 reset)
301662306a36Sopenharmony_ci{
301762306a36Sopenharmony_ci	struct wmi_tlv_request_peer_stats_info *cmd;
301862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
301962306a36Sopenharmony_ci	struct sk_buff *skb;
302062306a36Sopenharmony_ci
302162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
302262306a36Sopenharmony_ci	if (!skb)
302362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
302462306a36Sopenharmony_ci
302562306a36Sopenharmony_ci	tlv = (void *)skb->data;
302662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_PEER_STATS_INFO_CMD);
302762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
302862306a36Sopenharmony_ci	cmd = (void *)tlv->value;
302962306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
303062306a36Sopenharmony_ci	cmd->request_type = __cpu_to_le32(type);
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci	if (type == WMI_REQUEST_ONE_PEER_STATS_INFO)
303362306a36Sopenharmony_ci		ether_addr_copy(cmd->peer_macaddr.addr, addr);
303462306a36Sopenharmony_ci
303562306a36Sopenharmony_ci	cmd->reset_after_request = __cpu_to_le32(reset);
303662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request peer stats info\n");
303762306a36Sopenharmony_ci	return skb;
303862306a36Sopenharmony_ci}
303962306a36Sopenharmony_ci
304062306a36Sopenharmony_cistatic int
304162306a36Sopenharmony_ciath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
304262306a36Sopenharmony_ci				       struct sk_buff *msdu)
304362306a36Sopenharmony_ci{
304462306a36Sopenharmony_ci	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
304562306a36Sopenharmony_ci	struct ath10k_wmi *wmi = &ar->wmi;
304662306a36Sopenharmony_ci
304762306a36Sopenharmony_ci	idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
304862306a36Sopenharmony_ci
304962306a36Sopenharmony_ci	return 0;
305062306a36Sopenharmony_ci}
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_cistatic int
305362306a36Sopenharmony_ciath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
305462306a36Sopenharmony_ci				 dma_addr_t paddr)
305562306a36Sopenharmony_ci{
305662306a36Sopenharmony_ci	struct ath10k_wmi *wmi = &ar->wmi;
305762306a36Sopenharmony_ci	struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
305862306a36Sopenharmony_ci	int ret;
305962306a36Sopenharmony_ci
306062306a36Sopenharmony_ci	pkt_addr = kmalloc(sizeof(*pkt_addr), GFP_ATOMIC);
306162306a36Sopenharmony_ci	if (!pkt_addr)
306262306a36Sopenharmony_ci		return -ENOMEM;
306362306a36Sopenharmony_ci
306462306a36Sopenharmony_ci	pkt_addr->vaddr = skb;
306562306a36Sopenharmony_ci	pkt_addr->paddr = paddr;
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_ci	spin_lock_bh(&ar->data_lock);
306862306a36Sopenharmony_ci	ret = idr_alloc(&wmi->mgmt_pending_tx, pkt_addr, 0,
306962306a36Sopenharmony_ci			wmi->mgmt_max_num_pending_tx, GFP_ATOMIC);
307062306a36Sopenharmony_ci	spin_unlock_bh(&ar->data_lock);
307162306a36Sopenharmony_ci
307262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx alloc msdu_id ret %d\n", ret);
307362306a36Sopenharmony_ci	return ret;
307462306a36Sopenharmony_ci}
307562306a36Sopenharmony_ci
307662306a36Sopenharmony_cistatic struct sk_buff *
307762306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
307862306a36Sopenharmony_ci				   dma_addr_t paddr)
307962306a36Sopenharmony_ci{
308062306a36Sopenharmony_ci	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
308162306a36Sopenharmony_ci	struct wmi_tlv_mgmt_tx_cmd *cmd;
308262306a36Sopenharmony_ci	struct ieee80211_hdr *hdr;
308362306a36Sopenharmony_ci	struct ath10k_vif *arvif;
308462306a36Sopenharmony_ci	u32 buf_len = msdu->len;
308562306a36Sopenharmony_ci	struct wmi_tlv *tlv;
308662306a36Sopenharmony_ci	struct sk_buff *skb;
308762306a36Sopenharmony_ci	int len, desc_id;
308862306a36Sopenharmony_ci	u32 vdev_id;
308962306a36Sopenharmony_ci	void *ptr;
309062306a36Sopenharmony_ci
309162306a36Sopenharmony_ci	if (!cb->vif)
309262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
309362306a36Sopenharmony_ci
309462306a36Sopenharmony_ci	hdr = (struct ieee80211_hdr *)msdu->data;
309562306a36Sopenharmony_ci	arvif = (void *)cb->vif->drv_priv;
309662306a36Sopenharmony_ci	vdev_id = arvif->vdev_id;
309762306a36Sopenharmony_ci
309862306a36Sopenharmony_ci	if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
309962306a36Sopenharmony_ci			 (!(ieee80211_is_nullfunc(hdr->frame_control) ||
310062306a36Sopenharmony_ci			 ieee80211_is_qos_nullfunc(hdr->frame_control)))))
310162306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
310262306a36Sopenharmony_ci
310362306a36Sopenharmony_ci	len = sizeof(*cmd) + 2 * sizeof(*tlv);
310462306a36Sopenharmony_ci
310562306a36Sopenharmony_ci	if ((ieee80211_is_action(hdr->frame_control) ||
310662306a36Sopenharmony_ci	     ieee80211_is_deauth(hdr->frame_control) ||
310762306a36Sopenharmony_ci	     ieee80211_is_disassoc(hdr->frame_control)) &&
310862306a36Sopenharmony_ci	     ieee80211_has_protected(hdr->frame_control)) {
310962306a36Sopenharmony_ci		skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
311062306a36Sopenharmony_ci		buf_len += IEEE80211_CCMP_MIC_LEN;
311162306a36Sopenharmony_ci	}
311262306a36Sopenharmony_ci
311362306a36Sopenharmony_ci	buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN);
311462306a36Sopenharmony_ci	buf_len = round_up(buf_len, 4);
311562306a36Sopenharmony_ci
311662306a36Sopenharmony_ci	len += buf_len;
311762306a36Sopenharmony_ci	len = round_up(len, 4);
311862306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
311962306a36Sopenharmony_ci	if (!skb)
312062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
312162306a36Sopenharmony_ci
312262306a36Sopenharmony_ci	desc_id = ath10k_wmi_mgmt_tx_alloc_msdu_id(ar, msdu, paddr);
312362306a36Sopenharmony_ci	if (desc_id < 0)
312462306a36Sopenharmony_ci		goto err_free_skb;
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci	cb->msdu_id = desc_id;
312762306a36Sopenharmony_ci
312862306a36Sopenharmony_ci	ptr = (void *)skb->data;
312962306a36Sopenharmony_ci	tlv = ptr;
313062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
313162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
313262306a36Sopenharmony_ci	cmd = (void *)tlv->value;
313362306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
313462306a36Sopenharmony_ci	cmd->desc_id = __cpu_to_le32(desc_id);
313562306a36Sopenharmony_ci	cmd->chanfreq = 0;
313662306a36Sopenharmony_ci	cmd->buf_len = __cpu_to_le32(buf_len);
313762306a36Sopenharmony_ci	cmd->frame_len = __cpu_to_le32(msdu->len);
313862306a36Sopenharmony_ci	cmd->paddr = __cpu_to_le64(paddr);
313962306a36Sopenharmony_ci
314062306a36Sopenharmony_ci	ptr += sizeof(*tlv);
314162306a36Sopenharmony_ci	ptr += sizeof(*cmd);
314262306a36Sopenharmony_ci
314362306a36Sopenharmony_ci	tlv = ptr;
314462306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
314562306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(buf_len);
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
314862306a36Sopenharmony_ci	memcpy(ptr, msdu->data, buf_len);
314962306a36Sopenharmony_ci
315062306a36Sopenharmony_ci	return skb;
315162306a36Sopenharmony_ci
315262306a36Sopenharmony_cierr_free_skb:
315362306a36Sopenharmony_ci	dev_kfree_skb(skb);
315462306a36Sopenharmony_ci	return ERR_PTR(desc_id);
315562306a36Sopenharmony_ci}
315662306a36Sopenharmony_ci
315762306a36Sopenharmony_cistatic struct sk_buff *
315862306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
315962306a36Sopenharmony_ci				    enum wmi_force_fw_hang_type type,
316062306a36Sopenharmony_ci				    u32 delay_ms)
316162306a36Sopenharmony_ci{
316262306a36Sopenharmony_ci	struct wmi_force_fw_hang_cmd *cmd;
316362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
316462306a36Sopenharmony_ci	struct sk_buff *skb;
316562306a36Sopenharmony_ci
316662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
316762306a36Sopenharmony_ci	if (!skb)
316862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci	tlv = (void *)skb->data;
317162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD);
317262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
317362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
317462306a36Sopenharmony_ci	cmd->type = __cpu_to_le32(type);
317562306a36Sopenharmony_ci	cmd->delay_ms = __cpu_to_le32(delay_ms);
317662306a36Sopenharmony_ci
317762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv force fw hang\n");
317862306a36Sopenharmony_ci	return skb;
317962306a36Sopenharmony_ci}
318062306a36Sopenharmony_ci
318162306a36Sopenharmony_cistatic struct sk_buff *
318262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u64 module_enable,
318362306a36Sopenharmony_ci				 u32 log_level)
318462306a36Sopenharmony_ci{
318562306a36Sopenharmony_ci	struct wmi_tlv_dbglog_cmd *cmd;
318662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
318762306a36Sopenharmony_ci	struct sk_buff *skb;
318862306a36Sopenharmony_ci	size_t len, bmap_len;
318962306a36Sopenharmony_ci	u32 value;
319062306a36Sopenharmony_ci	void *ptr;
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci	if (module_enable) {
319362306a36Sopenharmony_ci		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
319462306a36Sopenharmony_ci				module_enable,
319562306a36Sopenharmony_ci				WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE);
319662306a36Sopenharmony_ci	} else {
319762306a36Sopenharmony_ci		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
319862306a36Sopenharmony_ci				WMI_TLV_DBGLOG_ALL_MODULES,
319962306a36Sopenharmony_ci				WMI_TLV_DBGLOG_LOG_LEVEL_WARN);
320062306a36Sopenharmony_ci	}
320162306a36Sopenharmony_ci
320262306a36Sopenharmony_ci	bmap_len = 0;
320362306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) + sizeof(*tlv) + bmap_len;
320462306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
320562306a36Sopenharmony_ci	if (!skb)
320662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
320762306a36Sopenharmony_ci
320862306a36Sopenharmony_ci	ptr = (void *)skb->data;
320962306a36Sopenharmony_ci
321062306a36Sopenharmony_ci	tlv = ptr;
321162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD);
321262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
321362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
321462306a36Sopenharmony_ci	cmd->param = __cpu_to_le32(WMI_TLV_DBGLOG_PARAM_LOG_LEVEL);
321562306a36Sopenharmony_ci	cmd->value = __cpu_to_le32(value);
321662306a36Sopenharmony_ci
321762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
321862306a36Sopenharmony_ci	ptr += sizeof(*cmd);
321962306a36Sopenharmony_ci
322062306a36Sopenharmony_ci	tlv = ptr;
322162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
322262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(bmap_len);
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ci	/* nothing to do here */
322562306a36Sopenharmony_ci
322662306a36Sopenharmony_ci	ptr += sizeof(*tlv);
322762306a36Sopenharmony_ci	ptr += sizeof(bmap_len);
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv dbglog value 0x%08x\n", value);
323062306a36Sopenharmony_ci	return skb;
323162306a36Sopenharmony_ci}
323262306a36Sopenharmony_ci
323362306a36Sopenharmony_cistatic struct sk_buff *
323462306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
323562306a36Sopenharmony_ci{
323662306a36Sopenharmony_ci	struct wmi_tlv_pktlog_enable *cmd;
323762306a36Sopenharmony_ci	struct wmi_tlv *tlv;
323862306a36Sopenharmony_ci	struct sk_buff *skb;
323962306a36Sopenharmony_ci	void *ptr;
324062306a36Sopenharmony_ci	size_t len;
324162306a36Sopenharmony_ci
324262306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
324362306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
324462306a36Sopenharmony_ci	if (!skb)
324562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ci	ptr = (void *)skb->data;
324862306a36Sopenharmony_ci	tlv = ptr;
324962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD);
325062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
325162306a36Sopenharmony_ci	cmd = (void *)tlv->value;
325262306a36Sopenharmony_ci	cmd->filter = __cpu_to_le32(filter);
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	ptr += sizeof(*tlv);
325562306a36Sopenharmony_ci	ptr += sizeof(*cmd);
325662306a36Sopenharmony_ci
325762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog enable filter 0x%08x\n",
325862306a36Sopenharmony_ci		   filter);
325962306a36Sopenharmony_ci	return skb;
326062306a36Sopenharmony_ci}
326162306a36Sopenharmony_ci
326262306a36Sopenharmony_cistatic struct sk_buff *
326362306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pdev_get_temperature(struct ath10k *ar)
326462306a36Sopenharmony_ci{
326562306a36Sopenharmony_ci	struct wmi_tlv_pdev_get_temp_cmd *cmd;
326662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
326762306a36Sopenharmony_ci	struct sk_buff *skb;
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
327062306a36Sopenharmony_ci	if (!skb)
327162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
327262306a36Sopenharmony_ci
327362306a36Sopenharmony_ci	tlv = (void *)skb->data;
327462306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_GET_TEMPERATURE_CMD);
327562306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
327662306a36Sopenharmony_ci	cmd = (void *)tlv->value;
327762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev get temperature tlv\n");
327862306a36Sopenharmony_ci	return skb;
327962306a36Sopenharmony_ci}
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_cistatic struct sk_buff *
328262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar)
328362306a36Sopenharmony_ci{
328462306a36Sopenharmony_ci	struct wmi_tlv_pktlog_disable *cmd;
328562306a36Sopenharmony_ci	struct wmi_tlv *tlv;
328662306a36Sopenharmony_ci	struct sk_buff *skb;
328762306a36Sopenharmony_ci	void *ptr;
328862306a36Sopenharmony_ci	size_t len;
328962306a36Sopenharmony_ci
329062306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
329162306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
329262306a36Sopenharmony_ci	if (!skb)
329362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
329462306a36Sopenharmony_ci
329562306a36Sopenharmony_ci	ptr = (void *)skb->data;
329662306a36Sopenharmony_ci	tlv = ptr;
329762306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD);
329862306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
329962306a36Sopenharmony_ci	cmd = (void *)tlv->value;
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	ptr += sizeof(*tlv);
330262306a36Sopenharmony_ci	ptr += sizeof(*cmd);
330362306a36Sopenharmony_ci
330462306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog disable\n");
330562306a36Sopenharmony_ci	return skb;
330662306a36Sopenharmony_ci}
330762306a36Sopenharmony_ci
330862306a36Sopenharmony_cistatic struct sk_buff *
330962306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id,
331062306a36Sopenharmony_ci			       u32 tim_ie_offset, struct sk_buff *bcn,
331162306a36Sopenharmony_ci			       u32 prb_caps, u32 prb_erp, void *prb_ies,
331262306a36Sopenharmony_ci			       size_t prb_ies_len)
331362306a36Sopenharmony_ci{
331462306a36Sopenharmony_ci	struct wmi_tlv_bcn_tmpl_cmd *cmd;
331562306a36Sopenharmony_ci	struct wmi_tlv_bcn_prb_info *info;
331662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
331762306a36Sopenharmony_ci	struct sk_buff *skb;
331862306a36Sopenharmony_ci	void *ptr;
331962306a36Sopenharmony_ci	size_t len;
332062306a36Sopenharmony_ci
332162306a36Sopenharmony_ci	if (WARN_ON(prb_ies_len > 0 && !prb_ies))
332262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
332362306a36Sopenharmony_ci
332462306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
332562306a36Sopenharmony_ci	      sizeof(*tlv) + sizeof(*info) + prb_ies_len +
332662306a36Sopenharmony_ci	      sizeof(*tlv) + roundup(bcn->len, 4);
332762306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
332862306a36Sopenharmony_ci	if (!skb)
332962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
333062306a36Sopenharmony_ci
333162306a36Sopenharmony_ci	ptr = (void *)skb->data;
333262306a36Sopenharmony_ci	tlv = ptr;
333362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD);
333462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
333562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
333662306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
333762306a36Sopenharmony_ci	cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset);
333862306a36Sopenharmony_ci	cmd->buf_len = __cpu_to_le32(bcn->len);
333962306a36Sopenharmony_ci
334062306a36Sopenharmony_ci	ptr += sizeof(*tlv);
334162306a36Sopenharmony_ci	ptr += sizeof(*cmd);
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	/* FIXME: prb_ies_len should be probably aligned to 4byte boundary but
334462306a36Sopenharmony_ci	 * then it is then impossible to pass original ie len.
334562306a36Sopenharmony_ci	 * This chunk is not used yet so if setting probe resp template yields
334662306a36Sopenharmony_ci	 * problems with beaconing or crashes firmware look here.
334762306a36Sopenharmony_ci	 */
334862306a36Sopenharmony_ci	tlv = ptr;
334962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
335062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len);
335162306a36Sopenharmony_ci	info = (void *)tlv->value;
335262306a36Sopenharmony_ci	info->caps = __cpu_to_le32(prb_caps);
335362306a36Sopenharmony_ci	info->erp = __cpu_to_le32(prb_erp);
335462306a36Sopenharmony_ci	memcpy(info->ies, prb_ies, prb_ies_len);
335562306a36Sopenharmony_ci
335662306a36Sopenharmony_ci	ptr += sizeof(*tlv);
335762306a36Sopenharmony_ci	ptr += sizeof(*info);
335862306a36Sopenharmony_ci	ptr += prb_ies_len;
335962306a36Sopenharmony_ci
336062306a36Sopenharmony_ci	tlv = ptr;
336162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
336262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(roundup(bcn->len, 4));
336362306a36Sopenharmony_ci	memcpy(tlv->value, bcn->data, bcn->len);
336462306a36Sopenharmony_ci
336562306a36Sopenharmony_ci	/* FIXME: Adjust TSF? */
336662306a36Sopenharmony_ci
336762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n",
336862306a36Sopenharmony_ci		   vdev_id);
336962306a36Sopenharmony_ci	return skb;
337062306a36Sopenharmony_ci}
337162306a36Sopenharmony_ci
337262306a36Sopenharmony_cistatic struct sk_buff *
337362306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id,
337462306a36Sopenharmony_ci			       struct sk_buff *prb)
337562306a36Sopenharmony_ci{
337662306a36Sopenharmony_ci	struct wmi_tlv_prb_tmpl_cmd *cmd;
337762306a36Sopenharmony_ci	struct wmi_tlv_bcn_prb_info *info;
337862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
337962306a36Sopenharmony_ci	struct sk_buff *skb;
338062306a36Sopenharmony_ci	void *ptr;
338162306a36Sopenharmony_ci	size_t len;
338262306a36Sopenharmony_ci
338362306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
338462306a36Sopenharmony_ci	      sizeof(*tlv) + sizeof(*info) +
338562306a36Sopenharmony_ci	      sizeof(*tlv) + roundup(prb->len, 4);
338662306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
338762306a36Sopenharmony_ci	if (!skb)
338862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
338962306a36Sopenharmony_ci
339062306a36Sopenharmony_ci	ptr = (void *)skb->data;
339162306a36Sopenharmony_ci	tlv = ptr;
339262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD);
339362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
339462306a36Sopenharmony_ci	cmd = (void *)tlv->value;
339562306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
339662306a36Sopenharmony_ci	cmd->buf_len = __cpu_to_le32(prb->len);
339762306a36Sopenharmony_ci
339862306a36Sopenharmony_ci	ptr += sizeof(*tlv);
339962306a36Sopenharmony_ci	ptr += sizeof(*cmd);
340062306a36Sopenharmony_ci
340162306a36Sopenharmony_ci	tlv = ptr;
340262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
340362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*info));
340462306a36Sopenharmony_ci	info = (void *)tlv->value;
340562306a36Sopenharmony_ci	info->caps = 0;
340662306a36Sopenharmony_ci	info->erp = 0;
340762306a36Sopenharmony_ci
340862306a36Sopenharmony_ci	ptr += sizeof(*tlv);
340962306a36Sopenharmony_ci	ptr += sizeof(*info);
341062306a36Sopenharmony_ci
341162306a36Sopenharmony_ci	tlv = ptr;
341262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
341362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(roundup(prb->len, 4));
341462306a36Sopenharmony_ci	memcpy(tlv->value, prb->data, prb->len);
341562306a36Sopenharmony_ci
341662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n",
341762306a36Sopenharmony_ci		   vdev_id);
341862306a36Sopenharmony_ci	return skb;
341962306a36Sopenharmony_ci}
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_cistatic struct sk_buff *
342262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id,
342362306a36Sopenharmony_ci				    const u8 *p2p_ie)
342462306a36Sopenharmony_ci{
342562306a36Sopenharmony_ci	struct wmi_tlv_p2p_go_bcn_ie *cmd;
342662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
342762306a36Sopenharmony_ci	struct sk_buff *skb;
342862306a36Sopenharmony_ci	void *ptr;
342962306a36Sopenharmony_ci	size_t len;
343062306a36Sopenharmony_ci
343162306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
343262306a36Sopenharmony_ci	      sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4);
343362306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
343462306a36Sopenharmony_ci	if (!skb)
343562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
343662306a36Sopenharmony_ci
343762306a36Sopenharmony_ci	ptr = (void *)skb->data;
343862306a36Sopenharmony_ci	tlv = ptr;
343962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE);
344062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
344162306a36Sopenharmony_ci	cmd = (void *)tlv->value;
344262306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
344362306a36Sopenharmony_ci	cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2);
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_ci	ptr += sizeof(*tlv);
344662306a36Sopenharmony_ci	ptr += sizeof(*cmd);
344762306a36Sopenharmony_ci
344862306a36Sopenharmony_ci	tlv = ptr;
344962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
345062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4));
345162306a36Sopenharmony_ci	memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2);
345262306a36Sopenharmony_ci
345362306a36Sopenharmony_ci	ptr += sizeof(*tlv);
345462306a36Sopenharmony_ci	ptr += roundup(p2p_ie[1] + 2, 4);
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n",
345762306a36Sopenharmony_ci		   vdev_id);
345862306a36Sopenharmony_ci	return skb;
345962306a36Sopenharmony_ci}
346062306a36Sopenharmony_ci
346162306a36Sopenharmony_cistatic struct sk_buff *
346262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
346362306a36Sopenharmony_ci					   enum wmi_tdls_state state)
346462306a36Sopenharmony_ci{
346562306a36Sopenharmony_ci	struct wmi_tdls_set_state_cmd *cmd;
346662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
346762306a36Sopenharmony_ci	struct sk_buff *skb;
346862306a36Sopenharmony_ci	void *ptr;
346962306a36Sopenharmony_ci	size_t len;
347062306a36Sopenharmony_ci	/* Set to options from wmi_tlv_tdls_options,
347162306a36Sopenharmony_ci	 * for now none of them are enabled.
347262306a36Sopenharmony_ci	 */
347362306a36Sopenharmony_ci	u32 options = 0;
347462306a36Sopenharmony_ci
347562306a36Sopenharmony_ci	if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
347662306a36Sopenharmony_ci		options |=  WMI_TLV_TDLS_BUFFER_STA_EN;
347762306a36Sopenharmony_ci
347862306a36Sopenharmony_ci	/* WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL means firm will handle TDLS
347962306a36Sopenharmony_ci	 * link inactivity detecting logic.
348062306a36Sopenharmony_ci	 */
348162306a36Sopenharmony_ci	if (state == WMI_TDLS_ENABLE_ACTIVE)
348262306a36Sopenharmony_ci		state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
348362306a36Sopenharmony_ci
348462306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
348562306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
348662306a36Sopenharmony_ci	if (!skb)
348762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
348862306a36Sopenharmony_ci
348962306a36Sopenharmony_ci	ptr = (void *)skb->data;
349062306a36Sopenharmony_ci	tlv = ptr;
349162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_SET_STATE_CMD);
349262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
349362306a36Sopenharmony_ci
349462306a36Sopenharmony_ci	cmd = (void *)tlv->value;
349562306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
349662306a36Sopenharmony_ci	cmd->state = __cpu_to_le32(state);
349762306a36Sopenharmony_ci	cmd->notification_interval_ms = __cpu_to_le32(5000);
349862306a36Sopenharmony_ci	cmd->tx_discovery_threshold = __cpu_to_le32(100);
349962306a36Sopenharmony_ci	cmd->tx_teardown_threshold = __cpu_to_le32(5);
350062306a36Sopenharmony_ci	cmd->rssi_teardown_threshold = __cpu_to_le32(-75);
350162306a36Sopenharmony_ci	cmd->rssi_delta = __cpu_to_le32(-20);
350262306a36Sopenharmony_ci	cmd->tdls_options = __cpu_to_le32(options);
350362306a36Sopenharmony_ci	cmd->tdls_peer_traffic_ind_window = __cpu_to_le32(2);
350462306a36Sopenharmony_ci	cmd->tdls_peer_traffic_response_timeout_ms = __cpu_to_le32(5000);
350562306a36Sopenharmony_ci	cmd->tdls_puapsd_mask = __cpu_to_le32(0xf);
350662306a36Sopenharmony_ci	cmd->tdls_puapsd_inactivity_time_ms = __cpu_to_le32(0);
350762306a36Sopenharmony_ci	cmd->tdls_puapsd_rx_frame_threshold = __cpu_to_le32(10);
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
351062306a36Sopenharmony_ci	ptr += sizeof(*cmd);
351162306a36Sopenharmony_ci
351262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv update fw tdls state %d for vdev %i\n",
351362306a36Sopenharmony_ci		   state, vdev_id);
351462306a36Sopenharmony_ci	return skb;
351562306a36Sopenharmony_ci}
351662306a36Sopenharmony_ci
351762306a36Sopenharmony_cistatic u32 ath10k_wmi_tlv_prepare_peer_qos(u8 uapsd_queues, u8 sp)
351862306a36Sopenharmony_ci{
351962306a36Sopenharmony_ci	u32 peer_qos = 0;
352062306a36Sopenharmony_ci
352162306a36Sopenharmony_ci	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
352262306a36Sopenharmony_ci		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VO;
352362306a36Sopenharmony_ci	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
352462306a36Sopenharmony_ci		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VI;
352562306a36Sopenharmony_ci	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
352662306a36Sopenharmony_ci		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BK;
352762306a36Sopenharmony_ci	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
352862306a36Sopenharmony_ci		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BE;
352962306a36Sopenharmony_ci
353062306a36Sopenharmony_ci	peer_qos |= SM(sp, WMI_TLV_TDLS_PEER_SP);
353162306a36Sopenharmony_ci
353262306a36Sopenharmony_ci	return peer_qos;
353362306a36Sopenharmony_ci}
353462306a36Sopenharmony_ci
353562306a36Sopenharmony_cistatic struct sk_buff *
353662306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar,
353762306a36Sopenharmony_ci				       const struct wmi_tdls_peer_update_cmd_arg *arg,
353862306a36Sopenharmony_ci				       const struct wmi_tdls_peer_capab_arg *cap,
353962306a36Sopenharmony_ci				       const struct wmi_channel_arg *chan_arg)
354062306a36Sopenharmony_ci{
354162306a36Sopenharmony_ci	struct wmi_tdls_peer_update_cmd *cmd;
354262306a36Sopenharmony_ci	struct wmi_tdls_peer_capab *peer_cap;
354362306a36Sopenharmony_ci	struct wmi_channel *chan;
354462306a36Sopenharmony_ci	struct wmi_tlv *tlv;
354562306a36Sopenharmony_ci	struct sk_buff *skb;
354662306a36Sopenharmony_ci	u32 peer_qos;
354762306a36Sopenharmony_ci	void *ptr;
354862306a36Sopenharmony_ci	int len;
354962306a36Sopenharmony_ci	int i;
355062306a36Sopenharmony_ci
355162306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
355262306a36Sopenharmony_ci	      sizeof(*tlv) + sizeof(*peer_cap) +
355362306a36Sopenharmony_ci	      sizeof(*tlv) + cap->peer_chan_len * sizeof(*chan);
355462306a36Sopenharmony_ci
355562306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
355662306a36Sopenharmony_ci	if (!skb)
355762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
355862306a36Sopenharmony_ci
355962306a36Sopenharmony_ci	ptr = (void *)skb->data;
356062306a36Sopenharmony_ci	tlv = ptr;
356162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_UPDATE_CMD);
356262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
356362306a36Sopenharmony_ci
356462306a36Sopenharmony_ci	cmd = (void *)tlv->value;
356562306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
356662306a36Sopenharmony_ci	ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
356762306a36Sopenharmony_ci	cmd->peer_state = __cpu_to_le32(arg->peer_state);
356862306a36Sopenharmony_ci
356962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
357062306a36Sopenharmony_ci	ptr += sizeof(*cmd);
357162306a36Sopenharmony_ci
357262306a36Sopenharmony_ci	tlv = ptr;
357362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_CAPABILITIES);
357462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*peer_cap));
357562306a36Sopenharmony_ci	peer_cap = (void *)tlv->value;
357662306a36Sopenharmony_ci	peer_qos = ath10k_wmi_tlv_prepare_peer_qos(cap->peer_uapsd_queues,
357762306a36Sopenharmony_ci						   cap->peer_max_sp);
357862306a36Sopenharmony_ci	peer_cap->peer_qos = __cpu_to_le32(peer_qos);
357962306a36Sopenharmony_ci	peer_cap->buff_sta_support = __cpu_to_le32(cap->buff_sta_support);
358062306a36Sopenharmony_ci	peer_cap->off_chan_support = __cpu_to_le32(cap->off_chan_support);
358162306a36Sopenharmony_ci	peer_cap->peer_curr_operclass = __cpu_to_le32(cap->peer_curr_operclass);
358262306a36Sopenharmony_ci	peer_cap->self_curr_operclass = __cpu_to_le32(cap->self_curr_operclass);
358362306a36Sopenharmony_ci	peer_cap->peer_chan_len = __cpu_to_le32(cap->peer_chan_len);
358462306a36Sopenharmony_ci	peer_cap->peer_operclass_len = __cpu_to_le32(cap->peer_operclass_len);
358562306a36Sopenharmony_ci
358662306a36Sopenharmony_ci	for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++)
358762306a36Sopenharmony_ci		peer_cap->peer_operclass[i] = cap->peer_operclass[i];
358862306a36Sopenharmony_ci
358962306a36Sopenharmony_ci	peer_cap->is_peer_responder = __cpu_to_le32(cap->is_peer_responder);
359062306a36Sopenharmony_ci	peer_cap->pref_offchan_num = __cpu_to_le32(cap->pref_offchan_num);
359162306a36Sopenharmony_ci	peer_cap->pref_offchan_bw = __cpu_to_le32(cap->pref_offchan_bw);
359262306a36Sopenharmony_ci
359362306a36Sopenharmony_ci	ptr += sizeof(*tlv);
359462306a36Sopenharmony_ci	ptr += sizeof(*peer_cap);
359562306a36Sopenharmony_ci
359662306a36Sopenharmony_ci	tlv = ptr;
359762306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
359862306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(cap->peer_chan_len * sizeof(*chan));
359962306a36Sopenharmony_ci
360062306a36Sopenharmony_ci	ptr += sizeof(*tlv);
360162306a36Sopenharmony_ci
360262306a36Sopenharmony_ci	for (i = 0; i < cap->peer_chan_len; i++) {
360362306a36Sopenharmony_ci		tlv = ptr;
360462306a36Sopenharmony_ci		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
360562306a36Sopenharmony_ci		tlv->len = __cpu_to_le16(sizeof(*chan));
360662306a36Sopenharmony_ci		chan = (void *)tlv->value;
360762306a36Sopenharmony_ci		ath10k_wmi_put_wmi_channel(ar, chan, &chan_arg[i]);
360862306a36Sopenharmony_ci
360962306a36Sopenharmony_ci		ptr += sizeof(*tlv);
361062306a36Sopenharmony_ci		ptr += sizeof(*chan);
361162306a36Sopenharmony_ci	}
361262306a36Sopenharmony_ci
361362306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
361462306a36Sopenharmony_ci		   "wmi tlv tdls peer update vdev %i state %d n_chans %u\n",
361562306a36Sopenharmony_ci		   arg->vdev_id, arg->peer_state, cap->peer_chan_len);
361662306a36Sopenharmony_ci	return skb;
361762306a36Sopenharmony_ci}
361862306a36Sopenharmony_ci
361962306a36Sopenharmony_cistatic struct sk_buff *
362062306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period,
362162306a36Sopenharmony_ci					  u32 duration, u32 next_offset,
362262306a36Sopenharmony_ci					  u32 enabled)
362362306a36Sopenharmony_ci{
362462306a36Sopenharmony_ci	struct wmi_tlv_set_quiet_cmd *cmd;
362562306a36Sopenharmony_ci	struct wmi_tlv *tlv;
362662306a36Sopenharmony_ci	struct sk_buff *skb;
362762306a36Sopenharmony_ci
362862306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
362962306a36Sopenharmony_ci	if (!skb)
363062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
363162306a36Sopenharmony_ci
363262306a36Sopenharmony_ci	tlv = (void *)skb->data;
363362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_QUIET_CMD);
363462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
363562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
363662306a36Sopenharmony_ci
363762306a36Sopenharmony_ci	/* vdev_id is not in use, set to 0 */
363862306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(0);
363962306a36Sopenharmony_ci	cmd->period = __cpu_to_le32(period);
364062306a36Sopenharmony_ci	cmd->duration = __cpu_to_le32(duration);
364162306a36Sopenharmony_ci	cmd->next_start = __cpu_to_le32(next_offset);
364262306a36Sopenharmony_ci	cmd->enabled = __cpu_to_le32(enabled);
364362306a36Sopenharmony_ci
364462306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI,
364562306a36Sopenharmony_ci		   "wmi tlv quiet param: period %u duration %u enabled %d\n",
364662306a36Sopenharmony_ci		   period, duration, enabled);
364762306a36Sopenharmony_ci	return skb;
364862306a36Sopenharmony_ci}
364962306a36Sopenharmony_ci
365062306a36Sopenharmony_cistatic struct sk_buff *
365162306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar)
365262306a36Sopenharmony_ci{
365362306a36Sopenharmony_ci	struct wmi_tlv_wow_enable_cmd *cmd;
365462306a36Sopenharmony_ci	struct wmi_tlv *tlv;
365562306a36Sopenharmony_ci	struct sk_buff *skb;
365662306a36Sopenharmony_ci	size_t len;
365762306a36Sopenharmony_ci
365862306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
365962306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
366062306a36Sopenharmony_ci	if (!skb)
366162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
366262306a36Sopenharmony_ci
366362306a36Sopenharmony_ci	tlv = (struct wmi_tlv *)skb->data;
366462306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ENABLE_CMD);
366562306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
366662306a36Sopenharmony_ci	cmd = (void *)tlv->value;
366762306a36Sopenharmony_ci
366862306a36Sopenharmony_ci	cmd->enable = __cpu_to_le32(1);
366962306a36Sopenharmony_ci	if (!ar->bus_param.link_can_suspend)
367062306a36Sopenharmony_ci		cmd->pause_iface_config = __cpu_to_le32(WOW_IFACE_PAUSE_DISABLED);
367162306a36Sopenharmony_ci
367262306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow enable\n");
367362306a36Sopenharmony_ci	return skb;
367462306a36Sopenharmony_ci}
367562306a36Sopenharmony_ci
367662306a36Sopenharmony_cistatic struct sk_buff *
367762306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_wow_add_wakeup_event(struct ath10k *ar,
367862306a36Sopenharmony_ci					   u32 vdev_id,
367962306a36Sopenharmony_ci					   enum wmi_wow_wakeup_event event,
368062306a36Sopenharmony_ci					   u32 enable)
368162306a36Sopenharmony_ci{
368262306a36Sopenharmony_ci	struct wmi_tlv_wow_add_del_event_cmd *cmd;
368362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
368462306a36Sopenharmony_ci	struct sk_buff *skb;
368562306a36Sopenharmony_ci	size_t len;
368662306a36Sopenharmony_ci
368762306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
368862306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
368962306a36Sopenharmony_ci	if (!skb)
369062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
369162306a36Sopenharmony_ci
369262306a36Sopenharmony_ci	tlv = (struct wmi_tlv *)skb->data;
369362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_DEL_EVT_CMD);
369462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
369562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
369662306a36Sopenharmony_ci
369762306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
369862306a36Sopenharmony_ci	cmd->is_add = __cpu_to_le32(enable);
369962306a36Sopenharmony_ci	cmd->event_bitmap = __cpu_to_le32(1 << event);
370062306a36Sopenharmony_ci
370162306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
370262306a36Sopenharmony_ci		   wow_wakeup_event(event), enable, vdev_id);
370362306a36Sopenharmony_ci	return skb;
370462306a36Sopenharmony_ci}
370562306a36Sopenharmony_ci
370662306a36Sopenharmony_cistatic struct sk_buff *
370762306a36Sopenharmony_ciath10k_wmi_tlv_gen_wow_host_wakeup_ind(struct ath10k *ar)
370862306a36Sopenharmony_ci{
370962306a36Sopenharmony_ci	struct wmi_tlv_wow_host_wakeup_ind *cmd;
371062306a36Sopenharmony_ci	struct wmi_tlv *tlv;
371162306a36Sopenharmony_ci	struct sk_buff *skb;
371262306a36Sopenharmony_ci	size_t len;
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
371562306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
371662306a36Sopenharmony_ci	if (!skb)
371762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
371862306a36Sopenharmony_ci
371962306a36Sopenharmony_ci	tlv = (struct wmi_tlv *)skb->data;
372062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_HOSTWAKEUP_FROM_SLEEP_CMD);
372162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
372262306a36Sopenharmony_ci	cmd = (void *)tlv->value;
372362306a36Sopenharmony_ci
372462306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
372562306a36Sopenharmony_ci	return skb;
372662306a36Sopenharmony_ci}
372762306a36Sopenharmony_ci
372862306a36Sopenharmony_cistatic struct sk_buff *
372962306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_wow_add_pattern(struct ath10k *ar, u32 vdev_id,
373062306a36Sopenharmony_ci				      u32 pattern_id, const u8 *pattern,
373162306a36Sopenharmony_ci				      const u8 *bitmask, int pattern_len,
373262306a36Sopenharmony_ci				      int pattern_offset)
373362306a36Sopenharmony_ci{
373462306a36Sopenharmony_ci	struct wmi_tlv_wow_add_pattern_cmd *cmd;
373562306a36Sopenharmony_ci	struct wmi_tlv_wow_bitmap_pattern *bitmap;
373662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
373762306a36Sopenharmony_ci	struct sk_buff *skb;
373862306a36Sopenharmony_ci	void *ptr;
373962306a36Sopenharmony_ci	size_t len;
374062306a36Sopenharmony_ci
374162306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
374262306a36Sopenharmony_ci	      sizeof(*tlv) +			/* array struct */
374362306a36Sopenharmony_ci	      sizeof(*tlv) + sizeof(*bitmap) +  /* bitmap */
374462306a36Sopenharmony_ci	      sizeof(*tlv) +			/* empty ipv4 sync */
374562306a36Sopenharmony_ci	      sizeof(*tlv) +			/* empty ipv6 sync */
374662306a36Sopenharmony_ci	      sizeof(*tlv) +			/* empty magic */
374762306a36Sopenharmony_ci	      sizeof(*tlv) +			/* empty info timeout */
374862306a36Sopenharmony_ci	      sizeof(*tlv) + sizeof(u32);	/* ratelimit interval */
374962306a36Sopenharmony_ci
375062306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
375162306a36Sopenharmony_ci	if (!skb)
375262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
375362306a36Sopenharmony_ci
375462306a36Sopenharmony_ci	/* cmd */
375562306a36Sopenharmony_ci	ptr = (void *)skb->data;
375662306a36Sopenharmony_ci	tlv = ptr;
375762306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_PATTERN_CMD);
375862306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
375962306a36Sopenharmony_ci	cmd = (void *)tlv->value;
376062306a36Sopenharmony_ci
376162306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
376262306a36Sopenharmony_ci	cmd->pattern_id = __cpu_to_le32(pattern_id);
376362306a36Sopenharmony_ci	cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_ci	ptr += sizeof(*tlv);
376662306a36Sopenharmony_ci	ptr += sizeof(*cmd);
376762306a36Sopenharmony_ci
376862306a36Sopenharmony_ci	/* bitmap */
376962306a36Sopenharmony_ci	tlv = ptr;
377062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
377162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*tlv) + sizeof(*bitmap));
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ci	ptr += sizeof(*tlv);
377462306a36Sopenharmony_ci
377562306a36Sopenharmony_ci	tlv = ptr;
377662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_BITMAP_PATTERN_T);
377762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*bitmap));
377862306a36Sopenharmony_ci	bitmap = (void *)tlv->value;
377962306a36Sopenharmony_ci
378062306a36Sopenharmony_ci	memcpy(bitmap->patternbuf, pattern, pattern_len);
378162306a36Sopenharmony_ci	memcpy(bitmap->bitmaskbuf, bitmask, pattern_len);
378262306a36Sopenharmony_ci	bitmap->pattern_offset = __cpu_to_le32(pattern_offset);
378362306a36Sopenharmony_ci	bitmap->pattern_len = __cpu_to_le32(pattern_len);
378462306a36Sopenharmony_ci	bitmap->bitmask_len = __cpu_to_le32(pattern_len);
378562306a36Sopenharmony_ci	bitmap->pattern_id = __cpu_to_le32(pattern_id);
378662306a36Sopenharmony_ci
378762306a36Sopenharmony_ci	ptr += sizeof(*tlv);
378862306a36Sopenharmony_ci	ptr += sizeof(*bitmap);
378962306a36Sopenharmony_ci
379062306a36Sopenharmony_ci	/* ipv4 sync */
379162306a36Sopenharmony_ci	tlv = ptr;
379262306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
379362306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(0);
379462306a36Sopenharmony_ci
379562306a36Sopenharmony_ci	ptr += sizeof(*tlv);
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_ci	/* ipv6 sync */
379862306a36Sopenharmony_ci	tlv = ptr;
379962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
380062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(0);
380162306a36Sopenharmony_ci
380262306a36Sopenharmony_ci	ptr += sizeof(*tlv);
380362306a36Sopenharmony_ci
380462306a36Sopenharmony_ci	/* magic */
380562306a36Sopenharmony_ci	tlv = ptr;
380662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
380762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(0);
380862306a36Sopenharmony_ci
380962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
381062306a36Sopenharmony_ci
381162306a36Sopenharmony_ci	/* pattern info timeout */
381262306a36Sopenharmony_ci	tlv = ptr;
381362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
381462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(0);
381562306a36Sopenharmony_ci
381662306a36Sopenharmony_ci	ptr += sizeof(*tlv);
381762306a36Sopenharmony_ci
381862306a36Sopenharmony_ci	/* ratelimit interval */
381962306a36Sopenharmony_ci	tlv = ptr;
382062306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
382162306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(u32));
382262306a36Sopenharmony_ci
382362306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d, pattern_offset %d\n",
382462306a36Sopenharmony_ci		   vdev_id, pattern_id, pattern_offset);
382562306a36Sopenharmony_ci	return skb;
382662306a36Sopenharmony_ci}
382762306a36Sopenharmony_ci
382862306a36Sopenharmony_cistatic struct sk_buff *
382962306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
383062306a36Sopenharmony_ci				      u32 pattern_id)
383162306a36Sopenharmony_ci{
383262306a36Sopenharmony_ci	struct wmi_tlv_wow_del_pattern_cmd *cmd;
383362306a36Sopenharmony_ci	struct wmi_tlv *tlv;
383462306a36Sopenharmony_ci	struct sk_buff *skb;
383562306a36Sopenharmony_ci	size_t len;
383662306a36Sopenharmony_ci
383762306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
383862306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
383962306a36Sopenharmony_ci	if (!skb)
384062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
384162306a36Sopenharmony_ci
384262306a36Sopenharmony_ci	tlv = (struct wmi_tlv *)skb->data;
384362306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_DEL_PATTERN_CMD);
384462306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
384562306a36Sopenharmony_ci	cmd = (void *)tlv->value;
384662306a36Sopenharmony_ci
384762306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
384862306a36Sopenharmony_ci	cmd->pattern_id = __cpu_to_le32(pattern_id);
384962306a36Sopenharmony_ci	cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
385062306a36Sopenharmony_ci
385162306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
385262306a36Sopenharmony_ci		   vdev_id, pattern_id);
385362306a36Sopenharmony_ci	return skb;
385462306a36Sopenharmony_ci}
385562306a36Sopenharmony_ci
385662306a36Sopenharmony_ci/* Request FW to start PNO operation */
385762306a36Sopenharmony_cistatic struct sk_buff *
385862306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
385962306a36Sopenharmony_ci				       u32 vdev_id,
386062306a36Sopenharmony_ci				       struct wmi_pno_scan_req *pno)
386162306a36Sopenharmony_ci{
386262306a36Sopenharmony_ci	struct nlo_configured_parameters *nlo_list;
386362306a36Sopenharmony_ci	struct wmi_tlv_wow_nlo_config_cmd *cmd;
386462306a36Sopenharmony_ci	struct wmi_tlv *tlv;
386562306a36Sopenharmony_ci	struct sk_buff *skb;
386662306a36Sopenharmony_ci	__le32 *channel_list;
386762306a36Sopenharmony_ci	u16 tlv_len;
386862306a36Sopenharmony_ci	size_t len;
386962306a36Sopenharmony_ci	void *ptr;
387062306a36Sopenharmony_ci	u32 i;
387162306a36Sopenharmony_ci
387262306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
387362306a36Sopenharmony_ci	      sizeof(*tlv) +
387462306a36Sopenharmony_ci	      /* TLV place holder for array of structures
387562306a36Sopenharmony_ci	       * nlo_configured_parameters(nlo_list)
387662306a36Sopenharmony_ci	       */
387762306a36Sopenharmony_ci	      sizeof(*tlv);
387862306a36Sopenharmony_ci	      /* TLV place holder for array of uint32 channel_list */
387962306a36Sopenharmony_ci
388062306a36Sopenharmony_ci	len += sizeof(u32) * min_t(u8, pno->a_networks[0].channel_count,
388162306a36Sopenharmony_ci				   WMI_NLO_MAX_CHAN);
388262306a36Sopenharmony_ci	len += sizeof(struct nlo_configured_parameters) *
388362306a36Sopenharmony_ci				min_t(u8, pno->uc_networks_count, WMI_NLO_MAX_SSIDS);
388462306a36Sopenharmony_ci
388562306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
388662306a36Sopenharmony_ci	if (!skb)
388762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
388862306a36Sopenharmony_ci
388962306a36Sopenharmony_ci	ptr = (void *)skb->data;
389062306a36Sopenharmony_ci	tlv = ptr;
389162306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
389262306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
389362306a36Sopenharmony_ci	cmd = (void *)tlv->value;
389462306a36Sopenharmony_ci
389562306a36Sopenharmony_ci	/* wmi_tlv_wow_nlo_config_cmd parameters*/
389662306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(pno->vdev_id);
389762306a36Sopenharmony_ci	cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);
389862306a36Sopenharmony_ci
389962306a36Sopenharmony_ci	/* current FW does not support min-max range for dwell time */
390062306a36Sopenharmony_ci	cmd->active_dwell_time = __cpu_to_le32(pno->active_max_time);
390162306a36Sopenharmony_ci	cmd->passive_dwell_time = __cpu_to_le32(pno->passive_max_time);
390262306a36Sopenharmony_ci
390362306a36Sopenharmony_ci	if (pno->do_passive_scan)
390462306a36Sopenharmony_ci		cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);
390562306a36Sopenharmony_ci
390662306a36Sopenharmony_ci	/* copy scan interval */
390762306a36Sopenharmony_ci	cmd->fast_scan_period = __cpu_to_le32(pno->fast_scan_period);
390862306a36Sopenharmony_ci	cmd->slow_scan_period = __cpu_to_le32(pno->slow_scan_period);
390962306a36Sopenharmony_ci	cmd->fast_scan_max_cycles = __cpu_to_le32(pno->fast_scan_max_cycles);
391062306a36Sopenharmony_ci	cmd->delay_start_time = __cpu_to_le32(pno->delay_start_time);
391162306a36Sopenharmony_ci
391262306a36Sopenharmony_ci	if (pno->enable_pno_scan_randomization) {
391362306a36Sopenharmony_ci		cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |
391462306a36Sopenharmony_ci				WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);
391562306a36Sopenharmony_ci		ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);
391662306a36Sopenharmony_ci		ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);
391762306a36Sopenharmony_ci	}
391862306a36Sopenharmony_ci
391962306a36Sopenharmony_ci	ptr += sizeof(*tlv);
392062306a36Sopenharmony_ci	ptr += sizeof(*cmd);
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci	/* nlo_configured_parameters(nlo_list) */
392362306a36Sopenharmony_ci	cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
392462306a36Sopenharmony_ci					       WMI_NLO_MAX_SSIDS));
392562306a36Sopenharmony_ci	tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
392662306a36Sopenharmony_ci		sizeof(struct nlo_configured_parameters);
392762306a36Sopenharmony_ci
392862306a36Sopenharmony_ci	tlv = ptr;
392962306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
393062306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(tlv_len);
393162306a36Sopenharmony_ci
393262306a36Sopenharmony_ci	ptr += sizeof(*tlv);
393362306a36Sopenharmony_ci	nlo_list = ptr;
393462306a36Sopenharmony_ci	for (i = 0; i < __le32_to_cpu(cmd->no_of_ssids); i++) {
393562306a36Sopenharmony_ci		tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);
393662306a36Sopenharmony_ci		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
393762306a36Sopenharmony_ci		tlv->len = __cpu_to_le16(sizeof(struct nlo_configured_parameters) -
393862306a36Sopenharmony_ci					 sizeof(*tlv));
393962306a36Sopenharmony_ci
394062306a36Sopenharmony_ci		/* copy ssid and it's length */
394162306a36Sopenharmony_ci		nlo_list[i].ssid.valid = __cpu_to_le32(true);
394262306a36Sopenharmony_ci		nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len;
394362306a36Sopenharmony_ci		memcpy(nlo_list[i].ssid.ssid.ssid,
394462306a36Sopenharmony_ci		       pno->a_networks[i].ssid.ssid,
394562306a36Sopenharmony_ci		       __le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));
394662306a36Sopenharmony_ci
394762306a36Sopenharmony_ci		/* copy rssi threshold */
394862306a36Sopenharmony_ci		if (pno->a_networks[i].rssi_threshold &&
394962306a36Sopenharmony_ci		    pno->a_networks[i].rssi_threshold > -300) {
395062306a36Sopenharmony_ci			nlo_list[i].rssi_cond.valid = __cpu_to_le32(true);
395162306a36Sopenharmony_ci			nlo_list[i].rssi_cond.rssi =
395262306a36Sopenharmony_ci				__cpu_to_le32(pno->a_networks[i].rssi_threshold);
395362306a36Sopenharmony_ci		}
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_ci		nlo_list[i].bcast_nw_type.valid = __cpu_to_le32(true);
395662306a36Sopenharmony_ci		nlo_list[i].bcast_nw_type.bcast_nw_type =
395762306a36Sopenharmony_ci			__cpu_to_le32(pno->a_networks[i].bcast_nw_type);
395862306a36Sopenharmony_ci	}
395962306a36Sopenharmony_ci
396062306a36Sopenharmony_ci	ptr += __le32_to_cpu(cmd->no_of_ssids) * sizeof(struct nlo_configured_parameters);
396162306a36Sopenharmony_ci
396262306a36Sopenharmony_ci	/* copy channel info */
396362306a36Sopenharmony_ci	cmd->num_of_channels = __cpu_to_le32(min_t(u8,
396462306a36Sopenharmony_ci						   pno->a_networks[0].channel_count,
396562306a36Sopenharmony_ci						   WMI_NLO_MAX_CHAN));
396662306a36Sopenharmony_ci
396762306a36Sopenharmony_ci	tlv = ptr;
396862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
396962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(__le32_to_cpu(cmd->num_of_channels) *
397062306a36Sopenharmony_ci				 sizeof(u_int32_t));
397162306a36Sopenharmony_ci	ptr += sizeof(*tlv);
397262306a36Sopenharmony_ci
397362306a36Sopenharmony_ci	channel_list = (__le32 *)ptr;
397462306a36Sopenharmony_ci	for (i = 0; i < __le32_to_cpu(cmd->num_of_channels); i++)
397562306a36Sopenharmony_ci		channel_list[i] = __cpu_to_le32(pno->a_networks[0].channels[i]);
397662306a36Sopenharmony_ci
397762306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
397862306a36Sopenharmony_ci		   vdev_id);
397962306a36Sopenharmony_ci
398062306a36Sopenharmony_ci	return skb;
398162306a36Sopenharmony_ci}
398262306a36Sopenharmony_ci
398362306a36Sopenharmony_ci/* Request FW to stop ongoing PNO operation */
398462306a36Sopenharmony_cistatic struct sk_buff *ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k *ar,
398562306a36Sopenharmony_ci							     u32 vdev_id)
398662306a36Sopenharmony_ci{
398762306a36Sopenharmony_ci	struct wmi_tlv_wow_nlo_config_cmd *cmd;
398862306a36Sopenharmony_ci	struct wmi_tlv *tlv;
398962306a36Sopenharmony_ci	struct sk_buff *skb;
399062306a36Sopenharmony_ci	void *ptr;
399162306a36Sopenharmony_ci	size_t len;
399262306a36Sopenharmony_ci
399362306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd) +
399462306a36Sopenharmony_ci	      sizeof(*tlv) +
399562306a36Sopenharmony_ci	      /* TLV place holder for array of structures
399662306a36Sopenharmony_ci	       * nlo_configured_parameters(nlo_list)
399762306a36Sopenharmony_ci	       */
399862306a36Sopenharmony_ci	      sizeof(*tlv);
399962306a36Sopenharmony_ci	      /* TLV place holder for array of uint32 channel_list */
400062306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
400162306a36Sopenharmony_ci	if (!skb)
400262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
400362306a36Sopenharmony_ci
400462306a36Sopenharmony_ci	ptr = (void *)skb->data;
400562306a36Sopenharmony_ci	tlv = ptr;
400662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
400762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
400862306a36Sopenharmony_ci	cmd = (void *)tlv->value;
400962306a36Sopenharmony_ci
401062306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
401162306a36Sopenharmony_ci	cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_STOP);
401262306a36Sopenharmony_ci
401362306a36Sopenharmony_ci	ptr += sizeof(*tlv);
401462306a36Sopenharmony_ci	ptr += sizeof(*cmd);
401562306a36Sopenharmony_ci
401662306a36Sopenharmony_ci	/* nlo_configured_parameters(nlo_list) */
401762306a36Sopenharmony_ci	tlv = ptr;
401862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
401962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(0);
402062306a36Sopenharmony_ci
402162306a36Sopenharmony_ci	ptr += sizeof(*tlv);
402262306a36Sopenharmony_ci
402362306a36Sopenharmony_ci	/* channel list */
402462306a36Sopenharmony_ci	tlv = ptr;
402562306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
402662306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(0);
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop pno config vdev_id %d\n", vdev_id);
402962306a36Sopenharmony_ci	return skb;
403062306a36Sopenharmony_ci}
403162306a36Sopenharmony_ci
403262306a36Sopenharmony_cistatic struct sk_buff *
403362306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_config_pno(struct ath10k *ar, u32 vdev_id,
403462306a36Sopenharmony_ci				 struct wmi_pno_scan_req *pno_scan)
403562306a36Sopenharmony_ci{
403662306a36Sopenharmony_ci	if (pno_scan->enable)
403762306a36Sopenharmony_ci		return ath10k_wmi_tlv_op_gen_config_pno_start(ar, vdev_id, pno_scan);
403862306a36Sopenharmony_ci	else
403962306a36Sopenharmony_ci		return ath10k_wmi_tlv_op_gen_config_pno_stop(ar, vdev_id);
404062306a36Sopenharmony_ci}
404162306a36Sopenharmony_ci
404262306a36Sopenharmony_cistatic struct sk_buff *
404362306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
404462306a36Sopenharmony_ci{
404562306a36Sopenharmony_ci	struct wmi_tlv_adaptive_qcs *cmd;
404662306a36Sopenharmony_ci	struct wmi_tlv *tlv;
404762306a36Sopenharmony_ci	struct sk_buff *skb;
404862306a36Sopenharmony_ci	void *ptr;
404962306a36Sopenharmony_ci	size_t len;
405062306a36Sopenharmony_ci
405162306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
405262306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
405362306a36Sopenharmony_ci	if (!skb)
405462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
405562306a36Sopenharmony_ci
405662306a36Sopenharmony_ci	ptr = (void *)skb->data;
405762306a36Sopenharmony_ci	tlv = ptr;
405862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESMGR_ADAPTIVE_OCS_CMD);
405962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
406062306a36Sopenharmony_ci	cmd = (void *)tlv->value;
406162306a36Sopenharmony_ci	cmd->enable = __cpu_to_le32(enable ? 1 : 0);
406262306a36Sopenharmony_ci
406362306a36Sopenharmony_ci	ptr += sizeof(*tlv);
406462306a36Sopenharmony_ci	ptr += sizeof(*cmd);
406562306a36Sopenharmony_ci
406662306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv adaptive qcs %d\n", enable);
406762306a36Sopenharmony_ci	return skb;
406862306a36Sopenharmony_ci}
406962306a36Sopenharmony_ci
407062306a36Sopenharmony_cistatic struct sk_buff *
407162306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value)
407262306a36Sopenharmony_ci{
407362306a36Sopenharmony_ci	struct wmi_echo_cmd *cmd;
407462306a36Sopenharmony_ci	struct wmi_tlv *tlv;
407562306a36Sopenharmony_ci	struct sk_buff *skb;
407662306a36Sopenharmony_ci	void *ptr;
407762306a36Sopenharmony_ci	size_t len;
407862306a36Sopenharmony_ci
407962306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
408062306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
408162306a36Sopenharmony_ci	if (!skb)
408262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
408362306a36Sopenharmony_ci
408462306a36Sopenharmony_ci	ptr = (void *)skb->data;
408562306a36Sopenharmony_ci	tlv = ptr;
408662306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_ECHO_CMD);
408762306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
408862306a36Sopenharmony_ci	cmd = (void *)tlv->value;
408962306a36Sopenharmony_ci	cmd->value = cpu_to_le32(value);
409062306a36Sopenharmony_ci
409162306a36Sopenharmony_ci	ptr += sizeof(*tlv);
409262306a36Sopenharmony_ci	ptr += sizeof(*cmd);
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_ci	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv echo value 0x%08x\n", value);
409562306a36Sopenharmony_ci	return skb;
409662306a36Sopenharmony_ci}
409762306a36Sopenharmony_ci
409862306a36Sopenharmony_cistatic struct sk_buff *
409962306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k *ar,
410062306a36Sopenharmony_ci					 const struct wmi_vdev_spectral_conf_arg *arg)
410162306a36Sopenharmony_ci{
410262306a36Sopenharmony_ci	struct wmi_vdev_spectral_conf_cmd *cmd;
410362306a36Sopenharmony_ci	struct sk_buff *skb;
410462306a36Sopenharmony_ci	struct wmi_tlv *tlv;
410562306a36Sopenharmony_ci	void *ptr;
410662306a36Sopenharmony_ci	size_t len;
410762306a36Sopenharmony_ci
410862306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
410962306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
411062306a36Sopenharmony_ci	if (!skb)
411162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
411262306a36Sopenharmony_ci
411362306a36Sopenharmony_ci	ptr = (void *)skb->data;
411462306a36Sopenharmony_ci	tlv = ptr;
411562306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD);
411662306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
411762306a36Sopenharmony_ci	cmd = (void *)tlv->value;
411862306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
411962306a36Sopenharmony_ci	cmd->scan_count = __cpu_to_le32(arg->scan_count);
412062306a36Sopenharmony_ci	cmd->scan_period = __cpu_to_le32(arg->scan_period);
412162306a36Sopenharmony_ci	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
412262306a36Sopenharmony_ci	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
412362306a36Sopenharmony_ci	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
412462306a36Sopenharmony_ci	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
412562306a36Sopenharmony_ci	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
412662306a36Sopenharmony_ci	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
412762306a36Sopenharmony_ci	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
412862306a36Sopenharmony_ci	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
412962306a36Sopenharmony_ci	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
413062306a36Sopenharmony_ci	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
413162306a36Sopenharmony_ci	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
413262306a36Sopenharmony_ci	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
413362306a36Sopenharmony_ci	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
413462306a36Sopenharmony_ci	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
413562306a36Sopenharmony_ci	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
413662306a36Sopenharmony_ci	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
413762306a36Sopenharmony_ci
413862306a36Sopenharmony_ci	return skb;
413962306a36Sopenharmony_ci}
414062306a36Sopenharmony_ci
414162306a36Sopenharmony_cistatic struct sk_buff *
414262306a36Sopenharmony_ciath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
414362306a36Sopenharmony_ci					   u32 trigger, u32 enable)
414462306a36Sopenharmony_ci{
414562306a36Sopenharmony_ci	struct wmi_vdev_spectral_enable_cmd *cmd;
414662306a36Sopenharmony_ci	struct sk_buff *skb;
414762306a36Sopenharmony_ci	struct wmi_tlv *tlv;
414862306a36Sopenharmony_ci	void *ptr;
414962306a36Sopenharmony_ci	size_t len;
415062306a36Sopenharmony_ci
415162306a36Sopenharmony_ci	len = sizeof(*tlv) + sizeof(*cmd);
415262306a36Sopenharmony_ci	skb = ath10k_wmi_alloc_skb(ar, len);
415362306a36Sopenharmony_ci	if (!skb)
415462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
415562306a36Sopenharmony_ci
415662306a36Sopenharmony_ci	ptr = (void *)skb->data;
415762306a36Sopenharmony_ci	tlv = ptr;
415862306a36Sopenharmony_ci	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD);
415962306a36Sopenharmony_ci	tlv->len = __cpu_to_le16(sizeof(*cmd));
416062306a36Sopenharmony_ci	cmd = (void *)tlv->value;
416162306a36Sopenharmony_ci	cmd->vdev_id = __cpu_to_le32(vdev_id);
416262306a36Sopenharmony_ci	cmd->trigger_cmd = __cpu_to_le32(trigger);
416362306a36Sopenharmony_ci	cmd->enable_cmd = __cpu_to_le32(enable);
416462306a36Sopenharmony_ci
416562306a36Sopenharmony_ci	return skb;
416662306a36Sopenharmony_ci}
416762306a36Sopenharmony_ci
416862306a36Sopenharmony_ci/****************/
416962306a36Sopenharmony_ci/* TLV mappings */
417062306a36Sopenharmony_ci/****************/
417162306a36Sopenharmony_ci
417262306a36Sopenharmony_cistatic struct wmi_cmd_map wmi_tlv_cmd_map = {
417362306a36Sopenharmony_ci	.init_cmdid = WMI_TLV_INIT_CMDID,
417462306a36Sopenharmony_ci	.start_scan_cmdid = WMI_TLV_START_SCAN_CMDID,
417562306a36Sopenharmony_ci	.stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
417662306a36Sopenharmony_ci	.scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
417762306a36Sopenharmony_ci	.scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
417862306a36Sopenharmony_ci	.scan_prob_req_oui_cmdid = WMI_TLV_SCAN_PROB_REQ_OUI_CMDID,
417962306a36Sopenharmony_ci	.pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
418062306a36Sopenharmony_ci	.pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
418162306a36Sopenharmony_ci	.pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
418262306a36Sopenharmony_ci	.pdev_pktlog_enable_cmdid = WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID,
418362306a36Sopenharmony_ci	.pdev_pktlog_disable_cmdid = WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID,
418462306a36Sopenharmony_ci	.pdev_set_wmm_params_cmdid = WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID,
418562306a36Sopenharmony_ci	.pdev_set_ht_cap_ie_cmdid = WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID,
418662306a36Sopenharmony_ci	.pdev_set_vht_cap_ie_cmdid = WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID,
418762306a36Sopenharmony_ci	.pdev_set_dscp_tid_map_cmdid = WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID,
418862306a36Sopenharmony_ci	.pdev_set_quiet_mode_cmdid = WMI_TLV_PDEV_SET_QUIET_MODE_CMDID,
418962306a36Sopenharmony_ci	.pdev_green_ap_ps_enable_cmdid = WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID,
419062306a36Sopenharmony_ci	.pdev_get_tpc_config_cmdid = WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID,
419162306a36Sopenharmony_ci	.pdev_set_base_macaddr_cmdid = WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID,
419262306a36Sopenharmony_ci	.vdev_create_cmdid = WMI_TLV_VDEV_CREATE_CMDID,
419362306a36Sopenharmony_ci	.vdev_delete_cmdid = WMI_TLV_VDEV_DELETE_CMDID,
419462306a36Sopenharmony_ci	.vdev_start_request_cmdid = WMI_TLV_VDEV_START_REQUEST_CMDID,
419562306a36Sopenharmony_ci	.vdev_restart_request_cmdid = WMI_TLV_VDEV_RESTART_REQUEST_CMDID,
419662306a36Sopenharmony_ci	.vdev_up_cmdid = WMI_TLV_VDEV_UP_CMDID,
419762306a36Sopenharmony_ci	.vdev_stop_cmdid = WMI_TLV_VDEV_STOP_CMDID,
419862306a36Sopenharmony_ci	.vdev_down_cmdid = WMI_TLV_VDEV_DOWN_CMDID,
419962306a36Sopenharmony_ci	.vdev_set_param_cmdid = WMI_TLV_VDEV_SET_PARAM_CMDID,
420062306a36Sopenharmony_ci	.vdev_install_key_cmdid = WMI_TLV_VDEV_INSTALL_KEY_CMDID,
420162306a36Sopenharmony_ci	.peer_create_cmdid = WMI_TLV_PEER_CREATE_CMDID,
420262306a36Sopenharmony_ci	.peer_delete_cmdid = WMI_TLV_PEER_DELETE_CMDID,
420362306a36Sopenharmony_ci	.peer_flush_tids_cmdid = WMI_TLV_PEER_FLUSH_TIDS_CMDID,
420462306a36Sopenharmony_ci	.peer_set_param_cmdid = WMI_TLV_PEER_SET_PARAM_CMDID,
420562306a36Sopenharmony_ci	.peer_assoc_cmdid = WMI_TLV_PEER_ASSOC_CMDID,
420662306a36Sopenharmony_ci	.peer_add_wds_entry_cmdid = WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID,
420762306a36Sopenharmony_ci	.peer_remove_wds_entry_cmdid = WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID,
420862306a36Sopenharmony_ci	.peer_mcast_group_cmdid = WMI_TLV_PEER_MCAST_GROUP_CMDID,
420962306a36Sopenharmony_ci	.bcn_tx_cmdid = WMI_TLV_BCN_TX_CMDID,
421062306a36Sopenharmony_ci	.pdev_send_bcn_cmdid = WMI_TLV_PDEV_SEND_BCN_CMDID,
421162306a36Sopenharmony_ci	.bcn_tmpl_cmdid = WMI_TLV_BCN_TMPL_CMDID,
421262306a36Sopenharmony_ci	.bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID,
421362306a36Sopenharmony_ci	.prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
421462306a36Sopenharmony_ci	.mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID,
421562306a36Sopenharmony_ci	.mgmt_tx_send_cmdid = WMI_TLV_MGMT_TX_SEND_CMD,
421662306a36Sopenharmony_ci	.prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID,
421762306a36Sopenharmony_ci	.addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID,
421862306a36Sopenharmony_ci	.addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID,
421962306a36Sopenharmony_ci	.addba_status_cmdid = WMI_TLV_ADDBA_STATUS_CMDID,
422062306a36Sopenharmony_ci	.delba_send_cmdid = WMI_TLV_DELBA_SEND_CMDID,
422162306a36Sopenharmony_ci	.addba_set_resp_cmdid = WMI_TLV_ADDBA_SET_RESP_CMDID,
422262306a36Sopenharmony_ci	.send_singleamsdu_cmdid = WMI_TLV_SEND_SINGLEAMSDU_CMDID,
422362306a36Sopenharmony_ci	.sta_powersave_mode_cmdid = WMI_TLV_STA_POWERSAVE_MODE_CMDID,
422462306a36Sopenharmony_ci	.sta_powersave_param_cmdid = WMI_TLV_STA_POWERSAVE_PARAM_CMDID,
422562306a36Sopenharmony_ci	.sta_mimo_ps_mode_cmdid = WMI_TLV_STA_MIMO_PS_MODE_CMDID,
422662306a36Sopenharmony_ci	.pdev_dfs_enable_cmdid = WMI_TLV_PDEV_DFS_ENABLE_CMDID,
422762306a36Sopenharmony_ci	.pdev_dfs_disable_cmdid = WMI_TLV_PDEV_DFS_DISABLE_CMDID,
422862306a36Sopenharmony_ci	.roam_scan_mode = WMI_TLV_ROAM_SCAN_MODE,
422962306a36Sopenharmony_ci	.roam_scan_rssi_threshold = WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD,
423062306a36Sopenharmony_ci	.roam_scan_period = WMI_TLV_ROAM_SCAN_PERIOD,
423162306a36Sopenharmony_ci	.roam_scan_rssi_change_threshold =
423262306a36Sopenharmony_ci				WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
423362306a36Sopenharmony_ci	.roam_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
423462306a36Sopenharmony_ci	.ofl_scan_add_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
423562306a36Sopenharmony_ci	.ofl_scan_remove_ap_profile = WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE,
423662306a36Sopenharmony_ci	.ofl_scan_period = WMI_TLV_OFL_SCAN_PERIOD,
423762306a36Sopenharmony_ci	.p2p_dev_set_device_info = WMI_TLV_P2P_DEV_SET_DEVICE_INFO,
423862306a36Sopenharmony_ci	.p2p_dev_set_discoverability = WMI_TLV_P2P_DEV_SET_DISCOVERABILITY,
423962306a36Sopenharmony_ci	.p2p_go_set_beacon_ie = WMI_TLV_P2P_GO_SET_BEACON_IE,
424062306a36Sopenharmony_ci	.p2p_go_set_probe_resp_ie = WMI_TLV_P2P_GO_SET_PROBE_RESP_IE,
424162306a36Sopenharmony_ci	.p2p_set_vendor_ie_data_cmdid = WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID,
424262306a36Sopenharmony_ci	.ap_ps_peer_param_cmdid = WMI_TLV_AP_PS_PEER_PARAM_CMDID,
424362306a36Sopenharmony_ci	.ap_ps_peer_uapsd_coex_cmdid = WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID,
424462306a36Sopenharmony_ci	.peer_rate_retry_sched_cmdid = WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID,
424562306a36Sopenharmony_ci	.wlan_profile_trigger_cmdid = WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID,
424662306a36Sopenharmony_ci	.wlan_profile_set_hist_intvl_cmdid =
424762306a36Sopenharmony_ci				WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
424862306a36Sopenharmony_ci	.wlan_profile_get_profile_data_cmdid =
424962306a36Sopenharmony_ci				WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
425062306a36Sopenharmony_ci	.wlan_profile_enable_profile_id_cmdid =
425162306a36Sopenharmony_ci				WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
425262306a36Sopenharmony_ci	.wlan_profile_list_profile_id_cmdid =
425362306a36Sopenharmony_ci				WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
425462306a36Sopenharmony_ci	.pdev_suspend_cmdid = WMI_TLV_PDEV_SUSPEND_CMDID,
425562306a36Sopenharmony_ci	.pdev_resume_cmdid = WMI_TLV_PDEV_RESUME_CMDID,
425662306a36Sopenharmony_ci	.add_bcn_filter_cmdid = WMI_TLV_ADD_BCN_FILTER_CMDID,
425762306a36Sopenharmony_ci	.rmv_bcn_filter_cmdid = WMI_TLV_RMV_BCN_FILTER_CMDID,
425862306a36Sopenharmony_ci	.wow_add_wake_pattern_cmdid = WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID,
425962306a36Sopenharmony_ci	.wow_del_wake_pattern_cmdid = WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID,
426062306a36Sopenharmony_ci	.wow_enable_disable_wake_event_cmdid =
426162306a36Sopenharmony_ci				WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
426262306a36Sopenharmony_ci	.wow_enable_cmdid = WMI_TLV_WOW_ENABLE_CMDID,
426362306a36Sopenharmony_ci	.wow_hostwakeup_from_sleep_cmdid =
426462306a36Sopenharmony_ci				WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
426562306a36Sopenharmony_ci	.rtt_measreq_cmdid = WMI_TLV_RTT_MEASREQ_CMDID,
426662306a36Sopenharmony_ci	.rtt_tsf_cmdid = WMI_TLV_RTT_TSF_CMDID,
426762306a36Sopenharmony_ci	.vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID,
426862306a36Sopenharmony_ci	.vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID,
426962306a36Sopenharmony_ci	.request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID,
427062306a36Sopenharmony_ci	.request_peer_stats_info_cmdid = WMI_TLV_REQUEST_PEER_STATS_INFO_CMDID,
427162306a36Sopenharmony_ci	.set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID,
427262306a36Sopenharmony_ci	.network_list_offload_config_cmdid =
427362306a36Sopenharmony_ci				WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID,
427462306a36Sopenharmony_ci	.gtk_offload_cmdid = WMI_TLV_GTK_OFFLOAD_CMDID,
427562306a36Sopenharmony_ci	.csa_offload_enable_cmdid = WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID,
427662306a36Sopenharmony_ci	.csa_offload_chanswitch_cmdid = WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID,
427762306a36Sopenharmony_ci	.chatter_set_mode_cmdid = WMI_TLV_CHATTER_SET_MODE_CMDID,
427862306a36Sopenharmony_ci	.peer_tid_addba_cmdid = WMI_TLV_PEER_TID_ADDBA_CMDID,
427962306a36Sopenharmony_ci	.peer_tid_delba_cmdid = WMI_TLV_PEER_TID_DELBA_CMDID,
428062306a36Sopenharmony_ci	.sta_dtim_ps_method_cmdid = WMI_TLV_STA_DTIM_PS_METHOD_CMDID,
428162306a36Sopenharmony_ci	.sta_uapsd_auto_trig_cmdid = WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID,
428262306a36Sopenharmony_ci	.sta_keepalive_cmd = WMI_TLV_STA_KEEPALIVE_CMDID,
428362306a36Sopenharmony_ci	.echo_cmdid = WMI_TLV_ECHO_CMDID,
428462306a36Sopenharmony_ci	.pdev_utf_cmdid = WMI_TLV_PDEV_UTF_CMDID,
428562306a36Sopenharmony_ci	.dbglog_cfg_cmdid = WMI_TLV_DBGLOG_CFG_CMDID,
428662306a36Sopenharmony_ci	.pdev_qvit_cmdid = WMI_TLV_PDEV_QVIT_CMDID,
428762306a36Sopenharmony_ci	.pdev_ftm_intg_cmdid = WMI_TLV_PDEV_FTM_INTG_CMDID,
428862306a36Sopenharmony_ci	.vdev_set_keepalive_cmdid = WMI_TLV_VDEV_SET_KEEPALIVE_CMDID,
428962306a36Sopenharmony_ci	.vdev_get_keepalive_cmdid = WMI_TLV_VDEV_GET_KEEPALIVE_CMDID,
429062306a36Sopenharmony_ci	.force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID,
429162306a36Sopenharmony_ci	.gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID,
429262306a36Sopenharmony_ci	.gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID,
429362306a36Sopenharmony_ci	.pdev_get_temperature_cmdid = WMI_TLV_PDEV_GET_TEMPERATURE_CMDID,
429462306a36Sopenharmony_ci	.vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
429562306a36Sopenharmony_ci	.tdls_set_state_cmdid = WMI_TLV_TDLS_SET_STATE_CMDID,
429662306a36Sopenharmony_ci	.tdls_peer_update_cmdid = WMI_TLV_TDLS_PEER_UPDATE_CMDID,
429762306a36Sopenharmony_ci	.adaptive_qcs_cmdid = WMI_TLV_RESMGR_ADAPTIVE_OCS_CMDID,
429862306a36Sopenharmony_ci	.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
429962306a36Sopenharmony_ci	.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
430062306a36Sopenharmony_ci	.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
430162306a36Sopenharmony_ci	.wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
430262306a36Sopenharmony_ci	.wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
430362306a36Sopenharmony_ci	.wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
430462306a36Sopenharmony_ci	.wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
430562306a36Sopenharmony_ci	.peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
430662306a36Sopenharmony_ci	.peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
430762306a36Sopenharmony_ci	.rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
430862306a36Sopenharmony_ci	.oem_req_cmdid = WMI_CMD_UNSUPPORTED,
430962306a36Sopenharmony_ci	.nan_cmdid = WMI_CMD_UNSUPPORTED,
431062306a36Sopenharmony_ci	.vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
431162306a36Sopenharmony_ci	.qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
431262306a36Sopenharmony_ci	.pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
431362306a36Sopenharmony_ci	.pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
431462306a36Sopenharmony_ci	.peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
431562306a36Sopenharmony_ci	.peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
431662306a36Sopenharmony_ci	.peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
431762306a36Sopenharmony_ci	.pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
431862306a36Sopenharmony_ci	.pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
431962306a36Sopenharmony_ci	.pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
432062306a36Sopenharmony_ci	.pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
432162306a36Sopenharmony_ci	.pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
432262306a36Sopenharmony_ci	.pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
432362306a36Sopenharmony_ci	.tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
432462306a36Sopenharmony_ci	.fwtest_cmdid = WMI_CMD_UNSUPPORTED,
432562306a36Sopenharmony_ci	.vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
432662306a36Sopenharmony_ci	.peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
432762306a36Sopenharmony_ci	.pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
432862306a36Sopenharmony_ci	.pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
432962306a36Sopenharmony_ci	.pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
433062306a36Sopenharmony_ci};
433162306a36Sopenharmony_ci
433262306a36Sopenharmony_cistatic struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
433362306a36Sopenharmony_ci	.tx_chain_mask = WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK,
433462306a36Sopenharmony_ci	.rx_chain_mask = WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK,
433562306a36Sopenharmony_ci	.txpower_limit2g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G,
433662306a36Sopenharmony_ci	.txpower_limit5g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G,
433762306a36Sopenharmony_ci	.txpower_scale = WMI_TLV_PDEV_PARAM_TXPOWER_SCALE,
433862306a36Sopenharmony_ci	.beacon_gen_mode = WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE,
433962306a36Sopenharmony_ci	.beacon_tx_mode = WMI_TLV_PDEV_PARAM_BEACON_TX_MODE,
434062306a36Sopenharmony_ci	.resmgr_offchan_mode = WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
434162306a36Sopenharmony_ci	.protection_mode = WMI_TLV_PDEV_PARAM_PROTECTION_MODE,
434262306a36Sopenharmony_ci	.dynamic_bw = WMI_TLV_PDEV_PARAM_DYNAMIC_BW,
434362306a36Sopenharmony_ci	.non_agg_sw_retry_th = WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
434462306a36Sopenharmony_ci	.agg_sw_retry_th = WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH,
434562306a36Sopenharmony_ci	.sta_kickout_th = WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH,
434662306a36Sopenharmony_ci	.ac_aggrsize_scaling = WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING,
434762306a36Sopenharmony_ci	.ltr_enable = WMI_TLV_PDEV_PARAM_LTR_ENABLE,
434862306a36Sopenharmony_ci	.ltr_ac_latency_be = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE,
434962306a36Sopenharmony_ci	.ltr_ac_latency_bk = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK,
435062306a36Sopenharmony_ci	.ltr_ac_latency_vi = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI,
435162306a36Sopenharmony_ci	.ltr_ac_latency_vo = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO,
435262306a36Sopenharmony_ci	.ltr_ac_latency_timeout = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
435362306a36Sopenharmony_ci	.ltr_sleep_override = WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
435462306a36Sopenharmony_ci	.ltr_rx_override = WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE,
435562306a36Sopenharmony_ci	.ltr_tx_activity_timeout = WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
435662306a36Sopenharmony_ci	.l1ss_enable = WMI_TLV_PDEV_PARAM_L1SS_ENABLE,
435762306a36Sopenharmony_ci	.dsleep_enable = WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE,
435862306a36Sopenharmony_ci	.pcielp_txbuf_flush = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
435962306a36Sopenharmony_ci	.pcielp_txbuf_watermark = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
436062306a36Sopenharmony_ci	.pcielp_txbuf_tmo_en = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
436162306a36Sopenharmony_ci	.pcielp_txbuf_tmo_value = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
436262306a36Sopenharmony_ci	.pdev_stats_update_period = WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
436362306a36Sopenharmony_ci	.vdev_stats_update_period = WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
436462306a36Sopenharmony_ci	.peer_stats_update_period = WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
436562306a36Sopenharmony_ci	.bcnflt_stats_update_period =
436662306a36Sopenharmony_ci				WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
436762306a36Sopenharmony_ci	.pmf_qos = WMI_TLV_PDEV_PARAM_PMF_QOS,
436862306a36Sopenharmony_ci	.arp_ac_override = WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE,
436962306a36Sopenharmony_ci	.dcs = WMI_TLV_PDEV_PARAM_DCS,
437062306a36Sopenharmony_ci	.ani_enable = WMI_TLV_PDEV_PARAM_ANI_ENABLE,
437162306a36Sopenharmony_ci	.ani_poll_period = WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD,
437262306a36Sopenharmony_ci	.ani_listen_period = WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD,
437362306a36Sopenharmony_ci	.ani_ofdm_level = WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL,
437462306a36Sopenharmony_ci	.ani_cck_level = WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL,
437562306a36Sopenharmony_ci	.dyntxchain = WMI_TLV_PDEV_PARAM_DYNTXCHAIN,
437662306a36Sopenharmony_ci	.proxy_sta = WMI_TLV_PDEV_PARAM_PROXY_STA,
437762306a36Sopenharmony_ci	.idle_ps_config = WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG,
437862306a36Sopenharmony_ci	.power_gating_sleep = WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP,
437962306a36Sopenharmony_ci	.fast_channel_reset = WMI_TLV_PDEV_PARAM_UNSUPPORTED,
438062306a36Sopenharmony_ci	.burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR,
438162306a36Sopenharmony_ci	.burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE,
438262306a36Sopenharmony_ci	.cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
438362306a36Sopenharmony_ci	.aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
438462306a36Sopenharmony_ci	.rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
438562306a36Sopenharmony_ci	.smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
438662306a36Sopenharmony_ci	.igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
438762306a36Sopenharmony_ci	.igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
438862306a36Sopenharmony_ci	.antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
438962306a36Sopenharmony_ci	.rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
439062306a36Sopenharmony_ci	.set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
439162306a36Sopenharmony_ci	.proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
439262306a36Sopenharmony_ci	.set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
439362306a36Sopenharmony_ci	.set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
439462306a36Sopenharmony_ci	.remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
439562306a36Sopenharmony_ci	.peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
439662306a36Sopenharmony_ci	.igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
439762306a36Sopenharmony_ci	.block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
439862306a36Sopenharmony_ci	.set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
439962306a36Sopenharmony_ci	.set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
440062306a36Sopenharmony_ci	.set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
440162306a36Sopenharmony_ci	.txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
440262306a36Sopenharmony_ci	.set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
440362306a36Sopenharmony_ci	.set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
440462306a36Sopenharmony_ci	.en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
440562306a36Sopenharmony_ci	.mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
440662306a36Sopenharmony_ci	.noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
440762306a36Sopenharmony_ci	.noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
440862306a36Sopenharmony_ci	.dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
440962306a36Sopenharmony_ci	.set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
441062306a36Sopenharmony_ci	.atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
441162306a36Sopenharmony_ci	.atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
441262306a36Sopenharmony_ci	.ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
441362306a36Sopenharmony_ci	.mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
441462306a36Sopenharmony_ci	.sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
441562306a36Sopenharmony_ci	.signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
441662306a36Sopenharmony_ci	.signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
441762306a36Sopenharmony_ci	.enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
441862306a36Sopenharmony_ci	.enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
441962306a36Sopenharmony_ci	.cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
442062306a36Sopenharmony_ci	.rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
442162306a36Sopenharmony_ci	.pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
442262306a36Sopenharmony_ci	.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
442362306a36Sopenharmony_ci	.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
442462306a36Sopenharmony_ci	.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
442562306a36Sopenharmony_ci	.rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
442662306a36Sopenharmony_ci	.rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
442762306a36Sopenharmony_ci	.peer_stats_info_enable = WMI_TLV_PDEV_PARAM_PEER_STATS_INFO_ENABLE,
442862306a36Sopenharmony_ci};
442962306a36Sopenharmony_ci
443062306a36Sopenharmony_cistatic struct wmi_peer_param_map wmi_tlv_peer_param_map = {
443162306a36Sopenharmony_ci	.smps_state = WMI_TLV_PEER_SMPS_STATE,
443262306a36Sopenharmony_ci	.ampdu = WMI_TLV_PEER_AMPDU,
443362306a36Sopenharmony_ci	.authorize = WMI_TLV_PEER_AUTHORIZE,
443462306a36Sopenharmony_ci	.chan_width = WMI_TLV_PEER_CHAN_WIDTH,
443562306a36Sopenharmony_ci	.nss = WMI_TLV_PEER_NSS,
443662306a36Sopenharmony_ci	.use_4addr = WMI_TLV_PEER_USE_4ADDR,
443762306a36Sopenharmony_ci	.membership = WMI_TLV_PEER_MEMBERSHIP,
443862306a36Sopenharmony_ci	.user_pos = WMI_TLV_PEER_USERPOS,
443962306a36Sopenharmony_ci	.crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED,
444062306a36Sopenharmony_ci	.tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR,
444162306a36Sopenharmony_ci	.set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S,
444262306a36Sopenharmony_ci	.ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH,
444362306a36Sopenharmony_ci	.phymode = WMI_TLV_PEER_PHYMODE,
444462306a36Sopenharmony_ci	.use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR,
444562306a36Sopenharmony_ci	.dummy_var = WMI_TLV_PEER_DUMMY_VAR,
444662306a36Sopenharmony_ci};
444762306a36Sopenharmony_ci
444862306a36Sopenharmony_cistatic struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
444962306a36Sopenharmony_ci	.rts_threshold = WMI_TLV_VDEV_PARAM_RTS_THRESHOLD,
445062306a36Sopenharmony_ci	.fragmentation_threshold = WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
445162306a36Sopenharmony_ci	.beacon_interval = WMI_TLV_VDEV_PARAM_BEACON_INTERVAL,
445262306a36Sopenharmony_ci	.listen_interval = WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL,
445362306a36Sopenharmony_ci	.multicast_rate = WMI_TLV_VDEV_PARAM_MULTICAST_RATE,
445462306a36Sopenharmony_ci	.mgmt_tx_rate = WMI_TLV_VDEV_PARAM_MGMT_TX_RATE,
445562306a36Sopenharmony_ci	.slot_time = WMI_TLV_VDEV_PARAM_SLOT_TIME,
445662306a36Sopenharmony_ci	.preamble = WMI_TLV_VDEV_PARAM_PREAMBLE,
445762306a36Sopenharmony_ci	.swba_time = WMI_TLV_VDEV_PARAM_SWBA_TIME,
445862306a36Sopenharmony_ci	.wmi_vdev_stats_update_period = WMI_TLV_VDEV_STATS_UPDATE_PERIOD,
445962306a36Sopenharmony_ci	.wmi_vdev_pwrsave_ageout_time = WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME,
446062306a36Sopenharmony_ci	.wmi_vdev_host_swba_interval = WMI_TLV_VDEV_HOST_SWBA_INTERVAL,
446162306a36Sopenharmony_ci	.dtim_period = WMI_TLV_VDEV_PARAM_DTIM_PERIOD,
446262306a36Sopenharmony_ci	.wmi_vdev_oc_scheduler_air_time_limit =
446362306a36Sopenharmony_ci				WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
446462306a36Sopenharmony_ci	.wds = WMI_TLV_VDEV_PARAM_WDS,
446562306a36Sopenharmony_ci	.atim_window = WMI_TLV_VDEV_PARAM_ATIM_WINDOW,
446662306a36Sopenharmony_ci	.bmiss_count_max = WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX,
446762306a36Sopenharmony_ci	.bmiss_first_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT,
446862306a36Sopenharmony_ci	.bmiss_final_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT,
446962306a36Sopenharmony_ci	.feature_wmm = WMI_TLV_VDEV_PARAM_FEATURE_WMM,
447062306a36Sopenharmony_ci	.chwidth = WMI_TLV_VDEV_PARAM_CHWIDTH,
447162306a36Sopenharmony_ci	.chextoffset = WMI_TLV_VDEV_PARAM_CHEXTOFFSET,
447262306a36Sopenharmony_ci	.disable_htprotection =	WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION,
447362306a36Sopenharmony_ci	.sta_quickkickout = WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT,
447462306a36Sopenharmony_ci	.mgmt_rate = WMI_TLV_VDEV_PARAM_MGMT_RATE,
447562306a36Sopenharmony_ci	.protection_mode = WMI_TLV_VDEV_PARAM_PROTECTION_MODE,
447662306a36Sopenharmony_ci	.fixed_rate = WMI_TLV_VDEV_PARAM_FIXED_RATE,
447762306a36Sopenharmony_ci	.sgi = WMI_TLV_VDEV_PARAM_SGI,
447862306a36Sopenharmony_ci	.ldpc = WMI_TLV_VDEV_PARAM_LDPC,
447962306a36Sopenharmony_ci	.tx_stbc = WMI_TLV_VDEV_PARAM_TX_STBC,
448062306a36Sopenharmony_ci	.rx_stbc = WMI_TLV_VDEV_PARAM_RX_STBC,
448162306a36Sopenharmony_ci	.intra_bss_fwd = WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD,
448262306a36Sopenharmony_ci	.def_keyid = WMI_TLV_VDEV_PARAM_DEF_KEYID,
448362306a36Sopenharmony_ci	.nss = WMI_TLV_VDEV_PARAM_NSS,
448462306a36Sopenharmony_ci	.bcast_data_rate = WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE,
448562306a36Sopenharmony_ci	.mcast_data_rate = WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE,
448662306a36Sopenharmony_ci	.mcast_indicate = WMI_TLV_VDEV_PARAM_MCAST_INDICATE,
448762306a36Sopenharmony_ci	.dhcp_indicate = WMI_TLV_VDEV_PARAM_DHCP_INDICATE,
448862306a36Sopenharmony_ci	.unknown_dest_indicate = WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
448962306a36Sopenharmony_ci	.ap_keepalive_min_idle_inactive_time_secs =
449062306a36Sopenharmony_ci		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
449162306a36Sopenharmony_ci	.ap_keepalive_max_idle_inactive_time_secs =
449262306a36Sopenharmony_ci		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
449362306a36Sopenharmony_ci	.ap_keepalive_max_unresponsive_time_secs =
449462306a36Sopenharmony_ci		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
449562306a36Sopenharmony_ci	.ap_enable_nawds = WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS,
449662306a36Sopenharmony_ci	.mcast2ucast_set = WMI_TLV_VDEV_PARAM_UNSUPPORTED,
449762306a36Sopenharmony_ci	.enable_rtscts = WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS,
449862306a36Sopenharmony_ci	.txbf = WMI_TLV_VDEV_PARAM_TXBF,
449962306a36Sopenharmony_ci	.packet_powersave = WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE,
450062306a36Sopenharmony_ci	.drop_unencry = WMI_TLV_VDEV_PARAM_DROP_UNENCRY,
450162306a36Sopenharmony_ci	.tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
450262306a36Sopenharmony_ci	.ap_detect_out_of_sync_sleeping_sta_time_secs =
450362306a36Sopenharmony_ci					WMI_TLV_VDEV_PARAM_UNSUPPORTED,
450462306a36Sopenharmony_ci	.rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
450562306a36Sopenharmony_ci	.cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
450662306a36Sopenharmony_ci	.mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
450762306a36Sopenharmony_ci	.rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
450862306a36Sopenharmony_ci	.vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
450962306a36Sopenharmony_ci	.vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
451062306a36Sopenharmony_ci	.early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
451162306a36Sopenharmony_ci	.early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
451262306a36Sopenharmony_ci	.early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
451362306a36Sopenharmony_ci	.early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
451462306a36Sopenharmony_ci	.early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
451562306a36Sopenharmony_ci	.early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
451662306a36Sopenharmony_ci	.proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
451762306a36Sopenharmony_ci	.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
451862306a36Sopenharmony_ci	.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
451962306a36Sopenharmony_ci	.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
452062306a36Sopenharmony_ci};
452162306a36Sopenharmony_ci
452262306a36Sopenharmony_cistatic const struct wmi_ops wmi_tlv_ops = {
452362306a36Sopenharmony_ci	.rx = ath10k_wmi_tlv_op_rx,
452462306a36Sopenharmony_ci	.map_svc = wmi_tlv_svc_map,
452562306a36Sopenharmony_ci	.map_svc_ext = wmi_tlv_svc_map_ext,
452662306a36Sopenharmony_ci
452762306a36Sopenharmony_ci	.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
452862306a36Sopenharmony_ci	.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
452962306a36Sopenharmony_ci	.pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev,
453062306a36Sopenharmony_ci	.pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev,
453162306a36Sopenharmony_ci	.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
453262306a36Sopenharmony_ci	.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
453362306a36Sopenharmony_ci	.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
453462306a36Sopenharmony_ci	.pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
453562306a36Sopenharmony_ci	.pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
453662306a36Sopenharmony_ci	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
453762306a36Sopenharmony_ci	.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
453862306a36Sopenharmony_ci	.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
453962306a36Sopenharmony_ci	.pull_svc_avail = ath10k_wmi_tlv_op_pull_svc_avail,
454062306a36Sopenharmony_ci	.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
454162306a36Sopenharmony_ci	.pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
454262306a36Sopenharmony_ci	.pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
454362306a36Sopenharmony_ci	.pull_echo_ev = ath10k_wmi_tlv_op_pull_echo_ev,
454462306a36Sopenharmony_ci	.get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
454562306a36Sopenharmony_ci
454662306a36Sopenharmony_ci	.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
454762306a36Sopenharmony_ci	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
454862306a36Sopenharmony_ci	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
454962306a36Sopenharmony_ci	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
455062306a36Sopenharmony_ci	.gen_init = ath10k_wmi_tlv_op_gen_init,
455162306a36Sopenharmony_ci	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
455262306a36Sopenharmony_ci	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
455362306a36Sopenharmony_ci	.gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
455462306a36Sopenharmony_ci	.gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
455562306a36Sopenharmony_ci	.gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
455662306a36Sopenharmony_ci	.gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
455762306a36Sopenharmony_ci	.gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
455862306a36Sopenharmony_ci	.gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
455962306a36Sopenharmony_ci	.gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
456062306a36Sopenharmony_ci	.gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
456162306a36Sopenharmony_ci	.gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
456262306a36Sopenharmony_ci	.gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
456362306a36Sopenharmony_ci	.gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
456462306a36Sopenharmony_ci	.gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
456562306a36Sopenharmony_ci	.gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
456662306a36Sopenharmony_ci	.gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
456762306a36Sopenharmony_ci	.gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
456862306a36Sopenharmony_ci	.gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
456962306a36Sopenharmony_ci	.gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
457062306a36Sopenharmony_ci	.gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
457162306a36Sopenharmony_ci	.gen_scan_prob_req_oui = ath10k_wmi_tlv_op_gen_scan_prob_req_oui,
457262306a36Sopenharmony_ci	.gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
457362306a36Sopenharmony_ci	.gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
457462306a36Sopenharmony_ci	.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
457562306a36Sopenharmony_ci	.gen_request_peer_stats_info = ath10k_wmi_tlv_op_gen_request_peer_stats_info,
457662306a36Sopenharmony_ci	.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
457762306a36Sopenharmony_ci	/* .gen_mgmt_tx = not implemented; HTT is used */
457862306a36Sopenharmony_ci	.gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send,
457962306a36Sopenharmony_ci	.cleanup_mgmt_tx_send = ath10k_wmi_tlv_op_cleanup_mgmt_tx_send,
458062306a36Sopenharmony_ci	.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
458162306a36Sopenharmony_ci	.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
458262306a36Sopenharmony_ci	.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
458362306a36Sopenharmony_ci	.gen_pdev_set_quiet_mode = ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode,
458462306a36Sopenharmony_ci	.gen_pdev_get_temperature = ath10k_wmi_tlv_op_gen_pdev_get_temperature,
458562306a36Sopenharmony_ci	/* .gen_addba_clear_resp not implemented */
458662306a36Sopenharmony_ci	/* .gen_addba_send not implemented */
458762306a36Sopenharmony_ci	/* .gen_addba_set_resp not implemented */
458862306a36Sopenharmony_ci	/* .gen_delba_send not implemented */
458962306a36Sopenharmony_ci	.gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
459062306a36Sopenharmony_ci	.gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
459162306a36Sopenharmony_ci	.gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
459262306a36Sopenharmony_ci	.gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
459362306a36Sopenharmony_ci	.gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
459462306a36Sopenharmony_ci	.gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
459562306a36Sopenharmony_ci	.gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
459662306a36Sopenharmony_ci	.gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
459762306a36Sopenharmony_ci	.gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
459862306a36Sopenharmony_ci	.gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
459962306a36Sopenharmony_ci	.gen_wow_config_pno = ath10k_wmi_tlv_op_gen_config_pno,
460062306a36Sopenharmony_ci	.gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
460162306a36Sopenharmony_ci	.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
460262306a36Sopenharmony_ci	.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
460362306a36Sopenharmony_ci	.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
460462306a36Sopenharmony_ci	.get_vdev_subtype = ath10k_wmi_tlv_op_get_vdev_subtype,
460562306a36Sopenharmony_ci	.gen_echo = ath10k_wmi_tlv_op_gen_echo,
460662306a36Sopenharmony_ci	.gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
460762306a36Sopenharmony_ci	.gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
460862306a36Sopenharmony_ci};
460962306a36Sopenharmony_ci
461062306a36Sopenharmony_cistatic const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
461162306a36Sopenharmony_ci	.auth = WMI_TLV_PEER_AUTH,
461262306a36Sopenharmony_ci	.qos = WMI_TLV_PEER_QOS,
461362306a36Sopenharmony_ci	.need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
461462306a36Sopenharmony_ci	.need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
461562306a36Sopenharmony_ci	.apsd = WMI_TLV_PEER_APSD,
461662306a36Sopenharmony_ci	.ht = WMI_TLV_PEER_HT,
461762306a36Sopenharmony_ci	.bw40 = WMI_TLV_PEER_40MHZ,
461862306a36Sopenharmony_ci	.stbc = WMI_TLV_PEER_STBC,
461962306a36Sopenharmony_ci	.ldbc = WMI_TLV_PEER_LDPC,
462062306a36Sopenharmony_ci	.dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
462162306a36Sopenharmony_ci	.static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
462262306a36Sopenharmony_ci	.spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
462362306a36Sopenharmony_ci	.vht = WMI_TLV_PEER_VHT,
462462306a36Sopenharmony_ci	.bw80 = WMI_TLV_PEER_80MHZ,
462562306a36Sopenharmony_ci	.pmf = WMI_TLV_PEER_PMF,
462662306a36Sopenharmony_ci	.bw160 = WMI_TLV_PEER_160MHZ,
462762306a36Sopenharmony_ci};
462862306a36Sopenharmony_ci
462962306a36Sopenharmony_ci/************/
463062306a36Sopenharmony_ci/* TLV init */
463162306a36Sopenharmony_ci/************/
463262306a36Sopenharmony_ci
463362306a36Sopenharmony_civoid ath10k_wmi_tlv_attach(struct ath10k *ar)
463462306a36Sopenharmony_ci{
463562306a36Sopenharmony_ci	ar->wmi.cmd = &wmi_tlv_cmd_map;
463662306a36Sopenharmony_ci	ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
463762306a36Sopenharmony_ci	ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
463862306a36Sopenharmony_ci	ar->wmi.peer_param = &wmi_tlv_peer_param_map;
463962306a36Sopenharmony_ci	ar->wmi.ops = &wmi_tlv_ops;
464062306a36Sopenharmony_ci	ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
464162306a36Sopenharmony_ci}
4642