xref: /linux/drivers/net/wireless/ath/ath10k/wmi-tlv.c (revision 90602c251cda8a1e526efb250f28c1ea3f87cd78)
1f0553ca9SKalle Valo // SPDX-License-Identifier: ISC
2ca996ec5SMichal Kazior /*
3ca996ec5SMichal Kazior  * Copyright (c) 2005-2011 Atheros Communications Inc.
48b1083d6SKalle Valo  * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
5fe36e70fSRakesh Pillai  * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
6bc2ef649SKarthikeyan Periyasamy  * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
7ca996ec5SMichal Kazior  */
8ca996ec5SMichal Kazior #include "core.h"
9ca996ec5SMichal Kazior #include "debug.h"
10b4aa539dSMichal Kazior #include "mac.h"
11ca996ec5SMichal Kazior #include "hw.h"
12ca996ec5SMichal Kazior #include "wmi.h"
13ca996ec5SMichal Kazior #include "wmi-ops.h"
14ca996ec5SMichal Kazior #include "wmi-tlv.h"
15fe3cbdfcSMichal Kazior #include "p2p.h"
16a81a98ceSAlan Liu #include "testmode.h"
17f40a307eSSurabhi Vishnoi #include <linux/bitfield.h>
18ca996ec5SMichal Kazior 
19ca996ec5SMichal Kazior /***************/
20ca996ec5SMichal Kazior /* TLV helpers */
21ca996ec5SMichal Kazior /**************/
22ca996ec5SMichal Kazior 
23ca996ec5SMichal Kazior struct wmi_tlv_policy {
24ca996ec5SMichal Kazior 	size_t min_len;
25ca996ec5SMichal Kazior };
26ca996ec5SMichal Kazior 
27ca996ec5SMichal Kazior static const struct wmi_tlv_policy wmi_tlv_policies[] = {
28ca996ec5SMichal Kazior 	[WMI_TLV_TAG_ARRAY_BYTE]
29f5431e87SJanusz Dziedzic 		= { .min_len = 0 },
30ca996ec5SMichal Kazior 	[WMI_TLV_TAG_ARRAY_UINT32]
31f5431e87SJanusz Dziedzic 		= { .min_len = 0 },
32ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_SCAN_EVENT]
33ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_scan_event) },
34ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR]
35ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_mgmt_rx_ev) },
36ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT]
37ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_chan_info_event) },
38ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT]
39ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_vdev_start_response_event) },
40ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT]
41ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_peer_sta_kickout_event) },
42ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT]
43ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_host_swba_event) },
44ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_TIM_INFO]
45ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_tim_info) },
46ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO]
47ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_p2p_noa_info) },
48ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT]
49ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_svc_rdy_ev) },
50ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES]
51ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct hal_reg_capabilities) },
52ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ]
53ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wlan_host_mem_req) },
54ca996ec5SMichal Kazior 	[WMI_TLV_TAG_STRUCT_READY_EVENT]
55ca996ec5SMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_rdy_ev) },
566bf12062SMichal Kazior 	[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]
576bf12062SMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
5804de6c6cSMichal Kazior 	[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
5904de6c6cSMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
60fe3cbdfcSMichal Kazior 	[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
61fe3cbdfcSMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_p2p_noa_ev) },
62c1a4654aSMichal Kazior 	[WMI_TLV_TAG_STRUCT_ROAM_EVENT]
63c1a4654aSMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_roam_ev) },
64f5431e87SJanusz Dziedzic 	[WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO]
65f5431e87SJanusz Dziedzic 		= { .min_len = sizeof(struct wmi_tlv_wow_event_info) },
66b4aa539dSMichal Kazior 	[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT]
67b4aa539dSMichal Kazior 		= { .min_len = sizeof(struct wmi_tlv_tx_pause_ev) },
68ca996ec5SMichal Kazior };
69ca996ec5SMichal Kazior 
70ca996ec5SMichal Kazior static int
ath10k_wmi_tlv_iter(struct ath10k * ar,const void * ptr,size_t len,int (* iter)(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data),void * data)71ca996ec5SMichal Kazior ath10k_wmi_tlv_iter(struct ath10k *ar, const void *ptr, size_t len,
72ca996ec5SMichal Kazior 		    int (*iter)(struct ath10k *ar, u16 tag, u16 len,
73ca996ec5SMichal Kazior 				const void *ptr, void *data),
74ca996ec5SMichal Kazior 		    void *data)
75ca996ec5SMichal Kazior {
76ca996ec5SMichal Kazior 	const void *begin = ptr;
77ca996ec5SMichal Kazior 	const struct wmi_tlv *tlv;
78ca996ec5SMichal Kazior 	u16 tlv_tag, tlv_len;
79ca996ec5SMichal Kazior 	int ret;
80ca996ec5SMichal Kazior 
81ca996ec5SMichal Kazior 	while (len > 0) {
82ca996ec5SMichal Kazior 		if (len < sizeof(*tlv)) {
83ca996ec5SMichal Kazior 			ath10k_dbg(ar, ATH10K_DBG_WMI,
84ca996ec5SMichal Kazior 				   "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
85ca996ec5SMichal Kazior 				   ptr - begin, len, sizeof(*tlv));
86ca996ec5SMichal Kazior 			return -EINVAL;
87ca996ec5SMichal Kazior 		}
88ca996ec5SMichal Kazior 
89ca996ec5SMichal Kazior 		tlv = ptr;
90ca996ec5SMichal Kazior 		tlv_tag = __le16_to_cpu(tlv->tag);
91ca996ec5SMichal Kazior 		tlv_len = __le16_to_cpu(tlv->len);
92ca996ec5SMichal Kazior 		ptr += sizeof(*tlv);
93ca996ec5SMichal Kazior 		len -= sizeof(*tlv);
94ca996ec5SMichal Kazior 
95ca996ec5SMichal Kazior 		if (tlv_len > len) {
96ca996ec5SMichal Kazior 			ath10k_dbg(ar, ATH10K_DBG_WMI,
97779750bbSTom Rix 				   "wmi tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",
98ca996ec5SMichal Kazior 				   tlv_tag, ptr - begin, len, tlv_len);
99ca996ec5SMichal Kazior 			return -EINVAL;
100ca996ec5SMichal Kazior 		}
101ca996ec5SMichal Kazior 
102ca996ec5SMichal Kazior 		if (tlv_tag < ARRAY_SIZE(wmi_tlv_policies) &&
103ca996ec5SMichal Kazior 		    wmi_tlv_policies[tlv_tag].min_len &&
104ca996ec5SMichal Kazior 		    wmi_tlv_policies[tlv_tag].min_len > tlv_len) {
105ca996ec5SMichal Kazior 			ath10k_dbg(ar, ATH10K_DBG_WMI,
106779750bbSTom Rix 				   "wmi tlv parse failure of tag %u at byte %zd (%u bytes is less than min length %zu)\n",
107ca996ec5SMichal Kazior 				   tlv_tag, ptr - begin, tlv_len,
108ca996ec5SMichal Kazior 				   wmi_tlv_policies[tlv_tag].min_len);
109ca996ec5SMichal Kazior 			return -EINVAL;
110ca996ec5SMichal Kazior 		}
111ca996ec5SMichal Kazior 
112ca996ec5SMichal Kazior 		ret = iter(ar, tlv_tag, tlv_len, ptr, data);
113ca996ec5SMichal Kazior 		if (ret)
114ca996ec5SMichal Kazior 			return ret;
115ca996ec5SMichal Kazior 
116ca996ec5SMichal Kazior 		ptr += tlv_len;
117ca996ec5SMichal Kazior 		len -= tlv_len;
118ca996ec5SMichal Kazior 	}
119ca996ec5SMichal Kazior 
120ca996ec5SMichal Kazior 	return 0;
121ca996ec5SMichal Kazior }
122ca996ec5SMichal Kazior 
ath10k_wmi_tlv_iter_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)123ca996ec5SMichal Kazior static int ath10k_wmi_tlv_iter_parse(struct ath10k *ar, u16 tag, u16 len,
124ca996ec5SMichal Kazior 				     const void *ptr, void *data)
125ca996ec5SMichal Kazior {
126ca996ec5SMichal Kazior 	const void **tb = data;
127ca996ec5SMichal Kazior 
128ca996ec5SMichal Kazior 	if (tag < WMI_TLV_TAG_MAX)
129ca996ec5SMichal Kazior 		tb[tag] = ptr;
130ca996ec5SMichal Kazior 
131ca996ec5SMichal Kazior 	return 0;
132ca996ec5SMichal Kazior }
133ca996ec5SMichal Kazior 
ath10k_wmi_tlv_parse(struct ath10k * ar,const void ** tb,const void * ptr,size_t len)134ca996ec5SMichal Kazior static int ath10k_wmi_tlv_parse(struct ath10k *ar, const void **tb,
135ca996ec5SMichal Kazior 				const void *ptr, size_t len)
136ca996ec5SMichal Kazior {
137ca996ec5SMichal Kazior 	return ath10k_wmi_tlv_iter(ar, ptr, len, ath10k_wmi_tlv_iter_parse,
138ca996ec5SMichal Kazior 				   (void *)tb);
139ca996ec5SMichal Kazior }
140ca996ec5SMichal Kazior 
141ca996ec5SMichal Kazior static const void **
ath10k_wmi_tlv_parse_alloc(struct ath10k * ar,const void * ptr,size_t len,gfp_t gfp)142ca996ec5SMichal Kazior ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
143ca996ec5SMichal Kazior 			   size_t len, gfp_t gfp)
144ca996ec5SMichal Kazior {
145ca996ec5SMichal Kazior 	const void **tb;
146ca996ec5SMichal Kazior 	int ret;
147ca996ec5SMichal Kazior 
1486396bb22SKees Cook 	tb = kcalloc(WMI_TLV_TAG_MAX, sizeof(*tb), gfp);
149ca996ec5SMichal Kazior 	if (!tb)
150ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
151ca996ec5SMichal Kazior 
152ca996ec5SMichal Kazior 	ret = ath10k_wmi_tlv_parse(ar, tb, ptr, len);
153ca996ec5SMichal Kazior 	if (ret) {
154ca996ec5SMichal Kazior 		kfree(tb);
155ca996ec5SMichal Kazior 		return ERR_PTR(ret);
156ca996ec5SMichal Kazior 	}
157ca996ec5SMichal Kazior 
158ca996ec5SMichal Kazior 	return tb;
159ca996ec5SMichal Kazior }
160ca996ec5SMichal Kazior 
ath10k_wmi_tlv_len(const void * ptr)161ca996ec5SMichal Kazior static u16 ath10k_wmi_tlv_len(const void *ptr)
162ca996ec5SMichal Kazior {
163ca996ec5SMichal Kazior 	return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len);
164ca996ec5SMichal Kazior }
165ca996ec5SMichal Kazior 
1666bf12062SMichal Kazior /**************/
1676bf12062SMichal Kazior /* TLV events */
1686bf12062SMichal Kazior /**************/
ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k * ar,struct sk_buff * skb)1696bf12062SMichal Kazior static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
1706bf12062SMichal Kazior 					      struct sk_buff *skb)
1716bf12062SMichal Kazior {
1726bf12062SMichal Kazior 	const void **tb;
1736bf12062SMichal Kazior 	const struct wmi_tlv_bcn_tx_status_ev *ev;
17481a9a17dSMichal Kazior 	struct ath10k_vif *arvif;
1756bf12062SMichal Kazior 	u32 vdev_id, tx_status;
1766bf12062SMichal Kazior 	int ret;
1776bf12062SMichal Kazior 
1786bf12062SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1796bf12062SMichal Kazior 	if (IS_ERR(tb)) {
1806bf12062SMichal Kazior 		ret = PTR_ERR(tb);
1816bf12062SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1826bf12062SMichal Kazior 		return ret;
1836bf12062SMichal Kazior 	}
1846bf12062SMichal Kazior 
1856bf12062SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT];
1866bf12062SMichal Kazior 	if (!ev) {
1876bf12062SMichal Kazior 		kfree(tb);
1886bf12062SMichal Kazior 		return -EPROTO;
1896bf12062SMichal Kazior 	}
1906bf12062SMichal Kazior 
1916bf12062SMichal Kazior 	tx_status = __le32_to_cpu(ev->tx_status);
1926bf12062SMichal Kazior 	vdev_id = __le32_to_cpu(ev->vdev_id);
1936bf12062SMichal Kazior 
1946bf12062SMichal Kazior 	switch (tx_status) {
1956bf12062SMichal Kazior 	case WMI_TLV_BCN_TX_STATUS_OK:
1966bf12062SMichal Kazior 		break;
1976bf12062SMichal Kazior 	case WMI_TLV_BCN_TX_STATUS_XRETRY:
1986bf12062SMichal Kazior 	case WMI_TLV_BCN_TX_STATUS_DROP:
1996bf12062SMichal Kazior 	case WMI_TLV_BCN_TX_STATUS_FILTERED:
2006bf12062SMichal Kazior 		/* FIXME: It's probably worth telling mac80211 to stop the
2016bf12062SMichal Kazior 		 * interface as it is crippled.
2026bf12062SMichal Kazior 		 */
2036bf12062SMichal Kazior 		ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d",
2046bf12062SMichal Kazior 			    vdev_id, tx_status);
2056bf12062SMichal Kazior 		break;
2066bf12062SMichal Kazior 	}
2076bf12062SMichal Kazior 
20881a9a17dSMichal Kazior 	arvif = ath10k_get_arvif(ar, vdev_id);
209d0a9123eSJohannes Berg 	if (arvif && arvif->is_up && arvif->vif->bss_conf.csa_active)
21081a9a17dSMichal Kazior 		ieee80211_queue_work(ar->hw, &arvif->ap_csa_work);
21181a9a17dSMichal Kazior 
2126bf12062SMichal Kazior 	kfree(tb);
2136bf12062SMichal Kazior 	return 0;
2146bf12062SMichal Kazior }
2156bf12062SMichal Kazior 
ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k * ar,struct sk_buff * skb)216fe36e70fSRakesh Pillai static void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar,
217fe36e70fSRakesh Pillai 						  struct sk_buff *skb)
218fe36e70fSRakesh Pillai {
219fe36e70fSRakesh Pillai 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n");
220fe36e70fSRakesh Pillai 	complete(&ar->vdev_delete_done);
221fe36e70fSRakesh Pillai }
222fe36e70fSRakesh Pillai 
ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)2230f7cb268SWen Gong static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 len,
2240f7cb268SWen Gong 						const void *ptr, void *data)
2250f7cb268SWen Gong {
2260f7cb268SWen Gong 	const struct wmi_tlv_peer_stats_info *stat = ptr;
2270f7cb268SWen Gong 	struct ieee80211_sta *sta;
2280f7cb268SWen Gong 	struct ath10k_sta *arsta;
2290f7cb268SWen Gong 
2300f7cb268SWen Gong 	if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
2310f7cb268SWen Gong 		return -EPROTO;
2320f7cb268SWen Gong 
2330f7cb268SWen Gong 	ath10k_dbg(ar, ATH10K_DBG_WMI,
2340f7cb268SWen Gong 		   "wmi tlv stats peer addr %pMF rx rate code 0x%x bit rate %d kbps\n",
2350f7cb268SWen Gong 		   stat->peer_macaddr.addr,
2360f7cb268SWen Gong 		   __le32_to_cpu(stat->last_rx_rate_code),
2370f7cb268SWen Gong 		   __le32_to_cpu(stat->last_rx_bitrate_kbps));
2380f7cb268SWen Gong 
2390f7cb268SWen Gong 	ath10k_dbg(ar, ATH10K_DBG_WMI,
2400f7cb268SWen Gong 		   "wmi tlv stats tx rate code 0x%x bit rate %d kbps\n",
2410f7cb268SWen Gong 		   __le32_to_cpu(stat->last_tx_rate_code),
2420f7cb268SWen Gong 		   __le32_to_cpu(stat->last_tx_bitrate_kbps));
2430f7cb268SWen Gong 
2442615e3cdSAnand K Mistry 	rcu_read_lock();
2450f7cb268SWen Gong 	sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
2460f7cb268SWen Gong 	if (!sta) {
2472615e3cdSAnand K Mistry 		rcu_read_unlock();
2480f7cb268SWen Gong 		ath10k_warn(ar, "not found station for peer stats\n");
2490f7cb268SWen Gong 		return -EINVAL;
2500f7cb268SWen Gong 	}
2510f7cb268SWen Gong 
2520f7cb268SWen Gong 	arsta = (struct ath10k_sta *)sta->drv_priv;
2530f7cb268SWen Gong 	arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
2540f7cb268SWen Gong 	arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
2554cc02c7cSWen Gong 	arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
2564cc02c7cSWen Gong 	arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
2572615e3cdSAnand K Mistry 	rcu_read_unlock();
2580f7cb268SWen Gong 
2590f7cb268SWen Gong 	return 0;
2600f7cb268SWen Gong }
2610f7cb268SWen Gong 
ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k * ar,struct sk_buff * skb)2620f7cb268SWen Gong static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
2630f7cb268SWen Gong 						  struct sk_buff *skb)
2640f7cb268SWen Gong {
2650f7cb268SWen Gong 	const void **tb;
2660f7cb268SWen Gong 	const struct wmi_tlv_peer_stats_info_ev *ev;
2670f7cb268SWen Gong 	const void *data;
2680f7cb268SWen Gong 	u32 num_peer_stats;
2690f7cb268SWen Gong 	int ret;
2700f7cb268SWen Gong 
2710f7cb268SWen Gong 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
2720f7cb268SWen Gong 	if (IS_ERR(tb)) {
2730f7cb268SWen Gong 		ret = PTR_ERR(tb);
2740f7cb268SWen Gong 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
2750f7cb268SWen Gong 		return ret;
2760f7cb268SWen Gong 	}
2770f7cb268SWen Gong 
2780f7cb268SWen Gong 	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STATS_INFO_EVENT];
2790f7cb268SWen Gong 	data = tb[WMI_TLV_TAG_ARRAY_STRUCT];
2800f7cb268SWen Gong 
2810f7cb268SWen Gong 	if (!ev || !data) {
2820f7cb268SWen Gong 		kfree(tb);
2830f7cb268SWen Gong 		return -EPROTO;
2840f7cb268SWen Gong 	}
2850f7cb268SWen Gong 
2860f7cb268SWen Gong 	num_peer_stats = __le32_to_cpu(ev->num_peers);
2870f7cb268SWen Gong 
2880f7cb268SWen Gong 	ath10k_dbg(ar, ATH10K_DBG_WMI,
2890f7cb268SWen Gong 		   "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
2900f7cb268SWen Gong 		   __le32_to_cpu(ev->vdev_id),
2910f7cb268SWen Gong 		   num_peer_stats,
2920f7cb268SWen Gong 		   __le32_to_cpu(ev->more_data));
2930f7cb268SWen Gong 
2940f7cb268SWen Gong 	ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
2950f7cb268SWen Gong 				  ath10k_wmi_tlv_parse_peer_stats_info, NULL);
2960f7cb268SWen Gong 	if (ret)
2970f7cb268SWen Gong 		ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
2980f7cb268SWen Gong 
2990f7cb268SWen Gong 	kfree(tb);
3000f7cb268SWen Gong 	return 0;
3010f7cb268SWen Gong }
3020f7cb268SWen Gong 
ath10k_wmi_tlv_event_peer_stats_info(struct ath10k * ar,struct sk_buff * skb)3030f7cb268SWen Gong static void ath10k_wmi_tlv_event_peer_stats_info(struct ath10k *ar,
3040f7cb268SWen Gong 						 struct sk_buff *skb)
3050f7cb268SWen Gong {
3060f7cb268SWen Gong 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PEER_STATS_INFO_EVENTID\n");
3070f7cb268SWen Gong 	ath10k_wmi_tlv_op_pull_peer_stats_info(ar, skb);
3080f7cb268SWen Gong 	complete(&ar->peer_stats_info_complete);
3090f7cb268SWen Gong }
3100f7cb268SWen Gong 
ath10k_wmi_tlv_event_diag_data(struct ath10k * ar,struct sk_buff * skb)31104de6c6cSMichal Kazior static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
31204de6c6cSMichal Kazior 					  struct sk_buff *skb)
31304de6c6cSMichal Kazior {
31404de6c6cSMichal Kazior 	const void **tb;
31504de6c6cSMichal Kazior 	const struct wmi_tlv_diag_data_ev *ev;
31604de6c6cSMichal Kazior 	const struct wmi_tlv_diag_item *item;
31704de6c6cSMichal Kazior 	const void *data;
31804de6c6cSMichal Kazior 	int ret, num_items, len;
31904de6c6cSMichal Kazior 
32004de6c6cSMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
32104de6c6cSMichal Kazior 	if (IS_ERR(tb)) {
32204de6c6cSMichal Kazior 		ret = PTR_ERR(tb);
32304de6c6cSMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
32404de6c6cSMichal Kazior 		return ret;
32504de6c6cSMichal Kazior 	}
32604de6c6cSMichal Kazior 
32704de6c6cSMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT];
32804de6c6cSMichal Kazior 	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
32904de6c6cSMichal Kazior 	if (!ev || !data) {
33004de6c6cSMichal Kazior 		kfree(tb);
33104de6c6cSMichal Kazior 		return -EPROTO;
33204de6c6cSMichal Kazior 	}
33304de6c6cSMichal Kazior 
33404de6c6cSMichal Kazior 	num_items = __le32_to_cpu(ev->num_items);
33504de6c6cSMichal Kazior 	len = ath10k_wmi_tlv_len(data);
33604de6c6cSMichal Kazior 
33704de6c6cSMichal Kazior 	while (num_items--) {
33804de6c6cSMichal Kazior 		if (len == 0)
33904de6c6cSMichal Kazior 			break;
34004de6c6cSMichal Kazior 		if (len < sizeof(*item)) {
34104de6c6cSMichal Kazior 			ath10k_warn(ar, "failed to parse diag data: can't fit item header\n");
34204de6c6cSMichal Kazior 			break;
34304de6c6cSMichal Kazior 		}
34404de6c6cSMichal Kazior 
34504de6c6cSMichal Kazior 		item = data;
34604de6c6cSMichal Kazior 
34704de6c6cSMichal Kazior 		if (len < sizeof(*item) + __le16_to_cpu(item->len)) {
34804de6c6cSMichal Kazior 			ath10k_warn(ar, "failed to parse diag data: item is too long\n");
34904de6c6cSMichal Kazior 			break;
35004de6c6cSMichal Kazior 		}
35104de6c6cSMichal Kazior 
35204de6c6cSMichal Kazior 		trace_ath10k_wmi_diag_container(ar,
35304de6c6cSMichal Kazior 						item->type,
35404de6c6cSMichal Kazior 						__le32_to_cpu(item->timestamp),
35504de6c6cSMichal Kazior 						__le32_to_cpu(item->code),
35604de6c6cSMichal Kazior 						__le16_to_cpu(item->len),
35704de6c6cSMichal Kazior 						item->payload);
35804de6c6cSMichal Kazior 
35904de6c6cSMichal Kazior 		len -= sizeof(*item);
36004de6c6cSMichal Kazior 		len -= roundup(__le16_to_cpu(item->len), 4);
36104de6c6cSMichal Kazior 
36204de6c6cSMichal Kazior 		data += sizeof(*item);
36304de6c6cSMichal Kazior 		data += roundup(__le16_to_cpu(item->len), 4);
36404de6c6cSMichal Kazior 	}
36504de6c6cSMichal Kazior 
36604de6c6cSMichal Kazior 	if (num_items != -1 || len != 0)
36704de6c6cSMichal Kazior 		ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n",
36804de6c6cSMichal Kazior 			    num_items, len);
36904de6c6cSMichal Kazior 
37004de6c6cSMichal Kazior 	kfree(tb);
37104de6c6cSMichal Kazior 	return 0;
37204de6c6cSMichal Kazior }
37304de6c6cSMichal Kazior 
ath10k_wmi_tlv_event_diag(struct ath10k * ar,struct sk_buff * skb)374c3113c39SMichal Kazior static int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
375c3113c39SMichal Kazior 				     struct sk_buff *skb)
376c3113c39SMichal Kazior {
377c3113c39SMichal Kazior 	const void **tb;
378c3113c39SMichal Kazior 	const void *data;
379c3113c39SMichal Kazior 	int ret, len;
380c3113c39SMichal Kazior 
381c3113c39SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
382c3113c39SMichal Kazior 	if (IS_ERR(tb)) {
383c3113c39SMichal Kazior 		ret = PTR_ERR(tb);
384c3113c39SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
385c3113c39SMichal Kazior 		return ret;
386c3113c39SMichal Kazior 	}
387c3113c39SMichal Kazior 
388c3113c39SMichal Kazior 	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
389c3113c39SMichal Kazior 	if (!data) {
390c3113c39SMichal Kazior 		kfree(tb);
391c3113c39SMichal Kazior 		return -EPROTO;
392c3113c39SMichal Kazior 	}
393c3113c39SMichal Kazior 	len = ath10k_wmi_tlv_len(data);
394c3113c39SMichal Kazior 
395c3113c39SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len);
396c3113c39SMichal Kazior 	trace_ath10k_wmi_diag(ar, data, len);
397c3113c39SMichal Kazior 
398c3113c39SMichal Kazior 	kfree(tb);
399c3113c39SMichal Kazior 	return 0;
400c3113c39SMichal Kazior }
401c3113c39SMichal Kazior 
ath10k_wmi_tlv_event_p2p_noa(struct ath10k * ar,struct sk_buff * skb)402fe3cbdfcSMichal Kazior static int ath10k_wmi_tlv_event_p2p_noa(struct ath10k *ar,
403fe3cbdfcSMichal Kazior 					struct sk_buff *skb)
404fe3cbdfcSMichal Kazior {
405fe3cbdfcSMichal Kazior 	const void **tb;
406fe3cbdfcSMichal Kazior 	const struct wmi_tlv_p2p_noa_ev *ev;
407fe3cbdfcSMichal Kazior 	const struct wmi_p2p_noa_info *noa;
408fe3cbdfcSMichal Kazior 	int ret, vdev_id;
409fe3cbdfcSMichal Kazior 
410fe3cbdfcSMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
411fe3cbdfcSMichal Kazior 	if (IS_ERR(tb)) {
412fe3cbdfcSMichal Kazior 		ret = PTR_ERR(tb);
413fe3cbdfcSMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
414fe3cbdfcSMichal Kazior 		return ret;
415fe3cbdfcSMichal Kazior 	}
416fe3cbdfcSMichal Kazior 
417fe3cbdfcSMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT];
418fe3cbdfcSMichal Kazior 	noa = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO];
419fe3cbdfcSMichal Kazior 
420fe3cbdfcSMichal Kazior 	if (!ev || !noa) {
421fe3cbdfcSMichal Kazior 		kfree(tb);
422fe3cbdfcSMichal Kazior 		return -EPROTO;
423fe3cbdfcSMichal Kazior 	}
424fe3cbdfcSMichal Kazior 
425fe3cbdfcSMichal Kazior 	vdev_id = __le32_to_cpu(ev->vdev_id);
426fe3cbdfcSMichal Kazior 
427fe3cbdfcSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
428779750bbSTom Rix 		   "wmi tlv p2p noa vdev_id %i descriptors %u\n",
429fe3cbdfcSMichal Kazior 		   vdev_id, noa->num_descriptors);
430fe3cbdfcSMichal Kazior 
431fe3cbdfcSMichal Kazior 	ath10k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
432b4aa539dSMichal Kazior 	kfree(tb);
433b4aa539dSMichal Kazior 	return 0;
434b4aa539dSMichal Kazior }
435b4aa539dSMichal Kazior 
ath10k_wmi_tlv_event_tx_pause(struct ath10k * ar,struct sk_buff * skb)436b4aa539dSMichal Kazior static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
437b4aa539dSMichal Kazior 					 struct sk_buff *skb)
438b4aa539dSMichal Kazior {
439b4aa539dSMichal Kazior 	const void **tb;
440b4aa539dSMichal Kazior 	const struct wmi_tlv_tx_pause_ev *ev;
441b4aa539dSMichal Kazior 	int ret, vdev_id;
442b4aa539dSMichal Kazior 	u32 pause_id, action, vdev_map, peer_id, tid_map;
443b4aa539dSMichal Kazior 
444b4aa539dSMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
445b4aa539dSMichal Kazior 	if (IS_ERR(tb)) {
446b4aa539dSMichal Kazior 		ret = PTR_ERR(tb);
447b4aa539dSMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
448b4aa539dSMichal Kazior 		return ret;
449b4aa539dSMichal Kazior 	}
450b4aa539dSMichal Kazior 
451b4aa539dSMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT];
452b4aa539dSMichal Kazior 	if (!ev) {
453b4aa539dSMichal Kazior 		kfree(tb);
454b4aa539dSMichal Kazior 		return -EPROTO;
455b4aa539dSMichal Kazior 	}
456b4aa539dSMichal Kazior 
457b4aa539dSMichal Kazior 	pause_id = __le32_to_cpu(ev->pause_id);
458b4aa539dSMichal Kazior 	action = __le32_to_cpu(ev->action);
459b4aa539dSMichal Kazior 	vdev_map = __le32_to_cpu(ev->vdev_map);
460b4aa539dSMichal Kazior 	peer_id = __le32_to_cpu(ev->peer_id);
461b4aa539dSMichal Kazior 	tid_map = __le32_to_cpu(ev->tid_map);
462b4aa539dSMichal Kazior 
463b4aa539dSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
464b4aa539dSMichal Kazior 		   "wmi tlv tx pause pause_id %u action %u vdev_map 0x%08x peer_id %u tid_map 0x%08x\n",
465b4aa539dSMichal Kazior 		   pause_id, action, vdev_map, peer_id, tid_map);
466b4aa539dSMichal Kazior 
467acd0b27bSMichal Kazior 	switch (pause_id) {
468acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_MCC:
469acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
470acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
471acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_AP_PS:
472acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
473b4aa539dSMichal Kazior 		for (vdev_id = 0; vdev_map; vdev_id++) {
474b4aa539dSMichal Kazior 			if (!(vdev_map & BIT(vdev_id)))
475b4aa539dSMichal Kazior 				continue;
476b4aa539dSMichal Kazior 
477b4aa539dSMichal Kazior 			vdev_map &= ~BIT(vdev_id);
478acd0b27bSMichal Kazior 			ath10k_mac_handle_tx_pause_vdev(ar, vdev_id, pause_id,
479acd0b27bSMichal Kazior 							action);
480acd0b27bSMichal Kazior 		}
481acd0b27bSMichal Kazior 		break;
482acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
483acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
484acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
485acd0b27bSMichal Kazior 	case WMI_TLV_TX_PAUSE_ID_HOST:
486acd0b27bSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_MAC,
487acd0b27bSMichal Kazior 			   "mac ignoring unsupported tx pause id %d\n",
488acd0b27bSMichal Kazior 			   pause_id);
489acd0b27bSMichal Kazior 		break;
490acd0b27bSMichal Kazior 	default:
491acd0b27bSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_MAC,
492acd0b27bSMichal Kazior 			   "mac ignoring unknown tx pause vdev %d\n",
493acd0b27bSMichal Kazior 			   pause_id);
494acd0b27bSMichal Kazior 		break;
495b4aa539dSMichal Kazior 	}
496fe3cbdfcSMichal Kazior 
497fe3cbdfcSMichal Kazior 	kfree(tb);
498fe3cbdfcSMichal Kazior 	return 0;
499fe3cbdfcSMichal Kazior }
500fe3cbdfcSMichal Kazior 
ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k * ar,struct sk_buff * skb)5011382993fSWen Gong static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
5021382993fSWen Gong 						     struct sk_buff *skb)
5031382993fSWen Gong {
5041382993fSWen Gong 	const struct wmi_tlv_rfkill_state_change_ev *ev;
5051382993fSWen Gong 	const void **tb;
5061382993fSWen Gong 	bool radio;
5071382993fSWen Gong 	int ret;
5081382993fSWen Gong 
5091382993fSWen Gong 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
5101382993fSWen Gong 	if (IS_ERR(tb)) {
5111382993fSWen Gong 		ret = PTR_ERR(tb);
5121382993fSWen Gong 		ath10k_warn(ar,
5131382993fSWen Gong 			    "failed to parse rfkill state change event: %d\n",
5141382993fSWen Gong 			    ret);
5151382993fSWen Gong 		return;
5161382993fSWen Gong 	}
5171382993fSWen Gong 
5181382993fSWen Gong 	ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
5191382993fSWen Gong 	if (!ev) {
5201382993fSWen Gong 		kfree(tb);
5211382993fSWen Gong 		return;
5221382993fSWen Gong 	}
5231382993fSWen Gong 
5241382993fSWen Gong 	ath10k_dbg(ar, ATH10K_DBG_MAC,
5251382993fSWen Gong 		   "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
5261382993fSWen Gong 		   __le32_to_cpu(ev->gpio_pin_num),
5271382993fSWen Gong 		   __le32_to_cpu(ev->int_type),
5281382993fSWen Gong 		   __le32_to_cpu(ev->radio_state));
5291382993fSWen Gong 
5301382993fSWen Gong 	radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
5311382993fSWen Gong 
5321382993fSWen Gong 	spin_lock_bh(&ar->data_lock);
5331382993fSWen Gong 
5341382993fSWen Gong 	if (!radio)
5351382993fSWen Gong 		ar->hw_rfkill_on = true;
5361382993fSWen Gong 
5371382993fSWen Gong 	spin_unlock_bh(&ar->data_lock);
5381382993fSWen Gong 
5391382993fSWen Gong 	/* notify cfg80211 radio state change */
5401382993fSWen Gong 	ath10k_mac_rfkill_enable_radio(ar, radio);
5411382993fSWen Gong 	wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
5421382993fSWen Gong }
5431382993fSWen Gong 
ath10k_wmi_tlv_event_temperature(struct ath10k * ar,struct sk_buff * skb)544e98199a8SRyan Hsu static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
545e98199a8SRyan Hsu 					    struct sk_buff *skb)
546e98199a8SRyan Hsu {
547e98199a8SRyan Hsu 	const struct wmi_tlv_pdev_temperature_event *ev;
548e98199a8SRyan Hsu 
549e98199a8SRyan Hsu 	ev = (struct wmi_tlv_pdev_temperature_event *)skb->data;
550e98199a8SRyan Hsu 	if (WARN_ON(skb->len < sizeof(*ev)))
551e98199a8SRyan Hsu 		return -EPROTO;
552e98199a8SRyan Hsu 
553e98199a8SRyan Hsu 	ath10k_thermal_event_temperature(ar, __le32_to_cpu(ev->temperature));
554e98199a8SRyan Hsu 	return 0;
555e98199a8SRyan Hsu }
556e98199a8SRyan Hsu 
ath10k_wmi_event_tdls_peer(struct ath10k * ar,struct sk_buff * skb)5574c9f8d11SYingying Tang static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
5584c9f8d11SYingying Tang {
5594c9f8d11SYingying Tang 	struct ieee80211_sta *station;
5604c9f8d11SYingying Tang 	const struct wmi_tlv_tdls_peer_event *ev;
5614c9f8d11SYingying Tang 	const void **tb;
5624c9f8d11SYingying Tang 	struct ath10k_vif *arvif;
5634c9f8d11SYingying Tang 
5644c9f8d11SYingying Tang 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
5654c9f8d11SYingying Tang 	if (IS_ERR(tb)) {
5664c9f8d11SYingying Tang 		ath10k_warn(ar, "tdls peer failed to parse tlv");
5674c9f8d11SYingying Tang 		return;
5684c9f8d11SYingying Tang 	}
5694c9f8d11SYingying Tang 	ev = tb[WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT];
5704c9f8d11SYingying Tang 	if (!ev) {
5714c9f8d11SYingying Tang 		kfree(tb);
5724c9f8d11SYingying Tang 		ath10k_warn(ar, "tdls peer NULL event");
5734c9f8d11SYingying Tang 		return;
5744c9f8d11SYingying Tang 	}
5754c9f8d11SYingying Tang 
5764c9f8d11SYingying Tang 	switch (__le32_to_cpu(ev->peer_reason)) {
5774c9f8d11SYingying Tang 	case WMI_TDLS_TEARDOWN_REASON_TX:
5784c9f8d11SYingying Tang 	case WMI_TDLS_TEARDOWN_REASON_RSSI:
5794c9f8d11SYingying Tang 	case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
58009078368SShuah Khan 		rcu_read_lock();
5814c9f8d11SYingying Tang 		station = ieee80211_find_sta_by_ifaddr(ar->hw,
5824c9f8d11SYingying Tang 						       ev->peer_macaddr.addr,
5834c9f8d11SYingying Tang 						       NULL);
5844c9f8d11SYingying Tang 		if (!station) {
5854c9f8d11SYingying Tang 			ath10k_warn(ar, "did not find station from tdls peer event");
58609078368SShuah Khan 			goto exit;
5874c9f8d11SYingying Tang 		}
58847311891SPeter Kosyh 
5894c9f8d11SYingying Tang 		arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
59047311891SPeter Kosyh 		if (!arvif) {
59147311891SPeter Kosyh 			ath10k_warn(ar, "no vif for vdev_id %d found",
59247311891SPeter Kosyh 				    __le32_to_cpu(ev->vdev_id));
59347311891SPeter Kosyh 			goto exit;
59447311891SPeter Kosyh 		}
59547311891SPeter Kosyh 
5964c9f8d11SYingying Tang 		ieee80211_tdls_oper_request(
5974c9f8d11SYingying Tang 					arvif->vif, station->addr,
5984c9f8d11SYingying Tang 					NL80211_TDLS_TEARDOWN,
5994c9f8d11SYingying Tang 					WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
6004c9f8d11SYingying Tang 					GFP_ATOMIC
6014c9f8d11SYingying Tang 					);
6024c9f8d11SYingying Tang 		break;
603eaaf52e4SShuah Khan 	default:
604eaaf52e4SShuah Khan 		kfree(tb);
605eaaf52e4SShuah Khan 		return;
6064c9f8d11SYingying Tang 	}
60709078368SShuah Khan 
60809078368SShuah Khan exit:
60909078368SShuah Khan 	rcu_read_unlock();
6104c9f8d11SYingying Tang 	kfree(tb);
6114c9f8d11SYingying Tang }
6124c9f8d11SYingying Tang 
ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k * ar,struct sk_buff * skb)613c6f537a1SDundi Raviteja static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
614c6f537a1SDundi Raviteja 						 struct sk_buff *skb)
615c6f537a1SDundi Raviteja {
616c6f537a1SDundi Raviteja 	struct wmi_peer_delete_resp_ev_arg *arg;
617c6f537a1SDundi Raviteja 	struct wmi_tlv *tlv_hdr;
618c6f537a1SDundi Raviteja 
619c6f537a1SDundi Raviteja 	tlv_hdr = (struct wmi_tlv *)skb->data;
620c6f537a1SDundi Raviteja 	arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value;
621c6f537a1SDundi Raviteja 
622c6f537a1SDundi Raviteja 	ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id);
623c6f537a1SDundi Raviteja 	ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr);
624c6f537a1SDundi Raviteja 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n");
625c6f537a1SDundi Raviteja 
626c6f537a1SDundi Raviteja 	complete(&ar->peer_delete_done);
627c6f537a1SDundi Raviteja 
628c6f537a1SDundi Raviteja 	return 0;
629c6f537a1SDundi Raviteja }
630c6f537a1SDundi Raviteja 
631ca996ec5SMichal Kazior /***********/
632ca996ec5SMichal Kazior /* TLV ops */
633ca996ec5SMichal Kazior /***********/
634ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_rx(struct ath10k * ar,struct sk_buff * skb)635ca996ec5SMichal Kazior static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
636ca996ec5SMichal Kazior {
637ca996ec5SMichal Kazior 	struct wmi_cmd_hdr *cmd_hdr;
638ca996ec5SMichal Kazior 	enum wmi_tlv_event_id id;
639a81a98ceSAlan Liu 	bool consumed;
640ca996ec5SMichal Kazior 
641ca996ec5SMichal Kazior 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
642ca996ec5SMichal Kazior 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
643ca996ec5SMichal Kazior 
644ca996ec5SMichal Kazior 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
645469d479fSMichal Kazior 		goto out;
646ca996ec5SMichal Kazior 
647ca996ec5SMichal Kazior 	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
648ca996ec5SMichal Kazior 
649a81a98ceSAlan Liu 	consumed = ath10k_tm_event_wmi(ar, id, skb);
650a81a98ceSAlan Liu 
651a81a98ceSAlan Liu 	/* Ready event must be handled normally also in UTF mode so that we
652a81a98ceSAlan Liu 	 * know the UTF firmware has booted, others we are just bypass WMI
653a81a98ceSAlan Liu 	 * events to testmode.
654a81a98ceSAlan Liu 	 */
655a81a98ceSAlan Liu 	if (consumed && id != WMI_TLV_READY_EVENTID) {
656a81a98ceSAlan Liu 		ath10k_dbg(ar, ATH10K_DBG_WMI,
657a81a98ceSAlan Liu 			   "wmi tlv testmode consumed 0x%x\n", id);
658a81a98ceSAlan Liu 		goto out;
659a81a98ceSAlan Liu 	}
660a81a98ceSAlan Liu 
661ca996ec5SMichal Kazior 	switch (id) {
662ca996ec5SMichal Kazior 	case WMI_TLV_MGMT_RX_EVENTID:
663ca996ec5SMichal Kazior 		ath10k_wmi_event_mgmt_rx(ar, skb);
664ca996ec5SMichal Kazior 		/* mgmt_rx() owns the skb now! */
665ca996ec5SMichal Kazior 		return;
666ca996ec5SMichal Kazior 	case WMI_TLV_SCAN_EVENTID:
667ca996ec5SMichal Kazior 		ath10k_wmi_event_scan(ar, skb);
668ca996ec5SMichal Kazior 		break;
669ca996ec5SMichal Kazior 	case WMI_TLV_CHAN_INFO_EVENTID:
670ca996ec5SMichal Kazior 		ath10k_wmi_event_chan_info(ar, skb);
671ca996ec5SMichal Kazior 		break;
672ca996ec5SMichal Kazior 	case WMI_TLV_ECHO_EVENTID:
673ca996ec5SMichal Kazior 		ath10k_wmi_event_echo(ar, skb);
674ca996ec5SMichal Kazior 		break;
675ca996ec5SMichal Kazior 	case WMI_TLV_DEBUG_MESG_EVENTID:
676ca996ec5SMichal Kazior 		ath10k_wmi_event_debug_mesg(ar, skb);
677ca996ec5SMichal Kazior 		break;
678ca996ec5SMichal Kazior 	case WMI_TLV_UPDATE_STATS_EVENTID:
679ca996ec5SMichal Kazior 		ath10k_wmi_event_update_stats(ar, skb);
680ca996ec5SMichal Kazior 		break;
6810f7cb268SWen Gong 	case WMI_TLV_PEER_STATS_INFO_EVENTID:
6820f7cb268SWen Gong 		ath10k_wmi_tlv_event_peer_stats_info(ar, skb);
6830f7cb268SWen Gong 		break;
684ca996ec5SMichal Kazior 	case WMI_TLV_VDEV_START_RESP_EVENTID:
685ca996ec5SMichal Kazior 		ath10k_wmi_event_vdev_start_resp(ar, skb);
686ca996ec5SMichal Kazior 		break;
687ca996ec5SMichal Kazior 	case WMI_TLV_VDEV_STOPPED_EVENTID:
688ca996ec5SMichal Kazior 		ath10k_wmi_event_vdev_stopped(ar, skb);
689ca996ec5SMichal Kazior 		break;
690fe36e70fSRakesh Pillai 	case WMI_TLV_VDEV_DELETE_RESP_EVENTID:
691fe36e70fSRakesh Pillai 		ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb);
692fe36e70fSRakesh Pillai 		break;
693ca996ec5SMichal Kazior 	case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
694ca996ec5SMichal Kazior 		ath10k_wmi_event_peer_sta_kickout(ar, skb);
695ca996ec5SMichal Kazior 		break;
696ca996ec5SMichal Kazior 	case WMI_TLV_HOST_SWBA_EVENTID:
697ca996ec5SMichal Kazior 		ath10k_wmi_event_host_swba(ar, skb);
698ca996ec5SMichal Kazior 		break;
699ca996ec5SMichal Kazior 	case WMI_TLV_TBTTOFFSET_UPDATE_EVENTID:
700ca996ec5SMichal Kazior 		ath10k_wmi_event_tbttoffset_update(ar, skb);
701ca996ec5SMichal Kazior 		break;
702ca996ec5SMichal Kazior 	case WMI_TLV_PHYERR_EVENTID:
703ca996ec5SMichal Kazior 		ath10k_wmi_event_phyerr(ar, skb);
704ca996ec5SMichal Kazior 		break;
705ca996ec5SMichal Kazior 	case WMI_TLV_ROAM_EVENTID:
706ca996ec5SMichal Kazior 		ath10k_wmi_event_roam(ar, skb);
707ca996ec5SMichal Kazior 		break;
708ca996ec5SMichal Kazior 	case WMI_TLV_PROFILE_MATCH:
709ca996ec5SMichal Kazior 		ath10k_wmi_event_profile_match(ar, skb);
710ca996ec5SMichal Kazior 		break;
711ca996ec5SMichal Kazior 	case WMI_TLV_DEBUG_PRINT_EVENTID:
712ca996ec5SMichal Kazior 		ath10k_wmi_event_debug_print(ar, skb);
713ca996ec5SMichal Kazior 		break;
714ca996ec5SMichal Kazior 	case WMI_TLV_PDEV_QVIT_EVENTID:
715ca996ec5SMichal Kazior 		ath10k_wmi_event_pdev_qvit(ar, skb);
716ca996ec5SMichal Kazior 		break;
717ca996ec5SMichal Kazior 	case WMI_TLV_WLAN_PROFILE_DATA_EVENTID:
718ca996ec5SMichal Kazior 		ath10k_wmi_event_wlan_profile_data(ar, skb);
719ca996ec5SMichal Kazior 		break;
720ca996ec5SMichal Kazior 	case WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID:
721ca996ec5SMichal Kazior 		ath10k_wmi_event_rtt_measurement_report(ar, skb);
722ca996ec5SMichal Kazior 		break;
723ca996ec5SMichal Kazior 	case WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID:
724ca996ec5SMichal Kazior 		ath10k_wmi_event_tsf_measurement_report(ar, skb);
725ca996ec5SMichal Kazior 		break;
726ca996ec5SMichal Kazior 	case WMI_TLV_RTT_ERROR_REPORT_EVENTID:
727ca996ec5SMichal Kazior 		ath10k_wmi_event_rtt_error_report(ar, skb);
728ca996ec5SMichal Kazior 		break;
729ca996ec5SMichal Kazior 	case WMI_TLV_WOW_WAKEUP_HOST_EVENTID:
730ca996ec5SMichal Kazior 		ath10k_wmi_event_wow_wakeup_host(ar, skb);
731ca996ec5SMichal Kazior 		break;
732ca996ec5SMichal Kazior 	case WMI_TLV_DCS_INTERFERENCE_EVENTID:
733ca996ec5SMichal Kazior 		ath10k_wmi_event_dcs_interference(ar, skb);
734ca996ec5SMichal Kazior 		break;
735ca996ec5SMichal Kazior 	case WMI_TLV_PDEV_TPC_CONFIG_EVENTID:
736ca996ec5SMichal Kazior 		ath10k_wmi_event_pdev_tpc_config(ar, skb);
737ca996ec5SMichal Kazior 		break;
738ca996ec5SMichal Kazior 	case WMI_TLV_PDEV_FTM_INTG_EVENTID:
739ca996ec5SMichal Kazior 		ath10k_wmi_event_pdev_ftm_intg(ar, skb);
740ca996ec5SMichal Kazior 		break;
741ca996ec5SMichal Kazior 	case WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID:
742ca996ec5SMichal Kazior 		ath10k_wmi_event_gtk_offload_status(ar, skb);
743ca996ec5SMichal Kazior 		break;
744ca996ec5SMichal Kazior 	case WMI_TLV_GTK_REKEY_FAIL_EVENTID:
745ca996ec5SMichal Kazior 		ath10k_wmi_event_gtk_rekey_fail(ar, skb);
746ca996ec5SMichal Kazior 		break;
747ca996ec5SMichal Kazior 	case WMI_TLV_TX_DELBA_COMPLETE_EVENTID:
748ca996ec5SMichal Kazior 		ath10k_wmi_event_delba_complete(ar, skb);
749ca996ec5SMichal Kazior 		break;
750ca996ec5SMichal Kazior 	case WMI_TLV_TX_ADDBA_COMPLETE_EVENTID:
751ca996ec5SMichal Kazior 		ath10k_wmi_event_addba_complete(ar, skb);
752ca996ec5SMichal Kazior 		break;
753ca996ec5SMichal Kazior 	case WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID:
754ca996ec5SMichal Kazior 		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
755ca996ec5SMichal Kazior 		break;
756ca996ec5SMichal Kazior 	case WMI_TLV_SERVICE_READY_EVENTID:
757ca996ec5SMichal Kazior 		ath10k_wmi_event_service_ready(ar, skb);
758c8ecfc1cSRaja Mani 		return;
759ca996ec5SMichal Kazior 	case WMI_TLV_READY_EVENTID:
760ca996ec5SMichal Kazior 		ath10k_wmi_event_ready(ar, skb);
761ca996ec5SMichal Kazior 		break;
762cea19a6cSCarl Huang 	case WMI_TLV_SERVICE_AVAILABLE_EVENTID:
763cea19a6cSCarl Huang 		ath10k_wmi_event_service_available(ar, skb);
764cea19a6cSCarl Huang 		break;
7656bf12062SMichal Kazior 	case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID:
7666bf12062SMichal Kazior 		ath10k_wmi_tlv_event_bcn_tx_status(ar, skb);
7676bf12062SMichal Kazior 		break;
76804de6c6cSMichal Kazior 	case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID:
76904de6c6cSMichal Kazior 		ath10k_wmi_tlv_event_diag_data(ar, skb);
77004de6c6cSMichal Kazior 		break;
771c3113c39SMichal Kazior 	case WMI_TLV_DIAG_EVENTID:
772c3113c39SMichal Kazior 		ath10k_wmi_tlv_event_diag(ar, skb);
773c3113c39SMichal Kazior 		break;
774fe3cbdfcSMichal Kazior 	case WMI_TLV_P2P_NOA_EVENTID:
775fe3cbdfcSMichal Kazior 		ath10k_wmi_tlv_event_p2p_noa(ar, skb);
776fe3cbdfcSMichal Kazior 		break;
777b4aa539dSMichal Kazior 	case WMI_TLV_TX_PAUSE_EVENTID:
778b4aa539dSMichal Kazior 		ath10k_wmi_tlv_event_tx_pause(ar, skb);
779b4aa539dSMichal Kazior 		break;
7801382993fSWen Gong 	case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
7811382993fSWen Gong 		ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
7821382993fSWen Gong 		break;
783e98199a8SRyan Hsu 	case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
784e98199a8SRyan Hsu 		ath10k_wmi_tlv_event_temperature(ar, skb);
785e98199a8SRyan Hsu 		break;
7864c9f8d11SYingying Tang 	case WMI_TLV_TDLS_PEER_EVENTID:
7874c9f8d11SYingying Tang 		ath10k_wmi_event_tdls_peer(ar, skb);
7884c9f8d11SYingying Tang 		break;
789c6f537a1SDundi Raviteja 	case WMI_TLV_PEER_DELETE_RESP_EVENTID:
790c6f537a1SDundi Raviteja 		ath10k_wmi_tlv_event_peer_delete_resp(ar, skb);
791c6f537a1SDundi Raviteja 		break;
792dc405152SRakesh Pillai 	case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
793dc405152SRakesh Pillai 		ath10k_wmi_event_mgmt_tx_compl(ar, skb);
794dc405152SRakesh Pillai 		break;
795cc123facSRakesh Pillai 	case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID:
796cc123facSRakesh Pillai 		ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb);
797cc123facSRakesh Pillai 		break;
798ca996ec5SMichal Kazior 	default:
799bd085be6SGovind Singh 		ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id);
800ca996ec5SMichal Kazior 		break;
801ca996ec5SMichal Kazior 	}
802ca996ec5SMichal Kazior 
803469d479fSMichal Kazior out:
804ca996ec5SMichal Kazior 	dev_kfree_skb(skb);
805ca996ec5SMichal Kazior }
806ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_scan_ev_arg * arg)807ca996ec5SMichal Kazior static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
808ca996ec5SMichal Kazior 					  struct sk_buff *skb,
809ca996ec5SMichal Kazior 					  struct wmi_scan_ev_arg *arg)
810ca996ec5SMichal Kazior {
811ca996ec5SMichal Kazior 	const void **tb;
812ca996ec5SMichal Kazior 	const struct wmi_scan_event *ev;
813ca996ec5SMichal Kazior 	int ret;
814ca996ec5SMichal Kazior 
815ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
816ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
817ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
818ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
819ca996ec5SMichal Kazior 		return ret;
820ca996ec5SMichal Kazior 	}
821ca996ec5SMichal Kazior 
822ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_SCAN_EVENT];
823ca996ec5SMichal Kazior 	if (!ev) {
824ca996ec5SMichal Kazior 		kfree(tb);
825ca996ec5SMichal Kazior 		return -EPROTO;
826ca996ec5SMichal Kazior 	}
827ca996ec5SMichal Kazior 
828ca996ec5SMichal Kazior 	arg->event_type = ev->event_type;
829ca996ec5SMichal Kazior 	arg->reason = ev->reason;
830ca996ec5SMichal Kazior 	arg->channel_freq = ev->channel_freq;
831ca996ec5SMichal Kazior 	arg->scan_req_id = ev->scan_req_id;
832ca996ec5SMichal Kazior 	arg->scan_id = ev->scan_id;
833ca996ec5SMichal Kazior 	arg->vdev_id = ev->vdev_id;
834ca996ec5SMichal Kazior 
835ca996ec5SMichal Kazior 	kfree(tb);
836ca996ec5SMichal Kazior 	return 0;
837ca996ec5SMichal Kazior }
838ca996ec5SMichal Kazior 
839dc405152SRakesh Pillai static int
ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_tlv_mgmt_tx_compl_ev_arg * arg)840dc405152SRakesh Pillai ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
841dc405152SRakesh Pillai 					struct wmi_tlv_mgmt_tx_compl_ev_arg *arg)
842dc405152SRakesh Pillai {
843dc405152SRakesh Pillai 	const void **tb;
844dc405152SRakesh Pillai 	const struct wmi_tlv_mgmt_tx_compl_ev *ev;
845dc405152SRakesh Pillai 	int ret;
846dc405152SRakesh Pillai 
847dc405152SRakesh Pillai 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
848dc405152SRakesh Pillai 	if (IS_ERR(tb)) {
849dc405152SRakesh Pillai 		ret = PTR_ERR(tb);
850dc405152SRakesh Pillai 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
851dc405152SRakesh Pillai 		return ret;
852dc405152SRakesh Pillai 	}
853dc405152SRakesh Pillai 
854dc405152SRakesh Pillai 	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
855ad25ee36SXingyuan Mo 	if (!ev) {
856ad25ee36SXingyuan Mo 		kfree(tb);
857ad25ee36SXingyuan Mo 		return -EPROTO;
858ad25ee36SXingyuan Mo 	}
859dc405152SRakesh Pillai 
860dc405152SRakesh Pillai 	arg->desc_id = ev->desc_id;
861dc405152SRakesh Pillai 	arg->status = ev->status;
862dc405152SRakesh Pillai 	arg->pdev_id = ev->pdev_id;
8634b816f17SAbhishek Ambure 	arg->ppdu_id = ev->ppdu_id;
8644b816f17SAbhishek Ambure 
8654b816f17SAbhishek Ambure 	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
8664b816f17SAbhishek Ambure 		arg->ack_rssi = ev->ack_rssi;
867dc405152SRakesh Pillai 
868dc405152SRakesh Pillai 	kfree(tb);
869dc405152SRakesh Pillai 	return 0;
870dc405152SRakesh Pillai }
871dc405152SRakesh Pillai 
872cc123facSRakesh Pillai struct wmi_tlv_tx_bundle_compl_parse {
873cc123facSRakesh Pillai 	const __le32 *num_reports;
874cc123facSRakesh Pillai 	const __le32 *desc_ids;
875cc123facSRakesh Pillai 	const __le32 *status;
8764b816f17SAbhishek Ambure 	const __le32 *ppdu_ids;
8774b816f17SAbhishek Ambure 	const __le32 *ack_rssi;
878cc123facSRakesh Pillai 	bool desc_ids_done;
879cc123facSRakesh Pillai 	bool status_done;
8804b816f17SAbhishek Ambure 	bool ppdu_ids_done;
8814b816f17SAbhishek Ambure 	bool ack_rssi_done;
882cc123facSRakesh Pillai };
883cc123facSRakesh Pillai 
884cc123facSRakesh Pillai static int
ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)885cc123facSRakesh Pillai ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len,
886cc123facSRakesh Pillai 					  const void *ptr, void *data)
887cc123facSRakesh Pillai {
888cc123facSRakesh Pillai 	struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data;
889cc123facSRakesh Pillai 
890cc123facSRakesh Pillai 	switch (tag) {
891cc123facSRakesh Pillai 	case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT:
892cc123facSRakesh Pillai 		bundle_tx_compl->num_reports = ptr;
893cc123facSRakesh Pillai 		break;
894cc123facSRakesh Pillai 	case WMI_TLV_TAG_ARRAY_UINT32:
895cc123facSRakesh Pillai 		if (!bundle_tx_compl->desc_ids_done) {
896cc123facSRakesh Pillai 			bundle_tx_compl->desc_ids_done = true;
897cc123facSRakesh Pillai 			bundle_tx_compl->desc_ids = ptr;
898cc123facSRakesh Pillai 		} else if (!bundle_tx_compl->status_done) {
899cc123facSRakesh Pillai 			bundle_tx_compl->status_done = true;
900cc123facSRakesh Pillai 			bundle_tx_compl->status = ptr;
9014b816f17SAbhishek Ambure 		} else if (!bundle_tx_compl->ppdu_ids_done) {
9024b816f17SAbhishek Ambure 			bundle_tx_compl->ppdu_ids_done = true;
9034b816f17SAbhishek Ambure 			bundle_tx_compl->ppdu_ids = ptr;
9044b816f17SAbhishek Ambure 		} else if (!bundle_tx_compl->ack_rssi_done) {
9054b816f17SAbhishek Ambure 			bundle_tx_compl->ack_rssi_done = true;
9064b816f17SAbhishek Ambure 			bundle_tx_compl->ack_rssi = ptr;
907cc123facSRakesh Pillai 		}
908cc123facSRakesh Pillai 		break;
909cc123facSRakesh Pillai 	default:
910cc123facSRakesh Pillai 		break;
911cc123facSRakesh Pillai 	}
912cc123facSRakesh Pillai 	return 0;
913cc123facSRakesh Pillai }
914cc123facSRakesh Pillai 
ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg * arg)915cc123facSRakesh Pillai static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
916cc123facSRakesh Pillai 				struct ath10k *ar, struct sk_buff *skb,
917cc123facSRakesh Pillai 				struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
918cc123facSRakesh Pillai {
919cc123facSRakesh Pillai 	struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { };
920cc123facSRakesh Pillai 	int ret;
921cc123facSRakesh Pillai 
922cc123facSRakesh Pillai 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
923cc123facSRakesh Pillai 				  ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse,
924cc123facSRakesh Pillai 				  &bundle_tx_compl);
925cc123facSRakesh Pillai 	if (ret) {
926cc123facSRakesh Pillai 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
927cc123facSRakesh Pillai 		return ret;
928cc123facSRakesh Pillai 	}
929cc123facSRakesh Pillai 
930cc123facSRakesh Pillai 	if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids ||
931cc123facSRakesh Pillai 	    !bundle_tx_compl.status)
932cc123facSRakesh Pillai 		return -EPROTO;
933cc123facSRakesh Pillai 
934cc123facSRakesh Pillai 	arg->num_reports = *bundle_tx_compl.num_reports;
935cc123facSRakesh Pillai 	arg->desc_ids = bundle_tx_compl.desc_ids;
936cc123facSRakesh Pillai 	arg->status = bundle_tx_compl.status;
9374b816f17SAbhishek Ambure 	arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
9384b816f17SAbhishek Ambure 
9394b816f17SAbhishek Ambure 	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
9404b816f17SAbhishek Ambure 		arg->ack_rssi = bundle_tx_compl.ack_rssi;
941cc123facSRakesh Pillai 
942cc123facSRakesh Pillai 	return 0;
943cc123facSRakesh Pillai }
944cc123facSRakesh Pillai 
ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_mgmt_rx_ev_arg * arg)945ca996ec5SMichal Kazior static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
946ca996ec5SMichal Kazior 					     struct sk_buff *skb,
947ca996ec5SMichal Kazior 					     struct wmi_mgmt_rx_ev_arg *arg)
948ca996ec5SMichal Kazior {
949ca996ec5SMichal Kazior 	const void **tb;
950ca996ec5SMichal Kazior 	const struct wmi_tlv_mgmt_rx_ev *ev;
951ca996ec5SMichal Kazior 	const u8 *frame;
952ca996ec5SMichal Kazior 	u32 msdu_len;
9537005eafcSWen Gong 	int ret, i;
954ca996ec5SMichal Kazior 
955ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
956ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
957ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
958ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
959ca996ec5SMichal Kazior 		return ret;
960ca996ec5SMichal Kazior 	}
961ca996ec5SMichal Kazior 
962ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR];
963ca996ec5SMichal Kazior 	frame = tb[WMI_TLV_TAG_ARRAY_BYTE];
964ca996ec5SMichal Kazior 
965ca996ec5SMichal Kazior 	if (!ev || !frame) {
966ca996ec5SMichal Kazior 		kfree(tb);
967ca996ec5SMichal Kazior 		return -EPROTO;
968ca996ec5SMichal Kazior 	}
969ca996ec5SMichal Kazior 
970ca996ec5SMichal Kazior 	arg->channel = ev->channel;
971ca996ec5SMichal Kazior 	arg->buf_len = ev->buf_len;
972ca996ec5SMichal Kazior 	arg->status = ev->status;
973ca996ec5SMichal Kazior 	arg->snr = ev->snr;
974ca996ec5SMichal Kazior 	arg->phy_mode = ev->phy_mode;
975ca996ec5SMichal Kazior 	arg->rate = ev->rate;
976ca996ec5SMichal Kazior 
9777005eafcSWen Gong 	for (i = 0; i < ARRAY_SIZE(ev->rssi); i++)
9787005eafcSWen Gong 		arg->rssi[i] = ev->rssi[i];
9797005eafcSWen Gong 
980ca996ec5SMichal Kazior 	msdu_len = __le32_to_cpu(arg->buf_len);
981ca996ec5SMichal Kazior 
982ca996ec5SMichal Kazior 	if (skb->len < (frame - skb->data) + msdu_len) {
983ca996ec5SMichal Kazior 		kfree(tb);
984ca996ec5SMichal Kazior 		return -EPROTO;
985ca996ec5SMichal Kazior 	}
986ca996ec5SMichal Kazior 
987ca996ec5SMichal Kazior 	/* shift the sk_buff to point to `frame` */
988ca996ec5SMichal Kazior 	skb_trim(skb, 0);
989ca996ec5SMichal Kazior 	skb_put(skb, frame - skb->data);
990ca996ec5SMichal Kazior 	skb_pull(skb, frame - skb->data);
991ca996ec5SMichal Kazior 	skb_put(skb, msdu_len);
992ca996ec5SMichal Kazior 
993ca996ec5SMichal Kazior 	kfree(tb);
994ca996ec5SMichal Kazior 	return 0;
995ca996ec5SMichal Kazior }
996ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_ch_info_ev_arg * arg)997ca996ec5SMichal Kazior static int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar,
998ca996ec5SMichal Kazior 					     struct sk_buff *skb,
999ca996ec5SMichal Kazior 					     struct wmi_ch_info_ev_arg *arg)
1000ca996ec5SMichal Kazior {
1001ca996ec5SMichal Kazior 	const void **tb;
10026be6c04bSRakesh Pillai 	const struct wmi_tlv_chan_info_event *ev;
1003ca996ec5SMichal Kazior 	int ret;
1004ca996ec5SMichal Kazior 
1005ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1006ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
1007ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
1008ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1009ca996ec5SMichal Kazior 		return ret;
1010ca996ec5SMichal Kazior 	}
1011ca996ec5SMichal Kazior 
1012ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT];
1013ca996ec5SMichal Kazior 	if (!ev) {
1014ca996ec5SMichal Kazior 		kfree(tb);
1015ca996ec5SMichal Kazior 		return -EPROTO;
1016ca996ec5SMichal Kazior 	}
1017ca996ec5SMichal Kazior 
1018ca996ec5SMichal Kazior 	arg->err_code = ev->err_code;
1019ca996ec5SMichal Kazior 	arg->freq = ev->freq;
1020ca996ec5SMichal Kazior 	arg->cmd_flags = ev->cmd_flags;
1021ca996ec5SMichal Kazior 	arg->noise_floor = ev->noise_floor;
1022ca996ec5SMichal Kazior 	arg->rx_clear_count = ev->rx_clear_count;
1023ca996ec5SMichal Kazior 	arg->cycle_count = ev->cycle_count;
102413104929SRakesh Pillai 	if (test_bit(ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL,
102513104929SRakesh Pillai 		     ar->running_fw->fw_file.fw_features))
102613104929SRakesh Pillai 		arg->mac_clk_mhz = ev->mac_clk_mhz;
1027ca996ec5SMichal Kazior 
1028ca996ec5SMichal Kazior 	kfree(tb);
1029ca996ec5SMichal Kazior 	return 0;
1030ca996ec5SMichal Kazior }
1031ca996ec5SMichal Kazior 
1032ca996ec5SMichal Kazior static int
ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_vdev_start_ev_arg * arg)1033ca996ec5SMichal Kazior ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
1034ca996ec5SMichal Kazior 				     struct wmi_vdev_start_ev_arg *arg)
1035ca996ec5SMichal Kazior {
1036ca996ec5SMichal Kazior 	const void **tb;
1037ca996ec5SMichal Kazior 	const struct wmi_vdev_start_response_event *ev;
1038ca996ec5SMichal Kazior 	int ret;
1039ca996ec5SMichal Kazior 
1040ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1041ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
1042ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
1043ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1044ca996ec5SMichal Kazior 		return ret;
1045ca996ec5SMichal Kazior 	}
1046ca996ec5SMichal Kazior 
1047ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT];
1048ca996ec5SMichal Kazior 	if (!ev) {
1049ca996ec5SMichal Kazior 		kfree(tb);
1050ca996ec5SMichal Kazior 		return -EPROTO;
1051ca996ec5SMichal Kazior 	}
1052ca996ec5SMichal Kazior 
1053ca996ec5SMichal Kazior 	skb_pull(skb, sizeof(*ev));
1054ca996ec5SMichal Kazior 	arg->vdev_id = ev->vdev_id;
1055ca996ec5SMichal Kazior 	arg->req_id = ev->req_id;
1056ca996ec5SMichal Kazior 	arg->resp_type = ev->resp_type;
1057ca996ec5SMichal Kazior 	arg->status = ev->status;
1058ca996ec5SMichal Kazior 
1059ca996ec5SMichal Kazior 	kfree(tb);
1060ca996ec5SMichal Kazior 	return 0;
1061ca996ec5SMichal Kazior }
1062ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_peer_kick_ev_arg * arg)1063ca996ec5SMichal Kazior static int ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k *ar,
1064ca996ec5SMichal Kazior 					       struct sk_buff *skb,
1065ca996ec5SMichal Kazior 					       struct wmi_peer_kick_ev_arg *arg)
1066ca996ec5SMichal Kazior {
1067ca996ec5SMichal Kazior 	const void **tb;
1068ca996ec5SMichal Kazior 	const struct wmi_peer_sta_kickout_event *ev;
1069ca996ec5SMichal Kazior 	int ret;
1070ca996ec5SMichal Kazior 
1071ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1072ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
1073ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
1074ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1075ca996ec5SMichal Kazior 		return ret;
1076ca996ec5SMichal Kazior 	}
1077ca996ec5SMichal Kazior 
1078ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT];
1079ca996ec5SMichal Kazior 	if (!ev) {
1080ca996ec5SMichal Kazior 		kfree(tb);
1081ca996ec5SMichal Kazior 		return -EPROTO;
1082ca996ec5SMichal Kazior 	}
1083ca996ec5SMichal Kazior 
1084ca996ec5SMichal Kazior 	arg->mac_addr = ev->peer_macaddr.addr;
1085ca996ec5SMichal Kazior 
1086ca996ec5SMichal Kazior 	kfree(tb);
1087ca996ec5SMichal Kazior 	return 0;
1088ca996ec5SMichal Kazior }
1089ca996ec5SMichal Kazior 
1090ca996ec5SMichal Kazior struct wmi_tlv_swba_parse {
1091ca996ec5SMichal Kazior 	const struct wmi_host_swba_event *ev;
1092ca996ec5SMichal Kazior 	bool tim_done;
1093ca996ec5SMichal Kazior 	bool noa_done;
1094ca996ec5SMichal Kazior 	size_t n_tim;
1095ca996ec5SMichal Kazior 	size_t n_noa;
1096ca996ec5SMichal Kazior 	struct wmi_swba_ev_arg *arg;
1097ca996ec5SMichal Kazior };
1098ca996ec5SMichal Kazior 
ath10k_wmi_tlv_swba_tim_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1099ca996ec5SMichal Kazior static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
1100ca996ec5SMichal Kazior 					 const void *ptr, void *data)
1101ca996ec5SMichal Kazior {
1102ca996ec5SMichal Kazior 	struct wmi_tlv_swba_parse *swba = data;
1103a03fee34SRaja Mani 	struct wmi_tim_info_arg *tim_info_arg;
1104a03fee34SRaja Mani 	const struct wmi_tim_info *tim_info_ev = ptr;
1105ca996ec5SMichal Kazior 
1106ca996ec5SMichal Kazior 	if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO)
1107ca996ec5SMichal Kazior 		return -EPROTO;
1108ca996ec5SMichal Kazior 
1109ca996ec5SMichal Kazior 	if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info))
1110ca996ec5SMichal Kazior 		return -ENOBUFS;
1111ca996ec5SMichal Kazior 
1112a03fee34SRaja Mani 	if (__le32_to_cpu(tim_info_ev->tim_len) >
1113a03fee34SRaja Mani 	     sizeof(tim_info_ev->tim_bitmap)) {
1114a03fee34SRaja Mani 		ath10k_warn(ar, "refusing to parse invalid swba structure\n");
1115a03fee34SRaja Mani 		return -EPROTO;
1116a03fee34SRaja Mani 	}
1117a03fee34SRaja Mani 
1118a03fee34SRaja Mani 	tim_info_arg = &swba->arg->tim_info[swba->n_tim];
1119a03fee34SRaja Mani 	tim_info_arg->tim_len = tim_info_ev->tim_len;
1120a03fee34SRaja Mani 	tim_info_arg->tim_mcast = tim_info_ev->tim_mcast;
1121a03fee34SRaja Mani 	tim_info_arg->tim_bitmap = tim_info_ev->tim_bitmap;
1122a03fee34SRaja Mani 	tim_info_arg->tim_changed = tim_info_ev->tim_changed;
1123a03fee34SRaja Mani 	tim_info_arg->tim_num_ps_pending = tim_info_ev->tim_num_ps_pending;
1124a03fee34SRaja Mani 
1125a03fee34SRaja Mani 	swba->n_tim++;
1126a03fee34SRaja Mani 
1127ca996ec5SMichal Kazior 	return 0;
1128ca996ec5SMichal Kazior }
1129ca996ec5SMichal Kazior 
ath10k_wmi_tlv_swba_noa_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1130ca996ec5SMichal Kazior static int ath10k_wmi_tlv_swba_noa_parse(struct ath10k *ar, u16 tag, u16 len,
1131ca996ec5SMichal Kazior 					 const void *ptr, void *data)
1132ca996ec5SMichal Kazior {
1133ca996ec5SMichal Kazior 	struct wmi_tlv_swba_parse *swba = data;
1134ca996ec5SMichal Kazior 
1135ca996ec5SMichal Kazior 	if (tag != WMI_TLV_TAG_STRUCT_P2P_NOA_INFO)
1136ca996ec5SMichal Kazior 		return -EPROTO;
1137ca996ec5SMichal Kazior 
1138ca996ec5SMichal Kazior 	if (swba->n_noa >= ARRAY_SIZE(swba->arg->noa_info))
1139ca996ec5SMichal Kazior 		return -ENOBUFS;
1140ca996ec5SMichal Kazior 
1141ca996ec5SMichal Kazior 	swba->arg->noa_info[swba->n_noa++] = ptr;
1142ca996ec5SMichal Kazior 	return 0;
1143ca996ec5SMichal Kazior }
1144ca996ec5SMichal Kazior 
ath10k_wmi_tlv_swba_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1145ca996ec5SMichal Kazior static int ath10k_wmi_tlv_swba_parse(struct ath10k *ar, u16 tag, u16 len,
1146ca996ec5SMichal Kazior 				     const void *ptr, void *data)
1147ca996ec5SMichal Kazior {
1148ca996ec5SMichal Kazior 	struct wmi_tlv_swba_parse *swba = data;
1149ca996ec5SMichal Kazior 	int ret;
1150ca996ec5SMichal Kazior 
1151ca996ec5SMichal Kazior 	switch (tag) {
1152ca996ec5SMichal Kazior 	case WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT:
1153ca996ec5SMichal Kazior 		swba->ev = ptr;
1154ca996ec5SMichal Kazior 		break;
1155ca996ec5SMichal Kazior 	case WMI_TLV_TAG_ARRAY_STRUCT:
1156ca996ec5SMichal Kazior 		if (!swba->tim_done) {
1157ca996ec5SMichal Kazior 			swba->tim_done = true;
1158ca996ec5SMichal Kazior 			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
1159ca996ec5SMichal Kazior 						  ath10k_wmi_tlv_swba_tim_parse,
1160ca996ec5SMichal Kazior 						  swba);
1161ca996ec5SMichal Kazior 			if (ret)
1162ca996ec5SMichal Kazior 				return ret;
1163ca996ec5SMichal Kazior 		} else if (!swba->noa_done) {
1164ca996ec5SMichal Kazior 			swba->noa_done = true;
1165ca996ec5SMichal Kazior 			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
1166ca996ec5SMichal Kazior 						  ath10k_wmi_tlv_swba_noa_parse,
1167ca996ec5SMichal Kazior 						  swba);
1168ca996ec5SMichal Kazior 			if (ret)
1169ca996ec5SMichal Kazior 				return ret;
1170ca996ec5SMichal Kazior 		}
1171ca996ec5SMichal Kazior 		break;
1172ca996ec5SMichal Kazior 	default:
1173ca996ec5SMichal Kazior 		break;
1174ca996ec5SMichal Kazior 	}
1175ca996ec5SMichal Kazior 	return 0;
1176ca996ec5SMichal Kazior }
1177ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_swba_ev_arg * arg)1178ca996ec5SMichal Kazior static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
1179ca996ec5SMichal Kazior 					  struct sk_buff *skb,
1180ca996ec5SMichal Kazior 					  struct wmi_swba_ev_arg *arg)
1181ca996ec5SMichal Kazior {
1182ca996ec5SMichal Kazior 	struct wmi_tlv_swba_parse swba = { .arg = arg };
1183ca996ec5SMichal Kazior 	u32 map;
1184ca996ec5SMichal Kazior 	size_t n_vdevs;
1185ca996ec5SMichal Kazior 	int ret;
1186ca996ec5SMichal Kazior 
1187ca996ec5SMichal Kazior 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1188ca996ec5SMichal Kazior 				  ath10k_wmi_tlv_swba_parse, &swba);
1189ca996ec5SMichal Kazior 	if (ret) {
1190ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1191ca996ec5SMichal Kazior 		return ret;
1192ca996ec5SMichal Kazior 	}
1193ca996ec5SMichal Kazior 
1194ca996ec5SMichal Kazior 	if (!swba.ev)
1195ca996ec5SMichal Kazior 		return -EPROTO;
1196ca996ec5SMichal Kazior 
1197ca996ec5SMichal Kazior 	arg->vdev_map = swba.ev->vdev_map;
1198ca996ec5SMichal Kazior 
1199ca996ec5SMichal Kazior 	for (map = __le32_to_cpu(arg->vdev_map), n_vdevs = 0; map; map >>= 1)
1200ca996ec5SMichal Kazior 		if (map & BIT(0))
1201ca996ec5SMichal Kazior 			n_vdevs++;
1202ca996ec5SMichal Kazior 
1203ca996ec5SMichal Kazior 	if (n_vdevs != swba.n_tim ||
1204ca996ec5SMichal Kazior 	    n_vdevs != swba.n_noa)
1205ca996ec5SMichal Kazior 		return -EPROTO;
1206ca996ec5SMichal Kazior 
1207ca996ec5SMichal Kazior 	return 0;
1208ca996ec5SMichal Kazior }
1209ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k * ar,struct sk_buff * skb,struct wmi_phyerr_hdr_arg * arg)1210991adf71SRaja Mani static int ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k *ar,
1211ca996ec5SMichal Kazior 						struct sk_buff *skb,
1212991adf71SRaja Mani 						struct wmi_phyerr_hdr_arg *arg)
1213ca996ec5SMichal Kazior {
1214ca996ec5SMichal Kazior 	const void **tb;
1215ca996ec5SMichal Kazior 	const struct wmi_tlv_phyerr_ev *ev;
1216ca996ec5SMichal Kazior 	const void *phyerrs;
1217ca996ec5SMichal Kazior 	int ret;
1218ca996ec5SMichal Kazior 
1219ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1220ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
1221ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
1222ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1223ca996ec5SMichal Kazior 		return ret;
1224ca996ec5SMichal Kazior 	}
1225ca996ec5SMichal Kazior 
1226ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR];
1227ca996ec5SMichal Kazior 	phyerrs = tb[WMI_TLV_TAG_ARRAY_BYTE];
1228ca996ec5SMichal Kazior 
1229ca996ec5SMichal Kazior 	if (!ev || !phyerrs) {
1230ca996ec5SMichal Kazior 		kfree(tb);
1231ca996ec5SMichal Kazior 		return -EPROTO;
1232ca996ec5SMichal Kazior 	}
1233ca996ec5SMichal Kazior 
1234991adf71SRaja Mani 	arg->num_phyerrs  = __le32_to_cpu(ev->num_phyerrs);
1235991adf71SRaja Mani 	arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
1236991adf71SRaja Mani 	arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
1237991adf71SRaja Mani 	arg->buf_len = __le32_to_cpu(ev->buf_len);
1238ca996ec5SMichal Kazior 	arg->phyerrs = phyerrs;
1239ca996ec5SMichal Kazior 
1240ca996ec5SMichal Kazior 	kfree(tb);
1241ca996ec5SMichal Kazior 	return 0;
1242ca996ec5SMichal Kazior }
1243ca996ec5SMichal Kazior 
1244ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER_NS0 0x5F414351
1245ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER_NS1 0x00004C4D
1246ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER_NS2 0x00000000
1247ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER_NS3 0x00000000
1248ca996ec5SMichal Kazior 
1249ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER0_MAJOR 1
1250ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER0_MINOR 0
1251ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER0 ((((WMI_TLV_ABI_VER0_MAJOR) << 24) & 0xFF000000) | \
1252ca996ec5SMichal Kazior 			  (((WMI_TLV_ABI_VER0_MINOR) <<  0) & 0x00FFFFFF))
1253ca996ec5SMichal Kazior #define WMI_TLV_ABI_VER1 53
1254ca996ec5SMichal Kazior 
1255ca996ec5SMichal Kazior static int
ath10k_wmi_tlv_parse_mem_reqs(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1256ca996ec5SMichal Kazior ath10k_wmi_tlv_parse_mem_reqs(struct ath10k *ar, u16 tag, u16 len,
1257ca996ec5SMichal Kazior 			      const void *ptr, void *data)
1258ca996ec5SMichal Kazior {
1259ca996ec5SMichal Kazior 	struct wmi_svc_rdy_ev_arg *arg = data;
1260ca996ec5SMichal Kazior 	int i;
1261ca996ec5SMichal Kazior 
1262ca996ec5SMichal Kazior 	if (tag != WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ)
1263ca996ec5SMichal Kazior 		return -EPROTO;
1264ca996ec5SMichal Kazior 
1265ca996ec5SMichal Kazior 	for (i = 0; i < ARRAY_SIZE(arg->mem_reqs); i++) {
1266ca996ec5SMichal Kazior 		if (!arg->mem_reqs[i]) {
1267ca996ec5SMichal Kazior 			arg->mem_reqs[i] = ptr;
1268ca996ec5SMichal Kazior 			return 0;
1269ca996ec5SMichal Kazior 		}
1270ca996ec5SMichal Kazior 	}
1271ca996ec5SMichal Kazior 
1272ca996ec5SMichal Kazior 	return -ENOMEM;
1273ca996ec5SMichal Kazior }
1274ca996ec5SMichal Kazior 
1275229329ffSRakesh Pillai struct wmi_tlv_svc_rdy_parse {
1276ca996ec5SMichal Kazior 	const struct hal_reg_capabilities *reg;
1277ca996ec5SMichal Kazior 	const struct wmi_tlv_svc_rdy_ev *ev;
1278ca996ec5SMichal Kazior 	const __le32 *svc_bmap;
1279ca996ec5SMichal Kazior 	const struct wlan_host_mem_req *mem_reqs;
1280229329ffSRakesh Pillai 	bool svc_bmap_done;
1281229329ffSRakesh Pillai 	bool dbs_hw_mode_done;
1282229329ffSRakesh Pillai };
1283229329ffSRakesh Pillai 
ath10k_wmi_tlv_svc_rdy_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1284229329ffSRakesh Pillai static int ath10k_wmi_tlv_svc_rdy_parse(struct ath10k *ar, u16 tag, u16 len,
1285229329ffSRakesh Pillai 					const void *ptr, void *data)
1286229329ffSRakesh Pillai {
1287229329ffSRakesh Pillai 	struct wmi_tlv_svc_rdy_parse *svc_rdy = data;
1288229329ffSRakesh Pillai 
1289229329ffSRakesh Pillai 	switch (tag) {
1290229329ffSRakesh Pillai 	case WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT:
1291229329ffSRakesh Pillai 		svc_rdy->ev = ptr;
1292229329ffSRakesh Pillai 		break;
1293229329ffSRakesh Pillai 	case WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES:
1294229329ffSRakesh Pillai 		svc_rdy->reg = ptr;
1295229329ffSRakesh Pillai 		break;
1296229329ffSRakesh Pillai 	case WMI_TLV_TAG_ARRAY_STRUCT:
1297229329ffSRakesh Pillai 		svc_rdy->mem_reqs = ptr;
1298229329ffSRakesh Pillai 		break;
1299229329ffSRakesh Pillai 	case WMI_TLV_TAG_ARRAY_UINT32:
1300229329ffSRakesh Pillai 		if (!svc_rdy->svc_bmap_done) {
1301229329ffSRakesh Pillai 			svc_rdy->svc_bmap_done = true;
1302229329ffSRakesh Pillai 			svc_rdy->svc_bmap = ptr;
1303229329ffSRakesh Pillai 		} else if (!svc_rdy->dbs_hw_mode_done) {
1304229329ffSRakesh Pillai 			svc_rdy->dbs_hw_mode_done = true;
1305229329ffSRakesh Pillai 		}
1306229329ffSRakesh Pillai 		break;
1307229329ffSRakesh Pillai 	default:
1308229329ffSRakesh Pillai 		break;
1309229329ffSRakesh Pillai 	}
1310229329ffSRakesh Pillai 	return 0;
1311229329ffSRakesh Pillai }
1312229329ffSRakesh Pillai 
ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_svc_rdy_ev_arg * arg)1313229329ffSRakesh Pillai static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
1314229329ffSRakesh Pillai 					     struct sk_buff *skb,
1315229329ffSRakesh Pillai 					     struct wmi_svc_rdy_ev_arg *arg)
1316229329ffSRakesh Pillai {
1317229329ffSRakesh Pillai 	const struct hal_reg_capabilities *reg;
1318229329ffSRakesh Pillai 	const struct wmi_tlv_svc_rdy_ev *ev;
1319229329ffSRakesh Pillai 	const __le32 *svc_bmap;
1320229329ffSRakesh Pillai 	const struct wlan_host_mem_req *mem_reqs;
1321229329ffSRakesh Pillai 	struct wmi_tlv_svc_rdy_parse svc_rdy = { };
1322ca996ec5SMichal Kazior 	int ret;
1323ca996ec5SMichal Kazior 
1324229329ffSRakesh Pillai 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1325229329ffSRakesh Pillai 				  ath10k_wmi_tlv_svc_rdy_parse, &svc_rdy);
1326229329ffSRakesh Pillai 	if (ret) {
1327ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1328ca996ec5SMichal Kazior 		return ret;
1329ca996ec5SMichal Kazior 	}
1330ca996ec5SMichal Kazior 
1331229329ffSRakesh Pillai 	ev = svc_rdy.ev;
1332229329ffSRakesh Pillai 	reg = svc_rdy.reg;
1333229329ffSRakesh Pillai 	svc_bmap = svc_rdy.svc_bmap;
1334229329ffSRakesh Pillai 	mem_reqs = svc_rdy.mem_reqs;
1335ca996ec5SMichal Kazior 
1336229329ffSRakesh Pillai 	if (!ev || !reg || !svc_bmap || !mem_reqs)
1337ca996ec5SMichal Kazior 		return -EPROTO;
1338ca996ec5SMichal Kazior 
1339ca996ec5SMichal Kazior 	/* This is an internal ABI compatibility check for WMI TLV so check it
1340ca996ec5SMichal Kazior 	 * here instead of the generic WMI code.
1341ca996ec5SMichal Kazior 	 */
1342ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
1343ca996ec5SMichal Kazior 		   "wmi tlv abi 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x\n",
1344ca996ec5SMichal Kazior 		   __le32_to_cpu(ev->abi.abi_ver0), WMI_TLV_ABI_VER0,
1345ca996ec5SMichal Kazior 		   __le32_to_cpu(ev->abi.abi_ver_ns0), WMI_TLV_ABI_VER_NS0,
1346ca996ec5SMichal Kazior 		   __le32_to_cpu(ev->abi.abi_ver_ns1), WMI_TLV_ABI_VER_NS1,
1347ca996ec5SMichal Kazior 		   __le32_to_cpu(ev->abi.abi_ver_ns2), WMI_TLV_ABI_VER_NS2,
1348ca996ec5SMichal Kazior 		   __le32_to_cpu(ev->abi.abi_ver_ns3), WMI_TLV_ABI_VER_NS3);
1349ca996ec5SMichal Kazior 
1350ca996ec5SMichal Kazior 	if (__le32_to_cpu(ev->abi.abi_ver0) != WMI_TLV_ABI_VER0 ||
1351ca996ec5SMichal Kazior 	    __le32_to_cpu(ev->abi.abi_ver_ns0) != WMI_TLV_ABI_VER_NS0 ||
1352ca996ec5SMichal Kazior 	    __le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 ||
1353ca996ec5SMichal Kazior 	    __le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 ||
1354ca996ec5SMichal Kazior 	    __le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) {
1355bc2ef649SKarthikeyan Periyasamy 		return -EOPNOTSUPP;
1356ca996ec5SMichal Kazior 	}
1357ca996ec5SMichal Kazior 
1358ca996ec5SMichal Kazior 	arg->min_tx_power = ev->hw_min_tx_power;
1359ca996ec5SMichal Kazior 	arg->max_tx_power = ev->hw_max_tx_power;
1360ca996ec5SMichal Kazior 	arg->ht_cap = ev->ht_cap_info;
1361ca996ec5SMichal Kazior 	arg->vht_cap = ev->vht_cap_info;
136273690c48STomislav Požega 	arg->vht_supp_mcs = ev->vht_supp_mcs;
1363ca996ec5SMichal Kazior 	arg->sw_ver0 = ev->abi.abi_ver0;
1364ca996ec5SMichal Kazior 	arg->sw_ver1 = ev->abi.abi_ver1;
1365ca996ec5SMichal Kazior 	arg->fw_build = ev->fw_build_vers;
1366ca996ec5SMichal Kazior 	arg->phy_capab = ev->phy_capability;
1367ca996ec5SMichal Kazior 	arg->num_rf_chains = ev->num_rf_chains;
1368ca996ec5SMichal Kazior 	arg->eeprom_rd = reg->eeprom_rd;
1369fa879490STomislav Požega 	arg->low_2ghz_chan = reg->low_2ghz_chan;
1370fa879490STomislav Požega 	arg->high_2ghz_chan = reg->high_2ghz_chan;
137198dc04baSZhi Chen 	arg->low_5ghz_chan = reg->low_5ghz_chan;
137298dc04baSZhi Chen 	arg->high_5ghz_chan = reg->high_5ghz_chan;
1373ca996ec5SMichal Kazior 	arg->num_mem_reqs = ev->num_mem_reqs;
1374ca996ec5SMichal Kazior 	arg->service_map = svc_bmap;
1375ca996ec5SMichal Kazior 	arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
13761382993fSWen Gong 	arg->sys_cap_info = ev->sys_cap_info;
1377ca996ec5SMichal Kazior 
1378ca996ec5SMichal Kazior 	ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
1379ca996ec5SMichal Kazior 				  ath10k_wmi_tlv_parse_mem_reqs, arg);
1380ca996ec5SMichal Kazior 	if (ret) {
1381ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse mem_reqs tlv: %d\n", ret);
1382ca996ec5SMichal Kazior 		return ret;
1383ca996ec5SMichal Kazior 	}
1384ca996ec5SMichal Kazior 
1385ca996ec5SMichal Kazior 	return 0;
1386ca996ec5SMichal Kazior }
1387ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_rdy_ev_arg * arg)1388ca996ec5SMichal Kazior static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
1389ca996ec5SMichal Kazior 					 struct sk_buff *skb,
1390ca996ec5SMichal Kazior 					 struct wmi_rdy_ev_arg *arg)
1391ca996ec5SMichal Kazior {
1392ca996ec5SMichal Kazior 	const void **tb;
1393ca996ec5SMichal Kazior 	const struct wmi_tlv_rdy_ev *ev;
1394ca996ec5SMichal Kazior 	int ret;
1395ca996ec5SMichal Kazior 
1396ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1397ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
1398ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
1399ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1400ca996ec5SMichal Kazior 		return ret;
1401ca996ec5SMichal Kazior 	}
1402ca996ec5SMichal Kazior 
1403ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_READY_EVENT];
1404ca996ec5SMichal Kazior 	if (!ev) {
1405ca996ec5SMichal Kazior 		kfree(tb);
1406ca996ec5SMichal Kazior 		return -EPROTO;
1407ca996ec5SMichal Kazior 	}
1408ca996ec5SMichal Kazior 
1409ca996ec5SMichal Kazior 	arg->sw_version = ev->abi.abi_ver0;
1410ca996ec5SMichal Kazior 	arg->abi_version = ev->abi.abi_ver1;
1411ca996ec5SMichal Kazior 	arg->status = ev->status;
1412ca996ec5SMichal Kazior 	arg->mac_addr = ev->mac_addr.addr;
1413ca996ec5SMichal Kazior 
1414ca996ec5SMichal Kazior 	kfree(tb);
1415ca996ec5SMichal Kazior 	return 0;
1416ca996ec5SMichal Kazior }
1417ca996ec5SMichal Kazior 
ath10k_wmi_tlv_svc_avail_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1418cea19a6cSCarl Huang static int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len,
1419cea19a6cSCarl Huang 					  const void *ptr, void *data)
1420cea19a6cSCarl Huang {
1421cea19a6cSCarl Huang 	struct wmi_svc_avail_ev_arg *arg = data;
1422cea19a6cSCarl Huang 
1423cea19a6cSCarl Huang 	switch (tag) {
1424cea19a6cSCarl Huang 	case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT:
1425c7cee9c0SRakesh Pillai 		arg->service_map_ext_valid = true;
1426cea19a6cSCarl Huang 		arg->service_map_ext_len = *(__le32 *)ptr;
1427cea19a6cSCarl Huang 		arg->service_map_ext = ptr + sizeof(__le32);
1428cea19a6cSCarl Huang 		return 0;
1429cea19a6cSCarl Huang 	default:
1430cea19a6cSCarl Huang 		break;
1431cea19a6cSCarl Huang 	}
1432c7cee9c0SRakesh Pillai 
1433c7cee9c0SRakesh Pillai 	return 0;
1434cea19a6cSCarl Huang }
1435cea19a6cSCarl Huang 
ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k * ar,struct sk_buff * skb,struct wmi_svc_avail_ev_arg * arg)1436cea19a6cSCarl Huang static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar,
1437cea19a6cSCarl Huang 					    struct sk_buff *skb,
1438cea19a6cSCarl Huang 					    struct wmi_svc_avail_ev_arg *arg)
1439cea19a6cSCarl Huang {
1440cea19a6cSCarl Huang 	int ret;
1441cea19a6cSCarl Huang 
1442cea19a6cSCarl Huang 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1443cea19a6cSCarl Huang 				  ath10k_wmi_tlv_svc_avail_parse, arg);
1444cea19a6cSCarl Huang 
1445cea19a6cSCarl Huang 	if (ret) {
1446cea19a6cSCarl Huang 		ath10k_warn(ar, "failed to parse svc_avail tlv: %d\n", ret);
1447cea19a6cSCarl Huang 		return ret;
1448cea19a6cSCarl Huang 	}
1449cea19a6cSCarl Huang 
1450cea19a6cSCarl Huang 	return 0;
1451cea19a6cSCarl Huang }
1452cea19a6cSCarl Huang 
ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats * src,struct ath10k_fw_stats_vdev * dst)14537777d8c7SMichal Kazior static void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
14547777d8c7SMichal Kazior 					   struct ath10k_fw_stats_vdev *dst)
14557777d8c7SMichal Kazior {
14567777d8c7SMichal Kazior 	int i;
14577777d8c7SMichal Kazior 
14587777d8c7SMichal Kazior 	dst->vdev_id = __le32_to_cpu(src->vdev_id);
14597777d8c7SMichal Kazior 	dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
14607777d8c7SMichal Kazior 	dst->data_snr = __le32_to_cpu(src->data_snr);
14617777d8c7SMichal Kazior 	dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
14627777d8c7SMichal Kazior 	dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
14637777d8c7SMichal Kazior 	dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
14647777d8c7SMichal Kazior 	dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
14657777d8c7SMichal Kazior 	dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
14667777d8c7SMichal Kazior 	dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
14677777d8c7SMichal Kazior 
14687777d8c7SMichal Kazior 	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
14697777d8c7SMichal Kazior 		dst->num_tx_frames[i] =
14707777d8c7SMichal Kazior 			__le32_to_cpu(src->num_tx_frames[i]);
14717777d8c7SMichal Kazior 
14727777d8c7SMichal Kazior 	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
14737777d8c7SMichal Kazior 		dst->num_tx_frames_retries[i] =
14747777d8c7SMichal Kazior 			__le32_to_cpu(src->num_tx_frames_retries[i]);
14757777d8c7SMichal Kazior 
14767777d8c7SMichal Kazior 	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
14777777d8c7SMichal Kazior 		dst->num_tx_frames_failures[i] =
14787777d8c7SMichal Kazior 			__le32_to_cpu(src->num_tx_frames_failures[i]);
14797777d8c7SMichal Kazior 
14807777d8c7SMichal Kazior 	for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
14817777d8c7SMichal Kazior 		dst->tx_rate_history[i] =
14827777d8c7SMichal Kazior 			__le32_to_cpu(src->tx_rate_history[i]);
14837777d8c7SMichal Kazior 
14847777d8c7SMichal Kazior 	for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
14857777d8c7SMichal Kazior 		dst->beacon_rssi_history[i] =
14867777d8c7SMichal Kazior 			__le32_to_cpu(src->beacon_rssi_history[i]);
14877777d8c7SMichal Kazior }
14887777d8c7SMichal Kazior 
ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k * ar,struct sk_buff * skb,struct ath10k_fw_stats * stats)1489ca996ec5SMichal Kazior static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
1490ca996ec5SMichal Kazior 					   struct sk_buff *skb,
1491ca996ec5SMichal Kazior 					   struct ath10k_fw_stats *stats)
1492ca996ec5SMichal Kazior {
1493ca996ec5SMichal Kazior 	const void **tb;
14947777d8c7SMichal Kazior 	const struct wmi_tlv_stats_ev *ev;
1495f40a307eSSurabhi Vishnoi 	u32 num_peer_stats_extd;
1496ca996ec5SMichal Kazior 	const void *data;
14977777d8c7SMichal Kazior 	u32 num_pdev_stats;
14987777d8c7SMichal Kazior 	u32 num_vdev_stats;
14997777d8c7SMichal Kazior 	u32 num_peer_stats;
15007777d8c7SMichal Kazior 	u32 num_bcnflt_stats;
15017777d8c7SMichal Kazior 	u32 num_chan_stats;
1502ca996ec5SMichal Kazior 	size_t data_len;
1503f40a307eSSurabhi Vishnoi 	u32 stats_id;
1504ca996ec5SMichal Kazior 	int ret;
15057777d8c7SMichal Kazior 	int i;
1506ca996ec5SMichal Kazior 
1507ca996ec5SMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1508ca996ec5SMichal Kazior 	if (IS_ERR(tb)) {
1509ca996ec5SMichal Kazior 		ret = PTR_ERR(tb);
1510ca996ec5SMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1511ca996ec5SMichal Kazior 		return ret;
1512ca996ec5SMichal Kazior 	}
1513ca996ec5SMichal Kazior 
1514ca996ec5SMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_STATS_EVENT];
1515ca996ec5SMichal Kazior 	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
1516ca996ec5SMichal Kazior 
1517ca996ec5SMichal Kazior 	if (!ev || !data) {
1518ca996ec5SMichal Kazior 		kfree(tb);
1519ca996ec5SMichal Kazior 		return -EPROTO;
1520ca996ec5SMichal Kazior 	}
1521ca996ec5SMichal Kazior 
1522ca996ec5SMichal Kazior 	data_len = ath10k_wmi_tlv_len(data);
1523ca996ec5SMichal Kazior 	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
1524ca996ec5SMichal Kazior 	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
1525ca996ec5SMichal Kazior 	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
15267777d8c7SMichal Kazior 	num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
15277777d8c7SMichal Kazior 	num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
1528f40a307eSSurabhi Vishnoi 	stats_id = __le32_to_cpu(ev->stats_id);
1529f40a307eSSurabhi Vishnoi 	num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd);
1530ca996ec5SMichal Kazior 
15317777d8c7SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
1532f40a307eSSurabhi Vishnoi 		   "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n",
15337777d8c7SMichal Kazior 		   num_pdev_stats, num_vdev_stats, num_peer_stats,
1534f40a307eSSurabhi Vishnoi 		   num_bcnflt_stats, num_chan_stats, num_peer_stats_extd);
15357777d8c7SMichal Kazior 
15367777d8c7SMichal Kazior 	for (i = 0; i < num_pdev_stats; i++) {
15377777d8c7SMichal Kazior 		const struct wmi_pdev_stats *src;
15387777d8c7SMichal Kazior 		struct ath10k_fw_stats_pdev *dst;
15397777d8c7SMichal Kazior 
15407777d8c7SMichal Kazior 		src = data;
1541097e46d2SChristian Lamparter 		if (data_len < sizeof(*src)) {
1542097e46d2SChristian Lamparter 			kfree(tb);
15437777d8c7SMichal Kazior 			return -EPROTO;
1544097e46d2SChristian Lamparter 		}
15457777d8c7SMichal Kazior 
15467777d8c7SMichal Kazior 		data += sizeof(*src);
15477777d8c7SMichal Kazior 		data_len -= sizeof(*src);
15487777d8c7SMichal Kazior 
15497777d8c7SMichal Kazior 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
15507777d8c7SMichal Kazior 		if (!dst)
15517777d8c7SMichal Kazior 			continue;
15527777d8c7SMichal Kazior 
15537777d8c7SMichal Kazior 		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
15547777d8c7SMichal Kazior 		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
15557777d8c7SMichal Kazior 		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
15567777d8c7SMichal Kazior 		list_add_tail(&dst->list, &stats->pdevs);
15577777d8c7SMichal Kazior 	}
15587777d8c7SMichal Kazior 
15597777d8c7SMichal Kazior 	for (i = 0; i < num_vdev_stats; i++) {
15607777d8c7SMichal Kazior 		const struct wmi_tlv_vdev_stats *src;
15617777d8c7SMichal Kazior 		struct ath10k_fw_stats_vdev *dst;
15627777d8c7SMichal Kazior 
15637777d8c7SMichal Kazior 		src = data;
1564097e46d2SChristian Lamparter 		if (data_len < sizeof(*src)) {
1565097e46d2SChristian Lamparter 			kfree(tb);
15667777d8c7SMichal Kazior 			return -EPROTO;
1567097e46d2SChristian Lamparter 		}
15687777d8c7SMichal Kazior 
15697777d8c7SMichal Kazior 		data += sizeof(*src);
15707777d8c7SMichal Kazior 		data_len -= sizeof(*src);
15717777d8c7SMichal Kazior 
15727777d8c7SMichal Kazior 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
15737777d8c7SMichal Kazior 		if (!dst)
15747777d8c7SMichal Kazior 			continue;
15757777d8c7SMichal Kazior 
15767777d8c7SMichal Kazior 		ath10k_wmi_tlv_pull_vdev_stats(src, dst);
15777777d8c7SMichal Kazior 		list_add_tail(&dst->list, &stats->vdevs);
15787777d8c7SMichal Kazior 	}
15797777d8c7SMichal Kazior 
15807777d8c7SMichal Kazior 	for (i = 0; i < num_peer_stats; i++) {
15817777d8c7SMichal Kazior 		const struct wmi_10x_peer_stats *src;
15827777d8c7SMichal Kazior 		struct ath10k_fw_stats_peer *dst;
15837777d8c7SMichal Kazior 
15847777d8c7SMichal Kazior 		src = data;
1585097e46d2SChristian Lamparter 		if (data_len < sizeof(*src)) {
1586097e46d2SChristian Lamparter 			kfree(tb);
15877777d8c7SMichal Kazior 			return -EPROTO;
1588097e46d2SChristian Lamparter 		}
15897777d8c7SMichal Kazior 
15907777d8c7SMichal Kazior 		data += sizeof(*src);
15917777d8c7SMichal Kazior 		data_len -= sizeof(*src);
15927777d8c7SMichal Kazior 
15937777d8c7SMichal Kazior 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
15947777d8c7SMichal Kazior 		if (!dst)
15957777d8c7SMichal Kazior 			continue;
15967777d8c7SMichal Kazior 
15977777d8c7SMichal Kazior 		ath10k_wmi_pull_peer_stats(&src->old, dst);
15987777d8c7SMichal Kazior 		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
1599f40a307eSSurabhi Vishnoi 
1600f40a307eSSurabhi Vishnoi 		if (stats_id & WMI_TLV_STAT_PEER_EXTD) {
1601f40a307eSSurabhi Vishnoi 			const struct wmi_tlv_peer_stats_extd *extd;
1602f40a307eSSurabhi Vishnoi 			unsigned long rx_duration_high;
1603f40a307eSSurabhi Vishnoi 
1604f40a307eSSurabhi Vishnoi 			extd = data + sizeof(*src) * (num_peer_stats - i - 1)
1605f40a307eSSurabhi Vishnoi 			       + sizeof(*extd) * i;
1606f40a307eSSurabhi Vishnoi 
1607f40a307eSSurabhi Vishnoi 			dst->rx_duration = __le32_to_cpu(extd->rx_duration);
1608f40a307eSSurabhi Vishnoi 			rx_duration_high = __le32_to_cpu
1609f40a307eSSurabhi Vishnoi 						(extd->rx_duration_high);
1610f40a307eSSurabhi Vishnoi 
1611f40a307eSSurabhi Vishnoi 			if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT,
1612f40a307eSSurabhi Vishnoi 				     &rx_duration_high)) {
1613f40a307eSSurabhi Vishnoi 				rx_duration_high =
1614f40a307eSSurabhi Vishnoi 					FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK,
1615f40a307eSSurabhi Vishnoi 						  rx_duration_high);
1616f40a307eSSurabhi Vishnoi 				dst->rx_duration |= (u64)rx_duration_high <<
1617f40a307eSSurabhi Vishnoi 						    WMI_TLV_PEER_RX_DURATION_SHIFT;
1618f40a307eSSurabhi Vishnoi 			}
1619f40a307eSSurabhi Vishnoi 		}
1620f40a307eSSurabhi Vishnoi 
16217777d8c7SMichal Kazior 		list_add_tail(&dst->list, &stats->peers);
16227777d8c7SMichal Kazior 	}
1623ca996ec5SMichal Kazior 
1624ca996ec5SMichal Kazior 	kfree(tb);
1625ca996ec5SMichal Kazior 	return 0;
1626ca996ec5SMichal Kazior }
1627ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_pull_roam_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_roam_ev_arg * arg)1628c1a4654aSMichal Kazior static int ath10k_wmi_tlv_op_pull_roam_ev(struct ath10k *ar,
1629c1a4654aSMichal Kazior 					  struct sk_buff *skb,
1630c1a4654aSMichal Kazior 					  struct wmi_roam_ev_arg *arg)
1631c1a4654aSMichal Kazior {
1632c1a4654aSMichal Kazior 	const void **tb;
1633c1a4654aSMichal Kazior 	const struct wmi_tlv_roam_ev *ev;
1634c1a4654aSMichal Kazior 	int ret;
1635c1a4654aSMichal Kazior 
1636c1a4654aSMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1637c1a4654aSMichal Kazior 	if (IS_ERR(tb)) {
1638c1a4654aSMichal Kazior 		ret = PTR_ERR(tb);
1639c1a4654aSMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1640c1a4654aSMichal Kazior 		return ret;
1641c1a4654aSMichal Kazior 	}
1642c1a4654aSMichal Kazior 
1643c1a4654aSMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_ROAM_EVENT];
1644c1a4654aSMichal Kazior 	if (!ev) {
1645c1a4654aSMichal Kazior 		kfree(tb);
1646c1a4654aSMichal Kazior 		return -EPROTO;
1647c1a4654aSMichal Kazior 	}
1648c1a4654aSMichal Kazior 
1649c1a4654aSMichal Kazior 	arg->vdev_id = ev->vdev_id;
1650c1a4654aSMichal Kazior 	arg->reason = ev->reason;
1651c1a4654aSMichal Kazior 	arg->rssi = ev->rssi;
1652c1a4654aSMichal Kazior 
1653c1a4654aSMichal Kazior 	kfree(tb);
1654c1a4654aSMichal Kazior 	return 0;
1655c1a4654aSMichal Kazior }
1656c1a4654aSMichal Kazior 
1657f5431e87SJanusz Dziedzic static int
ath10k_wmi_tlv_op_pull_wow_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_wow_ev_arg * arg)1658f5431e87SJanusz Dziedzic ath10k_wmi_tlv_op_pull_wow_ev(struct ath10k *ar, struct sk_buff *skb,
1659f5431e87SJanusz Dziedzic 			      struct wmi_wow_ev_arg *arg)
1660f5431e87SJanusz Dziedzic {
1661f5431e87SJanusz Dziedzic 	const void **tb;
1662f5431e87SJanusz Dziedzic 	const struct wmi_tlv_wow_event_info *ev;
1663f5431e87SJanusz Dziedzic 	int ret;
1664f5431e87SJanusz Dziedzic 
1665f5431e87SJanusz Dziedzic 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1666f5431e87SJanusz Dziedzic 	if (IS_ERR(tb)) {
1667f5431e87SJanusz Dziedzic 		ret = PTR_ERR(tb);
1668f5431e87SJanusz Dziedzic 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1669f5431e87SJanusz Dziedzic 		return ret;
1670f5431e87SJanusz Dziedzic 	}
1671f5431e87SJanusz Dziedzic 
1672f5431e87SJanusz Dziedzic 	ev = tb[WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO];
1673f5431e87SJanusz Dziedzic 	if (!ev) {
1674f5431e87SJanusz Dziedzic 		kfree(tb);
1675f5431e87SJanusz Dziedzic 		return -EPROTO;
1676f5431e87SJanusz Dziedzic 	}
1677f5431e87SJanusz Dziedzic 
1678f5431e87SJanusz Dziedzic 	arg->vdev_id = __le32_to_cpu(ev->vdev_id);
1679f5431e87SJanusz Dziedzic 	arg->flag = __le32_to_cpu(ev->flag);
1680f5431e87SJanusz Dziedzic 	arg->wake_reason = __le32_to_cpu(ev->wake_reason);
1681f5431e87SJanusz Dziedzic 	arg->data_len = __le32_to_cpu(ev->data_len);
1682f5431e87SJanusz Dziedzic 
1683f5431e87SJanusz Dziedzic 	kfree(tb);
1684f5431e87SJanusz Dziedzic 	return 0;
1685f5431e87SJanusz Dziedzic }
1686f5431e87SJanusz Dziedzic 
ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_echo_ev_arg * arg)168784d4911bSMichal Kazior static int ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k *ar,
168884d4911bSMichal Kazior 					  struct sk_buff *skb,
168984d4911bSMichal Kazior 					  struct wmi_echo_ev_arg *arg)
169084d4911bSMichal Kazior {
169184d4911bSMichal Kazior 	const void **tb;
169284d4911bSMichal Kazior 	const struct wmi_echo_event *ev;
169384d4911bSMichal Kazior 	int ret;
169484d4911bSMichal Kazior 
169584d4911bSMichal Kazior 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
169684d4911bSMichal Kazior 	if (IS_ERR(tb)) {
169784d4911bSMichal Kazior 		ret = PTR_ERR(tb);
169884d4911bSMichal Kazior 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
169984d4911bSMichal Kazior 		return ret;
170084d4911bSMichal Kazior 	}
170184d4911bSMichal Kazior 
170284d4911bSMichal Kazior 	ev = tb[WMI_TLV_TAG_STRUCT_ECHO_EVENT];
170384d4911bSMichal Kazior 	if (!ev) {
170484d4911bSMichal Kazior 		kfree(tb);
170584d4911bSMichal Kazior 		return -EPROTO;
170684d4911bSMichal Kazior 	}
170784d4911bSMichal Kazior 
170884d4911bSMichal Kazior 	arg->value = ev->value;
170984d4911bSMichal Kazior 
171084d4911bSMichal Kazior 	kfree(tb);
171184d4911bSMichal Kazior 	return 0;
171284d4911bSMichal Kazior }
171384d4911bSMichal Kazior 
1714ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k * ar,u32 opt)1715ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
1716ca996ec5SMichal Kazior {
1717ca996ec5SMichal Kazior 	struct wmi_tlv_pdev_suspend *cmd;
1718ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
1719ca996ec5SMichal Kazior 	struct sk_buff *skb;
1720ca996ec5SMichal Kazior 
1721ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1722ca996ec5SMichal Kazior 	if (!skb)
1723ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
1724ca996ec5SMichal Kazior 
1725ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
1726ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD);
1727ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1728ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
1729ca996ec5SMichal Kazior 	cmd->opt = __cpu_to_le32(opt);
1730ca996ec5SMichal Kazior 
1731ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev suspend\n");
1732ca996ec5SMichal Kazior 	return skb;
1733ca996ec5SMichal Kazior }
1734ca996ec5SMichal Kazior 
1735ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k * ar)1736ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k *ar)
1737ca996ec5SMichal Kazior {
1738ca996ec5SMichal Kazior 	struct wmi_tlv_resume_cmd *cmd;
1739ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
1740ca996ec5SMichal Kazior 	struct sk_buff *skb;
1741ca996ec5SMichal Kazior 
1742ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1743ca996ec5SMichal Kazior 	if (!skb)
1744ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
1745ca996ec5SMichal Kazior 
1746ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
1747ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD);
1748ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1749ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
1750ca996ec5SMichal Kazior 	cmd->reserved = __cpu_to_le32(0);
1751ca996ec5SMichal Kazior 
1752ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev resume\n");
1753ca996ec5SMichal Kazior 	return skb;
1754ca996ec5SMichal Kazior }
1755ca996ec5SMichal Kazior 
1756ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k * ar,u16 rd,u16 rd2g,u16 rd5g,u16 ctl2g,u16 ctl5g,enum wmi_dfs_region dfs_reg)1757ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
1758ca996ec5SMichal Kazior 				  u16 rd, u16 rd2g, u16 rd5g,
1759ca996ec5SMichal Kazior 				  u16 ctl2g, u16 ctl5g,
1760ca996ec5SMichal Kazior 				  enum wmi_dfs_region dfs_reg)
1761ca996ec5SMichal Kazior {
1762ca996ec5SMichal Kazior 	struct wmi_tlv_pdev_set_rd_cmd *cmd;
1763ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
1764ca996ec5SMichal Kazior 	struct sk_buff *skb;
1765ca996ec5SMichal Kazior 
1766ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1767ca996ec5SMichal Kazior 	if (!skb)
1768ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
1769ca996ec5SMichal Kazior 
1770ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
1771ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD);
1772ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1773ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
1774ca996ec5SMichal Kazior 	cmd->regd = __cpu_to_le32(rd);
1775ca996ec5SMichal Kazior 	cmd->regd_2ghz = __cpu_to_le32(rd2g);
1776ca996ec5SMichal Kazior 	cmd->regd_5ghz = __cpu_to_le32(rd5g);
17774e322f7dSErik Stromdahl 	cmd->conform_limit_2ghz = __cpu_to_le32(ctl2g);
17784e322f7dSErik Stromdahl 	cmd->conform_limit_5ghz = __cpu_to_le32(ctl5g);
1779ca996ec5SMichal Kazior 
1780ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
1781ca996ec5SMichal Kazior 	return skb;
1782ca996ec5SMichal Kazior }
1783ca996ec5SMichal Kazior 
ath10k_wmi_tlv_txbf_conf_scheme(struct ath10k * ar)178408e75ea8SVivek Natarajan static enum wmi_txbf_conf ath10k_wmi_tlv_txbf_conf_scheme(struct ath10k *ar)
178508e75ea8SVivek Natarajan {
178608e75ea8SVivek Natarajan 	return WMI_TXBF_CONF_AFTER_ASSOC;
178708e75ea8SVivek Natarajan }
178808e75ea8SVivek Natarajan 
1789ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k * ar,u32 param_id,u32 param_value)1790ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
1791ca996ec5SMichal Kazior 				     u32 param_value)
1792ca996ec5SMichal Kazior {
1793ca996ec5SMichal Kazior 	struct wmi_tlv_pdev_set_param_cmd *cmd;
1794ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
1795ca996ec5SMichal Kazior 	struct sk_buff *skb;
1796ca996ec5SMichal Kazior 
1797ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1798ca996ec5SMichal Kazior 	if (!skb)
1799ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
1800ca996ec5SMichal Kazior 
1801ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
1802ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD);
1803ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1804ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
1805ca996ec5SMichal Kazior 	cmd->param_id = __cpu_to_le32(param_id);
1806ca996ec5SMichal Kazior 	cmd->param_value = __cpu_to_le32(param_value);
1807ca996ec5SMichal Kazior 
18081c136e41SRakesh Pillai 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n",
18091c136e41SRakesh Pillai 		   param_id, param_value);
1810ca996ec5SMichal Kazior 	return skb;
1811ca996ec5SMichal Kazior }
1812ca996ec5SMichal Kazior 
1813d961284dSYu Wang static void
ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k * ar,void * host_mem_chunks)1814d961284dSYu Wang ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
1815d961284dSYu Wang {
181640f4ef5eSSurabhi Vishnoi 	struct host_memory_chunk_tlv *chunk;
1817d961284dSYu Wang 	struct wmi_tlv *tlv;
181840f4ef5eSSurabhi Vishnoi 	dma_addr_t paddr;
1819d961284dSYu Wang 	int i;
1820d961284dSYu Wang 	__le16 tlv_len, tlv_tag;
1821d961284dSYu Wang 
1822d961284dSYu Wang 	tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK);
1823d961284dSYu Wang 	tlv_len = __cpu_to_le16(sizeof(*chunk));
1824d961284dSYu Wang 	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
1825d961284dSYu Wang 		tlv = host_mem_chunks;
1826d961284dSYu Wang 		tlv->tag = tlv_tag;
1827d961284dSYu Wang 		tlv->len = tlv_len;
1828d961284dSYu Wang 		chunk = (void *)tlv->value;
1829d961284dSYu Wang 
1830d961284dSYu Wang 		chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
1831d961284dSYu Wang 		chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
1832d961284dSYu Wang 		chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
1833d961284dSYu Wang 
183440f4ef5eSSurabhi Vishnoi 		if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
183540f4ef5eSSurabhi Vishnoi 			     ar->wmi.svc_map)) {
183640f4ef5eSSurabhi Vishnoi 			paddr = ar->wmi.mem_chunks[i].paddr;
183740f4ef5eSSurabhi Vishnoi 			chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr));
183840f4ef5eSSurabhi Vishnoi 		}
183940f4ef5eSSurabhi Vishnoi 
1840d961284dSYu Wang 		ath10k_dbg(ar, ATH10K_DBG_WMI,
1841d961284dSYu Wang 			   "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
1842d961284dSYu Wang 			   i,
1843d961284dSYu Wang 			   ar->wmi.mem_chunks[i].len,
1844d961284dSYu Wang 			   (unsigned long long)ar->wmi.mem_chunks[i].paddr,
1845d961284dSYu Wang 			   ar->wmi.mem_chunks[i].req_id);
1846d961284dSYu Wang 
1847d961284dSYu Wang 		host_mem_chunks += sizeof(*tlv);
1848d961284dSYu Wang 		host_mem_chunks += sizeof(*chunk);
1849d961284dSYu Wang 	}
1850d961284dSYu Wang }
1851d961284dSYu Wang 
ath10k_wmi_tlv_op_gen_init(struct ath10k * ar)1852ca996ec5SMichal Kazior static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
1853ca996ec5SMichal Kazior {
1854ca996ec5SMichal Kazior 	struct sk_buff *skb;
1855ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
1856ca996ec5SMichal Kazior 	struct wmi_tlv_init_cmd *cmd;
1857ca996ec5SMichal Kazior 	struct wmi_tlv_resource_config *cfg;
1858d961284dSYu Wang 	void *chunks;
1859ca996ec5SMichal Kazior 	size_t len, chunks_len;
1860ca996ec5SMichal Kazior 	void *ptr;
1861ca996ec5SMichal Kazior 
1862d961284dSYu Wang 	chunks_len = ar->wmi.num_mem_chunks *
186340f4ef5eSSurabhi Vishnoi 		     (sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv));
1864ca996ec5SMichal Kazior 	len = (sizeof(*tlv) + sizeof(*cmd)) +
1865ca996ec5SMichal Kazior 	      (sizeof(*tlv) + sizeof(*cfg)) +
1866ca996ec5SMichal Kazior 	      (sizeof(*tlv) + chunks_len);
1867ca996ec5SMichal Kazior 
1868ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
1869ca996ec5SMichal Kazior 	if (!skb)
1870ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
1871ca996ec5SMichal Kazior 
1872ca996ec5SMichal Kazior 	ptr = skb->data;
1873ca996ec5SMichal Kazior 
1874ca996ec5SMichal Kazior 	tlv = ptr;
1875ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_INIT_CMD);
1876ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1877ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
1878ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
1879ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
1880ca996ec5SMichal Kazior 
1881ca996ec5SMichal Kazior 	tlv = ptr;
1882ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG);
1883ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cfg));
1884ca996ec5SMichal Kazior 	cfg = (void *)tlv->value;
1885ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
1886ca996ec5SMichal Kazior 	ptr += sizeof(*cfg);
1887ca996ec5SMichal Kazior 
1888ca996ec5SMichal Kazior 	tlv = ptr;
1889ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
1890ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(chunks_len);
1891ca996ec5SMichal Kazior 	chunks = (void *)tlv->value;
1892ca996ec5SMichal Kazior 
1893ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
1894ca996ec5SMichal Kazior 	ptr += chunks_len;
1895ca996ec5SMichal Kazior 
1896ca996ec5SMichal Kazior 	cmd->abi.abi_ver0 = __cpu_to_le32(WMI_TLV_ABI_VER0);
1897ca996ec5SMichal Kazior 	cmd->abi.abi_ver1 = __cpu_to_le32(WMI_TLV_ABI_VER1);
1898ca996ec5SMichal Kazior 	cmd->abi.abi_ver_ns0 = __cpu_to_le32(WMI_TLV_ABI_VER_NS0);
1899ca996ec5SMichal Kazior 	cmd->abi.abi_ver_ns1 = __cpu_to_le32(WMI_TLV_ABI_VER_NS1);
1900ca996ec5SMichal Kazior 	cmd->abi.abi_ver_ns2 = __cpu_to_le32(WMI_TLV_ABI_VER_NS2);
1901ca996ec5SMichal Kazior 	cmd->abi.abi_ver_ns3 = __cpu_to_le32(WMI_TLV_ABI_VER_NS3);
1902ca996ec5SMichal Kazior 	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
1903ca996ec5SMichal Kazior 
1904ca996ec5SMichal Kazior 	cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
19059f2992feSRakesh Pillai 
19068e8374dbSErik Stromdahl 	if (ar->hw_params.num_peers)
19079f2992feSRakesh Pillai 		cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers);
19088e8374dbSErik Stromdahl 	else
19098e8374dbSErik Stromdahl 		cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
19109f2992feSRakesh Pillai 	cfg->ast_skid_limit = __cpu_to_le32(ar->hw_params.ast_skid_limit);
19119f2992feSRakesh Pillai 	cfg->num_wds_entries = __cpu_to_le32(ar->hw_params.num_wds_entries);
1912c545070eSMichal Kazior 
1913c545070eSMichal Kazior 	if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
1914039a0051SMichal Kazior 		cfg->num_offload_peers = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1915039a0051SMichal Kazior 		cfg->num_offload_reorder_bufs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1916c545070eSMichal Kazior 	} else {
1917ca996ec5SMichal Kazior 		cfg->num_offload_peers = __cpu_to_le32(0);
1918ca996ec5SMichal Kazior 		cfg->num_offload_reorder_bufs = __cpu_to_le32(0);
1919c545070eSMichal Kazior 	}
1920c545070eSMichal Kazior 
1921ca996ec5SMichal Kazior 	cfg->num_peer_keys = __cpu_to_le32(2);
19229faaa143SErik Stromdahl 	if (ar->hw_params.num_peers)
19239faaa143SErik Stromdahl 		cfg->num_tids = __cpu_to_le32(ar->hw_params.num_peers * 2);
19249faaa143SErik Stromdahl 	else
1925ca996ec5SMichal Kazior 		cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
1926ca996ec5SMichal Kazior 	cfg->tx_chain_mask = __cpu_to_le32(0x7);
1927ca996ec5SMichal Kazior 	cfg->rx_chain_mask = __cpu_to_le32(0x7);
1928ca996ec5SMichal Kazior 	cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
1929ca996ec5SMichal Kazior 	cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64);
1930ca996ec5SMichal Kazior 	cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64);
1931ca996ec5SMichal Kazior 	cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28);
1932ccec9038SDavid Liu 	cfg->rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
1933ca996ec5SMichal Kazior 	cfg->scan_max_pending_reqs = __cpu_to_le32(4);
1934039a0051SMichal Kazior 	cfg->bmiss_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1935039a0051SMichal Kazior 	cfg->roam_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1936ca996ec5SMichal Kazior 	cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8);
1937ca996ec5SMichal Kazior 	cfg->num_mcast_groups = __cpu_to_le32(0);
1938ca996ec5SMichal Kazior 	cfg->num_mcast_table_elems = __cpu_to_le32(0);
1939ca996ec5SMichal Kazior 	cfg->mcast2ucast_mode = __cpu_to_le32(0);
1940ca996ec5SMichal Kazior 	cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
1941ca996ec5SMichal Kazior 	cfg->dma_burst_size = __cpu_to_le32(0);
1942ca996ec5SMichal Kazior 	cfg->mac_aggr_delim = __cpu_to_le32(0);
1943ca996ec5SMichal Kazior 	cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
1944ca996ec5SMichal Kazior 	cfg->vow_config = __cpu_to_le32(0);
1945ca996ec5SMichal Kazior 	cfg->gtk_offload_max_vdev = __cpu_to_le32(2);
1946a73dbce3SAlagu Sankar 	cfg->num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx);
1947ca996ec5SMichal Kazior 	cfg->max_frag_entries = __cpu_to_le32(2);
19488cca3d60SMarek Puzyniak 	cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS);
1949ca996ec5SMichal Kazior 	cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
1950ca996ec5SMichal Kazior 	cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2);
1951ca996ec5SMichal Kazior 	cfg->num_multicast_filter_entries = __cpu_to_le32(5);
195225c86619SJanusz Dziedzic 	cfg->num_wow_filters = __cpu_to_le32(ar->wow.max_num_patterns);
1953ca996ec5SMichal Kazior 	cfg->num_keep_alive_pattern = __cpu_to_le32(6);
1954ca996ec5SMichal Kazior 	cfg->keep_alive_pattern_size = __cpu_to_le32(0);
1955ca996ec5SMichal Kazior 	cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1);
1956ca996ec5SMichal Kazior 	cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1);
1957673bc519SSurabhi Vishnoi 	cfg->wmi_send_separate = __cpu_to_le32(0);
1958673bc519SSurabhi Vishnoi 	cfg->num_ocb_vdevs = __cpu_to_le32(0);
1959673bc519SSurabhi Vishnoi 	cfg->num_ocb_channels = __cpu_to_le32(0);
1960673bc519SSurabhi Vishnoi 	cfg->num_ocb_schedules = __cpu_to_le32(0);
196154327133SRakesh Pillai 	cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL);
1962ca996ec5SMichal Kazior 
19634b816f17SAbhishek Ambure 	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
19644b816f17SAbhishek Ambure 		cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
19654b816f17SAbhishek Ambure 
1966d961284dSYu Wang 	ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks);
1967ca996ec5SMichal Kazior 
1968ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
1969ca996ec5SMichal Kazior 	return skb;
1970ca996ec5SMichal Kazior }
1971ca996ec5SMichal Kazior 
1972ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_start_scan(struct ath10k * ar,const struct wmi_start_scan_arg * arg)1973ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
1974ca996ec5SMichal Kazior 				 const struct wmi_start_scan_arg *arg)
1975ca996ec5SMichal Kazior {
1976ca996ec5SMichal Kazior 	struct wmi_tlv_start_scan_cmd *cmd;
1977ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
1978ca996ec5SMichal Kazior 	struct sk_buff *skb;
1979ca996ec5SMichal Kazior 	size_t len, chan_len, ssid_len, bssid_len, ie_len;
1980ca996ec5SMichal Kazior 	__le32 *chans;
1981ca996ec5SMichal Kazior 	struct wmi_ssid *ssids;
1982ca996ec5SMichal Kazior 	struct wmi_mac_addr *addrs;
1983ca996ec5SMichal Kazior 	void *ptr;
1984ca996ec5SMichal Kazior 	int i, ret;
1985ca996ec5SMichal Kazior 
1986ca996ec5SMichal Kazior 	ret = ath10k_wmi_start_scan_verify(arg);
1987ca996ec5SMichal Kazior 	if (ret)
1988ca996ec5SMichal Kazior 		return ERR_PTR(ret);
1989ca996ec5SMichal Kazior 
1990ca996ec5SMichal Kazior 	chan_len = arg->n_channels * sizeof(__le32);
1991ca996ec5SMichal Kazior 	ssid_len = arg->n_ssids * sizeof(struct wmi_ssid);
1992ca996ec5SMichal Kazior 	bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr);
1993ca996ec5SMichal Kazior 	ie_len = roundup(arg->ie_len, 4);
1994ca996ec5SMichal Kazior 	len = (sizeof(*tlv) + sizeof(*cmd)) +
1995c8291988SZhi Chen 	      sizeof(*tlv) + chan_len +
1996c8291988SZhi Chen 	      sizeof(*tlv) + ssid_len +
1997c8291988SZhi Chen 	      sizeof(*tlv) + bssid_len +
1998c8291988SZhi Chen 	      sizeof(*tlv) + ie_len;
1999ca996ec5SMichal Kazior 
2000ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
2001ca996ec5SMichal Kazior 	if (!skb)
2002ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2003ca996ec5SMichal Kazior 
2004ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
2005ca996ec5SMichal Kazior 	tlv = ptr;
2006ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_START_SCAN_CMD);
2007ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2008ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2009ca996ec5SMichal Kazior 
2010ca996ec5SMichal Kazior 	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
2011dbd3f9f3SMichal Kazior 	cmd->burst_duration_ms = __cpu_to_le32(arg->burst_duration_ms);
2012ca996ec5SMichal Kazior 	cmd->num_channels = __cpu_to_le32(arg->n_channels);
2013ca996ec5SMichal Kazior 	cmd->num_ssids = __cpu_to_le32(arg->n_ssids);
2014ca996ec5SMichal Kazior 	cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
2015ca996ec5SMichal Kazior 	cmd->ie_len = __cpu_to_le32(arg->ie_len);
2016ca996ec5SMichal Kazior 	cmd->num_probes = __cpu_to_le32(3);
201760e1d0fbSCarl Huang 	ether_addr_copy(cmd->mac_addr.addr, arg->mac_addr.addr);
201860e1d0fbSCarl Huang 	ether_addr_copy(cmd->mac_mask.addr, arg->mac_mask.addr);
2019ca996ec5SMichal Kazior 
2020ca996ec5SMichal Kazior 	/* FIXME: There are some scan flag inconsistencies across firmwares,
2021ca996ec5SMichal Kazior 	 * e.g. WMI-TLV inverts the logic behind the following flag.
2022ca996ec5SMichal Kazior 	 */
2023ca996ec5SMichal Kazior 	cmd->common.scan_ctrl_flags ^= __cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);
2024ca996ec5SMichal Kazior 
2025ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2026ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
2027ca996ec5SMichal Kazior 
2028ca996ec5SMichal Kazior 	tlv = ptr;
2029ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
2030ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(chan_len);
2031ca996ec5SMichal Kazior 	chans = (void *)tlv->value;
2032ca996ec5SMichal Kazior 	for (i = 0; i < arg->n_channels; i++)
2033ca996ec5SMichal Kazior 		chans[i] = __cpu_to_le32(arg->channels[i]);
2034ca996ec5SMichal Kazior 
2035ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2036ca996ec5SMichal Kazior 	ptr += chan_len;
2037ca996ec5SMichal Kazior 
2038ca996ec5SMichal Kazior 	tlv = ptr;
2039ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
2040ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(ssid_len);
2041ca996ec5SMichal Kazior 	ssids = (void *)tlv->value;
2042ca996ec5SMichal Kazior 	for (i = 0; i < arg->n_ssids; i++) {
2043ca996ec5SMichal Kazior 		ssids[i].ssid_len = __cpu_to_le32(arg->ssids[i].len);
2044ca996ec5SMichal Kazior 		memcpy(ssids[i].ssid, arg->ssids[i].ssid, arg->ssids[i].len);
2045ca996ec5SMichal Kazior 	}
2046ca996ec5SMichal Kazior 
2047ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2048ca996ec5SMichal Kazior 	ptr += ssid_len;
2049ca996ec5SMichal Kazior 
2050ca996ec5SMichal Kazior 	tlv = ptr;
2051ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
2052ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(bssid_len);
2053ca996ec5SMichal Kazior 	addrs = (void *)tlv->value;
2054ca996ec5SMichal Kazior 	for (i = 0; i < arg->n_bssids; i++)
2055ca996ec5SMichal Kazior 		ether_addr_copy(addrs[i].addr, arg->bssids[i].bssid);
2056ca996ec5SMichal Kazior 
2057ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2058ca996ec5SMichal Kazior 	ptr += bssid_len;
2059ca996ec5SMichal Kazior 
2060ca996ec5SMichal Kazior 	tlv = ptr;
2061ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2062ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(ie_len);
2063ca996ec5SMichal Kazior 	memcpy(tlv->value, arg->ie, arg->ie_len);
2064ca996ec5SMichal Kazior 
2065ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2066ca996ec5SMichal Kazior 	ptr += ie_len;
2067ca996ec5SMichal Kazior 
2068ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start scan\n");
2069ca996ec5SMichal Kazior 	return skb;
2070ca996ec5SMichal Kazior }
2071ca996ec5SMichal Kazior 
2072ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k * ar,const struct wmi_stop_scan_arg * arg)2073ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar,
2074ca996ec5SMichal Kazior 				const struct wmi_stop_scan_arg *arg)
2075ca996ec5SMichal Kazior {
2076ca996ec5SMichal Kazior 	struct wmi_stop_scan_cmd *cmd;
2077ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2078ca996ec5SMichal Kazior 	struct sk_buff *skb;
2079ca996ec5SMichal Kazior 	u32 scan_id;
2080ca996ec5SMichal Kazior 	u32 req_id;
2081ca996ec5SMichal Kazior 
2082ca996ec5SMichal Kazior 	if (arg->req_id > 0xFFF)
2083ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2084ca996ec5SMichal Kazior 	if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
2085ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2086ca996ec5SMichal Kazior 
2087ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2088ca996ec5SMichal Kazior 	if (!skb)
2089ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2090ca996ec5SMichal Kazior 
2091ca996ec5SMichal Kazior 	scan_id = arg->u.scan_id;
2092ca996ec5SMichal Kazior 	scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
2093ca996ec5SMichal Kazior 
2094ca996ec5SMichal Kazior 	req_id = arg->req_id;
2095ca996ec5SMichal Kazior 	req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
2096ca996ec5SMichal Kazior 
2097ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2098ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD);
2099ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2100ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2101ca996ec5SMichal Kazior 	cmd->req_type = __cpu_to_le32(arg->req_type);
2102ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id);
2103ca996ec5SMichal Kazior 	cmd->scan_id = __cpu_to_le32(scan_id);
2104ca996ec5SMichal Kazior 	cmd->scan_req_id = __cpu_to_le32(req_id);
2105ca996ec5SMichal Kazior 
2106ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop scan\n");
2107ca996ec5SMichal Kazior 	return skb;
2108ca996ec5SMichal Kazior }
2109ca996ec5SMichal Kazior 
ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k * ar,enum wmi_vdev_subtype subtype)2110a7368c39SSurabhi Vishnoi static int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar,
2111a7368c39SSurabhi Vishnoi 					      enum wmi_vdev_subtype subtype)
2112a7368c39SSurabhi Vishnoi {
2113a7368c39SSurabhi Vishnoi 	switch (subtype) {
2114a7368c39SSurabhi Vishnoi 	case WMI_VDEV_SUBTYPE_NONE:
2115a7368c39SSurabhi Vishnoi 		return WMI_TLV_VDEV_SUBTYPE_NONE;
2116a7368c39SSurabhi Vishnoi 	case WMI_VDEV_SUBTYPE_P2P_DEVICE:
2117a7368c39SSurabhi Vishnoi 		return WMI_TLV_VDEV_SUBTYPE_P2P_DEV;
2118a7368c39SSurabhi Vishnoi 	case WMI_VDEV_SUBTYPE_P2P_CLIENT:
2119a7368c39SSurabhi Vishnoi 		return WMI_TLV_VDEV_SUBTYPE_P2P_CLI;
2120a7368c39SSurabhi Vishnoi 	case WMI_VDEV_SUBTYPE_P2P_GO:
2121a7368c39SSurabhi Vishnoi 		return WMI_TLV_VDEV_SUBTYPE_P2P_GO;
2122a7368c39SSurabhi Vishnoi 	case WMI_VDEV_SUBTYPE_PROXY_STA:
2123a7368c39SSurabhi Vishnoi 		return WMI_TLV_VDEV_SUBTYPE_PROXY_STA;
2124a7368c39SSurabhi Vishnoi 	case WMI_VDEV_SUBTYPE_MESH_11S:
2125a7368c39SSurabhi Vishnoi 		return WMI_TLV_VDEV_SUBTYPE_MESH_11S;
2126a7368c39SSurabhi Vishnoi 	case WMI_VDEV_SUBTYPE_MESH_NON_11S:
2127bc2ef649SKarthikeyan Periyasamy 		return -EOPNOTSUPP;
2128a7368c39SSurabhi Vishnoi 	}
2129bc2ef649SKarthikeyan Periyasamy 	return -EOPNOTSUPP;
2130a7368c39SSurabhi Vishnoi }
2131a7368c39SSurabhi Vishnoi 
2132ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k * ar,u32 vdev_id,enum wmi_vdev_type vdev_type,enum wmi_vdev_subtype vdev_subtype,const u8 mac_addr[ETH_ALEN])2133ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar,
2134ca996ec5SMichal Kazior 				  u32 vdev_id,
2135ca996ec5SMichal Kazior 				  enum wmi_vdev_type vdev_type,
2136ca996ec5SMichal Kazior 				  enum wmi_vdev_subtype vdev_subtype,
2137ca996ec5SMichal Kazior 				  const u8 mac_addr[ETH_ALEN])
2138ca996ec5SMichal Kazior {
2139ca996ec5SMichal Kazior 	struct wmi_vdev_create_cmd *cmd;
2140ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2141ca996ec5SMichal Kazior 	struct sk_buff *skb;
2142ca996ec5SMichal Kazior 
2143ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2144ca996ec5SMichal Kazior 	if (!skb)
2145ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2146ca996ec5SMichal Kazior 
2147ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2148ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD);
2149ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2150ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2151ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2152ca996ec5SMichal Kazior 	cmd->vdev_type = __cpu_to_le32(vdev_type);
2153ca996ec5SMichal Kazior 	cmd->vdev_subtype = __cpu_to_le32(vdev_subtype);
2154ca996ec5SMichal Kazior 	ether_addr_copy(cmd->vdev_macaddr.addr, mac_addr);
2155ca996ec5SMichal Kazior 
2156ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev create\n");
2157ca996ec5SMichal Kazior 	return skb;
2158ca996ec5SMichal Kazior }
2159ca996ec5SMichal Kazior 
2160ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k * ar,u32 vdev_id)2161ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
2162ca996ec5SMichal Kazior {
2163ca996ec5SMichal Kazior 	struct wmi_vdev_delete_cmd *cmd;
2164ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2165ca996ec5SMichal Kazior 	struct sk_buff *skb;
2166ca996ec5SMichal Kazior 
2167ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2168ca996ec5SMichal Kazior 	if (!skb)
2169ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2170ca996ec5SMichal Kazior 
2171ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2172ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD);
2173ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2174ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2175ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2176ca996ec5SMichal Kazior 
2177ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev delete\n");
2178ca996ec5SMichal Kazior 	return skb;
2179ca996ec5SMichal Kazior }
2180ca996ec5SMichal Kazior 
2181ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k * ar,const struct wmi_vdev_start_request_arg * arg,bool restart)2182ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
2183ca996ec5SMichal Kazior 				 const struct wmi_vdev_start_request_arg *arg,
2184ca996ec5SMichal Kazior 				 bool restart)
2185ca996ec5SMichal Kazior {
2186ca996ec5SMichal Kazior 	struct wmi_tlv_vdev_start_cmd *cmd;
2187ca996ec5SMichal Kazior 	struct wmi_channel *ch;
2188ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2189ca996ec5SMichal Kazior 	struct sk_buff *skb;
2190ca996ec5SMichal Kazior 	size_t len;
2191ca996ec5SMichal Kazior 	void *ptr;
2192ca996ec5SMichal Kazior 	u32 flags = 0;
2193ca996ec5SMichal Kazior 
2194ca996ec5SMichal Kazior 	if (WARN_ON(arg->hidden_ssid && !arg->ssid))
2195ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2196ca996ec5SMichal Kazior 	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
2197ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2198ca996ec5SMichal Kazior 
2199ca996ec5SMichal Kazior 	len = (sizeof(*tlv) + sizeof(*cmd)) +
2200ca996ec5SMichal Kazior 	      (sizeof(*tlv) + sizeof(*ch)) +
2201ca996ec5SMichal Kazior 	      (sizeof(*tlv) + 0);
2202ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
2203ca996ec5SMichal Kazior 	if (!skb)
2204ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2205ca996ec5SMichal Kazior 
2206ca996ec5SMichal Kazior 	if (arg->hidden_ssid)
2207ca996ec5SMichal Kazior 		flags |= WMI_VDEV_START_HIDDEN_SSID;
2208ca996ec5SMichal Kazior 	if (arg->pmf_enabled)
2209ca996ec5SMichal Kazior 		flags |= WMI_VDEV_START_PMF_ENABLED;
2210ca996ec5SMichal Kazior 
2211ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
2212ca996ec5SMichal Kazior 
2213ca996ec5SMichal Kazior 	tlv = ptr;
2214ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD);
2215ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2216ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2217ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2218ca996ec5SMichal Kazior 	cmd->bcn_intval = __cpu_to_le32(arg->bcn_intval);
2219ca996ec5SMichal Kazior 	cmd->dtim_period = __cpu_to_le32(arg->dtim_period);
2220ca996ec5SMichal Kazior 	cmd->flags = __cpu_to_le32(flags);
2221ca996ec5SMichal Kazior 	cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate);
2222ca996ec5SMichal Kazior 	cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power);
2223ca996ec5SMichal Kazior 	cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack);
2224ca996ec5SMichal Kazior 
2225ca996ec5SMichal Kazior 	if (arg->ssid) {
2226ca996ec5SMichal Kazior 		cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len);
2227ca996ec5SMichal Kazior 		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
2228ca996ec5SMichal Kazior 	}
2229ca996ec5SMichal Kazior 
2230ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2231ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
2232ca996ec5SMichal Kazior 
2233ca996ec5SMichal Kazior 	tlv = ptr;
2234ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
2235ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*ch));
2236ca996ec5SMichal Kazior 	ch = (void *)tlv->value;
2237795def8bSLei Wang 	ath10k_wmi_put_wmi_channel(ar, ch, &arg->channel);
2238ca996ec5SMichal Kazior 
2239ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2240ca996ec5SMichal Kazior 	ptr += sizeof(*ch);
2241ca996ec5SMichal Kazior 
2242ca996ec5SMichal Kazior 	tlv = ptr;
2243ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2244ca996ec5SMichal Kazior 	tlv->len = 0;
2245ca996ec5SMichal Kazior 
2246ca996ec5SMichal Kazior 	/* Note: This is a nested TLV containing:
2247ca996ec5SMichal Kazior 	 * [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
2248ca996ec5SMichal Kazior 	 */
2249ca996ec5SMichal Kazior 
2250ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2251ca996ec5SMichal Kazior 	ptr += 0;
2252ca996ec5SMichal Kazior 
2253ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev start\n");
2254ca996ec5SMichal Kazior 	return skb;
2255ca996ec5SMichal Kazior }
2256ca996ec5SMichal Kazior 
2257ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k * ar,u32 vdev_id)2258ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
2259ca996ec5SMichal Kazior {
2260ca996ec5SMichal Kazior 	struct wmi_vdev_stop_cmd *cmd;
2261ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2262ca996ec5SMichal Kazior 	struct sk_buff *skb;
2263ca996ec5SMichal Kazior 
2264ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2265ca996ec5SMichal Kazior 	if (!skb)
2266ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2267ca996ec5SMichal Kazior 
2268ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2269ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD);
2270ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2271ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2272ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2273ca996ec5SMichal Kazior 
2274ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev stop\n");
2275ca996ec5SMichal Kazior 	return skb;
2276ca996ec5SMichal Kazior }
2277ca996ec5SMichal Kazior 
2278ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k * ar,u32 vdev_id,u32 aid,const u8 * bssid)2279ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
2280ca996ec5SMichal Kazior 			      const u8 *bssid)
2281ca996ec5SMichal Kazior 
2282ca996ec5SMichal Kazior {
2283ca996ec5SMichal Kazior 	struct wmi_vdev_up_cmd *cmd;
2284ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2285ca996ec5SMichal Kazior 	struct sk_buff *skb;
2286ca996ec5SMichal Kazior 
2287ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2288ca996ec5SMichal Kazior 	if (!skb)
2289ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2290ca996ec5SMichal Kazior 
2291ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2292ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_UP_CMD);
2293ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2294ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2295ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2296ca996ec5SMichal Kazior 	cmd->vdev_assoc_id = __cpu_to_le32(aid);
2297ca996ec5SMichal Kazior 	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
2298ca996ec5SMichal Kazior 
2299ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev up\n");
2300ca996ec5SMichal Kazior 	return skb;
2301ca996ec5SMichal Kazior }
2302ca996ec5SMichal Kazior 
2303ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k * ar,u32 vdev_id)2304ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
2305ca996ec5SMichal Kazior {
2306ca996ec5SMichal Kazior 	struct wmi_vdev_down_cmd *cmd;
2307ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2308ca996ec5SMichal Kazior 	struct sk_buff *skb;
2309ca996ec5SMichal Kazior 
2310ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2311ca996ec5SMichal Kazior 	if (!skb)
2312ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2313ca996ec5SMichal Kazior 
2314ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2315ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD);
2316ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2317ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2318ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2319ca996ec5SMichal Kazior 
2320ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev down\n");
2321ca996ec5SMichal Kazior 	return skb;
2322ca996ec5SMichal Kazior }
2323ca996ec5SMichal Kazior 
2324ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k * ar,u32 vdev_id,u32 param_id,u32 param_value)2325ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
2326ca996ec5SMichal Kazior 				     u32 param_id, u32 param_value)
2327ca996ec5SMichal Kazior {
2328ca996ec5SMichal Kazior 	struct wmi_vdev_set_param_cmd *cmd;
2329ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2330ca996ec5SMichal Kazior 	struct sk_buff *skb;
2331ca996ec5SMichal Kazior 
2332ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2333ca996ec5SMichal Kazior 	if (!skb)
2334ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2335ca996ec5SMichal Kazior 
2336ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2337ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD);
2338ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2339ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2340ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2341ca996ec5SMichal Kazior 	cmd->param_id = __cpu_to_le32(param_id);
2342ca996ec5SMichal Kazior 	cmd->param_value = __cpu_to_le32(param_value);
2343ca996ec5SMichal Kazior 
23441c136e41SRakesh Pillai 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n",
23451c136e41SRakesh Pillai 		   vdev_id, param_id, param_value);
2346ca996ec5SMichal Kazior 	return skb;
2347ca996ec5SMichal Kazior }
2348ca996ec5SMichal Kazior 
2349ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k * ar,const struct wmi_vdev_install_key_arg * arg)2350ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
2351ca996ec5SMichal Kazior 				       const struct wmi_vdev_install_key_arg *arg)
2352ca996ec5SMichal Kazior {
2353ca996ec5SMichal Kazior 	struct wmi_vdev_install_key_cmd *cmd;
2354ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2355ca996ec5SMichal Kazior 	struct sk_buff *skb;
2356ca996ec5SMichal Kazior 	size_t len;
2357ca996ec5SMichal Kazior 	void *ptr;
2358ca996ec5SMichal Kazior 
23597d94f862SAbhishek Ambure 	if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
23607d94f862SAbhishek Ambure 	    arg->key_data)
2361ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
23627d94f862SAbhishek Ambure 	if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
23637d94f862SAbhishek Ambure 	    !arg->key_data)
2364ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2365ca996ec5SMichal Kazior 
2366ca996ec5SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd) +
2367ca996ec5SMichal Kazior 	      sizeof(*tlv) + roundup(arg->key_len, sizeof(__le32));
2368ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
2369ca996ec5SMichal Kazior 	if (!skb)
2370ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2371ca996ec5SMichal Kazior 
2372ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
2373ca996ec5SMichal Kazior 	tlv = ptr;
2374ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD);
2375ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2376ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2377ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2378ca996ec5SMichal Kazior 	cmd->key_idx = __cpu_to_le32(arg->key_idx);
2379ca996ec5SMichal Kazior 	cmd->key_flags = __cpu_to_le32(arg->key_flags);
2380ca996ec5SMichal Kazior 	cmd->key_cipher = __cpu_to_le32(arg->key_cipher);
2381ca996ec5SMichal Kazior 	cmd->key_len = __cpu_to_le32(arg->key_len);
2382ca996ec5SMichal Kazior 	cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len);
2383ca996ec5SMichal Kazior 	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
2384ca996ec5SMichal Kazior 
2385ca996ec5SMichal Kazior 	if (arg->macaddr)
2386ca996ec5SMichal Kazior 		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
2387ca996ec5SMichal Kazior 
2388ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2389ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
2390ca996ec5SMichal Kazior 
2391ca996ec5SMichal Kazior 	tlv = ptr;
2392ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2393ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(roundup(arg->key_len, sizeof(__le32)));
2394ca996ec5SMichal Kazior 	if (arg->key_data)
2395ca996ec5SMichal Kazior 		memcpy(tlv->value, arg->key_data, arg->key_len);
2396ca996ec5SMichal Kazior 
2397ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2398ca996ec5SMichal Kazior 	ptr += roundup(arg->key_len, sizeof(__le32));
2399ca996ec5SMichal Kazior 
2400ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev install key\n");
2401ca996ec5SMichal Kazior 	return skb;
2402ca996ec5SMichal Kazior }
2403ca996ec5SMichal Kazior 
ath10k_wmi_tlv_put_uapsd_ac(struct ath10k * ar,void * ptr,const struct wmi_sta_uapsd_auto_trig_arg * arg)24040c7e477cSJanusz Dziedzic static void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr,
24050c7e477cSJanusz Dziedzic 					 const struct wmi_sta_uapsd_auto_trig_arg *arg)
24060c7e477cSJanusz Dziedzic {
24070c7e477cSJanusz Dziedzic 	struct wmi_sta_uapsd_auto_trig_param *ac;
24080c7e477cSJanusz Dziedzic 	struct wmi_tlv *tlv;
24090c7e477cSJanusz Dziedzic 
24100c7e477cSJanusz Dziedzic 	tlv = ptr;
24110c7e477cSJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM);
24120c7e477cSJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*ac));
24130c7e477cSJanusz Dziedzic 	ac = (void *)tlv->value;
24140c7e477cSJanusz Dziedzic 
24150c7e477cSJanusz Dziedzic 	ac->wmm_ac = __cpu_to_le32(arg->wmm_ac);
24160c7e477cSJanusz Dziedzic 	ac->user_priority = __cpu_to_le32(arg->user_priority);
24170c7e477cSJanusz Dziedzic 	ac->service_interval = __cpu_to_le32(arg->service_interval);
24180c7e477cSJanusz Dziedzic 	ac->suspend_interval = __cpu_to_le32(arg->suspend_interval);
24190c7e477cSJanusz Dziedzic 	ac->delay_interval = __cpu_to_le32(arg->delay_interval);
24200c7e477cSJanusz Dziedzic 
24210c7e477cSJanusz Dziedzic 	ath10k_dbg(ar, ATH10K_DBG_WMI,
24220c7e477cSJanusz Dziedzic 		   "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n",
24230c7e477cSJanusz Dziedzic 		   ac->wmm_ac, ac->user_priority, ac->service_interval,
24240c7e477cSJanusz Dziedzic 		   ac->suspend_interval, ac->delay_interval);
24250c7e477cSJanusz Dziedzic 
24260c7e477cSJanusz Dziedzic 	return ptr + sizeof(*tlv) + sizeof(*ac);
24270c7e477cSJanusz Dziedzic }
24280c7e477cSJanusz Dziedzic 
24290c7e477cSJanusz Dziedzic static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k * ar,u32 vdev_id,const u8 peer_addr[ETH_ALEN],const struct wmi_sta_uapsd_auto_trig_arg * args,u32 num_ac)24300c7e477cSJanusz Dziedzic ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id,
24310c7e477cSJanusz Dziedzic 				     const u8 peer_addr[ETH_ALEN],
24320c7e477cSJanusz Dziedzic 				     const struct wmi_sta_uapsd_auto_trig_arg *args,
24330c7e477cSJanusz Dziedzic 				     u32 num_ac)
24340c7e477cSJanusz Dziedzic {
24350c7e477cSJanusz Dziedzic 	struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd;
24360c7e477cSJanusz Dziedzic 	struct wmi_sta_uapsd_auto_trig_param *ac;
24370c7e477cSJanusz Dziedzic 	struct wmi_tlv *tlv;
24380c7e477cSJanusz Dziedzic 	struct sk_buff *skb;
24390c7e477cSJanusz Dziedzic 	size_t len;
24400c7e477cSJanusz Dziedzic 	size_t ac_tlv_len;
24410c7e477cSJanusz Dziedzic 	void *ptr;
24420c7e477cSJanusz Dziedzic 	int i;
24430c7e477cSJanusz Dziedzic 
24440c7e477cSJanusz Dziedzic 	ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac));
24450c7e477cSJanusz Dziedzic 	len = sizeof(*tlv) + sizeof(*cmd) +
24460c7e477cSJanusz Dziedzic 	      sizeof(*tlv) + ac_tlv_len;
24470c7e477cSJanusz Dziedzic 	skb = ath10k_wmi_alloc_skb(ar, len);
24480c7e477cSJanusz Dziedzic 	if (!skb)
24490c7e477cSJanusz Dziedzic 		return ERR_PTR(-ENOMEM);
24500c7e477cSJanusz Dziedzic 
24510c7e477cSJanusz Dziedzic 	ptr = (void *)skb->data;
24520c7e477cSJanusz Dziedzic 	tlv = ptr;
24530c7e477cSJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD);
24540c7e477cSJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*cmd));
24550c7e477cSJanusz Dziedzic 	cmd = (void *)tlv->value;
24560c7e477cSJanusz Dziedzic 	cmd->vdev_id = __cpu_to_le32(vdev_id);
24570c7e477cSJanusz Dziedzic 	cmd->num_ac = __cpu_to_le32(num_ac);
24580c7e477cSJanusz Dziedzic 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
24590c7e477cSJanusz Dziedzic 
24600c7e477cSJanusz Dziedzic 	ptr += sizeof(*tlv);
24610c7e477cSJanusz Dziedzic 	ptr += sizeof(*cmd);
24620c7e477cSJanusz Dziedzic 
24630c7e477cSJanusz Dziedzic 	tlv = ptr;
24640c7e477cSJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
24650c7e477cSJanusz Dziedzic 	tlv->len = __cpu_to_le16(ac_tlv_len);
24660c7e477cSJanusz Dziedzic 	ac = (void *)tlv->value;
24670c7e477cSJanusz Dziedzic 
24680c7e477cSJanusz Dziedzic 	ptr += sizeof(*tlv);
24690c7e477cSJanusz Dziedzic 	for (i = 0; i < num_ac; i++)
24700c7e477cSJanusz Dziedzic 		ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]);
24710c7e477cSJanusz Dziedzic 
24720c7e477cSJanusz Dziedzic 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n");
24730c7e477cSJanusz Dziedzic 	return skb;
24740c7e477cSJanusz Dziedzic }
24750c7e477cSJanusz Dziedzic 
ath10k_wmi_tlv_put_wmm(void * ptr,const struct wmi_wmm_params_arg * arg)24765e752e42SMichal Kazior static void *ath10k_wmi_tlv_put_wmm(void *ptr,
24775e752e42SMichal Kazior 				    const struct wmi_wmm_params_arg *arg)
24785e752e42SMichal Kazior {
24795e752e42SMichal Kazior 	struct wmi_wmm_params *wmm;
24805e752e42SMichal Kazior 	struct wmi_tlv *tlv;
24815e752e42SMichal Kazior 
24825e752e42SMichal Kazior 	tlv = ptr;
24835e752e42SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS);
24845e752e42SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*wmm));
24855e752e42SMichal Kazior 	wmm = (void *)tlv->value;
24865e752e42SMichal Kazior 	ath10k_wmi_set_wmm_param(wmm, arg);
24875e752e42SMichal Kazior 
24885e752e42SMichal Kazior 	return ptr + sizeof(*tlv) + sizeof(*wmm);
24895e752e42SMichal Kazior }
24905e752e42SMichal Kazior 
2491ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k * ar,u32 vdev_id,const struct wmi_wmm_params_all_arg * arg)24926d492fe2SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
24936d492fe2SMichal Kazior 				    const struct wmi_wmm_params_all_arg *arg)
24946d492fe2SMichal Kazior {
24956d492fe2SMichal Kazior 	struct wmi_tlv_vdev_set_wmm_cmd *cmd;
24966d492fe2SMichal Kazior 	struct wmi_tlv *tlv;
24976d492fe2SMichal Kazior 	struct sk_buff *skb;
24986d492fe2SMichal Kazior 	size_t len;
24996d492fe2SMichal Kazior 	void *ptr;
25006d492fe2SMichal Kazior 
2501c8c60cfdSMarek Puzyniak 	len = sizeof(*tlv) + sizeof(*cmd);
25026d492fe2SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
25036d492fe2SMichal Kazior 	if (!skb)
25046d492fe2SMichal Kazior 		return ERR_PTR(-ENOMEM);
25056d492fe2SMichal Kazior 
25066d492fe2SMichal Kazior 	ptr = (void *)skb->data;
25076d492fe2SMichal Kazior 	tlv = ptr;
25086d492fe2SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD);
25096d492fe2SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
25106d492fe2SMichal Kazior 	cmd = (void *)tlv->value;
25116d492fe2SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
25126d492fe2SMichal Kazior 
2513c8c60cfdSMarek Puzyniak 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[0].params, &arg->ac_be);
2514c8c60cfdSMarek Puzyniak 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[1].params, &arg->ac_bk);
2515c8c60cfdSMarek Puzyniak 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[2].params, &arg->ac_vi);
2516c8c60cfdSMarek Puzyniak 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[3].params, &arg->ac_vo);
25176d492fe2SMichal Kazior 
25186d492fe2SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n");
25196d492fe2SMichal Kazior 	return skb;
25206d492fe2SMichal Kazior }
25216d492fe2SMichal Kazior 
25226d492fe2SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k * ar,const struct wmi_sta_keepalive_arg * arg)25236e8b188bSJanusz Dziedzic ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar,
25246e8b188bSJanusz Dziedzic 				    const struct wmi_sta_keepalive_arg *arg)
25256e8b188bSJanusz Dziedzic {
25266e8b188bSJanusz Dziedzic 	struct wmi_tlv_sta_keepalive_cmd *cmd;
25276e8b188bSJanusz Dziedzic 	struct wmi_sta_keepalive_arp_resp *arp;
25286e8b188bSJanusz Dziedzic 	struct sk_buff *skb;
25296e8b188bSJanusz Dziedzic 	struct wmi_tlv *tlv;
25306e8b188bSJanusz Dziedzic 	void *ptr;
25316e8b188bSJanusz Dziedzic 	size_t len;
25326e8b188bSJanusz Dziedzic 
25336e8b188bSJanusz Dziedzic 	len = sizeof(*tlv) + sizeof(*cmd) +
25346e8b188bSJanusz Dziedzic 	      sizeof(*tlv) + sizeof(*arp);
25356e8b188bSJanusz Dziedzic 	skb = ath10k_wmi_alloc_skb(ar, len);
25366e8b188bSJanusz Dziedzic 	if (!skb)
25376e8b188bSJanusz Dziedzic 		return ERR_PTR(-ENOMEM);
25386e8b188bSJanusz Dziedzic 
25396e8b188bSJanusz Dziedzic 	ptr = (void *)skb->data;
25406e8b188bSJanusz Dziedzic 	tlv = ptr;
25416e8b188bSJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD);
25426e8b188bSJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*cmd));
25436e8b188bSJanusz Dziedzic 	cmd = (void *)tlv->value;
25446e8b188bSJanusz Dziedzic 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
25456e8b188bSJanusz Dziedzic 	cmd->enabled = __cpu_to_le32(arg->enabled);
25466e8b188bSJanusz Dziedzic 	cmd->method = __cpu_to_le32(arg->method);
25476e8b188bSJanusz Dziedzic 	cmd->interval = __cpu_to_le32(arg->interval);
25486e8b188bSJanusz Dziedzic 
25496e8b188bSJanusz Dziedzic 	ptr += sizeof(*tlv);
25506e8b188bSJanusz Dziedzic 	ptr += sizeof(*cmd);
25516e8b188bSJanusz Dziedzic 
25526e8b188bSJanusz Dziedzic 	tlv = ptr;
25536e8b188bSJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE);
25546e8b188bSJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*arp));
25556e8b188bSJanusz Dziedzic 	arp = (void *)tlv->value;
25566e8b188bSJanusz Dziedzic 
25576e8b188bSJanusz Dziedzic 	arp->src_ip4_addr = arg->src_ip4_addr;
25586e8b188bSJanusz Dziedzic 	arp->dest_ip4_addr = arg->dest_ip4_addr;
25596e8b188bSJanusz Dziedzic 	ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
25606e8b188bSJanusz Dziedzic 
256123de5797SColin Ian King 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d interval %d\n",
25626e8b188bSJanusz Dziedzic 		   arg->vdev_id, arg->enabled, arg->method, arg->interval);
25636e8b188bSJanusz Dziedzic 	return skb;
25646e8b188bSJanusz Dziedzic }
25656e8b188bSJanusz Dziedzic 
25666e8b188bSJanusz Dziedzic static struct sk_buff *
ath10k_wmi_tlv_op_gen_peer_create(struct ath10k * ar,u32 vdev_id,const u8 peer_addr[ETH_ALEN],enum wmi_peer_type peer_type)2567ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
25687390ed34SMarek Puzyniak 				  const u8 peer_addr[ETH_ALEN],
25697390ed34SMarek Puzyniak 				  enum wmi_peer_type peer_type)
2570ca996ec5SMichal Kazior {
2571ca996ec5SMichal Kazior 	struct wmi_tlv_peer_create_cmd *cmd;
2572ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2573ca996ec5SMichal Kazior 	struct sk_buff *skb;
2574ca996ec5SMichal Kazior 
2575ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2576ca996ec5SMichal Kazior 	if (!skb)
2577ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2578ca996ec5SMichal Kazior 
2579ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2580ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD);
2581ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2582ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2583ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
25847390ed34SMarek Puzyniak 	cmd->peer_type = __cpu_to_le32(peer_type);
2585ca996ec5SMichal Kazior 	ether_addr_copy(cmd->peer_addr.addr, peer_addr);
2586ca996ec5SMichal Kazior 
2587ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer create\n");
2588ca996ec5SMichal Kazior 	return skb;
2589ca996ec5SMichal Kazior }
2590ca996ec5SMichal Kazior 
2591ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k * ar,u32 vdev_id,const u8 peer_addr[ETH_ALEN])2592ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
2593ca996ec5SMichal Kazior 				  const u8 peer_addr[ETH_ALEN])
2594ca996ec5SMichal Kazior {
2595ca996ec5SMichal Kazior 	struct wmi_peer_delete_cmd *cmd;
2596ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2597ca996ec5SMichal Kazior 	struct sk_buff *skb;
2598ca996ec5SMichal Kazior 
2599ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2600ca996ec5SMichal Kazior 	if (!skb)
2601ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2602ca996ec5SMichal Kazior 
2603ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2604ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD);
2605ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2606ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2607ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2608ca996ec5SMichal Kazior 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2609ca996ec5SMichal Kazior 
2610ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete\n");
2611ca996ec5SMichal Kazior 	return skb;
2612ca996ec5SMichal Kazior }
2613ca996ec5SMichal Kazior 
2614ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_peer_flush(struct ath10k * ar,u32 vdev_id,const u8 peer_addr[ETH_ALEN],u32 tid_bitmap)2615ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
2616ca996ec5SMichal Kazior 				 const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
2617ca996ec5SMichal Kazior {
2618ca996ec5SMichal Kazior 	struct wmi_peer_flush_tids_cmd *cmd;
2619ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2620ca996ec5SMichal Kazior 	struct sk_buff *skb;
2621ca996ec5SMichal Kazior 
2622ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2623ca996ec5SMichal Kazior 	if (!skb)
2624ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2625ca996ec5SMichal Kazior 
2626ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2627ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD);
2628ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2629ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2630ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2631ca996ec5SMichal Kazior 	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
2632ca996ec5SMichal Kazior 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2633ca996ec5SMichal Kazior 
2634ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer flush\n");
2635ca996ec5SMichal Kazior 	return skb;
2636ca996ec5SMichal Kazior }
2637ca996ec5SMichal Kazior 
2638ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k * ar,u32 vdev_id,const u8 * peer_addr,enum wmi_peer_param param_id,u32 param_value)2639ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
2640ca996ec5SMichal Kazior 				     const u8 *peer_addr,
2641ca996ec5SMichal Kazior 				     enum wmi_peer_param param_id,
2642ca996ec5SMichal Kazior 				     u32 param_value)
2643ca996ec5SMichal Kazior {
2644ca996ec5SMichal Kazior 	struct wmi_peer_set_param_cmd *cmd;
2645ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2646ca996ec5SMichal Kazior 	struct sk_buff *skb;
2647ca996ec5SMichal Kazior 
2648ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2649ca996ec5SMichal Kazior 	if (!skb)
2650ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2651ca996ec5SMichal Kazior 
2652ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2653ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD);
2654ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2655ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2656ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2657ca996ec5SMichal Kazior 	cmd->param_id = __cpu_to_le32(param_id);
2658ca996ec5SMichal Kazior 	cmd->param_value = __cpu_to_le32(param_value);
2659ca996ec5SMichal Kazior 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2660ca996ec5SMichal Kazior 
26611c136e41SRakesh Pillai 	ath10k_dbg(ar, ATH10K_DBG_WMI,
26621c136e41SRakesh Pillai 		   "wmi tlv vdev %d peer %pM set param %d value 0x%x\n",
26631c136e41SRakesh Pillai 		   vdev_id, peer_addr, param_id, param_value);
2664ca996ec5SMichal Kazior 	return skb;
2665ca996ec5SMichal Kazior }
2666ca996ec5SMichal Kazior 
2667ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k * ar,const struct wmi_peer_assoc_complete_arg * arg)2668ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k *ar,
2669ca996ec5SMichal Kazior 				 const struct wmi_peer_assoc_complete_arg *arg)
2670ca996ec5SMichal Kazior {
2671ca996ec5SMichal Kazior 	struct wmi_tlv_peer_assoc_cmd *cmd;
2672ca996ec5SMichal Kazior 	struct wmi_vht_rate_set *vht_rate;
2673ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2674ca996ec5SMichal Kazior 	struct sk_buff *skb;
2675ca996ec5SMichal Kazior 	size_t len, legacy_rate_len, ht_rate_len;
2676ca996ec5SMichal Kazior 	void *ptr;
2677ca996ec5SMichal Kazior 
2678ca996ec5SMichal Kazior 	if (arg->peer_mpdu_density > 16)
2679ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2680ca996ec5SMichal Kazior 	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
2681ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2682ca996ec5SMichal Kazior 	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
2683ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2684ca996ec5SMichal Kazior 
2685ca996ec5SMichal Kazior 	legacy_rate_len = roundup(arg->peer_legacy_rates.num_rates,
2686ca996ec5SMichal Kazior 				  sizeof(__le32));
2687ca996ec5SMichal Kazior 	ht_rate_len = roundup(arg->peer_ht_rates.num_rates, sizeof(__le32));
2688ca996ec5SMichal Kazior 	len = (sizeof(*tlv) + sizeof(*cmd)) +
2689ca996ec5SMichal Kazior 	      (sizeof(*tlv) + legacy_rate_len) +
2690ca996ec5SMichal Kazior 	      (sizeof(*tlv) + ht_rate_len) +
2691ca996ec5SMichal Kazior 	      (sizeof(*tlv) + sizeof(*vht_rate));
2692ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
2693ca996ec5SMichal Kazior 	if (!skb)
2694ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2695ca996ec5SMichal Kazior 
2696ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
2697ca996ec5SMichal Kazior 	tlv = ptr;
2698ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD);
2699ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2700ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2701ca996ec5SMichal Kazior 
2702ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2703ca996ec5SMichal Kazior 	cmd->new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
2704ca996ec5SMichal Kazior 	cmd->assoc_id = __cpu_to_le32(arg->peer_aid);
2705ca996ec5SMichal Kazior 	cmd->flags = __cpu_to_le32(arg->peer_flags);
2706ca996ec5SMichal Kazior 	cmd->caps = __cpu_to_le32(arg->peer_caps);
2707ca996ec5SMichal Kazior 	cmd->listen_intval = __cpu_to_le32(arg->peer_listen_intval);
2708ca996ec5SMichal Kazior 	cmd->ht_caps = __cpu_to_le32(arg->peer_ht_caps);
2709ca996ec5SMichal Kazior 	cmd->max_mpdu = __cpu_to_le32(arg->peer_max_mpdu);
2710ca996ec5SMichal Kazior 	cmd->mpdu_density = __cpu_to_le32(arg->peer_mpdu_density);
2711ca996ec5SMichal Kazior 	cmd->rate_caps = __cpu_to_le32(arg->peer_rate_caps);
2712ca996ec5SMichal Kazior 	cmd->nss = __cpu_to_le32(arg->peer_num_spatial_streams);
2713ca996ec5SMichal Kazior 	cmd->vht_caps = __cpu_to_le32(arg->peer_vht_caps);
2714ca996ec5SMichal Kazior 	cmd->phy_mode = __cpu_to_le32(arg->peer_phymode);
2715ca996ec5SMichal Kazior 	cmd->num_legacy_rates = __cpu_to_le32(arg->peer_legacy_rates.num_rates);
2716ca996ec5SMichal Kazior 	cmd->num_ht_rates = __cpu_to_le32(arg->peer_ht_rates.num_rates);
2717ca996ec5SMichal Kazior 	ether_addr_copy(cmd->mac_addr.addr, arg->addr);
2718ca996ec5SMichal Kazior 
2719ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2720ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
2721ca996ec5SMichal Kazior 
2722ca996ec5SMichal Kazior 	tlv = ptr;
2723ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2724ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(legacy_rate_len);
2725ca996ec5SMichal Kazior 	memcpy(tlv->value, arg->peer_legacy_rates.rates,
2726ca996ec5SMichal Kazior 	       arg->peer_legacy_rates.num_rates);
2727ca996ec5SMichal Kazior 
2728ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2729ca996ec5SMichal Kazior 	ptr += legacy_rate_len;
2730ca996ec5SMichal Kazior 
2731ca996ec5SMichal Kazior 	tlv = ptr;
2732ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2733ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(ht_rate_len);
2734ca996ec5SMichal Kazior 	memcpy(tlv->value, arg->peer_ht_rates.rates,
2735ca996ec5SMichal Kazior 	       arg->peer_ht_rates.num_rates);
2736ca996ec5SMichal Kazior 
2737ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2738ca996ec5SMichal Kazior 	ptr += ht_rate_len;
2739ca996ec5SMichal Kazior 
2740ca996ec5SMichal Kazior 	tlv = ptr;
2741ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VHT_RATE_SET);
2742ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*vht_rate));
2743ca996ec5SMichal Kazior 	vht_rate = (void *)tlv->value;
2744ca996ec5SMichal Kazior 
2745ca996ec5SMichal Kazior 	vht_rate->rx_max_rate = __cpu_to_le32(arg->peer_vht_rates.rx_max_rate);
2746ca996ec5SMichal Kazior 	vht_rate->rx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set);
2747ca996ec5SMichal Kazior 	vht_rate->tx_max_rate = __cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
2748ca996ec5SMichal Kazior 	vht_rate->tx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
2749ca996ec5SMichal Kazior 
2750ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2751ca996ec5SMichal Kazior 	ptr += sizeof(*vht_rate);
2752ca996ec5SMichal Kazior 
2753ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer assoc\n");
2754ca996ec5SMichal Kazior 	return skb;
2755ca996ec5SMichal Kazior }
2756ca996ec5SMichal Kazior 
2757ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k * ar,u32 vdev_id,enum wmi_sta_ps_mode psmode)2758ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
2759ca996ec5SMichal Kazior 				 enum wmi_sta_ps_mode psmode)
2760ca996ec5SMichal Kazior {
2761ca996ec5SMichal Kazior 	struct wmi_sta_powersave_mode_cmd *cmd;
2762ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2763ca996ec5SMichal Kazior 	struct sk_buff *skb;
2764ca996ec5SMichal Kazior 
2765ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2766ca996ec5SMichal Kazior 	if (!skb)
2767ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2768ca996ec5SMichal Kazior 
2769ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2770ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD);
2771ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2772ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2773ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2774ca996ec5SMichal Kazior 	cmd->sta_ps_mode = __cpu_to_le32(psmode);
2775ca996ec5SMichal Kazior 
2776ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set psmode\n");
2777ca996ec5SMichal Kazior 	return skb;
2778ca996ec5SMichal Kazior }
2779ca996ec5SMichal Kazior 
2780ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k * ar,u32 vdev_id,enum wmi_sta_powersave_param param_id,u32 param_value)2781ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
2782ca996ec5SMichal Kazior 				 enum wmi_sta_powersave_param param_id,
2783ca996ec5SMichal Kazior 				 u32 param_value)
2784ca996ec5SMichal Kazior {
2785ca996ec5SMichal Kazior 	struct wmi_sta_powersave_param_cmd *cmd;
2786ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2787ca996ec5SMichal Kazior 	struct sk_buff *skb;
2788ca996ec5SMichal Kazior 
2789ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2790ca996ec5SMichal Kazior 	if (!skb)
2791ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2792ca996ec5SMichal Kazior 
2793ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2794ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD);
2795ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2796ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2797ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2798ca996ec5SMichal Kazior 	cmd->param_id = __cpu_to_le32(param_id);
2799ca996ec5SMichal Kazior 	cmd->param_value = __cpu_to_le32(param_value);
2800ca996ec5SMichal Kazior 
2801ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set sta ps\n");
2802ca996ec5SMichal Kazior 	return skb;
2803ca996ec5SMichal Kazior }
2804ca996ec5SMichal Kazior 
2805ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k * ar,u32 vdev_id,const u8 * mac,enum wmi_ap_ps_peer_param param_id,u32 value)2806ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
2807ca996ec5SMichal Kazior 				enum wmi_ap_ps_peer_param param_id, u32 value)
2808ca996ec5SMichal Kazior {
2809ca996ec5SMichal Kazior 	struct wmi_ap_ps_peer_cmd *cmd;
2810ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2811ca996ec5SMichal Kazior 	struct sk_buff *skb;
2812ca996ec5SMichal Kazior 
2813ca996ec5SMichal Kazior 	if (!mac)
2814ca996ec5SMichal Kazior 		return ERR_PTR(-EINVAL);
2815ca996ec5SMichal Kazior 
28164543ab01SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2817ca996ec5SMichal Kazior 	if (!skb)
2818ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2819ca996ec5SMichal Kazior 
2820ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2821ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD);
2822ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2823ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2824ca996ec5SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2825ca996ec5SMichal Kazior 	cmd->param_id = __cpu_to_le32(param_id);
2826ca996ec5SMichal Kazior 	cmd->param_value = __cpu_to_le32(value);
2827ca996ec5SMichal Kazior 	ether_addr_copy(cmd->peer_macaddr.addr, mac);
2828ca996ec5SMichal Kazior 
2829ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv ap ps param\n");
2830ca996ec5SMichal Kazior 	return skb;
2831ca996ec5SMichal Kazior }
2832ca996ec5SMichal Kazior 
2833ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k * ar,const struct wmi_scan_chan_list_arg * arg)2834ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
2835ca996ec5SMichal Kazior 				     const struct wmi_scan_chan_list_arg *arg)
2836ca996ec5SMichal Kazior {
2837ca996ec5SMichal Kazior 	struct wmi_tlv_scan_chan_list_cmd *cmd;
2838ca996ec5SMichal Kazior 	struct wmi_channel *ci;
2839ca996ec5SMichal Kazior 	struct wmi_channel_arg *ch;
2840ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2841ca996ec5SMichal Kazior 	struct sk_buff *skb;
2842ca996ec5SMichal Kazior 	size_t chans_len, len;
2843ca996ec5SMichal Kazior 	int i;
2844ca996ec5SMichal Kazior 	void *ptr, *chans;
2845ca996ec5SMichal Kazior 
2846ca996ec5SMichal Kazior 	chans_len = arg->n_channels * (sizeof(*tlv) + sizeof(*ci));
2847ca996ec5SMichal Kazior 	len = (sizeof(*tlv) + sizeof(*cmd)) +
2848ca996ec5SMichal Kazior 	      (sizeof(*tlv) + chans_len);
2849ca996ec5SMichal Kazior 
2850ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
2851ca996ec5SMichal Kazior 	if (!skb)
2852ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2853ca996ec5SMichal Kazior 
2854ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
2855ca996ec5SMichal Kazior 	tlv = ptr;
2856ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD);
2857ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2858ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2859ca996ec5SMichal Kazior 	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
2860ca996ec5SMichal Kazior 
2861ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2862ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
2863ca996ec5SMichal Kazior 
2864ca996ec5SMichal Kazior 	tlv = ptr;
2865ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2866ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(chans_len);
2867ca996ec5SMichal Kazior 	chans = (void *)tlv->value;
2868ca996ec5SMichal Kazior 
2869ca996ec5SMichal Kazior 	for (i = 0; i < arg->n_channels; i++) {
2870ca996ec5SMichal Kazior 		ch = &arg->channels[i];
2871ca996ec5SMichal Kazior 
2872ca996ec5SMichal Kazior 		tlv = chans;
2873ca996ec5SMichal Kazior 		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
2874ca996ec5SMichal Kazior 		tlv->len = __cpu_to_le16(sizeof(*ci));
2875ca996ec5SMichal Kazior 		ci = (void *)tlv->value;
2876ca996ec5SMichal Kazior 
2877795def8bSLei Wang 		ath10k_wmi_put_wmi_channel(ar, ci, ch);
2878ca996ec5SMichal Kazior 
2879ca996ec5SMichal Kazior 		chans += sizeof(*tlv);
2880ca996ec5SMichal Kazior 		chans += sizeof(*ci);
2881ca996ec5SMichal Kazior 	}
2882ca996ec5SMichal Kazior 
2883ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2884ca996ec5SMichal Kazior 	ptr += chans_len;
2885ca996ec5SMichal Kazior 
2886ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan chan list\n");
2887ca996ec5SMichal Kazior 	return skb;
2888ca996ec5SMichal Kazior }
2889ca996ec5SMichal Kazior 
2890ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_scan_prob_req_oui(struct ath10k * ar,u32 prob_req_oui)289160e1d0fbSCarl Huang ath10k_wmi_tlv_op_gen_scan_prob_req_oui(struct ath10k *ar, u32 prob_req_oui)
289260e1d0fbSCarl Huang {
289360e1d0fbSCarl Huang 	struct wmi_scan_prob_req_oui_cmd *cmd;
289460e1d0fbSCarl Huang 	struct wmi_tlv *tlv;
289560e1d0fbSCarl Huang 	struct sk_buff *skb;
289660e1d0fbSCarl Huang 
289760e1d0fbSCarl Huang 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
289860e1d0fbSCarl Huang 	if (!skb)
289960e1d0fbSCarl Huang 		return ERR_PTR(-ENOMEM);
290060e1d0fbSCarl Huang 
290160e1d0fbSCarl Huang 	tlv = (void *)skb->data;
290260e1d0fbSCarl Huang 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_PROB_REQ_OUI_CMD);
290360e1d0fbSCarl Huang 	tlv->len = __cpu_to_le16(sizeof(*cmd));
290460e1d0fbSCarl Huang 	cmd = (void *)tlv->value;
290560e1d0fbSCarl Huang 	cmd->prob_req_oui = __cpu_to_le32(prob_req_oui);
290660e1d0fbSCarl Huang 
290760e1d0fbSCarl Huang 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan prob req oui\n");
290860e1d0fbSCarl Huang 	return skb;
290960e1d0fbSCarl Huang }
291060e1d0fbSCarl Huang 
291160e1d0fbSCarl Huang static struct sk_buff *
ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k * ar,u32 vdev_id,const void * bcn,size_t bcn_len,u32 bcn_paddr,bool dtim_zero,bool deliver_cab)29129ad50182SMichal Kazior ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
29139ad50182SMichal Kazior 				 const void *bcn, size_t bcn_len,
29149ad50182SMichal Kazior 				 u32 bcn_paddr, bool dtim_zero,
29159ad50182SMichal Kazior 				 bool deliver_cab)
29169ad50182SMichal Kazior 
2917ca996ec5SMichal Kazior {
2918ca996ec5SMichal Kazior 	struct wmi_bcn_tx_ref_cmd *cmd;
2919ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2920ca996ec5SMichal Kazior 	struct sk_buff *skb;
2921ca996ec5SMichal Kazior 	struct ieee80211_hdr *hdr;
2922ca996ec5SMichal Kazior 	u16 fc;
2923ca996ec5SMichal Kazior 
2924ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2925ca996ec5SMichal Kazior 	if (!skb)
2926ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2927ca996ec5SMichal Kazior 
29289ad50182SMichal Kazior 	hdr = (struct ieee80211_hdr *)bcn;
2929ca996ec5SMichal Kazior 	fc = le16_to_cpu(hdr->frame_control);
2930ca996ec5SMichal Kazior 
2931ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
2932ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD);
2933ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2934ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
29359ad50182SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
29369ad50182SMichal Kazior 	cmd->data_len = __cpu_to_le32(bcn_len);
29379ad50182SMichal Kazior 	cmd->data_ptr = __cpu_to_le32(bcn_paddr);
2938ca996ec5SMichal Kazior 	cmd->msdu_id = 0;
2939ca996ec5SMichal Kazior 	cmd->frame_control = __cpu_to_le32(fc);
2940ca996ec5SMichal Kazior 	cmd->flags = 0;
2941ca996ec5SMichal Kazior 
29429ad50182SMichal Kazior 	if (dtim_zero)
2943ca996ec5SMichal Kazior 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
2944ca996ec5SMichal Kazior 
29459ad50182SMichal Kazior 	if (deliver_cab)
2946ca996ec5SMichal Kazior 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
2947ca996ec5SMichal Kazior 
2948ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n");
2949ca996ec5SMichal Kazior 	return skb;
2950ca996ec5SMichal Kazior }
2951ca996ec5SMichal Kazior 
2952ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k * ar,const struct wmi_wmm_params_all_arg * arg)2953ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
29545e752e42SMichal Kazior 				   const struct wmi_wmm_params_all_arg *arg)
2955ca996ec5SMichal Kazior {
2956ca996ec5SMichal Kazior 	struct wmi_tlv_pdev_set_wmm_cmd *cmd;
2957ca996ec5SMichal Kazior 	struct wmi_wmm_params *wmm;
2958ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2959ca996ec5SMichal Kazior 	struct sk_buff *skb;
2960ca996ec5SMichal Kazior 	size_t len;
2961ca996ec5SMichal Kazior 	void *ptr;
2962ca996ec5SMichal Kazior 
2963ca996ec5SMichal Kazior 	len = (sizeof(*tlv) + sizeof(*cmd)) +
2964ca996ec5SMichal Kazior 	      (4 * (sizeof(*tlv) + sizeof(*wmm)));
2965ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
2966ca996ec5SMichal Kazior 	if (!skb)
2967ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
2968ca996ec5SMichal Kazior 
2969ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
2970ca996ec5SMichal Kazior 
2971ca996ec5SMichal Kazior 	tlv = ptr;
2972ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD);
2973ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2974ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
2975ca996ec5SMichal Kazior 
2976ca996ec5SMichal Kazior 	/* nothing to set here */
2977ca996ec5SMichal Kazior 
2978ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
2979ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
2980ca996ec5SMichal Kazior 
2981ca996ec5SMichal Kazior 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be);
2982ca996ec5SMichal Kazior 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk);
2983ca996ec5SMichal Kazior 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi);
2984ca996ec5SMichal Kazior 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo);
2985ca996ec5SMichal Kazior 
2986ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set wmm\n");
2987ca996ec5SMichal Kazior 	return skb;
2988ca996ec5SMichal Kazior }
2989ca996ec5SMichal Kazior 
2990ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_request_stats(struct ath10k * ar,u32 stats_mask)2991de23d3efSMichal Kazior ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
2992ca996ec5SMichal Kazior {
2993ca996ec5SMichal Kazior 	struct wmi_request_stats_cmd *cmd;
2994ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
2995ca996ec5SMichal Kazior 	struct sk_buff *skb;
2996ca996ec5SMichal Kazior 
2997ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2998ca996ec5SMichal Kazior 	if (!skb)
2999ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
3000ca996ec5SMichal Kazior 
3001ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
3002ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
3003ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3004ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
3005de23d3efSMichal Kazior 	cmd->stats_id = __cpu_to_le32(stats_mask);
3006ca996ec5SMichal Kazior 
3007ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
3008ca996ec5SMichal Kazior 	return skb;
3009ca996ec5SMichal Kazior }
3010ca996ec5SMichal Kazior 
30110f7cb268SWen Gong static struct sk_buff *
ath10k_wmi_tlv_op_gen_request_peer_stats_info(struct ath10k * ar,u32 vdev_id,enum wmi_peer_stats_info_request_type type,u8 * addr,u32 reset)30120f7cb268SWen Gong ath10k_wmi_tlv_op_gen_request_peer_stats_info(struct ath10k *ar,
30130f7cb268SWen Gong 					      u32 vdev_id,
30140f7cb268SWen Gong 					      enum wmi_peer_stats_info_request_type type,
30150f7cb268SWen Gong 					      u8 *addr,
30160f7cb268SWen Gong 					      u32 reset)
30170f7cb268SWen Gong {
30180f7cb268SWen Gong 	struct wmi_tlv_request_peer_stats_info *cmd;
30190f7cb268SWen Gong 	struct wmi_tlv *tlv;
30200f7cb268SWen Gong 	struct sk_buff *skb;
30210f7cb268SWen Gong 
30220f7cb268SWen Gong 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
30230f7cb268SWen Gong 	if (!skb)
30240f7cb268SWen Gong 		return ERR_PTR(-ENOMEM);
30250f7cb268SWen Gong 
30260f7cb268SWen Gong 	tlv = (void *)skb->data;
30270f7cb268SWen Gong 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_PEER_STATS_INFO_CMD);
30280f7cb268SWen Gong 	tlv->len = __cpu_to_le16(sizeof(*cmd));
30290f7cb268SWen Gong 	cmd = (void *)tlv->value;
30300f7cb268SWen Gong 	cmd->vdev_id = __cpu_to_le32(vdev_id);
30310f7cb268SWen Gong 	cmd->request_type = __cpu_to_le32(type);
30320f7cb268SWen Gong 
30330f7cb268SWen Gong 	if (type == WMI_REQUEST_ONE_PEER_STATS_INFO)
30340f7cb268SWen Gong 		ether_addr_copy(cmd->peer_macaddr.addr, addr);
30350f7cb268SWen Gong 
3036e47210f7SWen Gong 	cmd->reset_after_request = __cpu_to_le32(reset);
30370f7cb268SWen Gong 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request peer stats info\n");
30380f7cb268SWen Gong 	return skb;
30390f7cb268SWen Gong }
30400f7cb268SWen Gong 
3041dc405152SRakesh Pillai static int
ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k * ar,struct sk_buff * msdu)3042c730c477SRakesh Pillai ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
3043c730c477SRakesh Pillai 				       struct sk_buff *msdu)
3044c730c477SRakesh Pillai {
3045c730c477SRakesh Pillai 	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
3046*e15d84b3SManikanta Pubbisetty 	struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
3047c730c477SRakesh Pillai 	struct ath10k_wmi *wmi = &ar->wmi;
3048c730c477SRakesh Pillai 
3049*e15d84b3SManikanta Pubbisetty 	spin_lock_bh(&ar->data_lock);
3050*e15d84b3SManikanta Pubbisetty 	pkt_addr = idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
3051*e15d84b3SManikanta Pubbisetty 	spin_unlock_bh(&ar->data_lock);
3052*e15d84b3SManikanta Pubbisetty 
3053*e15d84b3SManikanta Pubbisetty 	kfree(pkt_addr);
3054c730c477SRakesh Pillai 
3055c730c477SRakesh Pillai 	return 0;
3056c730c477SRakesh Pillai }
3057c730c477SRakesh Pillai 
3058c730c477SRakesh Pillai static int
ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k * ar,struct sk_buff * skb,dma_addr_t paddr)3059dc405152SRakesh Pillai ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
3060dc405152SRakesh Pillai 				 dma_addr_t paddr)
3061dc405152SRakesh Pillai {
3062dc405152SRakesh Pillai 	struct ath10k_wmi *wmi = &ar->wmi;
3063dc405152SRakesh Pillai 	struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
3064dc405152SRakesh Pillai 	int ret;
3065dc405152SRakesh Pillai 
3066dc405152SRakesh Pillai 	pkt_addr = kmalloc(sizeof(*pkt_addr), GFP_ATOMIC);
3067dc405152SRakesh Pillai 	if (!pkt_addr)
3068dc405152SRakesh Pillai 		return -ENOMEM;
3069dc405152SRakesh Pillai 
3070dc405152SRakesh Pillai 	pkt_addr->vaddr = skb;
3071dc405152SRakesh Pillai 	pkt_addr->paddr = paddr;
3072dc405152SRakesh Pillai 
3073dc405152SRakesh Pillai 	spin_lock_bh(&ar->data_lock);
3074dc405152SRakesh Pillai 	ret = idr_alloc(&wmi->mgmt_pending_tx, pkt_addr, 0,
3075dc405152SRakesh Pillai 			wmi->mgmt_max_num_pending_tx, GFP_ATOMIC);
3076dc405152SRakesh Pillai 	spin_unlock_bh(&ar->data_lock);
3077dc405152SRakesh Pillai 
3078dc405152SRakesh Pillai 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx alloc msdu_id ret %d\n", ret);
3079dc405152SRakesh Pillai 	return ret;
3080dc405152SRakesh Pillai }
3081dc405152SRakesh Pillai 
3082ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k * ar,struct sk_buff * msdu,dma_addr_t paddr)308338a1390eSRakesh Pillai ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
308438a1390eSRakesh Pillai 				   dma_addr_t paddr)
30851807da49SRakesh Pillai {
30861807da49SRakesh Pillai 	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
30871807da49SRakesh Pillai 	struct wmi_tlv_mgmt_tx_cmd *cmd;
30881807da49SRakesh Pillai 	struct ieee80211_hdr *hdr;
308938a1390eSRakesh Pillai 	struct ath10k_vif *arvif;
309038a1390eSRakesh Pillai 	u32 buf_len = msdu->len;
309138a1390eSRakesh Pillai 	struct wmi_tlv *tlv;
30921807da49SRakesh Pillai 	struct sk_buff *skb;
3093dc405152SRakesh Pillai 	int len, desc_id;
309438a1390eSRakesh Pillai 	u32 vdev_id;
30951807da49SRakesh Pillai 	void *ptr;
30961807da49SRakesh Pillai 
30971807da49SRakesh Pillai 	if (!cb->vif)
30981807da49SRakesh Pillai 		return ERR_PTR(-EINVAL);
30991807da49SRakesh Pillai 
31001807da49SRakesh Pillai 	hdr = (struct ieee80211_hdr *)msdu->data;
31011807da49SRakesh Pillai 	arvif = (void *)cb->vif->drv_priv;
31021807da49SRakesh Pillai 	vdev_id = arvif->vdev_id;
31031807da49SRakesh Pillai 
31044b816f17SAbhishek Ambure 	if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
31054b816f17SAbhishek Ambure 			 (!(ieee80211_is_nullfunc(hdr->frame_control) ||
31064b816f17SAbhishek Ambure 			 ieee80211_is_qos_nullfunc(hdr->frame_control)))))
31071807da49SRakesh Pillai 		return ERR_PTR(-EINVAL);
31081807da49SRakesh Pillai 
31091807da49SRakesh Pillai 	len = sizeof(*cmd) + 2 * sizeof(*tlv);
31101807da49SRakesh Pillai 
31111807da49SRakesh Pillai 	if ((ieee80211_is_action(hdr->frame_control) ||
31121807da49SRakesh Pillai 	     ieee80211_is_deauth(hdr->frame_control) ||
31131807da49SRakesh Pillai 	     ieee80211_is_disassoc(hdr->frame_control)) &&
311442f1bc43SRakesh Pillai 	     ieee80211_has_protected(hdr->frame_control)) {
311542f1bc43SRakesh Pillai 		skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
31161807da49SRakesh Pillai 		buf_len += IEEE80211_CCMP_MIC_LEN;
311742f1bc43SRakesh Pillai 	}
31181807da49SRakesh Pillai 
31191807da49SRakesh Pillai 	buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN);
31201807da49SRakesh Pillai 	buf_len = round_up(buf_len, 4);
31211807da49SRakesh Pillai 
31221807da49SRakesh Pillai 	len += buf_len;
31231807da49SRakesh Pillai 	len = round_up(len, 4);
31241807da49SRakesh Pillai 	skb = ath10k_wmi_alloc_skb(ar, len);
31251807da49SRakesh Pillai 	if (!skb)
31261807da49SRakesh Pillai 		return ERR_PTR(-ENOMEM);
31271807da49SRakesh Pillai 
3128dc405152SRakesh Pillai 	desc_id = ath10k_wmi_mgmt_tx_alloc_msdu_id(ar, msdu, paddr);
3129dc405152SRakesh Pillai 	if (desc_id < 0)
3130dc405152SRakesh Pillai 		goto err_free_skb;
3131dc405152SRakesh Pillai 
3132c730c477SRakesh Pillai 	cb->msdu_id = desc_id;
3133c730c477SRakesh Pillai 
31341807da49SRakesh Pillai 	ptr = (void *)skb->data;
31351807da49SRakesh Pillai 	tlv = ptr;
31361807da49SRakesh Pillai 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
31371807da49SRakesh Pillai 	tlv->len = __cpu_to_le16(sizeof(*cmd));
31381807da49SRakesh Pillai 	cmd = (void *)tlv->value;
31391807da49SRakesh Pillai 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3140dc405152SRakesh Pillai 	cmd->desc_id = __cpu_to_le32(desc_id);
31411807da49SRakesh Pillai 	cmd->chanfreq = 0;
31421807da49SRakesh Pillai 	cmd->buf_len = __cpu_to_le32(buf_len);
31431807da49SRakesh Pillai 	cmd->frame_len = __cpu_to_le32(msdu->len);
314438a1390eSRakesh Pillai 	cmd->paddr = __cpu_to_le64(paddr);
31451807da49SRakesh Pillai 
31461807da49SRakesh Pillai 	ptr += sizeof(*tlv);
31471807da49SRakesh Pillai 	ptr += sizeof(*cmd);
31481807da49SRakesh Pillai 
31491807da49SRakesh Pillai 	tlv = ptr;
31501807da49SRakesh Pillai 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
31511807da49SRakesh Pillai 	tlv->len = __cpu_to_le16(buf_len);
31521807da49SRakesh Pillai 
31531807da49SRakesh Pillai 	ptr += sizeof(*tlv);
31541807da49SRakesh Pillai 	memcpy(ptr, msdu->data, buf_len);
31551807da49SRakesh Pillai 
31561807da49SRakesh Pillai 	return skb;
3157dc405152SRakesh Pillai 
3158dc405152SRakesh Pillai err_free_skb:
3159dc405152SRakesh Pillai 	dev_kfree_skb(skb);
3160dc405152SRakesh Pillai 	return ERR_PTR(desc_id);
31611807da49SRakesh Pillai }
31621807da49SRakesh Pillai 
31631807da49SRakesh Pillai static struct sk_buff *
ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k * ar,enum wmi_force_fw_hang_type type,u32 delay_ms)3164ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
3165ca996ec5SMichal Kazior 				    enum wmi_force_fw_hang_type type,
3166ca996ec5SMichal Kazior 				    u32 delay_ms)
3167ca996ec5SMichal Kazior {
3168ca996ec5SMichal Kazior 	struct wmi_force_fw_hang_cmd *cmd;
3169ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
3170ca996ec5SMichal Kazior 	struct sk_buff *skb;
3171ca996ec5SMichal Kazior 
3172ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3173ca996ec5SMichal Kazior 	if (!skb)
3174ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
3175ca996ec5SMichal Kazior 
3176ca996ec5SMichal Kazior 	tlv = (void *)skb->data;
3177ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD);
3178ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3179ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
3180ca996ec5SMichal Kazior 	cmd->type = __cpu_to_le32(type);
3181ca996ec5SMichal Kazior 	cmd->delay_ms = __cpu_to_le32(delay_ms);
3182ca996ec5SMichal Kazior 
3183ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv force fw hang\n");
3184ca996ec5SMichal Kazior 	return skb;
3185ca996ec5SMichal Kazior }
3186ca996ec5SMichal Kazior 
3187ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k * ar,u64 module_enable,u32 log_level)3188afcbc82cSMaharaja Kennadyrajan ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u64 module_enable,
31891e3c43a7SKalle Valo 				 u32 log_level)
31901e3c43a7SKalle Valo {
3191ca996ec5SMichal Kazior 	struct wmi_tlv_dbglog_cmd *cmd;
3192ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
3193ca996ec5SMichal Kazior 	struct sk_buff *skb;
3194ca996ec5SMichal Kazior 	size_t len, bmap_len;
3195ca996ec5SMichal Kazior 	u32 value;
3196ca996ec5SMichal Kazior 	void *ptr;
3197ca996ec5SMichal Kazior 
3198ca996ec5SMichal Kazior 	if (module_enable) {
3199ca996ec5SMichal Kazior 		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
3200ca996ec5SMichal Kazior 				module_enable,
3201ca996ec5SMichal Kazior 				WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE);
3202ca996ec5SMichal Kazior 	} else {
3203ca996ec5SMichal Kazior 		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
3204ca996ec5SMichal Kazior 				WMI_TLV_DBGLOG_ALL_MODULES,
3205ca996ec5SMichal Kazior 				WMI_TLV_DBGLOG_LOG_LEVEL_WARN);
3206ca996ec5SMichal Kazior 	}
3207ca996ec5SMichal Kazior 
3208ca996ec5SMichal Kazior 	bmap_len = 0;
3209ca996ec5SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd) + sizeof(*tlv) + bmap_len;
3210ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
3211ca996ec5SMichal Kazior 	if (!skb)
3212ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
3213ca996ec5SMichal Kazior 
3214ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
3215ca996ec5SMichal Kazior 
3216ca996ec5SMichal Kazior 	tlv = ptr;
3217ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD);
3218ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3219ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
3220ca996ec5SMichal Kazior 	cmd->param = __cpu_to_le32(WMI_TLV_DBGLOG_PARAM_LOG_LEVEL);
3221ca996ec5SMichal Kazior 	cmd->value = __cpu_to_le32(value);
3222ca996ec5SMichal Kazior 
3223ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
3224ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
3225ca996ec5SMichal Kazior 
3226ca996ec5SMichal Kazior 	tlv = ptr;
3227ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3228ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(bmap_len);
3229ca996ec5SMichal Kazior 
3230ca996ec5SMichal Kazior 	/* nothing to do here */
3231ca996ec5SMichal Kazior 
3232ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
3233ca996ec5SMichal Kazior 	ptr += sizeof(bmap_len);
3234ca996ec5SMichal Kazior 
3235ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv dbglog value 0x%08x\n", value);
3236ca996ec5SMichal Kazior 	return skb;
3237ca996ec5SMichal Kazior }
3238ca996ec5SMichal Kazior 
3239ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k * ar,u32 filter)3240ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
3241ca996ec5SMichal Kazior {
3242ca996ec5SMichal Kazior 	struct wmi_tlv_pktlog_enable *cmd;
3243ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
3244ca996ec5SMichal Kazior 	struct sk_buff *skb;
3245ca996ec5SMichal Kazior 	void *ptr;
3246ca996ec5SMichal Kazior 	size_t len;
3247ca996ec5SMichal Kazior 
3248ca996ec5SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd);
3249ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
3250ca996ec5SMichal Kazior 	if (!skb)
3251ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
3252ca996ec5SMichal Kazior 
3253ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
3254ca996ec5SMichal Kazior 	tlv = ptr;
3255ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD);
3256ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3257ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
3258ca996ec5SMichal Kazior 	cmd->filter = __cpu_to_le32(filter);
3259ca996ec5SMichal Kazior 
3260ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
3261ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
3262ca996ec5SMichal Kazior 
3263ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog enable filter 0x%08x\n",
3264ca996ec5SMichal Kazior 		   filter);
3265ca996ec5SMichal Kazior 	return skb;
3266ca996ec5SMichal Kazior }
3267ca996ec5SMichal Kazior 
3268ca996ec5SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_get_temperature(struct ath10k * ar)3269e98199a8SRyan Hsu ath10k_wmi_tlv_op_gen_pdev_get_temperature(struct ath10k *ar)
3270e98199a8SRyan Hsu {
3271e98199a8SRyan Hsu 	struct wmi_tlv_pdev_get_temp_cmd *cmd;
3272e98199a8SRyan Hsu 	struct wmi_tlv *tlv;
3273e98199a8SRyan Hsu 	struct sk_buff *skb;
3274e98199a8SRyan Hsu 
3275e98199a8SRyan Hsu 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3276e98199a8SRyan Hsu 	if (!skb)
3277e98199a8SRyan Hsu 		return ERR_PTR(-ENOMEM);
3278e98199a8SRyan Hsu 
3279e98199a8SRyan Hsu 	tlv = (void *)skb->data;
3280e98199a8SRyan Hsu 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_GET_TEMPERATURE_CMD);
3281e98199a8SRyan Hsu 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3282e98199a8SRyan Hsu 	cmd = (void *)tlv->value;
3283e98199a8SRyan Hsu 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev get temperature tlv\n");
3284e98199a8SRyan Hsu 	return skb;
3285e98199a8SRyan Hsu }
3286e98199a8SRyan Hsu 
3287e98199a8SRyan Hsu static struct sk_buff *
ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k * ar)3288ca996ec5SMichal Kazior ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar)
3289ca996ec5SMichal Kazior {
3290ca996ec5SMichal Kazior 	struct wmi_tlv_pktlog_disable *cmd;
3291ca996ec5SMichal Kazior 	struct wmi_tlv *tlv;
3292ca996ec5SMichal Kazior 	struct sk_buff *skb;
3293ca996ec5SMichal Kazior 	void *ptr;
3294ca996ec5SMichal Kazior 	size_t len;
3295ca996ec5SMichal Kazior 
3296ca996ec5SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd);
3297ca996ec5SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
3298ca996ec5SMichal Kazior 	if (!skb)
3299ca996ec5SMichal Kazior 		return ERR_PTR(-ENOMEM);
3300ca996ec5SMichal Kazior 
3301ca996ec5SMichal Kazior 	ptr = (void *)skb->data;
3302ca996ec5SMichal Kazior 	tlv = ptr;
3303ca996ec5SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD);
3304ca996ec5SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3305ca996ec5SMichal Kazior 	cmd = (void *)tlv->value;
3306ca996ec5SMichal Kazior 
3307ca996ec5SMichal Kazior 	ptr += sizeof(*tlv);
3308ca996ec5SMichal Kazior 	ptr += sizeof(*cmd);
3309ca996ec5SMichal Kazior 
3310ca996ec5SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog disable\n");
3311ca996ec5SMichal Kazior 	return skb;
3312ca996ec5SMichal Kazior }
3313ca996ec5SMichal Kazior 
3314be9ce9d8SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k * ar,u32 vdev_id,u32 tim_ie_offset,struct sk_buff * bcn,u32 prb_caps,u32 prb_erp,void * prb_ies,size_t prb_ies_len)3315be9ce9d8SMichal Kazior ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id,
3316be9ce9d8SMichal Kazior 			       u32 tim_ie_offset, struct sk_buff *bcn,
3317be9ce9d8SMichal Kazior 			       u32 prb_caps, u32 prb_erp, void *prb_ies,
3318be9ce9d8SMichal Kazior 			       size_t prb_ies_len)
3319be9ce9d8SMichal Kazior {
3320be9ce9d8SMichal Kazior 	struct wmi_tlv_bcn_tmpl_cmd *cmd;
3321be9ce9d8SMichal Kazior 	struct wmi_tlv_bcn_prb_info *info;
3322be9ce9d8SMichal Kazior 	struct wmi_tlv *tlv;
3323be9ce9d8SMichal Kazior 	struct sk_buff *skb;
3324be9ce9d8SMichal Kazior 	void *ptr;
3325be9ce9d8SMichal Kazior 	size_t len;
3326be9ce9d8SMichal Kazior 
3327be9ce9d8SMichal Kazior 	if (WARN_ON(prb_ies_len > 0 && !prb_ies))
3328be9ce9d8SMichal Kazior 		return ERR_PTR(-EINVAL);
3329be9ce9d8SMichal Kazior 
3330be9ce9d8SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd) +
3331be9ce9d8SMichal Kazior 	      sizeof(*tlv) + sizeof(*info) + prb_ies_len +
3332be9ce9d8SMichal Kazior 	      sizeof(*tlv) + roundup(bcn->len, 4);
3333be9ce9d8SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
3334be9ce9d8SMichal Kazior 	if (!skb)
3335be9ce9d8SMichal Kazior 		return ERR_PTR(-ENOMEM);
3336be9ce9d8SMichal Kazior 
3337be9ce9d8SMichal Kazior 	ptr = (void *)skb->data;
3338be9ce9d8SMichal Kazior 	tlv = ptr;
3339be9ce9d8SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD);
3340be9ce9d8SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3341be9ce9d8SMichal Kazior 	cmd = (void *)tlv->value;
3342be9ce9d8SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3343be9ce9d8SMichal Kazior 	cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset);
3344be9ce9d8SMichal Kazior 	cmd->buf_len = __cpu_to_le32(bcn->len);
3345be9ce9d8SMichal Kazior 
3346be9ce9d8SMichal Kazior 	ptr += sizeof(*tlv);
3347be9ce9d8SMichal Kazior 	ptr += sizeof(*cmd);
3348be9ce9d8SMichal Kazior 
3349be9ce9d8SMichal Kazior 	/* FIXME: prb_ies_len should be probably aligned to 4byte boundary but
3350be9ce9d8SMichal Kazior 	 * then it is then impossible to pass original ie len.
3351be9ce9d8SMichal Kazior 	 * This chunk is not used yet so if setting probe resp template yields
3352be9ce9d8SMichal Kazior 	 * problems with beaconing or crashes firmware look here.
3353be9ce9d8SMichal Kazior 	 */
3354be9ce9d8SMichal Kazior 	tlv = ptr;
3355be9ce9d8SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
3356be9ce9d8SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len);
3357be9ce9d8SMichal Kazior 	info = (void *)tlv->value;
3358be9ce9d8SMichal Kazior 	info->caps = __cpu_to_le32(prb_caps);
3359be9ce9d8SMichal Kazior 	info->erp = __cpu_to_le32(prb_erp);
3360be9ce9d8SMichal Kazior 	memcpy(info->ies, prb_ies, prb_ies_len);
3361be9ce9d8SMichal Kazior 
3362be9ce9d8SMichal Kazior 	ptr += sizeof(*tlv);
3363be9ce9d8SMichal Kazior 	ptr += sizeof(*info);
3364be9ce9d8SMichal Kazior 	ptr += prb_ies_len;
3365be9ce9d8SMichal Kazior 
3366be9ce9d8SMichal Kazior 	tlv = ptr;
3367be9ce9d8SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3368be9ce9d8SMichal Kazior 	tlv->len = __cpu_to_le16(roundup(bcn->len, 4));
3369be9ce9d8SMichal Kazior 	memcpy(tlv->value, bcn->data, bcn->len);
3370be9ce9d8SMichal Kazior 
3371be9ce9d8SMichal Kazior 	/* FIXME: Adjust TSF? */
3372be9ce9d8SMichal Kazior 
3373be9ce9d8SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n",
3374be9ce9d8SMichal Kazior 		   vdev_id);
3375be9ce9d8SMichal Kazior 	return skb;
3376be9ce9d8SMichal Kazior }
3377be9ce9d8SMichal Kazior 
33784c4955feSMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k * ar,u32 vdev_id,struct sk_buff * prb)33794c4955feSMichal Kazior ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id,
33804c4955feSMichal Kazior 			       struct sk_buff *prb)
33814c4955feSMichal Kazior {
33824c4955feSMichal Kazior 	struct wmi_tlv_prb_tmpl_cmd *cmd;
33834c4955feSMichal Kazior 	struct wmi_tlv_bcn_prb_info *info;
33844c4955feSMichal Kazior 	struct wmi_tlv *tlv;
33854c4955feSMichal Kazior 	struct sk_buff *skb;
33864c4955feSMichal Kazior 	void *ptr;
33874c4955feSMichal Kazior 	size_t len;
33884c4955feSMichal Kazior 
33894c4955feSMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd) +
33904c4955feSMichal Kazior 	      sizeof(*tlv) + sizeof(*info) +
33914c4955feSMichal Kazior 	      sizeof(*tlv) + roundup(prb->len, 4);
33924c4955feSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
33934c4955feSMichal Kazior 	if (!skb)
33944c4955feSMichal Kazior 		return ERR_PTR(-ENOMEM);
33954c4955feSMichal Kazior 
33964c4955feSMichal Kazior 	ptr = (void *)skb->data;
33974c4955feSMichal Kazior 	tlv = ptr;
33984c4955feSMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD);
33994c4955feSMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
34004c4955feSMichal Kazior 	cmd = (void *)tlv->value;
34014c4955feSMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
34024c4955feSMichal Kazior 	cmd->buf_len = __cpu_to_le32(prb->len);
34034c4955feSMichal Kazior 
34044c4955feSMichal Kazior 	ptr += sizeof(*tlv);
34054c4955feSMichal Kazior 	ptr += sizeof(*cmd);
34064c4955feSMichal Kazior 
34074c4955feSMichal Kazior 	tlv = ptr;
34084c4955feSMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
34094c4955feSMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*info));
34104c4955feSMichal Kazior 	info = (void *)tlv->value;
34114c4955feSMichal Kazior 	info->caps = 0;
34124c4955feSMichal Kazior 	info->erp = 0;
34134c4955feSMichal Kazior 
34144c4955feSMichal Kazior 	ptr += sizeof(*tlv);
34154c4955feSMichal Kazior 	ptr += sizeof(*info);
34164c4955feSMichal Kazior 
34174c4955feSMichal Kazior 	tlv = ptr;
34184c4955feSMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
34194c4955feSMichal Kazior 	tlv->len = __cpu_to_le16(roundup(prb->len, 4));
34204c4955feSMichal Kazior 	memcpy(tlv->value, prb->data, prb->len);
34214c4955feSMichal Kazior 
34224c4955feSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n",
34234c4955feSMichal Kazior 		   vdev_id);
34244c4955feSMichal Kazior 	return skb;
34254c4955feSMichal Kazior }
34264c4955feSMichal Kazior 
3427369242b4SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k * ar,u32 vdev_id,const u8 * p2p_ie)3428369242b4SMichal Kazior ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id,
3429369242b4SMichal Kazior 				    const u8 *p2p_ie)
3430369242b4SMichal Kazior {
3431369242b4SMichal Kazior 	struct wmi_tlv_p2p_go_bcn_ie *cmd;
3432369242b4SMichal Kazior 	struct wmi_tlv *tlv;
3433369242b4SMichal Kazior 	struct sk_buff *skb;
3434369242b4SMichal Kazior 	void *ptr;
3435369242b4SMichal Kazior 	size_t len;
3436369242b4SMichal Kazior 
3437369242b4SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd) +
3438369242b4SMichal Kazior 	      sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4);
3439369242b4SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
3440369242b4SMichal Kazior 	if (!skb)
3441369242b4SMichal Kazior 		return ERR_PTR(-ENOMEM);
3442369242b4SMichal Kazior 
3443369242b4SMichal Kazior 	ptr = (void *)skb->data;
3444369242b4SMichal Kazior 	tlv = ptr;
3445369242b4SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE);
3446369242b4SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3447369242b4SMichal Kazior 	cmd = (void *)tlv->value;
3448369242b4SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3449369242b4SMichal Kazior 	cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2);
3450369242b4SMichal Kazior 
3451369242b4SMichal Kazior 	ptr += sizeof(*tlv);
3452369242b4SMichal Kazior 	ptr += sizeof(*cmd);
3453369242b4SMichal Kazior 
3454369242b4SMichal Kazior 	tlv = ptr;
3455369242b4SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3456369242b4SMichal Kazior 	tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4));
3457369242b4SMichal Kazior 	memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2);
3458369242b4SMichal Kazior 
3459369242b4SMichal Kazior 	ptr += sizeof(*tlv);
3460369242b4SMichal Kazior 	ptr += roundup(p2p_ie[1] + 2, 4);
3461369242b4SMichal Kazior 
3462369242b4SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n",
3463369242b4SMichal Kazior 		   vdev_id);
3464369242b4SMichal Kazior 	return skb;
3465369242b4SMichal Kazior }
3466369242b4SMichal Kazior 
3467f5431e87SJanusz Dziedzic static struct sk_buff *
ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k * ar,u32 vdev_id,enum wmi_tdls_state state)3468ad45c888SMarek Puzyniak ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
3469ad45c888SMarek Puzyniak 					   enum wmi_tdls_state state)
3470ad45c888SMarek Puzyniak {
3471ad45c888SMarek Puzyniak 	struct wmi_tdls_set_state_cmd *cmd;
3472ad45c888SMarek Puzyniak 	struct wmi_tlv *tlv;
3473ad45c888SMarek Puzyniak 	struct sk_buff *skb;
3474ad45c888SMarek Puzyniak 	void *ptr;
3475ad45c888SMarek Puzyniak 	size_t len;
3476ad45c888SMarek Puzyniak 	/* Set to options from wmi_tlv_tdls_options,
3477ad45c888SMarek Puzyniak 	 * for now none of them are enabled.
3478ad45c888SMarek Puzyniak 	 */
3479ad45c888SMarek Puzyniak 	u32 options = 0;
3480ad45c888SMarek Puzyniak 
3481802ca335SYingying Tang 	if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
3482802ca335SYingying Tang 		options |=  WMI_TLV_TDLS_BUFFER_STA_EN;
3483802ca335SYingying Tang 
34844c9f8d11SYingying Tang 	/* WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL means firm will handle TDLS
34854c9f8d11SYingying Tang 	 * link inactivity detecting logic.
34864c9f8d11SYingying Tang 	 */
34874c9f8d11SYingying Tang 	if (state == WMI_TDLS_ENABLE_ACTIVE)
34884c9f8d11SYingying Tang 		state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
34894c9f8d11SYingying Tang 
3490ad45c888SMarek Puzyniak 	len = sizeof(*tlv) + sizeof(*cmd);
3491ad45c888SMarek Puzyniak 	skb = ath10k_wmi_alloc_skb(ar, len);
3492ad45c888SMarek Puzyniak 	if (!skb)
3493ad45c888SMarek Puzyniak 		return ERR_PTR(-ENOMEM);
3494ad45c888SMarek Puzyniak 
3495ad45c888SMarek Puzyniak 	ptr = (void *)skb->data;
3496ad45c888SMarek Puzyniak 	tlv = ptr;
3497ad45c888SMarek Puzyniak 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_SET_STATE_CMD);
3498ad45c888SMarek Puzyniak 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3499ad45c888SMarek Puzyniak 
3500ad45c888SMarek Puzyniak 	cmd = (void *)tlv->value;
3501ad45c888SMarek Puzyniak 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3502ad45c888SMarek Puzyniak 	cmd->state = __cpu_to_le32(state);
3503ad45c888SMarek Puzyniak 	cmd->notification_interval_ms = __cpu_to_le32(5000);
3504ad45c888SMarek Puzyniak 	cmd->tx_discovery_threshold = __cpu_to_le32(100);
3505ad45c888SMarek Puzyniak 	cmd->tx_teardown_threshold = __cpu_to_le32(5);
3506ad45c888SMarek Puzyniak 	cmd->rssi_teardown_threshold = __cpu_to_le32(-75);
3507ad45c888SMarek Puzyniak 	cmd->rssi_delta = __cpu_to_le32(-20);
3508ad45c888SMarek Puzyniak 	cmd->tdls_options = __cpu_to_le32(options);
3509ad45c888SMarek Puzyniak 	cmd->tdls_peer_traffic_ind_window = __cpu_to_le32(2);
3510ad45c888SMarek Puzyniak 	cmd->tdls_peer_traffic_response_timeout_ms = __cpu_to_le32(5000);
3511ad45c888SMarek Puzyniak 	cmd->tdls_puapsd_mask = __cpu_to_le32(0xf);
3512ad45c888SMarek Puzyniak 	cmd->tdls_puapsd_inactivity_time_ms = __cpu_to_le32(0);
3513ad45c888SMarek Puzyniak 	cmd->tdls_puapsd_rx_frame_threshold = __cpu_to_le32(10);
3514ad45c888SMarek Puzyniak 
3515ad45c888SMarek Puzyniak 	ptr += sizeof(*tlv);
3516ad45c888SMarek Puzyniak 	ptr += sizeof(*cmd);
3517ad45c888SMarek Puzyniak 
3518ad45c888SMarek Puzyniak 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv update fw tdls state %d for vdev %i\n",
3519ad45c888SMarek Puzyniak 		   state, vdev_id);
3520ad45c888SMarek Puzyniak 	return skb;
3521ad45c888SMarek Puzyniak }
3522ad45c888SMarek Puzyniak 
ath10k_wmi_tlv_prepare_peer_qos(u8 uapsd_queues,u8 sp)3523ad45c888SMarek Puzyniak static u32 ath10k_wmi_tlv_prepare_peer_qos(u8 uapsd_queues, u8 sp)
3524ad45c888SMarek Puzyniak {
3525ad45c888SMarek Puzyniak 	u32 peer_qos = 0;
3526ad45c888SMarek Puzyniak 
3527ad45c888SMarek Puzyniak 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
3528ad45c888SMarek Puzyniak 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VO;
3529ad45c888SMarek Puzyniak 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
3530ad45c888SMarek Puzyniak 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VI;
3531ad45c888SMarek Puzyniak 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
3532ad45c888SMarek Puzyniak 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BK;
3533ad45c888SMarek Puzyniak 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
3534ad45c888SMarek Puzyniak 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BE;
3535ad45c888SMarek Puzyniak 
3536ad45c888SMarek Puzyniak 	peer_qos |= SM(sp, WMI_TLV_TDLS_PEER_SP);
3537ad45c888SMarek Puzyniak 
3538ad45c888SMarek Puzyniak 	return peer_qos;
3539ad45c888SMarek Puzyniak }
3540ad45c888SMarek Puzyniak 
3541ad45c888SMarek Puzyniak static struct sk_buff *
ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k * ar,const struct wmi_tdls_peer_update_cmd_arg * arg,const struct wmi_tdls_peer_capab_arg * cap,const struct wmi_channel_arg * chan_arg)3542ad45c888SMarek Puzyniak ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar,
3543ad45c888SMarek Puzyniak 				       const struct wmi_tdls_peer_update_cmd_arg *arg,
3544ad45c888SMarek Puzyniak 				       const struct wmi_tdls_peer_capab_arg *cap,
3545ad45c888SMarek Puzyniak 				       const struct wmi_channel_arg *chan_arg)
3546ad45c888SMarek Puzyniak {
3547ad45c888SMarek Puzyniak 	struct wmi_tdls_peer_update_cmd *cmd;
3548ad45c888SMarek Puzyniak 	struct wmi_tdls_peer_capab *peer_cap;
3549ad45c888SMarek Puzyniak 	struct wmi_channel *chan;
3550ad45c888SMarek Puzyniak 	struct wmi_tlv *tlv;
3551ad45c888SMarek Puzyniak 	struct sk_buff *skb;
3552ad45c888SMarek Puzyniak 	u32 peer_qos;
3553ad45c888SMarek Puzyniak 	void *ptr;
3554ad45c888SMarek Puzyniak 	int len;
3555ad45c888SMarek Puzyniak 	int i;
3556ad45c888SMarek Puzyniak 
3557ad45c888SMarek Puzyniak 	len = sizeof(*tlv) + sizeof(*cmd) +
3558ad45c888SMarek Puzyniak 	      sizeof(*tlv) + sizeof(*peer_cap) +
3559ad45c888SMarek Puzyniak 	      sizeof(*tlv) + cap->peer_chan_len * sizeof(*chan);
3560ad45c888SMarek Puzyniak 
3561ad45c888SMarek Puzyniak 	skb = ath10k_wmi_alloc_skb(ar, len);
3562ad45c888SMarek Puzyniak 	if (!skb)
3563ad45c888SMarek Puzyniak 		return ERR_PTR(-ENOMEM);
3564ad45c888SMarek Puzyniak 
3565ad45c888SMarek Puzyniak 	ptr = (void *)skb->data;
3566ad45c888SMarek Puzyniak 	tlv = ptr;
3567ad45c888SMarek Puzyniak 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_UPDATE_CMD);
3568ad45c888SMarek Puzyniak 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3569ad45c888SMarek Puzyniak 
3570ad45c888SMarek Puzyniak 	cmd = (void *)tlv->value;
3571ad45c888SMarek Puzyniak 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
3572ad45c888SMarek Puzyniak 	ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
3573ad45c888SMarek Puzyniak 	cmd->peer_state = __cpu_to_le32(arg->peer_state);
3574ad45c888SMarek Puzyniak 
3575ad45c888SMarek Puzyniak 	ptr += sizeof(*tlv);
3576ad45c888SMarek Puzyniak 	ptr += sizeof(*cmd);
3577ad45c888SMarek Puzyniak 
3578ad45c888SMarek Puzyniak 	tlv = ptr;
3579ad45c888SMarek Puzyniak 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_CAPABILITIES);
3580ad45c888SMarek Puzyniak 	tlv->len = __cpu_to_le16(sizeof(*peer_cap));
3581ad45c888SMarek Puzyniak 	peer_cap = (void *)tlv->value;
3582ad45c888SMarek Puzyniak 	peer_qos = ath10k_wmi_tlv_prepare_peer_qos(cap->peer_uapsd_queues,
3583ad45c888SMarek Puzyniak 						   cap->peer_max_sp);
3584ad45c888SMarek Puzyniak 	peer_cap->peer_qos = __cpu_to_le32(peer_qos);
3585ad45c888SMarek Puzyniak 	peer_cap->buff_sta_support = __cpu_to_le32(cap->buff_sta_support);
3586ad45c888SMarek Puzyniak 	peer_cap->off_chan_support = __cpu_to_le32(cap->off_chan_support);
3587ad45c888SMarek Puzyniak 	peer_cap->peer_curr_operclass = __cpu_to_le32(cap->peer_curr_operclass);
3588ad45c888SMarek Puzyniak 	peer_cap->self_curr_operclass = __cpu_to_le32(cap->self_curr_operclass);
3589ad45c888SMarek Puzyniak 	peer_cap->peer_chan_len = __cpu_to_le32(cap->peer_chan_len);
3590ad45c888SMarek Puzyniak 	peer_cap->peer_operclass_len = __cpu_to_le32(cap->peer_operclass_len);
3591ad45c888SMarek Puzyniak 
3592ad45c888SMarek Puzyniak 	for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++)
3593ad45c888SMarek Puzyniak 		peer_cap->peer_operclass[i] = cap->peer_operclass[i];
3594ad45c888SMarek Puzyniak 
3595ad45c888SMarek Puzyniak 	peer_cap->is_peer_responder = __cpu_to_le32(cap->is_peer_responder);
3596ad45c888SMarek Puzyniak 	peer_cap->pref_offchan_num = __cpu_to_le32(cap->pref_offchan_num);
3597ad45c888SMarek Puzyniak 	peer_cap->pref_offchan_bw = __cpu_to_le32(cap->pref_offchan_bw);
3598ad45c888SMarek Puzyniak 
3599ad45c888SMarek Puzyniak 	ptr += sizeof(*tlv);
3600ad45c888SMarek Puzyniak 	ptr += sizeof(*peer_cap);
3601ad45c888SMarek Puzyniak 
3602ad45c888SMarek Puzyniak 	tlv = ptr;
3603ad45c888SMarek Puzyniak 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3604ad45c888SMarek Puzyniak 	tlv->len = __cpu_to_le16(cap->peer_chan_len * sizeof(*chan));
3605ad45c888SMarek Puzyniak 
3606ad45c888SMarek Puzyniak 	ptr += sizeof(*tlv);
3607ad45c888SMarek Puzyniak 
3608ad45c888SMarek Puzyniak 	for (i = 0; i < cap->peer_chan_len; i++) {
3609ad45c888SMarek Puzyniak 		tlv = ptr;
3610ad45c888SMarek Puzyniak 		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
3611ad45c888SMarek Puzyniak 		tlv->len = __cpu_to_le16(sizeof(*chan));
3612ad45c888SMarek Puzyniak 		chan = (void *)tlv->value;
3613795def8bSLei Wang 		ath10k_wmi_put_wmi_channel(ar, chan, &chan_arg[i]);
3614ad45c888SMarek Puzyniak 
3615ad45c888SMarek Puzyniak 		ptr += sizeof(*tlv);
3616ad45c888SMarek Puzyniak 		ptr += sizeof(*chan);
3617ad45c888SMarek Puzyniak 	}
3618ad45c888SMarek Puzyniak 
3619ad45c888SMarek Puzyniak 	ath10k_dbg(ar, ATH10K_DBG_WMI,
3620ad45c888SMarek Puzyniak 		   "wmi tlv tdls peer update vdev %i state %d n_chans %u\n",
3621ad45c888SMarek Puzyniak 		   arg->vdev_id, arg->peer_state, cap->peer_chan_len);
3622ad45c888SMarek Puzyniak 	return skb;
3623ad45c888SMarek Puzyniak }
3624ad45c888SMarek Puzyniak 
3625ad45c888SMarek Puzyniak static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode(struct ath10k * ar,u32 period,u32 duration,u32 next_offset,u32 enabled)3626cfb353c0SYu Wang ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period,
3627cfb353c0SYu Wang 					  u32 duration, u32 next_offset,
3628cfb353c0SYu Wang 					  u32 enabled)
3629cfb353c0SYu Wang {
3630cfb353c0SYu Wang 	struct wmi_tlv_set_quiet_cmd *cmd;
3631cfb353c0SYu Wang 	struct wmi_tlv *tlv;
3632cfb353c0SYu Wang 	struct sk_buff *skb;
3633cfb353c0SYu Wang 
3634cfb353c0SYu Wang 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3635cfb353c0SYu Wang 	if (!skb)
3636cfb353c0SYu Wang 		return ERR_PTR(-ENOMEM);
3637cfb353c0SYu Wang 
3638cfb353c0SYu Wang 	tlv = (void *)skb->data;
3639cfb353c0SYu Wang 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_QUIET_CMD);
3640cfb353c0SYu Wang 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3641cfb353c0SYu Wang 	cmd = (void *)tlv->value;
3642cfb353c0SYu Wang 
3643cfb353c0SYu Wang 	/* vdev_id is not in use, set to 0 */
3644cfb353c0SYu Wang 	cmd->vdev_id = __cpu_to_le32(0);
3645cfb353c0SYu Wang 	cmd->period = __cpu_to_le32(period);
3646cfb353c0SYu Wang 	cmd->duration = __cpu_to_le32(duration);
3647cfb353c0SYu Wang 	cmd->next_start = __cpu_to_le32(next_offset);
3648cfb353c0SYu Wang 	cmd->enabled = __cpu_to_le32(enabled);
3649cfb353c0SYu Wang 
3650cfb353c0SYu Wang 	ath10k_dbg(ar, ATH10K_DBG_WMI,
3651cfb353c0SYu Wang 		   "wmi tlv quiet param: period %u duration %u enabled %d\n",
3652cfb353c0SYu Wang 		   period, duration, enabled);
3653cfb353c0SYu Wang 	return skb;
3654cfb353c0SYu Wang }
3655cfb353c0SYu Wang 
3656cfb353c0SYu Wang static struct sk_buff *
ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k * ar)3657f5431e87SJanusz Dziedzic ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar)
3658f5431e87SJanusz Dziedzic {
3659f5431e87SJanusz Dziedzic 	struct wmi_tlv_wow_enable_cmd *cmd;
3660f5431e87SJanusz Dziedzic 	struct wmi_tlv *tlv;
3661f5431e87SJanusz Dziedzic 	struct sk_buff *skb;
3662f5431e87SJanusz Dziedzic 	size_t len;
3663f5431e87SJanusz Dziedzic 
3664f5431e87SJanusz Dziedzic 	len = sizeof(*tlv) + sizeof(*cmd);
3665f5431e87SJanusz Dziedzic 	skb = ath10k_wmi_alloc_skb(ar, len);
3666f5431e87SJanusz Dziedzic 	if (!skb)
3667f5431e87SJanusz Dziedzic 		return ERR_PTR(-ENOMEM);
3668f5431e87SJanusz Dziedzic 
3669f5431e87SJanusz Dziedzic 	tlv = (struct wmi_tlv *)skb->data;
3670f5431e87SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ENABLE_CMD);
3671f5431e87SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3672f5431e87SJanusz Dziedzic 	cmd = (void *)tlv->value;
3673f5431e87SJanusz Dziedzic 
3674f5431e87SJanusz Dziedzic 	cmd->enable = __cpu_to_le32(1);
3675de8781d7SGovind Singh 	if (!ar->bus_param.link_can_suspend)
3676de8781d7SGovind Singh 		cmd->pause_iface_config = __cpu_to_le32(WOW_IFACE_PAUSE_DISABLED);
3677f5431e87SJanusz Dziedzic 
3678f5431e87SJanusz Dziedzic 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow enable\n");
3679f5431e87SJanusz Dziedzic 	return skb;
3680f5431e87SJanusz Dziedzic }
3681f5431e87SJanusz Dziedzic 
3682f5431e87SJanusz Dziedzic static struct sk_buff *
ath10k_wmi_tlv_op_gen_wow_add_wakeup_event(struct ath10k * ar,u32 vdev_id,enum wmi_wow_wakeup_event event,u32 enable)3683f5431e87SJanusz Dziedzic ath10k_wmi_tlv_op_gen_wow_add_wakeup_event(struct ath10k *ar,
3684f5431e87SJanusz Dziedzic 					   u32 vdev_id,
3685f5431e87SJanusz Dziedzic 					   enum wmi_wow_wakeup_event event,
3686f5431e87SJanusz Dziedzic 					   u32 enable)
3687f5431e87SJanusz Dziedzic {
3688f5431e87SJanusz Dziedzic 	struct wmi_tlv_wow_add_del_event_cmd *cmd;
3689f5431e87SJanusz Dziedzic 	struct wmi_tlv *tlv;
3690f5431e87SJanusz Dziedzic 	struct sk_buff *skb;
3691f5431e87SJanusz Dziedzic 	size_t len;
3692f5431e87SJanusz Dziedzic 
3693f5431e87SJanusz Dziedzic 	len = sizeof(*tlv) + sizeof(*cmd);
3694f5431e87SJanusz Dziedzic 	skb = ath10k_wmi_alloc_skb(ar, len);
3695f5431e87SJanusz Dziedzic 	if (!skb)
3696f5431e87SJanusz Dziedzic 		return ERR_PTR(-ENOMEM);
3697f5431e87SJanusz Dziedzic 
3698f5431e87SJanusz Dziedzic 	tlv = (struct wmi_tlv *)skb->data;
3699f5431e87SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_DEL_EVT_CMD);
3700f5431e87SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3701f5431e87SJanusz Dziedzic 	cmd = (void *)tlv->value;
3702f5431e87SJanusz Dziedzic 
3703f5431e87SJanusz Dziedzic 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3704f5431e87SJanusz Dziedzic 	cmd->is_add = __cpu_to_le32(enable);
3705f5431e87SJanusz Dziedzic 	cmd->event_bitmap = __cpu_to_le32(1 << event);
3706f5431e87SJanusz Dziedzic 
3707f5431e87SJanusz Dziedzic 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
3708f5431e87SJanusz Dziedzic 		   wow_wakeup_event(event), enable, vdev_id);
3709f5431e87SJanusz Dziedzic 	return skb;
3710f5431e87SJanusz Dziedzic }
3711f5431e87SJanusz Dziedzic 
3712f5431e87SJanusz Dziedzic static struct sk_buff *
ath10k_wmi_tlv_gen_wow_host_wakeup_ind(struct ath10k * ar)3713f5431e87SJanusz Dziedzic ath10k_wmi_tlv_gen_wow_host_wakeup_ind(struct ath10k *ar)
3714f5431e87SJanusz Dziedzic {
3715f5431e87SJanusz Dziedzic 	struct wmi_tlv_wow_host_wakeup_ind *cmd;
3716f5431e87SJanusz Dziedzic 	struct wmi_tlv *tlv;
3717f5431e87SJanusz Dziedzic 	struct sk_buff *skb;
3718f5431e87SJanusz Dziedzic 	size_t len;
3719f5431e87SJanusz Dziedzic 
3720f5431e87SJanusz Dziedzic 	len = sizeof(*tlv) + sizeof(*cmd);
3721f5431e87SJanusz Dziedzic 	skb = ath10k_wmi_alloc_skb(ar, len);
3722f5431e87SJanusz Dziedzic 	if (!skb)
3723f5431e87SJanusz Dziedzic 		return ERR_PTR(-ENOMEM);
3724f5431e87SJanusz Dziedzic 
3725f5431e87SJanusz Dziedzic 	tlv = (struct wmi_tlv *)skb->data;
3726f5431e87SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_HOSTWAKEUP_FROM_SLEEP_CMD);
3727f5431e87SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3728f5431e87SJanusz Dziedzic 	cmd = (void *)tlv->value;
3729f5431e87SJanusz Dziedzic 
3730f5431e87SJanusz Dziedzic 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
3731f5431e87SJanusz Dziedzic 	return skb;
3732f5431e87SJanusz Dziedzic }
3733f5431e87SJanusz Dziedzic 
3734d4976104SJanusz Dziedzic static struct sk_buff *
ath10k_wmi_tlv_op_gen_wow_add_pattern(struct ath10k * ar,u32 vdev_id,u32 pattern_id,const u8 * pattern,const u8 * bitmask,int pattern_len,int pattern_offset)3735d4976104SJanusz Dziedzic ath10k_wmi_tlv_op_gen_wow_add_pattern(struct ath10k *ar, u32 vdev_id,
3736d4976104SJanusz Dziedzic 				      u32 pattern_id, const u8 *pattern,
3737d4976104SJanusz Dziedzic 				      const u8 *bitmask, int pattern_len,
3738d4976104SJanusz Dziedzic 				      int pattern_offset)
3739d4976104SJanusz Dziedzic {
3740d4976104SJanusz Dziedzic 	struct wmi_tlv_wow_add_pattern_cmd *cmd;
3741d4976104SJanusz Dziedzic 	struct wmi_tlv_wow_bitmap_pattern *bitmap;
3742d4976104SJanusz Dziedzic 	struct wmi_tlv *tlv;
3743d4976104SJanusz Dziedzic 	struct sk_buff *skb;
3744d4976104SJanusz Dziedzic 	void *ptr;
3745d4976104SJanusz Dziedzic 	size_t len;
3746d4976104SJanusz Dziedzic 
3747d4976104SJanusz Dziedzic 	len = sizeof(*tlv) + sizeof(*cmd) +
3748d4976104SJanusz Dziedzic 	      sizeof(*tlv) +			/* array struct */
3749d4976104SJanusz Dziedzic 	      sizeof(*tlv) + sizeof(*bitmap) +  /* bitmap */
3750d4976104SJanusz Dziedzic 	      sizeof(*tlv) +			/* empty ipv4 sync */
3751d4976104SJanusz Dziedzic 	      sizeof(*tlv) +			/* empty ipv6 sync */
3752d4976104SJanusz Dziedzic 	      sizeof(*tlv) +			/* empty magic */
3753d4976104SJanusz Dziedzic 	      sizeof(*tlv) +			/* empty info timeout */
3754d4976104SJanusz Dziedzic 	      sizeof(*tlv) + sizeof(u32);	/* ratelimit interval */
3755d4976104SJanusz Dziedzic 
3756d4976104SJanusz Dziedzic 	skb = ath10k_wmi_alloc_skb(ar, len);
3757d4976104SJanusz Dziedzic 	if (!skb)
3758d4976104SJanusz Dziedzic 		return ERR_PTR(-ENOMEM);
3759d4976104SJanusz Dziedzic 
3760d4976104SJanusz Dziedzic 	/* cmd */
3761d4976104SJanusz Dziedzic 	ptr = (void *)skb->data;
3762d4976104SJanusz Dziedzic 	tlv = ptr;
3763d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_PATTERN_CMD);
3764d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3765d4976104SJanusz Dziedzic 	cmd = (void *)tlv->value;
3766d4976104SJanusz Dziedzic 
3767d4976104SJanusz Dziedzic 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3768d4976104SJanusz Dziedzic 	cmd->pattern_id = __cpu_to_le32(pattern_id);
3769d4976104SJanusz Dziedzic 	cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
3770d4976104SJanusz Dziedzic 
3771d4976104SJanusz Dziedzic 	ptr += sizeof(*tlv);
3772d4976104SJanusz Dziedzic 	ptr += sizeof(*cmd);
3773d4976104SJanusz Dziedzic 
3774d4976104SJanusz Dziedzic 	/* bitmap */
3775d4976104SJanusz Dziedzic 	tlv = ptr;
3776d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3777d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*tlv) + sizeof(*bitmap));
3778d4976104SJanusz Dziedzic 
3779d4976104SJanusz Dziedzic 	ptr += sizeof(*tlv);
3780d4976104SJanusz Dziedzic 
3781d4976104SJanusz Dziedzic 	tlv = ptr;
3782d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_BITMAP_PATTERN_T);
3783d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*bitmap));
3784d4976104SJanusz Dziedzic 	bitmap = (void *)tlv->value;
3785d4976104SJanusz Dziedzic 
3786d4976104SJanusz Dziedzic 	memcpy(bitmap->patternbuf, pattern, pattern_len);
3787d4976104SJanusz Dziedzic 	memcpy(bitmap->bitmaskbuf, bitmask, pattern_len);
3788d4976104SJanusz Dziedzic 	bitmap->pattern_offset = __cpu_to_le32(pattern_offset);
3789d4976104SJanusz Dziedzic 	bitmap->pattern_len = __cpu_to_le32(pattern_len);
3790d4976104SJanusz Dziedzic 	bitmap->bitmask_len = __cpu_to_le32(pattern_len);
3791d4976104SJanusz Dziedzic 	bitmap->pattern_id = __cpu_to_le32(pattern_id);
3792d4976104SJanusz Dziedzic 
3793d4976104SJanusz Dziedzic 	ptr += sizeof(*tlv);
3794d4976104SJanusz Dziedzic 	ptr += sizeof(*bitmap);
3795d4976104SJanusz Dziedzic 
3796d4976104SJanusz Dziedzic 	/* ipv4 sync */
3797d4976104SJanusz Dziedzic 	tlv = ptr;
3798d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3799d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(0);
3800d4976104SJanusz Dziedzic 
3801d4976104SJanusz Dziedzic 	ptr += sizeof(*tlv);
3802d4976104SJanusz Dziedzic 
3803d4976104SJanusz Dziedzic 	/* ipv6 sync */
3804d4976104SJanusz Dziedzic 	tlv = ptr;
3805d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3806d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(0);
3807d4976104SJanusz Dziedzic 
3808d4976104SJanusz Dziedzic 	ptr += sizeof(*tlv);
3809d4976104SJanusz Dziedzic 
3810d4976104SJanusz Dziedzic 	/* magic */
3811d4976104SJanusz Dziedzic 	tlv = ptr;
3812d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3813d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(0);
3814d4976104SJanusz Dziedzic 
3815d4976104SJanusz Dziedzic 	ptr += sizeof(*tlv);
3816d4976104SJanusz Dziedzic 
3817d4976104SJanusz Dziedzic 	/* pattern info timeout */
3818d4976104SJanusz Dziedzic 	tlv = ptr;
3819d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3820d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(0);
3821d4976104SJanusz Dziedzic 
3822d4976104SJanusz Dziedzic 	ptr += sizeof(*tlv);
3823d4976104SJanusz Dziedzic 
3824d4976104SJanusz Dziedzic 	/* ratelimit interval */
3825d4976104SJanusz Dziedzic 	tlv = ptr;
3826d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3827d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(u32));
3828d4976104SJanusz Dziedzic 
3829d4976104SJanusz Dziedzic 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d, pattern_offset %d\n",
3830d4976104SJanusz Dziedzic 		   vdev_id, pattern_id, pattern_offset);
3831d4976104SJanusz Dziedzic 	return skb;
3832d4976104SJanusz Dziedzic }
3833d4976104SJanusz Dziedzic 
3834d4976104SJanusz Dziedzic static struct sk_buff *
ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k * ar,u32 vdev_id,u32 pattern_id)3835d4976104SJanusz Dziedzic ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
3836d4976104SJanusz Dziedzic 				      u32 pattern_id)
3837d4976104SJanusz Dziedzic {
3838d4976104SJanusz Dziedzic 	struct wmi_tlv_wow_del_pattern_cmd *cmd;
3839d4976104SJanusz Dziedzic 	struct wmi_tlv *tlv;
3840d4976104SJanusz Dziedzic 	struct sk_buff *skb;
3841d4976104SJanusz Dziedzic 	size_t len;
3842d4976104SJanusz Dziedzic 
3843d4976104SJanusz Dziedzic 	len = sizeof(*tlv) + sizeof(*cmd);
3844d4976104SJanusz Dziedzic 	skb = ath10k_wmi_alloc_skb(ar, len);
3845d4976104SJanusz Dziedzic 	if (!skb)
3846d4976104SJanusz Dziedzic 		return ERR_PTR(-ENOMEM);
3847d4976104SJanusz Dziedzic 
3848d4976104SJanusz Dziedzic 	tlv = (struct wmi_tlv *)skb->data;
3849d4976104SJanusz Dziedzic 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_DEL_PATTERN_CMD);
3850d4976104SJanusz Dziedzic 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3851d4976104SJanusz Dziedzic 	cmd = (void *)tlv->value;
3852d4976104SJanusz Dziedzic 
3853d4976104SJanusz Dziedzic 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3854d4976104SJanusz Dziedzic 	cmd->pattern_id = __cpu_to_le32(pattern_id);
3855d4976104SJanusz Dziedzic 	cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
3856d4976104SJanusz Dziedzic 
3857d4976104SJanusz Dziedzic 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
3858d4976104SJanusz Dziedzic 		   vdev_id, pattern_id);
3859d4976104SJanusz Dziedzic 	return skb;
3860d4976104SJanusz Dziedzic }
3861d4976104SJanusz Dziedzic 
3862ce834e28SWen Gong /* Request FW to start PNO operation */
3863ce834e28SWen Gong static struct sk_buff *
ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k * ar,u32 vdev_id,struct wmi_pno_scan_req * pno)3864ce834e28SWen Gong ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
3865ce834e28SWen Gong 				       u32 vdev_id,
3866ce834e28SWen Gong 				       struct wmi_pno_scan_req *pno)
3867ce834e28SWen Gong {
3868ce834e28SWen Gong 	struct nlo_configured_parameters *nlo_list;
3869ce834e28SWen Gong 	struct wmi_tlv_wow_nlo_config_cmd *cmd;
3870ce834e28SWen Gong 	struct wmi_tlv *tlv;
3871ce834e28SWen Gong 	struct sk_buff *skb;
3872ce834e28SWen Gong 	__le32 *channel_list;
3873e01cc82cSWen Gong 	u16 tlv_len;
3874ce834e28SWen Gong 	size_t len;
3875ce834e28SWen Gong 	void *ptr;
3876ce834e28SWen Gong 	u32 i;
3877ce834e28SWen Gong 
3878ce834e28SWen Gong 	len = sizeof(*tlv) + sizeof(*cmd) +
3879ce834e28SWen Gong 	      sizeof(*tlv) +
3880ce834e28SWen Gong 	      /* TLV place holder for array of structures
3881ce834e28SWen Gong 	       * nlo_configured_parameters(nlo_list)
3882ce834e28SWen Gong 	       */
3883ce834e28SWen Gong 	      sizeof(*tlv);
3884ce834e28SWen Gong 	      /* TLV place holder for array of uint32 channel_list */
3885ce834e28SWen Gong 
3886ce834e28SWen Gong 	len += sizeof(u32) * min_t(u8, pno->a_networks[0].channel_count,
3887ce834e28SWen Gong 				   WMI_NLO_MAX_CHAN);
3888ce834e28SWen Gong 	len += sizeof(struct nlo_configured_parameters) *
3889ce834e28SWen Gong 				min_t(u8, pno->uc_networks_count, WMI_NLO_MAX_SSIDS);
3890ce834e28SWen Gong 
3891ce834e28SWen Gong 	skb = ath10k_wmi_alloc_skb(ar, len);
3892ce834e28SWen Gong 	if (!skb)
3893ce834e28SWen Gong 		return ERR_PTR(-ENOMEM);
3894ce834e28SWen Gong 
3895ce834e28SWen Gong 	ptr = (void *)skb->data;
3896ce834e28SWen Gong 	tlv = ptr;
3897ce834e28SWen Gong 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
3898ce834e28SWen Gong 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3899ce834e28SWen Gong 	cmd = (void *)tlv->value;
3900ce834e28SWen Gong 
3901ce834e28SWen Gong 	/* wmi_tlv_wow_nlo_config_cmd parameters*/
3902ce834e28SWen Gong 	cmd->vdev_id = __cpu_to_le32(pno->vdev_id);
3903ce834e28SWen Gong 	cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);
3904ce834e28SWen Gong 
3905ce834e28SWen Gong 	/* current FW does not support min-max range for dwell time */
3906ce834e28SWen Gong 	cmd->active_dwell_time = __cpu_to_le32(pno->active_max_time);
3907ce834e28SWen Gong 	cmd->passive_dwell_time = __cpu_to_le32(pno->passive_max_time);
3908ce834e28SWen Gong 
3909ce834e28SWen Gong 	if (pno->do_passive_scan)
3910ce834e28SWen Gong 		cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);
3911ce834e28SWen Gong 
3912ce834e28SWen Gong 	/* copy scan interval */
3913ce834e28SWen Gong 	cmd->fast_scan_period = __cpu_to_le32(pno->fast_scan_period);
3914ce834e28SWen Gong 	cmd->slow_scan_period = __cpu_to_le32(pno->slow_scan_period);
3915ce834e28SWen Gong 	cmd->fast_scan_max_cycles = __cpu_to_le32(pno->fast_scan_max_cycles);
3916ce834e28SWen Gong 	cmd->delay_start_time = __cpu_to_le32(pno->delay_start_time);
3917ce834e28SWen Gong 
3918ce834e28SWen Gong 	if (pno->enable_pno_scan_randomization) {
3919ce834e28SWen Gong 		cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |
3920ce834e28SWen Gong 				WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);
3921ce834e28SWen Gong 		ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);
3922ce834e28SWen Gong 		ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);
3923ce834e28SWen Gong 	}
3924ce834e28SWen Gong 
3925ce834e28SWen Gong 	ptr += sizeof(*tlv);
3926ce834e28SWen Gong 	ptr += sizeof(*cmd);
3927ce834e28SWen Gong 
3928ce834e28SWen Gong 	/* nlo_configured_parameters(nlo_list) */
3929ce834e28SWen Gong 	cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
3930ce834e28SWen Gong 					       WMI_NLO_MAX_SSIDS));
3931e01cc82cSWen Gong 	tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
3932e01cc82cSWen Gong 		sizeof(struct nlo_configured_parameters);
3933ce834e28SWen Gong 
3934ce834e28SWen Gong 	tlv = ptr;
3935ce834e28SWen Gong 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3936e01cc82cSWen Gong 	tlv->len = __cpu_to_le16(tlv_len);
3937ce834e28SWen Gong 
3938ce834e28SWen Gong 	ptr += sizeof(*tlv);
3939ce834e28SWen Gong 	nlo_list = ptr;
3940ce834e28SWen Gong 	for (i = 0; i < __le32_to_cpu(cmd->no_of_ssids); i++) {
3941ce834e28SWen Gong 		tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);
3942ce834e28SWen Gong 		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3943ce834e28SWen Gong 		tlv->len = __cpu_to_le16(sizeof(struct nlo_configured_parameters) -
3944ce834e28SWen Gong 					 sizeof(*tlv));
3945ce834e28SWen Gong 
3946ce834e28SWen Gong 		/* copy ssid and it's length */
3947ce834e28SWen Gong 		nlo_list[i].ssid.valid = __cpu_to_le32(true);
3948ce834e28SWen Gong 		nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len;
3949ce834e28SWen Gong 		memcpy(nlo_list[i].ssid.ssid.ssid,
3950ce834e28SWen Gong 		       pno->a_networks[i].ssid.ssid,
3951ce834e28SWen Gong 		       __le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));
3952ce834e28SWen Gong 
3953ce834e28SWen Gong 		/* copy rssi threshold */
3954ce834e28SWen Gong 		if (pno->a_networks[i].rssi_threshold &&
3955ce834e28SWen Gong 		    pno->a_networks[i].rssi_threshold > -300) {
3956ce834e28SWen Gong 			nlo_list[i].rssi_cond.valid = __cpu_to_le32(true);
3957ce834e28SWen Gong 			nlo_list[i].rssi_cond.rssi =
3958ce834e28SWen Gong 				__cpu_to_le32(pno->a_networks[i].rssi_threshold);
3959ce834e28SWen Gong 		}
3960ce834e28SWen Gong 
3961ce834e28SWen Gong 		nlo_list[i].bcast_nw_type.valid = __cpu_to_le32(true);
3962ce834e28SWen Gong 		nlo_list[i].bcast_nw_type.bcast_nw_type =
3963ce834e28SWen Gong 			__cpu_to_le32(pno->a_networks[i].bcast_nw_type);
3964ce834e28SWen Gong 	}
3965ce834e28SWen Gong 
3966ce834e28SWen Gong 	ptr += __le32_to_cpu(cmd->no_of_ssids) * sizeof(struct nlo_configured_parameters);
3967ce834e28SWen Gong 
3968ce834e28SWen Gong 	/* copy channel info */
3969ce834e28SWen Gong 	cmd->num_of_channels = __cpu_to_le32(min_t(u8,
3970ce834e28SWen Gong 						   pno->a_networks[0].channel_count,
3971ce834e28SWen Gong 						   WMI_NLO_MAX_CHAN));
3972ce834e28SWen Gong 
3973ce834e28SWen Gong 	tlv = ptr;
3974ce834e28SWen Gong 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3975ce834e28SWen Gong 	tlv->len = __cpu_to_le16(__le32_to_cpu(cmd->num_of_channels) *
3976ce834e28SWen Gong 				 sizeof(u_int32_t));
3977ce834e28SWen Gong 	ptr += sizeof(*tlv);
3978ce834e28SWen Gong 
3979ce834e28SWen Gong 	channel_list = (__le32 *)ptr;
3980ce834e28SWen Gong 	for (i = 0; i < __le32_to_cpu(cmd->num_of_channels); i++)
3981ce834e28SWen Gong 		channel_list[i] = __cpu_to_le32(pno->a_networks[0].channels[i]);
3982ce834e28SWen Gong 
3983ce834e28SWen Gong 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
3984ce834e28SWen Gong 		   vdev_id);
3985ce834e28SWen Gong 
3986ce834e28SWen Gong 	return skb;
3987ce834e28SWen Gong }
3988ce834e28SWen Gong 
3989ce834e28SWen Gong /* Request FW to stop ongoing PNO operation */
ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k * ar,u32 vdev_id)3990ce834e28SWen Gong static struct sk_buff *ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k *ar,
3991ce834e28SWen Gong 							     u32 vdev_id)
3992ce834e28SWen Gong {
3993ce834e28SWen Gong 	struct wmi_tlv_wow_nlo_config_cmd *cmd;
3994ce834e28SWen Gong 	struct wmi_tlv *tlv;
3995ce834e28SWen Gong 	struct sk_buff *skb;
3996ce834e28SWen Gong 	void *ptr;
3997ce834e28SWen Gong 	size_t len;
3998ce834e28SWen Gong 
3999ce834e28SWen Gong 	len = sizeof(*tlv) + sizeof(*cmd) +
4000ce834e28SWen Gong 	      sizeof(*tlv) +
4001ce834e28SWen Gong 	      /* TLV place holder for array of structures
4002ce834e28SWen Gong 	       * nlo_configured_parameters(nlo_list)
4003ce834e28SWen Gong 	       */
4004ce834e28SWen Gong 	      sizeof(*tlv);
4005ce834e28SWen Gong 	      /* TLV place holder for array of uint32 channel_list */
4006ce834e28SWen Gong 	skb = ath10k_wmi_alloc_skb(ar, len);
4007ce834e28SWen Gong 	if (!skb)
4008ce834e28SWen Gong 		return ERR_PTR(-ENOMEM);
4009ce834e28SWen Gong 
4010ce834e28SWen Gong 	ptr = (void *)skb->data;
4011ce834e28SWen Gong 	tlv = ptr;
4012ce834e28SWen Gong 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
4013ce834e28SWen Gong 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4014ce834e28SWen Gong 	cmd = (void *)tlv->value;
4015ce834e28SWen Gong 
4016ce834e28SWen Gong 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4017ce834e28SWen Gong 	cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_STOP);
4018ce834e28SWen Gong 
4019ce834e28SWen Gong 	ptr += sizeof(*tlv);
4020ce834e28SWen Gong 	ptr += sizeof(*cmd);
4021ce834e28SWen Gong 
4022ce834e28SWen Gong 	/* nlo_configured_parameters(nlo_list) */
4023ce834e28SWen Gong 	tlv = ptr;
4024ce834e28SWen Gong 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4025ce834e28SWen Gong 	tlv->len = __cpu_to_le16(0);
4026ce834e28SWen Gong 
4027ce834e28SWen Gong 	ptr += sizeof(*tlv);
4028ce834e28SWen Gong 
4029ce834e28SWen Gong 	/* channel list */
4030ce834e28SWen Gong 	tlv = ptr;
4031ce834e28SWen Gong 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
4032ce834e28SWen Gong 	tlv->len = __cpu_to_le16(0);
4033ce834e28SWen Gong 
4034ce834e28SWen Gong 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop pno config vdev_id %d\n", vdev_id);
4035ce834e28SWen Gong 	return skb;
4036ce834e28SWen Gong }
4037ce834e28SWen Gong 
4038ce834e28SWen Gong static struct sk_buff *
ath10k_wmi_tlv_op_gen_config_pno(struct ath10k * ar,u32 vdev_id,struct wmi_pno_scan_req * pno_scan)4039ce834e28SWen Gong ath10k_wmi_tlv_op_gen_config_pno(struct ath10k *ar, u32 vdev_id,
4040ce834e28SWen Gong 				 struct wmi_pno_scan_req *pno_scan)
4041ce834e28SWen Gong {
4042ce834e28SWen Gong 	if (pno_scan->enable)
4043ce834e28SWen Gong 		return ath10k_wmi_tlv_op_gen_config_pno_start(ar, vdev_id, pno_scan);
4044ce834e28SWen Gong 	else
4045ce834e28SWen Gong 		return ath10k_wmi_tlv_op_gen_config_pno_stop(ar, vdev_id);
4046ce834e28SWen Gong }
4047ce834e28SWen Gong 
40485b272e30SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k * ar,bool enable)40495b272e30SMichal Kazior ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
40505b272e30SMichal Kazior {
40515b272e30SMichal Kazior 	struct wmi_tlv_adaptive_qcs *cmd;
40525b272e30SMichal Kazior 	struct wmi_tlv *tlv;
40535b272e30SMichal Kazior 	struct sk_buff *skb;
40545b272e30SMichal Kazior 	void *ptr;
40555b272e30SMichal Kazior 	size_t len;
40565b272e30SMichal Kazior 
40575b272e30SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd);
40585b272e30SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
40595b272e30SMichal Kazior 	if (!skb)
40605b272e30SMichal Kazior 		return ERR_PTR(-ENOMEM);
40615b272e30SMichal Kazior 
40625b272e30SMichal Kazior 	ptr = (void *)skb->data;
40635b272e30SMichal Kazior 	tlv = ptr;
40645b272e30SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESMGR_ADAPTIVE_OCS_CMD);
40655b272e30SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
40665b272e30SMichal Kazior 	cmd = (void *)tlv->value;
40675b272e30SMichal Kazior 	cmd->enable = __cpu_to_le32(enable ? 1 : 0);
40685b272e30SMichal Kazior 
40695b272e30SMichal Kazior 	ptr += sizeof(*tlv);
40705b272e30SMichal Kazior 	ptr += sizeof(*cmd);
40715b272e30SMichal Kazior 
40725b272e30SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv adaptive qcs %d\n", enable);
40735b272e30SMichal Kazior 	return skb;
40745b272e30SMichal Kazior }
40755b272e30SMichal Kazior 
4076e25854f2SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_echo(struct ath10k * ar,u32 value)4077e25854f2SMichal Kazior ath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value)
4078e25854f2SMichal Kazior {
4079e25854f2SMichal Kazior 	struct wmi_echo_cmd *cmd;
4080e25854f2SMichal Kazior 	struct wmi_tlv *tlv;
4081e25854f2SMichal Kazior 	struct sk_buff *skb;
4082e25854f2SMichal Kazior 	void *ptr;
4083e25854f2SMichal Kazior 	size_t len;
4084e25854f2SMichal Kazior 
4085e25854f2SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd);
4086e25854f2SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
4087e25854f2SMichal Kazior 	if (!skb)
4088e25854f2SMichal Kazior 		return ERR_PTR(-ENOMEM);
4089e25854f2SMichal Kazior 
4090e25854f2SMichal Kazior 	ptr = (void *)skb->data;
4091e25854f2SMichal Kazior 	tlv = ptr;
4092e25854f2SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_ECHO_CMD);
4093e25854f2SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4094e25854f2SMichal Kazior 	cmd = (void *)tlv->value;
4095e25854f2SMichal Kazior 	cmd->value = cpu_to_le32(value);
4096e25854f2SMichal Kazior 
4097e25854f2SMichal Kazior 	ptr += sizeof(*tlv);
4098e25854f2SMichal Kazior 	ptr += sizeof(*cmd);
4099e25854f2SMichal Kazior 
4100e25854f2SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv echo value 0x%08x\n", value);
4101e25854f2SMichal Kazior 	return skb;
4102e25854f2SMichal Kazior }
4103e25854f2SMichal Kazior 
41045a401f36SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k * ar,const struct wmi_vdev_spectral_conf_arg * arg)41055a401f36SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k *ar,
41065a401f36SMichal Kazior 					 const struct wmi_vdev_spectral_conf_arg *arg)
41075a401f36SMichal Kazior {
41085a401f36SMichal Kazior 	struct wmi_vdev_spectral_conf_cmd *cmd;
41095a401f36SMichal Kazior 	struct sk_buff *skb;
41105a401f36SMichal Kazior 	struct wmi_tlv *tlv;
41115a401f36SMichal Kazior 	void *ptr;
41125a401f36SMichal Kazior 	size_t len;
41135a401f36SMichal Kazior 
41145a401f36SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd);
41155a401f36SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
41165a401f36SMichal Kazior 	if (!skb)
41175a401f36SMichal Kazior 		return ERR_PTR(-ENOMEM);
41185a401f36SMichal Kazior 
41195a401f36SMichal Kazior 	ptr = (void *)skb->data;
41205a401f36SMichal Kazior 	tlv = ptr;
41215a401f36SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD);
41225a401f36SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
41235a401f36SMichal Kazior 	cmd = (void *)tlv->value;
41245a401f36SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
41255a401f36SMichal Kazior 	cmd->scan_count = __cpu_to_le32(arg->scan_count);
41265a401f36SMichal Kazior 	cmd->scan_period = __cpu_to_le32(arg->scan_period);
41275a401f36SMichal Kazior 	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
41285a401f36SMichal Kazior 	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
41295a401f36SMichal Kazior 	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
41305a401f36SMichal Kazior 	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
41315a401f36SMichal Kazior 	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
41325a401f36SMichal Kazior 	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
41335a401f36SMichal Kazior 	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
41345a401f36SMichal Kazior 	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
41355a401f36SMichal Kazior 	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
41365a401f36SMichal Kazior 	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
41375a401f36SMichal Kazior 	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
41385a401f36SMichal Kazior 	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
41395a401f36SMichal Kazior 	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
41405a401f36SMichal Kazior 	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
41415a401f36SMichal Kazior 	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
41425a401f36SMichal Kazior 	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
41435a401f36SMichal Kazior 
41445a401f36SMichal Kazior 	return skb;
41455a401f36SMichal Kazior }
41465a401f36SMichal Kazior 
41475a401f36SMichal Kazior static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k * ar,u32 vdev_id,u32 trigger,u32 enable)41485a401f36SMichal Kazior ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
41495a401f36SMichal Kazior 					   u32 trigger, u32 enable)
41505a401f36SMichal Kazior {
41515a401f36SMichal Kazior 	struct wmi_vdev_spectral_enable_cmd *cmd;
41525a401f36SMichal Kazior 	struct sk_buff *skb;
41535a401f36SMichal Kazior 	struct wmi_tlv *tlv;
41545a401f36SMichal Kazior 	void *ptr;
41555a401f36SMichal Kazior 	size_t len;
41565a401f36SMichal Kazior 
41575a401f36SMichal Kazior 	len = sizeof(*tlv) + sizeof(*cmd);
41585a401f36SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
41595a401f36SMichal Kazior 	if (!skb)
41605a401f36SMichal Kazior 		return ERR_PTR(-ENOMEM);
41615a401f36SMichal Kazior 
41625a401f36SMichal Kazior 	ptr = (void *)skb->data;
41635a401f36SMichal Kazior 	tlv = ptr;
41645a401f36SMichal Kazior 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD);
41655a401f36SMichal Kazior 	tlv->len = __cpu_to_le16(sizeof(*cmd));
41665a401f36SMichal Kazior 	cmd = (void *)tlv->value;
41675a401f36SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(vdev_id);
41685a401f36SMichal Kazior 	cmd->trigger_cmd = __cpu_to_le32(trigger);
41695a401f36SMichal Kazior 	cmd->enable_cmd = __cpu_to_le32(enable);
41705a401f36SMichal Kazior 
41715a401f36SMichal Kazior 	return skb;
41725a401f36SMichal Kazior }
41735a401f36SMichal Kazior 
4174ca996ec5SMichal Kazior /****************/
4175ca996ec5SMichal Kazior /* TLV mappings */
4176ca996ec5SMichal Kazior /****************/
4177ca996ec5SMichal Kazior 
4178ca996ec5SMichal Kazior static struct wmi_cmd_map wmi_tlv_cmd_map = {
4179ca996ec5SMichal Kazior 	.init_cmdid = WMI_TLV_INIT_CMDID,
4180ca996ec5SMichal Kazior 	.start_scan_cmdid = WMI_TLV_START_SCAN_CMDID,
4181ca996ec5SMichal Kazior 	.stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
4182ca996ec5SMichal Kazior 	.scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
4183ca996ec5SMichal Kazior 	.scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
418460e1d0fbSCarl Huang 	.scan_prob_req_oui_cmdid = WMI_TLV_SCAN_PROB_REQ_OUI_CMDID,
4185ca996ec5SMichal Kazior 	.pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
4186ca996ec5SMichal Kazior 	.pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
4187ca996ec5SMichal Kazior 	.pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
4188ca996ec5SMichal Kazior 	.pdev_pktlog_enable_cmdid = WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID,
4189ca996ec5SMichal Kazior 	.pdev_pktlog_disable_cmdid = WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID,
4190ca996ec5SMichal Kazior 	.pdev_set_wmm_params_cmdid = WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID,
4191ca996ec5SMichal Kazior 	.pdev_set_ht_cap_ie_cmdid = WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID,
4192ca996ec5SMichal Kazior 	.pdev_set_vht_cap_ie_cmdid = WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID,
4193ca996ec5SMichal Kazior 	.pdev_set_dscp_tid_map_cmdid = WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID,
4194ca996ec5SMichal Kazior 	.pdev_set_quiet_mode_cmdid = WMI_TLV_PDEV_SET_QUIET_MODE_CMDID,
4195ca996ec5SMichal Kazior 	.pdev_green_ap_ps_enable_cmdid = WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID,
4196ca996ec5SMichal Kazior 	.pdev_get_tpc_config_cmdid = WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID,
4197ca996ec5SMichal Kazior 	.pdev_set_base_macaddr_cmdid = WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID,
4198ca996ec5SMichal Kazior 	.vdev_create_cmdid = WMI_TLV_VDEV_CREATE_CMDID,
4199ca996ec5SMichal Kazior 	.vdev_delete_cmdid = WMI_TLV_VDEV_DELETE_CMDID,
4200ca996ec5SMichal Kazior 	.vdev_start_request_cmdid = WMI_TLV_VDEV_START_REQUEST_CMDID,
4201ca996ec5SMichal Kazior 	.vdev_restart_request_cmdid = WMI_TLV_VDEV_RESTART_REQUEST_CMDID,
4202ca996ec5SMichal Kazior 	.vdev_up_cmdid = WMI_TLV_VDEV_UP_CMDID,
4203ca996ec5SMichal Kazior 	.vdev_stop_cmdid = WMI_TLV_VDEV_STOP_CMDID,
4204ca996ec5SMichal Kazior 	.vdev_down_cmdid = WMI_TLV_VDEV_DOWN_CMDID,
4205ca996ec5SMichal Kazior 	.vdev_set_param_cmdid = WMI_TLV_VDEV_SET_PARAM_CMDID,
4206ca996ec5SMichal Kazior 	.vdev_install_key_cmdid = WMI_TLV_VDEV_INSTALL_KEY_CMDID,
4207ca996ec5SMichal Kazior 	.peer_create_cmdid = WMI_TLV_PEER_CREATE_CMDID,
4208ca996ec5SMichal Kazior 	.peer_delete_cmdid = WMI_TLV_PEER_DELETE_CMDID,
4209ca996ec5SMichal Kazior 	.peer_flush_tids_cmdid = WMI_TLV_PEER_FLUSH_TIDS_CMDID,
4210ca996ec5SMichal Kazior 	.peer_set_param_cmdid = WMI_TLV_PEER_SET_PARAM_CMDID,
4211ca996ec5SMichal Kazior 	.peer_assoc_cmdid = WMI_TLV_PEER_ASSOC_CMDID,
4212ca996ec5SMichal Kazior 	.peer_add_wds_entry_cmdid = WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID,
4213ca996ec5SMichal Kazior 	.peer_remove_wds_entry_cmdid = WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID,
4214ca996ec5SMichal Kazior 	.peer_mcast_group_cmdid = WMI_TLV_PEER_MCAST_GROUP_CMDID,
4215ca996ec5SMichal Kazior 	.bcn_tx_cmdid = WMI_TLV_BCN_TX_CMDID,
4216ca996ec5SMichal Kazior 	.pdev_send_bcn_cmdid = WMI_TLV_PDEV_SEND_BCN_CMDID,
4217ca996ec5SMichal Kazior 	.bcn_tmpl_cmdid = WMI_TLV_BCN_TMPL_CMDID,
4218ca996ec5SMichal Kazior 	.bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID,
4219ca996ec5SMichal Kazior 	.prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
4220ca996ec5SMichal Kazior 	.mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID,
42211807da49SRakesh Pillai 	.mgmt_tx_send_cmdid = WMI_TLV_MGMT_TX_SEND_CMD,
4222ca996ec5SMichal Kazior 	.prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID,
4223ca996ec5SMichal Kazior 	.addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID,
4224ca996ec5SMichal Kazior 	.addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID,
4225ca996ec5SMichal Kazior 	.addba_status_cmdid = WMI_TLV_ADDBA_STATUS_CMDID,
4226ca996ec5SMichal Kazior 	.delba_send_cmdid = WMI_TLV_DELBA_SEND_CMDID,
4227ca996ec5SMichal Kazior 	.addba_set_resp_cmdid = WMI_TLV_ADDBA_SET_RESP_CMDID,
4228ca996ec5SMichal Kazior 	.send_singleamsdu_cmdid = WMI_TLV_SEND_SINGLEAMSDU_CMDID,
4229ca996ec5SMichal Kazior 	.sta_powersave_mode_cmdid = WMI_TLV_STA_POWERSAVE_MODE_CMDID,
4230ca996ec5SMichal Kazior 	.sta_powersave_param_cmdid = WMI_TLV_STA_POWERSAVE_PARAM_CMDID,
4231ca996ec5SMichal Kazior 	.sta_mimo_ps_mode_cmdid = WMI_TLV_STA_MIMO_PS_MODE_CMDID,
4232ca996ec5SMichal Kazior 	.pdev_dfs_enable_cmdid = WMI_TLV_PDEV_DFS_ENABLE_CMDID,
4233ca996ec5SMichal Kazior 	.pdev_dfs_disable_cmdid = WMI_TLV_PDEV_DFS_DISABLE_CMDID,
4234ca996ec5SMichal Kazior 	.roam_scan_mode = WMI_TLV_ROAM_SCAN_MODE,
4235ca996ec5SMichal Kazior 	.roam_scan_rssi_threshold = WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD,
4236ca996ec5SMichal Kazior 	.roam_scan_period = WMI_TLV_ROAM_SCAN_PERIOD,
4237ca996ec5SMichal Kazior 	.roam_scan_rssi_change_threshold =
4238ca996ec5SMichal Kazior 				WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
4239ca996ec5SMichal Kazior 	.roam_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
4240ca996ec5SMichal Kazior 	.ofl_scan_add_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
4241ca996ec5SMichal Kazior 	.ofl_scan_remove_ap_profile = WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE,
4242ca996ec5SMichal Kazior 	.ofl_scan_period = WMI_TLV_OFL_SCAN_PERIOD,
4243ca996ec5SMichal Kazior 	.p2p_dev_set_device_info = WMI_TLV_P2P_DEV_SET_DEVICE_INFO,
4244ca996ec5SMichal Kazior 	.p2p_dev_set_discoverability = WMI_TLV_P2P_DEV_SET_DISCOVERABILITY,
4245ca996ec5SMichal Kazior 	.p2p_go_set_beacon_ie = WMI_TLV_P2P_GO_SET_BEACON_IE,
4246ca996ec5SMichal Kazior 	.p2p_go_set_probe_resp_ie = WMI_TLV_P2P_GO_SET_PROBE_RESP_IE,
4247ca996ec5SMichal Kazior 	.p2p_set_vendor_ie_data_cmdid = WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID,
4248ca996ec5SMichal Kazior 	.ap_ps_peer_param_cmdid = WMI_TLV_AP_PS_PEER_PARAM_CMDID,
4249ca996ec5SMichal Kazior 	.ap_ps_peer_uapsd_coex_cmdid = WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID,
4250ca996ec5SMichal Kazior 	.peer_rate_retry_sched_cmdid = WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID,
4251ca996ec5SMichal Kazior 	.wlan_profile_trigger_cmdid = WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID,
4252ca996ec5SMichal Kazior 	.wlan_profile_set_hist_intvl_cmdid =
4253ca996ec5SMichal Kazior 				WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
4254ca996ec5SMichal Kazior 	.wlan_profile_get_profile_data_cmdid =
4255ca996ec5SMichal Kazior 				WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
4256ca996ec5SMichal Kazior 	.wlan_profile_enable_profile_id_cmdid =
4257ca996ec5SMichal Kazior 				WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
4258ca996ec5SMichal Kazior 	.wlan_profile_list_profile_id_cmdid =
4259ca996ec5SMichal Kazior 				WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
4260ca996ec5SMichal Kazior 	.pdev_suspend_cmdid = WMI_TLV_PDEV_SUSPEND_CMDID,
4261ca996ec5SMichal Kazior 	.pdev_resume_cmdid = WMI_TLV_PDEV_RESUME_CMDID,
4262ca996ec5SMichal Kazior 	.add_bcn_filter_cmdid = WMI_TLV_ADD_BCN_FILTER_CMDID,
4263ca996ec5SMichal Kazior 	.rmv_bcn_filter_cmdid = WMI_TLV_RMV_BCN_FILTER_CMDID,
4264ca996ec5SMichal Kazior 	.wow_add_wake_pattern_cmdid = WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID,
4265ca996ec5SMichal Kazior 	.wow_del_wake_pattern_cmdid = WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID,
4266ca996ec5SMichal Kazior 	.wow_enable_disable_wake_event_cmdid =
4267ca996ec5SMichal Kazior 				WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
4268ca996ec5SMichal Kazior 	.wow_enable_cmdid = WMI_TLV_WOW_ENABLE_CMDID,
4269ca996ec5SMichal Kazior 	.wow_hostwakeup_from_sleep_cmdid =
4270ca996ec5SMichal Kazior 				WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
4271ca996ec5SMichal Kazior 	.rtt_measreq_cmdid = WMI_TLV_RTT_MEASREQ_CMDID,
4272ca996ec5SMichal Kazior 	.rtt_tsf_cmdid = WMI_TLV_RTT_TSF_CMDID,
4273ca996ec5SMichal Kazior 	.vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID,
4274ca996ec5SMichal Kazior 	.vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID,
4275ca996ec5SMichal Kazior 	.request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID,
42760f7cb268SWen Gong 	.request_peer_stats_info_cmdid = WMI_TLV_REQUEST_PEER_STATS_INFO_CMDID,
4277ca996ec5SMichal Kazior 	.set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID,
4278ca996ec5SMichal Kazior 	.network_list_offload_config_cmdid =
4279ca996ec5SMichal Kazior 				WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID,
4280ca996ec5SMichal Kazior 	.gtk_offload_cmdid = WMI_TLV_GTK_OFFLOAD_CMDID,
4281ca996ec5SMichal Kazior 	.csa_offload_enable_cmdid = WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID,
4282ca996ec5SMichal Kazior 	.csa_offload_chanswitch_cmdid = WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID,
4283ca996ec5SMichal Kazior 	.chatter_set_mode_cmdid = WMI_TLV_CHATTER_SET_MODE_CMDID,
4284ca996ec5SMichal Kazior 	.peer_tid_addba_cmdid = WMI_TLV_PEER_TID_ADDBA_CMDID,
4285ca996ec5SMichal Kazior 	.peer_tid_delba_cmdid = WMI_TLV_PEER_TID_DELBA_CMDID,
4286ca996ec5SMichal Kazior 	.sta_dtim_ps_method_cmdid = WMI_TLV_STA_DTIM_PS_METHOD_CMDID,
4287ca996ec5SMichal Kazior 	.sta_uapsd_auto_trig_cmdid = WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID,
4288ca996ec5SMichal Kazior 	.sta_keepalive_cmd = WMI_TLV_STA_KEEPALIVE_CMDID,
4289ca996ec5SMichal Kazior 	.echo_cmdid = WMI_TLV_ECHO_CMDID,
4290ca996ec5SMichal Kazior 	.pdev_utf_cmdid = WMI_TLV_PDEV_UTF_CMDID,
4291ca996ec5SMichal Kazior 	.dbglog_cfg_cmdid = WMI_TLV_DBGLOG_CFG_CMDID,
4292ca996ec5SMichal Kazior 	.pdev_qvit_cmdid = WMI_TLV_PDEV_QVIT_CMDID,
4293ca996ec5SMichal Kazior 	.pdev_ftm_intg_cmdid = WMI_TLV_PDEV_FTM_INTG_CMDID,
4294ca996ec5SMichal Kazior 	.vdev_set_keepalive_cmdid = WMI_TLV_VDEV_SET_KEEPALIVE_CMDID,
4295ca996ec5SMichal Kazior 	.vdev_get_keepalive_cmdid = WMI_TLV_VDEV_GET_KEEPALIVE_CMDID,
4296ca996ec5SMichal Kazior 	.force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID,
4297ca996ec5SMichal Kazior 	.gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID,
4298ca996ec5SMichal Kazior 	.gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID,
4299e98199a8SRyan Hsu 	.pdev_get_temperature_cmdid = WMI_TLV_PDEV_GET_TEMPERATURE_CMDID,
43006d492fe2SMichal Kazior 	.vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
4301ad45c888SMarek Puzyniak 	.tdls_set_state_cmdid = WMI_TLV_TDLS_SET_STATE_CMDID,
4302ad45c888SMarek Puzyniak 	.tdls_peer_update_cmdid = WMI_TLV_TDLS_PEER_UPDATE_CMDID,
43035b272e30SMichal Kazior 	.adaptive_qcs_cmdid = WMI_TLV_RESMGR_ADAPTIVE_OCS_CMDID,
4304772b4aeeSRaja Mani 	.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
4305772b4aeeSRaja Mani 	.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
4306772b4aeeSRaja Mani 	.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
4307772b4aeeSRaja Mani 	.wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
4308772b4aeeSRaja Mani 	.wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
4309772b4aeeSRaja Mani 	.wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
4310772b4aeeSRaja Mani 	.wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
4311772b4aeeSRaja Mani 	.peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
4312772b4aeeSRaja Mani 	.peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
4313772b4aeeSRaja Mani 	.rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
4314772b4aeeSRaja Mani 	.oem_req_cmdid = WMI_CMD_UNSUPPORTED,
4315772b4aeeSRaja Mani 	.nan_cmdid = WMI_CMD_UNSUPPORTED,
4316772b4aeeSRaja Mani 	.vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
4317772b4aeeSRaja Mani 	.qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
4318772b4aeeSRaja Mani 	.pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
4319772b4aeeSRaja Mani 	.pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
4320772b4aeeSRaja Mani 	.peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
4321772b4aeeSRaja Mani 	.peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
4322772b4aeeSRaja Mani 	.peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
4323772b4aeeSRaja Mani 	.pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
4324772b4aeeSRaja Mani 	.pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
4325772b4aeeSRaja Mani 	.pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
4326772b4aeeSRaja Mani 	.pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
4327772b4aeeSRaja Mani 	.pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
4328772b4aeeSRaja Mani 	.pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
4329772b4aeeSRaja Mani 	.tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
4330772b4aeeSRaja Mani 	.fwtest_cmdid = WMI_CMD_UNSUPPORTED,
4331772b4aeeSRaja Mani 	.vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
4332772b4aeeSRaja Mani 	.peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
4333772b4aeeSRaja Mani 	.pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
4334772b4aeeSRaja Mani 	.pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
4335772b4aeeSRaja Mani 	.pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
4336ca996ec5SMichal Kazior };
4337ca996ec5SMichal Kazior 
4338ca996ec5SMichal Kazior static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
4339ca996ec5SMichal Kazior 	.tx_chain_mask = WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK,
4340ca996ec5SMichal Kazior 	.rx_chain_mask = WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK,
4341ca996ec5SMichal Kazior 	.txpower_limit2g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G,
4342ca996ec5SMichal Kazior 	.txpower_limit5g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G,
4343ca996ec5SMichal Kazior 	.txpower_scale = WMI_TLV_PDEV_PARAM_TXPOWER_SCALE,
4344ca996ec5SMichal Kazior 	.beacon_gen_mode = WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE,
4345ca996ec5SMichal Kazior 	.beacon_tx_mode = WMI_TLV_PDEV_PARAM_BEACON_TX_MODE,
4346ca996ec5SMichal Kazior 	.resmgr_offchan_mode = WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
4347ca996ec5SMichal Kazior 	.protection_mode = WMI_TLV_PDEV_PARAM_PROTECTION_MODE,
4348ca996ec5SMichal Kazior 	.dynamic_bw = WMI_TLV_PDEV_PARAM_DYNAMIC_BW,
4349ca996ec5SMichal Kazior 	.non_agg_sw_retry_th = WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
4350ca996ec5SMichal Kazior 	.agg_sw_retry_th = WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH,
4351ca996ec5SMichal Kazior 	.sta_kickout_th = WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH,
4352ca996ec5SMichal Kazior 	.ac_aggrsize_scaling = WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING,
4353ca996ec5SMichal Kazior 	.ltr_enable = WMI_TLV_PDEV_PARAM_LTR_ENABLE,
4354ca996ec5SMichal Kazior 	.ltr_ac_latency_be = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE,
4355ca996ec5SMichal Kazior 	.ltr_ac_latency_bk = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK,
4356ca996ec5SMichal Kazior 	.ltr_ac_latency_vi = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI,
4357ca996ec5SMichal Kazior 	.ltr_ac_latency_vo = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO,
4358ca996ec5SMichal Kazior 	.ltr_ac_latency_timeout = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
4359ca996ec5SMichal Kazior 	.ltr_sleep_override = WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
4360ca996ec5SMichal Kazior 	.ltr_rx_override = WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE,
4361ca996ec5SMichal Kazior 	.ltr_tx_activity_timeout = WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
4362ca996ec5SMichal Kazior 	.l1ss_enable = WMI_TLV_PDEV_PARAM_L1SS_ENABLE,
4363ca996ec5SMichal Kazior 	.dsleep_enable = WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE,
4364ca996ec5SMichal Kazior 	.pcielp_txbuf_flush = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
4365ca996ec5SMichal Kazior 	.pcielp_txbuf_watermark = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
4366ca996ec5SMichal Kazior 	.pcielp_txbuf_tmo_en = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
4367ca996ec5SMichal Kazior 	.pcielp_txbuf_tmo_value = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
4368ca996ec5SMichal Kazior 	.pdev_stats_update_period = WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
4369ca996ec5SMichal Kazior 	.vdev_stats_update_period = WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
4370ca996ec5SMichal Kazior 	.peer_stats_update_period = WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
4371ca996ec5SMichal Kazior 	.bcnflt_stats_update_period =
4372ca996ec5SMichal Kazior 				WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
4373ca996ec5SMichal Kazior 	.pmf_qos = WMI_TLV_PDEV_PARAM_PMF_QOS,
4374ca996ec5SMichal Kazior 	.arp_ac_override = WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE,
4375ca996ec5SMichal Kazior 	.dcs = WMI_TLV_PDEV_PARAM_DCS,
4376ca996ec5SMichal Kazior 	.ani_enable = WMI_TLV_PDEV_PARAM_ANI_ENABLE,
4377ca996ec5SMichal Kazior 	.ani_poll_period = WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD,
4378ca996ec5SMichal Kazior 	.ani_listen_period = WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD,
4379ca996ec5SMichal Kazior 	.ani_ofdm_level = WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL,
4380ca996ec5SMichal Kazior 	.ani_cck_level = WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL,
4381ca996ec5SMichal Kazior 	.dyntxchain = WMI_TLV_PDEV_PARAM_DYNTXCHAIN,
4382ca996ec5SMichal Kazior 	.proxy_sta = WMI_TLV_PDEV_PARAM_PROXY_STA,
4383ca996ec5SMichal Kazior 	.idle_ps_config = WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG,
4384ca996ec5SMichal Kazior 	.power_gating_sleep = WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP,
4385ca996ec5SMichal Kazior 	.fast_channel_reset = WMI_TLV_PDEV_PARAM_UNSUPPORTED,
4386ca996ec5SMichal Kazior 	.burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR,
4387ca996ec5SMichal Kazior 	.burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE,
4388a7bd3e99SPeter Oh 	.cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
4389d86561ffSRaja Mani 	.aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
4390d86561ffSRaja Mani 	.rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4391d86561ffSRaja Mani 	.smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
4392d86561ffSRaja Mani 	.igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
4393d86561ffSRaja Mani 	.igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
4394d86561ffSRaja Mani 	.antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
4395d86561ffSRaja Mani 	.rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
4396d86561ffSRaja Mani 	.set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
4397d86561ffSRaja Mani 	.proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4398d86561ffSRaja Mani 	.set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4399d86561ffSRaja Mani 	.set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
4400d86561ffSRaja Mani 	.remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
4401d86561ffSRaja Mani 	.peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
4402d86561ffSRaja Mani 	.igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
4403d86561ffSRaja Mani 	.block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
4404d86561ffSRaja Mani 	.set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4405d86561ffSRaja Mani 	.set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4406d86561ffSRaja Mani 	.set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4407d86561ffSRaja Mani 	.txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4408d86561ffSRaja Mani 	.set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4409d86561ffSRaja Mani 	.set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4410d86561ffSRaja Mani 	.en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
4411d86561ffSRaja Mani 	.mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
4412d86561ffSRaja Mani 	.noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
4413d86561ffSRaja Mani 	.noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
4414d86561ffSRaja Mani 	.dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
4415d86561ffSRaja Mani 	.set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
4416d86561ffSRaja Mani 	.atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
4417d86561ffSRaja Mani 	.atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
4418d86561ffSRaja Mani 	.ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
4419d86561ffSRaja Mani 	.mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
4420d86561ffSRaja Mani 	.sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
4421d86561ffSRaja Mani 	.signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
4422d86561ffSRaja Mani 	.signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
4423d86561ffSRaja Mani 	.enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
4424d86561ffSRaja Mani 	.enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
4425d86561ffSRaja Mani 	.cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
4426d86561ffSRaja Mani 	.rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
4427d86561ffSRaja Mani 	.pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
4428d86561ffSRaja Mani 	.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
4429d86561ffSRaja Mani 	.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
4430d86561ffSRaja Mani 	.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
44311382993fSWen Gong 	.rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
44321382993fSWen Gong 	.rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
44332289bef2SWen Gong 	.peer_stats_info_enable = WMI_TLV_PDEV_PARAM_PEER_STATS_INFO_ENABLE,
4434ca996ec5SMichal Kazior };
4435ca996ec5SMichal Kazior 
4436c0e33fe6SRakesh Pillai static struct wmi_peer_param_map wmi_tlv_peer_param_map = {
4437c0e33fe6SRakesh Pillai 	.smps_state = WMI_TLV_PEER_SMPS_STATE,
4438c0e33fe6SRakesh Pillai 	.ampdu = WMI_TLV_PEER_AMPDU,
4439c0e33fe6SRakesh Pillai 	.authorize = WMI_TLV_PEER_AUTHORIZE,
4440c0e33fe6SRakesh Pillai 	.chan_width = WMI_TLV_PEER_CHAN_WIDTH,
4441c0e33fe6SRakesh Pillai 	.nss = WMI_TLV_PEER_NSS,
4442c0e33fe6SRakesh Pillai 	.use_4addr = WMI_TLV_PEER_USE_4ADDR,
4443c0e33fe6SRakesh Pillai 	.membership = WMI_TLV_PEER_MEMBERSHIP,
4444c0e33fe6SRakesh Pillai 	.user_pos = WMI_TLV_PEER_USERPOS,
4445c0e33fe6SRakesh Pillai 	.crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED,
4446c0e33fe6SRakesh Pillai 	.tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR,
4447c0e33fe6SRakesh Pillai 	.set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S,
4448c0e33fe6SRakesh Pillai 	.ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH,
4449c0e33fe6SRakesh Pillai 	.phymode = WMI_TLV_PEER_PHYMODE,
4450c0e33fe6SRakesh Pillai 	.use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR,
4451c0e33fe6SRakesh Pillai 	.dummy_var = WMI_TLV_PEER_DUMMY_VAR,
4452c0e33fe6SRakesh Pillai };
4453c0e33fe6SRakesh Pillai 
4454ca996ec5SMichal Kazior static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
4455ca996ec5SMichal Kazior 	.rts_threshold = WMI_TLV_VDEV_PARAM_RTS_THRESHOLD,
4456ca996ec5SMichal Kazior 	.fragmentation_threshold = WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
4457ca996ec5SMichal Kazior 	.beacon_interval = WMI_TLV_VDEV_PARAM_BEACON_INTERVAL,
4458ca996ec5SMichal Kazior 	.listen_interval = WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL,
4459ca996ec5SMichal Kazior 	.multicast_rate = WMI_TLV_VDEV_PARAM_MULTICAST_RATE,
4460ca996ec5SMichal Kazior 	.mgmt_tx_rate = WMI_TLV_VDEV_PARAM_MGMT_TX_RATE,
4461ca996ec5SMichal Kazior 	.slot_time = WMI_TLV_VDEV_PARAM_SLOT_TIME,
4462ca996ec5SMichal Kazior 	.preamble = WMI_TLV_VDEV_PARAM_PREAMBLE,
4463ca996ec5SMichal Kazior 	.swba_time = WMI_TLV_VDEV_PARAM_SWBA_TIME,
4464ca996ec5SMichal Kazior 	.wmi_vdev_stats_update_period = WMI_TLV_VDEV_STATS_UPDATE_PERIOD,
4465ca996ec5SMichal Kazior 	.wmi_vdev_pwrsave_ageout_time = WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME,
4466ca996ec5SMichal Kazior 	.wmi_vdev_host_swba_interval = WMI_TLV_VDEV_HOST_SWBA_INTERVAL,
4467ca996ec5SMichal Kazior 	.dtim_period = WMI_TLV_VDEV_PARAM_DTIM_PERIOD,
4468ca996ec5SMichal Kazior 	.wmi_vdev_oc_scheduler_air_time_limit =
4469ca996ec5SMichal Kazior 				WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
4470ca996ec5SMichal Kazior 	.wds = WMI_TLV_VDEV_PARAM_WDS,
4471ca996ec5SMichal Kazior 	.atim_window = WMI_TLV_VDEV_PARAM_ATIM_WINDOW,
4472ca996ec5SMichal Kazior 	.bmiss_count_max = WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX,
4473ca996ec5SMichal Kazior 	.bmiss_first_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT,
4474ca996ec5SMichal Kazior 	.bmiss_final_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT,
4475ca996ec5SMichal Kazior 	.feature_wmm = WMI_TLV_VDEV_PARAM_FEATURE_WMM,
4476ca996ec5SMichal Kazior 	.chwidth = WMI_TLV_VDEV_PARAM_CHWIDTH,
4477ca996ec5SMichal Kazior 	.chextoffset = WMI_TLV_VDEV_PARAM_CHEXTOFFSET,
4478ca996ec5SMichal Kazior 	.disable_htprotection =	WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION,
4479ca996ec5SMichal Kazior 	.sta_quickkickout = WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT,
4480ca996ec5SMichal Kazior 	.mgmt_rate = WMI_TLV_VDEV_PARAM_MGMT_RATE,
4481ca996ec5SMichal Kazior 	.protection_mode = WMI_TLV_VDEV_PARAM_PROTECTION_MODE,
4482ca996ec5SMichal Kazior 	.fixed_rate = WMI_TLV_VDEV_PARAM_FIXED_RATE,
4483ca996ec5SMichal Kazior 	.sgi = WMI_TLV_VDEV_PARAM_SGI,
4484ca996ec5SMichal Kazior 	.ldpc = WMI_TLV_VDEV_PARAM_LDPC,
4485ca996ec5SMichal Kazior 	.tx_stbc = WMI_TLV_VDEV_PARAM_TX_STBC,
4486ca996ec5SMichal Kazior 	.rx_stbc = WMI_TLV_VDEV_PARAM_RX_STBC,
4487ca996ec5SMichal Kazior 	.intra_bss_fwd = WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD,
4488ca996ec5SMichal Kazior 	.def_keyid = WMI_TLV_VDEV_PARAM_DEF_KEYID,
4489ca996ec5SMichal Kazior 	.nss = WMI_TLV_VDEV_PARAM_NSS,
4490ca996ec5SMichal Kazior 	.bcast_data_rate = WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE,
4491ca996ec5SMichal Kazior 	.mcast_data_rate = WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE,
4492ca996ec5SMichal Kazior 	.mcast_indicate = WMI_TLV_VDEV_PARAM_MCAST_INDICATE,
4493ca996ec5SMichal Kazior 	.dhcp_indicate = WMI_TLV_VDEV_PARAM_DHCP_INDICATE,
4494ca996ec5SMichal Kazior 	.unknown_dest_indicate = WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
4495ca996ec5SMichal Kazior 	.ap_keepalive_min_idle_inactive_time_secs =
4496ca996ec5SMichal Kazior 		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
4497ca996ec5SMichal Kazior 	.ap_keepalive_max_idle_inactive_time_secs =
4498ca996ec5SMichal Kazior 		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
4499ca996ec5SMichal Kazior 	.ap_keepalive_max_unresponsive_time_secs =
4500ca996ec5SMichal Kazior 		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
4501ca996ec5SMichal Kazior 	.ap_enable_nawds = WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS,
4502ca996ec5SMichal Kazior 	.mcast2ucast_set = WMI_TLV_VDEV_PARAM_UNSUPPORTED,
4503ca996ec5SMichal Kazior 	.enable_rtscts = WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS,
4504ca996ec5SMichal Kazior 	.txbf = WMI_TLV_VDEV_PARAM_TXBF,
4505ca996ec5SMichal Kazior 	.packet_powersave = WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE,
4506ca996ec5SMichal Kazior 	.drop_unencry = WMI_TLV_VDEV_PARAM_DROP_UNENCRY,
4507ca996ec5SMichal Kazior 	.tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
4508ca996ec5SMichal Kazior 	.ap_detect_out_of_sync_sleeping_sta_time_secs =
4509ca996ec5SMichal Kazior 					WMI_TLV_VDEV_PARAM_UNSUPPORTED,
451093841a15SRaja Mani 	.rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
451193841a15SRaja Mani 	.cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
451293841a15SRaja Mani 	.mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
451393841a15SRaja Mani 	.rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
451493841a15SRaja Mani 	.vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
451593841a15SRaja Mani 	.vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
451693841a15SRaja Mani 	.early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
451793841a15SRaja Mani 	.early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
451893841a15SRaja Mani 	.early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
451993841a15SRaja Mani 	.early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
452093841a15SRaja Mani 	.early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
452193841a15SRaja Mani 	.early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
452293841a15SRaja Mani 	.proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
452393841a15SRaja Mani 	.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
452493841a15SRaja Mani 	.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
452593841a15SRaja Mani 	.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
4526ca996ec5SMichal Kazior };
4527ca996ec5SMichal Kazior 
4528ca996ec5SMichal Kazior static const struct wmi_ops wmi_tlv_ops = {
4529ca996ec5SMichal Kazior 	.rx = ath10k_wmi_tlv_op_rx,
4530ca996ec5SMichal Kazior 	.map_svc = wmi_tlv_svc_map,
4531cea19a6cSCarl Huang 	.map_svc_ext = wmi_tlv_svc_map_ext,
4532ca996ec5SMichal Kazior 
4533ca996ec5SMichal Kazior 	.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
4534ca996ec5SMichal Kazior 	.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
4535dc405152SRakesh Pillai 	.pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev,
4536cc123facSRakesh Pillai 	.pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev,
4537ca996ec5SMichal Kazior 	.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
4538ca996ec5SMichal Kazior 	.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
4539ca996ec5SMichal Kazior 	.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
4540ca996ec5SMichal Kazior 	.pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
4541991adf71SRaja Mani 	.pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
4542991adf71SRaja Mani 	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
4543ca996ec5SMichal Kazior 	.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
4544ca996ec5SMichal Kazior 	.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
4545cea19a6cSCarl Huang 	.pull_svc_avail = ath10k_wmi_tlv_op_pull_svc_avail,
4546ca996ec5SMichal Kazior 	.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
4547c1a4654aSMichal Kazior 	.pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
4548f5431e87SJanusz Dziedzic 	.pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
454984d4911bSMichal Kazior 	.pull_echo_ev = ath10k_wmi_tlv_op_pull_echo_ev,
455008e75ea8SVivek Natarajan 	.get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
4551ca996ec5SMichal Kazior 
4552ca996ec5SMichal Kazior 	.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
4553ca996ec5SMichal Kazior 	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
4554ca996ec5SMichal Kazior 	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
4555ca996ec5SMichal Kazior 	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
4556ca996ec5SMichal Kazior 	.gen_init = ath10k_wmi_tlv_op_gen_init,
4557ca996ec5SMichal Kazior 	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
4558ca996ec5SMichal Kazior 	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
4559ca996ec5SMichal Kazior 	.gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
4560ca996ec5SMichal Kazior 	.gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
4561ca996ec5SMichal Kazior 	.gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
4562ca996ec5SMichal Kazior 	.gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
4563ca996ec5SMichal Kazior 	.gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
4564ca996ec5SMichal Kazior 	.gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
4565ca996ec5SMichal Kazior 	.gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
4566ca996ec5SMichal Kazior 	.gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
45676d492fe2SMichal Kazior 	.gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
4568ca996ec5SMichal Kazior 	.gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
4569ca996ec5SMichal Kazior 	.gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
4570ca996ec5SMichal Kazior 	.gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
4571ca996ec5SMichal Kazior 	.gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
4572ca996ec5SMichal Kazior 	.gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
4573ca996ec5SMichal Kazior 	.gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
4574ca996ec5SMichal Kazior 	.gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
4575ca996ec5SMichal Kazior 	.gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
4576ca996ec5SMichal Kazior 	.gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
457760e1d0fbSCarl Huang 	.gen_scan_prob_req_oui = ath10k_wmi_tlv_op_gen_scan_prob_req_oui,
4578ca996ec5SMichal Kazior 	.gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
4579ca996ec5SMichal Kazior 	.gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
4580ca996ec5SMichal Kazior 	.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
45810f7cb268SWen Gong 	.gen_request_peer_stats_info = ath10k_wmi_tlv_op_gen_request_peer_stats_info,
4582ca996ec5SMichal Kazior 	.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
4583ca996ec5SMichal Kazior 	/* .gen_mgmt_tx = not implemented; HTT is used */
458438a1390eSRakesh Pillai 	.gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send,
4585c730c477SRakesh Pillai 	.cleanup_mgmt_tx_send = ath10k_wmi_tlv_op_cleanup_mgmt_tx_send,
4586ca996ec5SMichal Kazior 	.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
4587ca996ec5SMichal Kazior 	.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
4588ca996ec5SMichal Kazior 	.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
4589cfb353c0SYu Wang 	.gen_pdev_set_quiet_mode = ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode,
4590e98199a8SRyan Hsu 	.gen_pdev_get_temperature = ath10k_wmi_tlv_op_gen_pdev_get_temperature,
4591dc8ab278SRajkumar Manoharan 	/* .gen_addba_clear_resp not implemented */
459265c0893dSRajkumar Manoharan 	/* .gen_addba_send not implemented */
459311597413SRajkumar Manoharan 	/* .gen_addba_set_resp not implemented */
459450abef85SRajkumar Manoharan 	/* .gen_delba_send not implemented */
4595be9ce9d8SMichal Kazior 	.gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
45964c4955feSMichal Kazior 	.gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
4597369242b4SMichal Kazior 	.gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
45980c7e477cSJanusz Dziedzic 	.gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
45996e8b188bSJanusz Dziedzic 	.gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
4600f5431e87SJanusz Dziedzic 	.gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
4601f5431e87SJanusz Dziedzic 	.gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
4602f5431e87SJanusz Dziedzic 	.gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
4603d4976104SJanusz Dziedzic 	.gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
4604d4976104SJanusz Dziedzic 	.gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
4605ce834e28SWen Gong 	.gen_wow_config_pno = ath10k_wmi_tlv_op_gen_config_pno,
4606ad45c888SMarek Puzyniak 	.gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
4607ad45c888SMarek Puzyniak 	.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
46085b272e30SMichal Kazior 	.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
4609bc6f9ae6SManikanta Pubbisetty 	.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
4610a7368c39SSurabhi Vishnoi 	.get_vdev_subtype = ath10k_wmi_tlv_op_get_vdev_subtype,
4611e25854f2SMichal Kazior 	.gen_echo = ath10k_wmi_tlv_op_gen_echo,
46125a401f36SMichal Kazior 	.gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
46135a401f36SMichal Kazior 	.gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
46148e1debd8SSebastian Gottschall 	/* .gen_gpio_config not implemented */
46158e1debd8SSebastian Gottschall 	/* .gen_gpio_output not implemented */
4616ca996ec5SMichal Kazior };
4617ca996ec5SMichal Kazior 
46183fab30f7STamizh chelvam static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
46193fab30f7STamizh chelvam 	.auth = WMI_TLV_PEER_AUTH,
46203fab30f7STamizh chelvam 	.qos = WMI_TLV_PEER_QOS,
46213fab30f7STamizh chelvam 	.need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
46223fab30f7STamizh chelvam 	.need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
46233fab30f7STamizh chelvam 	.apsd = WMI_TLV_PEER_APSD,
46243fab30f7STamizh chelvam 	.ht = WMI_TLV_PEER_HT,
46253fab30f7STamizh chelvam 	.bw40 = WMI_TLV_PEER_40MHZ,
46263fab30f7STamizh chelvam 	.stbc = WMI_TLV_PEER_STBC,
46273fab30f7STamizh chelvam 	.ldbc = WMI_TLV_PEER_LDPC,
46283fab30f7STamizh chelvam 	.dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
46293fab30f7STamizh chelvam 	.static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
46303fab30f7STamizh chelvam 	.spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
46313fab30f7STamizh chelvam 	.vht = WMI_TLV_PEER_VHT,
46323fab30f7STamizh chelvam 	.bw80 = WMI_TLV_PEER_80MHZ,
46333fab30f7STamizh chelvam 	.pmf = WMI_TLV_PEER_PMF,
4634bc1efd73SSebastian Gottschall 	.bw160 = WMI_TLV_PEER_160MHZ,
46353fab30f7STamizh chelvam };
46363fab30f7STamizh chelvam 
4637ca996ec5SMichal Kazior /************/
4638ca996ec5SMichal Kazior /* TLV init */
4639ca996ec5SMichal Kazior /************/
4640ca996ec5SMichal Kazior 
ath10k_wmi_tlv_attach(struct ath10k * ar)4641ca996ec5SMichal Kazior void ath10k_wmi_tlv_attach(struct ath10k *ar)
4642ca996ec5SMichal Kazior {
4643ca996ec5SMichal Kazior 	ar->wmi.cmd = &wmi_tlv_cmd_map;
4644ca996ec5SMichal Kazior 	ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
4645ca996ec5SMichal Kazior 	ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
4646c0e33fe6SRakesh Pillai 	ar->wmi.peer_param = &wmi_tlv_peer_param_map;
4647ca996ec5SMichal Kazior 	ar->wmi.ops = &wmi_tlv_ops;
46483fab30f7STamizh chelvam 	ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
4649ca996ec5SMichal Kazior }
4650