xref: /freebsd/sys/contrib/dev/athk/ath10k/wmi-tlv.c (revision 07724ba62b4c432ea04dce9465a5ab6e2c3f5a0d)
1da8fa4e3SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2da8fa4e3SBjoern A. Zeeb /*
3da8fa4e3SBjoern A. Zeeb  * Copyright (c) 2005-2011 Atheros Communications Inc.
4da8fa4e3SBjoern A. Zeeb  * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
5da8fa4e3SBjoern A. Zeeb  * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
6da8fa4e3SBjoern A. Zeeb  */
7da8fa4e3SBjoern A. Zeeb #include "core.h"
8da8fa4e3SBjoern A. Zeeb #include "debug.h"
9da8fa4e3SBjoern A. Zeeb #include "mac.h"
10da8fa4e3SBjoern A. Zeeb #include "hw.h"
11da8fa4e3SBjoern A. Zeeb #include "wmi.h"
12da8fa4e3SBjoern A. Zeeb #include "wmi-ops.h"
13da8fa4e3SBjoern A. Zeeb #include "wmi-tlv.h"
14da8fa4e3SBjoern A. Zeeb #include "p2p.h"
15da8fa4e3SBjoern A. Zeeb #include "testmode.h"
16da8fa4e3SBjoern A. Zeeb #include <linux/bitfield.h>
17da8fa4e3SBjoern A. Zeeb 
18da8fa4e3SBjoern A. Zeeb /***************/
19da8fa4e3SBjoern A. Zeeb /* TLV helpers */
20da8fa4e3SBjoern A. Zeeb /**************/
21da8fa4e3SBjoern A. Zeeb 
22da8fa4e3SBjoern A. Zeeb struct wmi_tlv_policy {
23da8fa4e3SBjoern A. Zeeb 	size_t min_len;
24da8fa4e3SBjoern A. Zeeb };
25da8fa4e3SBjoern A. Zeeb 
26da8fa4e3SBjoern A. Zeeb static const struct wmi_tlv_policy wmi_tlv_policies[] = {
27da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_ARRAY_BYTE]
28da8fa4e3SBjoern A. Zeeb 		= { .min_len = 0 },
29da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_ARRAY_UINT32]
30da8fa4e3SBjoern A. Zeeb 		= { .min_len = 0 },
31da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_SCAN_EVENT]
32da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_scan_event) },
33da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR]
34da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_mgmt_rx_ev) },
35da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT]
36da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_chan_info_event) },
37da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT]
38da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_vdev_start_response_event) },
39da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT]
40da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_peer_sta_kickout_event) },
41da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT]
42da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_host_swba_event) },
43da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_TIM_INFO]
44da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tim_info) },
45da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO]
46da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_p2p_noa_info) },
47da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT]
48da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_svc_rdy_ev) },
49da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES]
50da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct hal_reg_capabilities) },
51da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ]
52da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wlan_host_mem_req) },
53da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_READY_EVENT]
54da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_rdy_ev) },
55da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]
56da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
57da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
58da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
59da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
60da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_p2p_noa_ev) },
61da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_ROAM_EVENT]
62da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_roam_ev) },
63da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO]
64da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_wow_event_info) },
65da8fa4e3SBjoern A. Zeeb 	[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT]
66da8fa4e3SBjoern A. Zeeb 		= { .min_len = sizeof(struct wmi_tlv_tx_pause_ev) },
67da8fa4e3SBjoern A. Zeeb };
68da8fa4e3SBjoern A. Zeeb 
69da8fa4e3SBjoern A. Zeeb static int
70da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
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)71da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_iter(struct ath10k *ar, const void *ptr, size_t len,
72da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
73da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_iter(struct ath10k *ar, const u8 *ptr, size_t len,
74da8fa4e3SBjoern A. Zeeb #endif
75da8fa4e3SBjoern A. Zeeb 		    int (*iter)(struct ath10k *ar, u16 tag, u16 len,
76da8fa4e3SBjoern A. Zeeb 				const void *ptr, void *data),
77da8fa4e3SBjoern A. Zeeb 		    void *data)
78da8fa4e3SBjoern A. Zeeb {
79da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
80da8fa4e3SBjoern A. Zeeb 	const void *begin = ptr;
81da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
82da8fa4e3SBjoern A. Zeeb 	const u8 *begin = ptr;
83da8fa4e3SBjoern A. Zeeb #endif
84da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv *tlv;
85da8fa4e3SBjoern A. Zeeb 	u16 tlv_tag, tlv_len;
86da8fa4e3SBjoern A. Zeeb 	int ret;
87da8fa4e3SBjoern A. Zeeb 
88da8fa4e3SBjoern A. Zeeb 	while (len > 0) {
89da8fa4e3SBjoern A. Zeeb 		if (len < sizeof(*tlv)) {
90da8fa4e3SBjoern A. Zeeb 			ath10k_dbg(ar, ATH10K_DBG_WMI,
91da8fa4e3SBjoern A. Zeeb 				   "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
92da8fa4e3SBjoern A. Zeeb 				   ptr - begin, len, sizeof(*tlv));
93da8fa4e3SBjoern A. Zeeb 			return -EINVAL;
94da8fa4e3SBjoern A. Zeeb 		}
95da8fa4e3SBjoern A. Zeeb 
96da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
97da8fa4e3SBjoern A. Zeeb 		tlv = ptr;
98da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
99da8fa4e3SBjoern A. Zeeb 		tlv = (const void *)ptr;
100da8fa4e3SBjoern A. Zeeb #endif
101da8fa4e3SBjoern A. Zeeb 		tlv_tag = __le16_to_cpu(tlv->tag);
102da8fa4e3SBjoern A. Zeeb 		tlv_len = __le16_to_cpu(tlv->len);
103da8fa4e3SBjoern A. Zeeb 		ptr += sizeof(*tlv);
104da8fa4e3SBjoern A. Zeeb 		len -= sizeof(*tlv);
105da8fa4e3SBjoern A. Zeeb 
106da8fa4e3SBjoern A. Zeeb 		if (tlv_len > len) {
107da8fa4e3SBjoern A. Zeeb 			ath10k_dbg(ar, ATH10K_DBG_WMI,
108da8fa4e3SBjoern A. Zeeb 				   "wmi tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",
109da8fa4e3SBjoern A. Zeeb 				   tlv_tag, ptr - begin, len, tlv_len);
110da8fa4e3SBjoern A. Zeeb 			return -EINVAL;
111da8fa4e3SBjoern A. Zeeb 		}
112da8fa4e3SBjoern A. Zeeb 
113da8fa4e3SBjoern A. Zeeb 		if (tlv_tag < ARRAY_SIZE(wmi_tlv_policies) &&
114da8fa4e3SBjoern A. Zeeb 		    wmi_tlv_policies[tlv_tag].min_len &&
115da8fa4e3SBjoern A. Zeeb 		    wmi_tlv_policies[tlv_tag].min_len > tlv_len) {
116da8fa4e3SBjoern A. Zeeb 			ath10k_dbg(ar, ATH10K_DBG_WMI,
117da8fa4e3SBjoern A. Zeeb 				   "wmi tlv parse failure of tag %u at byte %zd (%u bytes is less than min length %zu)\n",
118da8fa4e3SBjoern A. Zeeb 				   tlv_tag, ptr - begin, tlv_len,
119da8fa4e3SBjoern A. Zeeb 				   wmi_tlv_policies[tlv_tag].min_len);
120da8fa4e3SBjoern A. Zeeb 			return -EINVAL;
121da8fa4e3SBjoern A. Zeeb 		}
122da8fa4e3SBjoern A. Zeeb 
123da8fa4e3SBjoern A. Zeeb 		ret = iter(ar, tlv_tag, tlv_len, ptr, data);
124da8fa4e3SBjoern A. Zeeb 		if (ret)
125da8fa4e3SBjoern A. Zeeb 			return ret;
126da8fa4e3SBjoern A. Zeeb 
127da8fa4e3SBjoern A. Zeeb 		ptr += tlv_len;
128da8fa4e3SBjoern A. Zeeb 		len -= tlv_len;
129da8fa4e3SBjoern A. Zeeb 	}
130da8fa4e3SBjoern A. Zeeb 
131da8fa4e3SBjoern A. Zeeb 	return 0;
132da8fa4e3SBjoern A. Zeeb }
133da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_iter_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)134da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_iter_parse(struct ath10k *ar, u16 tag, u16 len,
135da8fa4e3SBjoern A. Zeeb 				     const void *ptr, void *data)
136da8fa4e3SBjoern A. Zeeb {
137da8fa4e3SBjoern A. Zeeb 	const void **tb = data;
138da8fa4e3SBjoern A. Zeeb 
139da8fa4e3SBjoern A. Zeeb 	if (tag < WMI_TLV_TAG_MAX)
140da8fa4e3SBjoern A. Zeeb 		tb[tag] = ptr;
141da8fa4e3SBjoern A. Zeeb 
142da8fa4e3SBjoern A. Zeeb 	return 0;
143da8fa4e3SBjoern A. Zeeb }
144da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_parse(struct ath10k * ar,const void ** tb,const void * ptr,size_t len)145da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_parse(struct ath10k *ar, const void **tb,
146da8fa4e3SBjoern A. Zeeb 				const void *ptr, size_t len)
147da8fa4e3SBjoern A. Zeeb {
148da8fa4e3SBjoern A. Zeeb 	return ath10k_wmi_tlv_iter(ar, ptr, len, ath10k_wmi_tlv_iter_parse,
149da8fa4e3SBjoern A. Zeeb 				   (void *)tb);
150da8fa4e3SBjoern A. Zeeb }
151da8fa4e3SBjoern A. Zeeb 
152da8fa4e3SBjoern A. Zeeb static const void **
ath10k_wmi_tlv_parse_alloc(struct ath10k * ar,const void * ptr,size_t len,gfp_t gfp)153da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
154da8fa4e3SBjoern A. Zeeb 			   size_t len, gfp_t gfp)
155da8fa4e3SBjoern A. Zeeb {
156da8fa4e3SBjoern A. Zeeb 	const void **tb;
157da8fa4e3SBjoern A. Zeeb 	int ret;
158da8fa4e3SBjoern A. Zeeb 
159da8fa4e3SBjoern A. Zeeb 	tb = kcalloc(WMI_TLV_TAG_MAX, sizeof(*tb), gfp);
160da8fa4e3SBjoern A. Zeeb 	if (!tb)
161da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
162da8fa4e3SBjoern A. Zeeb 
163da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_parse(ar, tb, ptr, len);
164da8fa4e3SBjoern A. Zeeb 	if (ret) {
165da8fa4e3SBjoern A. Zeeb 		kfree(tb);
166da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(ret);
167da8fa4e3SBjoern A. Zeeb 	}
168da8fa4e3SBjoern A. Zeeb 
169da8fa4e3SBjoern A. Zeeb 	return tb;
170da8fa4e3SBjoern A. Zeeb }
171da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_len(const void * ptr)172da8fa4e3SBjoern A. Zeeb static u16 ath10k_wmi_tlv_len(const void *ptr)
173da8fa4e3SBjoern A. Zeeb {
174da8fa4e3SBjoern A. Zeeb 	return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len);
175da8fa4e3SBjoern A. Zeeb }
176da8fa4e3SBjoern A. Zeeb 
177da8fa4e3SBjoern A. Zeeb /**************/
178da8fa4e3SBjoern A. Zeeb /* TLV events */
179da8fa4e3SBjoern A. Zeeb /**************/
ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k * ar,struct sk_buff * skb)180da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
181da8fa4e3SBjoern A. Zeeb 					      struct sk_buff *skb)
182da8fa4e3SBjoern A. Zeeb {
183da8fa4e3SBjoern A. Zeeb 	const void **tb;
184da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_bcn_tx_status_ev *ev;
185da8fa4e3SBjoern A. Zeeb 	struct ath10k_vif *arvif;
186da8fa4e3SBjoern A. Zeeb 	u32 vdev_id, tx_status;
187da8fa4e3SBjoern A. Zeeb 	int ret;
188da8fa4e3SBjoern A. Zeeb 
189da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
190da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
191da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
192da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
193da8fa4e3SBjoern A. Zeeb 		return ret;
194da8fa4e3SBjoern A. Zeeb 	}
195da8fa4e3SBjoern A. Zeeb 
196da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT];
197da8fa4e3SBjoern A. Zeeb 	if (!ev) {
198da8fa4e3SBjoern A. Zeeb 		kfree(tb);
199da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
200da8fa4e3SBjoern A. Zeeb 	}
201da8fa4e3SBjoern A. Zeeb 
202da8fa4e3SBjoern A. Zeeb 	tx_status = __le32_to_cpu(ev->tx_status);
203da8fa4e3SBjoern A. Zeeb 	vdev_id = __le32_to_cpu(ev->vdev_id);
204da8fa4e3SBjoern A. Zeeb 
205da8fa4e3SBjoern A. Zeeb 	switch (tx_status) {
206da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_BCN_TX_STATUS_OK:
207da8fa4e3SBjoern A. Zeeb 		break;
208da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_BCN_TX_STATUS_XRETRY:
209da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_BCN_TX_STATUS_DROP:
210da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_BCN_TX_STATUS_FILTERED:
211da8fa4e3SBjoern A. Zeeb 		/* FIXME: It's probably worth telling mac80211 to stop the
212da8fa4e3SBjoern A. Zeeb 		 * interface as it is crippled.
213da8fa4e3SBjoern A. Zeeb 		 */
214da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d",
215da8fa4e3SBjoern A. Zeeb 			    vdev_id, tx_status);
216da8fa4e3SBjoern A. Zeeb 		break;
217da8fa4e3SBjoern A. Zeeb 	}
218da8fa4e3SBjoern A. Zeeb 
219da8fa4e3SBjoern A. Zeeb 	arvif = ath10k_get_arvif(ar, vdev_id);
220*07724ba6SBjoern A. Zeeb 	if (arvif && arvif->is_up && arvif->vif->bss_conf.csa_active)
221da8fa4e3SBjoern A. Zeeb 		ieee80211_queue_work(ar->hw, &arvif->ap_csa_work);
222da8fa4e3SBjoern A. Zeeb 
223da8fa4e3SBjoern A. Zeeb 	kfree(tb);
224da8fa4e3SBjoern A. Zeeb 	return 0;
225da8fa4e3SBjoern A. Zeeb }
226da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k * ar,struct sk_buff * skb)227da8fa4e3SBjoern A. Zeeb static void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar,
228da8fa4e3SBjoern A. Zeeb 						  struct sk_buff *skb)
229da8fa4e3SBjoern A. Zeeb {
230da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n");
231da8fa4e3SBjoern A. Zeeb 	complete(&ar->vdev_delete_done);
232da8fa4e3SBjoern A. Zeeb }
233da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)234da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 len,
235da8fa4e3SBjoern A. Zeeb 						const void *ptr, void *data)
236da8fa4e3SBjoern A. Zeeb {
237da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_peer_stats_info *stat = ptr;
238da8fa4e3SBjoern A. Zeeb 	struct ieee80211_sta *sta;
239da8fa4e3SBjoern A. Zeeb 	struct ath10k_sta *arsta;
240da8fa4e3SBjoern A. Zeeb 
241da8fa4e3SBjoern A. Zeeb 	if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
242da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
243da8fa4e3SBjoern A. Zeeb 
244da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
245da8fa4e3SBjoern A. Zeeb 		   "wmi tlv stats peer addr %pMF rx rate code 0x%x bit rate %d kbps\n",
246da8fa4e3SBjoern A. Zeeb 		   stat->peer_macaddr.addr,
247da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(stat->last_rx_rate_code),
248da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(stat->last_rx_bitrate_kbps));
249da8fa4e3SBjoern A. Zeeb 
250da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
251da8fa4e3SBjoern A. Zeeb 		   "wmi tlv stats tx rate code 0x%x bit rate %d kbps\n",
252da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(stat->last_tx_rate_code),
253da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(stat->last_tx_bitrate_kbps));
254da8fa4e3SBjoern A. Zeeb 
255da8fa4e3SBjoern A. Zeeb 	rcu_read_lock();
256da8fa4e3SBjoern A. Zeeb 	sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
257da8fa4e3SBjoern A. Zeeb 	if (!sta) {
258da8fa4e3SBjoern A. Zeeb 		rcu_read_unlock();
259da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "not found station for peer stats\n");
260da8fa4e3SBjoern A. Zeeb 		return -EINVAL;
261da8fa4e3SBjoern A. Zeeb 	}
262da8fa4e3SBjoern A. Zeeb 
263da8fa4e3SBjoern A. Zeeb 	arsta = (struct ath10k_sta *)sta->drv_priv;
264da8fa4e3SBjoern A. Zeeb 	arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
265da8fa4e3SBjoern A. Zeeb 	arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
266da8fa4e3SBjoern A. Zeeb 	arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
267da8fa4e3SBjoern A. Zeeb 	arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
268da8fa4e3SBjoern A. Zeeb 	rcu_read_unlock();
269da8fa4e3SBjoern A. Zeeb 
270da8fa4e3SBjoern A. Zeeb 	return 0;
271da8fa4e3SBjoern A. Zeeb }
272da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k * ar,struct sk_buff * skb)273da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
274da8fa4e3SBjoern A. Zeeb 						  struct sk_buff *skb)
275da8fa4e3SBjoern A. Zeeb {
276da8fa4e3SBjoern A. Zeeb 	const void **tb;
277da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_peer_stats_info_ev *ev;
278da8fa4e3SBjoern A. Zeeb 	const void *data;
279da8fa4e3SBjoern A. Zeeb 	u32 num_peer_stats;
280da8fa4e3SBjoern A. Zeeb 	int ret;
281da8fa4e3SBjoern A. Zeeb 
282da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
283da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
284da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
285da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
286da8fa4e3SBjoern A. Zeeb 		return ret;
287da8fa4e3SBjoern A. Zeeb 	}
288da8fa4e3SBjoern A. Zeeb 
289da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STATS_INFO_EVENT];
290da8fa4e3SBjoern A. Zeeb 	data = tb[WMI_TLV_TAG_ARRAY_STRUCT];
291da8fa4e3SBjoern A. Zeeb 
292da8fa4e3SBjoern A. Zeeb 	if (!ev || !data) {
293da8fa4e3SBjoern A. Zeeb 		kfree(tb);
294da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
295da8fa4e3SBjoern A. Zeeb 	}
296da8fa4e3SBjoern A. Zeeb 
297da8fa4e3SBjoern A. Zeeb 	num_peer_stats = __le32_to_cpu(ev->num_peers);
298da8fa4e3SBjoern A. Zeeb 
299da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
300da8fa4e3SBjoern A. Zeeb 		   "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
301da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->vdev_id),
302da8fa4e3SBjoern A. Zeeb 		   num_peer_stats,
303da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->more_data));
304da8fa4e3SBjoern A. Zeeb 
305da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
306da8fa4e3SBjoern A. Zeeb 				  ath10k_wmi_tlv_parse_peer_stats_info, NULL);
307da8fa4e3SBjoern A. Zeeb 	if (ret)
308da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
309da8fa4e3SBjoern A. Zeeb 
310da8fa4e3SBjoern A. Zeeb 	kfree(tb);
311da8fa4e3SBjoern A. Zeeb 	return 0;
312da8fa4e3SBjoern A. Zeeb }
313da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_peer_stats_info(struct ath10k * ar,struct sk_buff * skb)314da8fa4e3SBjoern A. Zeeb static void ath10k_wmi_tlv_event_peer_stats_info(struct ath10k *ar,
315da8fa4e3SBjoern A. Zeeb 						 struct sk_buff *skb)
316da8fa4e3SBjoern A. Zeeb {
317da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PEER_STATS_INFO_EVENTID\n");
318da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_tlv_op_pull_peer_stats_info(ar, skb);
319da8fa4e3SBjoern A. Zeeb 	complete(&ar->peer_stats_info_complete);
320da8fa4e3SBjoern A. Zeeb }
321da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_diag_data(struct ath10k * ar,struct sk_buff * skb)322da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
323da8fa4e3SBjoern A. Zeeb 					  struct sk_buff *skb)
324da8fa4e3SBjoern A. Zeeb {
325da8fa4e3SBjoern A. Zeeb 	const void **tb;
326da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_diag_data_ev *ev;
327da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_diag_item *item;
328da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
329da8fa4e3SBjoern A. Zeeb 	const void *data;
330da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
331da8fa4e3SBjoern A. Zeeb 	const u8 *data;
332da8fa4e3SBjoern A. Zeeb #endif
333da8fa4e3SBjoern A. Zeeb 	int ret, num_items, len;
334da8fa4e3SBjoern A. Zeeb 
335da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
336da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
337da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
338da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
339da8fa4e3SBjoern A. Zeeb 		return ret;
340da8fa4e3SBjoern A. Zeeb 	}
341da8fa4e3SBjoern A. Zeeb 
342da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT];
343da8fa4e3SBjoern A. Zeeb 	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
344da8fa4e3SBjoern A. Zeeb 	if (!ev || !data) {
345da8fa4e3SBjoern A. Zeeb 		kfree(tb);
346da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
347da8fa4e3SBjoern A. Zeeb 	}
348da8fa4e3SBjoern A. Zeeb 
349da8fa4e3SBjoern A. Zeeb 	num_items = __le32_to_cpu(ev->num_items);
350da8fa4e3SBjoern A. Zeeb 	len = ath10k_wmi_tlv_len(data);
351da8fa4e3SBjoern A. Zeeb 
352da8fa4e3SBjoern A. Zeeb 	while (num_items--) {
353da8fa4e3SBjoern A. Zeeb 		if (len == 0)
354da8fa4e3SBjoern A. Zeeb 			break;
355da8fa4e3SBjoern A. Zeeb 		if (len < sizeof(*item)) {
356da8fa4e3SBjoern A. Zeeb 			ath10k_warn(ar, "failed to parse diag data: can't fit item header\n");
357da8fa4e3SBjoern A. Zeeb 			break;
358da8fa4e3SBjoern A. Zeeb 		}
359da8fa4e3SBjoern A. Zeeb 
360da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
361da8fa4e3SBjoern A. Zeeb 		item = data;
362da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
363da8fa4e3SBjoern A. Zeeb 		item = (const void *)data;
364da8fa4e3SBjoern A. Zeeb #endif
365da8fa4e3SBjoern A. Zeeb 
366da8fa4e3SBjoern A. Zeeb 		if (len < sizeof(*item) + __le16_to_cpu(item->len)) {
367da8fa4e3SBjoern A. Zeeb 			ath10k_warn(ar, "failed to parse diag data: item is too long\n");
368da8fa4e3SBjoern A. Zeeb 			break;
369da8fa4e3SBjoern A. Zeeb 		}
370da8fa4e3SBjoern A. Zeeb 
371da8fa4e3SBjoern A. Zeeb 		trace_ath10k_wmi_diag_container(ar,
372da8fa4e3SBjoern A. Zeeb 						item->type,
373da8fa4e3SBjoern A. Zeeb 						__le32_to_cpu(item->timestamp),
374da8fa4e3SBjoern A. Zeeb 						__le32_to_cpu(item->code),
375da8fa4e3SBjoern A. Zeeb 						__le16_to_cpu(item->len),
376da8fa4e3SBjoern A. Zeeb 						item->payload);
377da8fa4e3SBjoern A. Zeeb 
378da8fa4e3SBjoern A. Zeeb 		len -= sizeof(*item);
379da8fa4e3SBjoern A. Zeeb 		len -= roundup(__le16_to_cpu(item->len), 4);
380da8fa4e3SBjoern A. Zeeb 
381da8fa4e3SBjoern A. Zeeb 		data += sizeof(*item);
382da8fa4e3SBjoern A. Zeeb 		data += roundup(__le16_to_cpu(item->len), 4);
383da8fa4e3SBjoern A. Zeeb 	}
384da8fa4e3SBjoern A. Zeeb 
385da8fa4e3SBjoern A. Zeeb 	if (num_items != -1 || len != 0)
386da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n",
387da8fa4e3SBjoern A. Zeeb 			    num_items, len);
388da8fa4e3SBjoern A. Zeeb 
389da8fa4e3SBjoern A. Zeeb 	kfree(tb);
390da8fa4e3SBjoern A. Zeeb 	return 0;
391da8fa4e3SBjoern A. Zeeb }
392da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_diag(struct ath10k * ar,struct sk_buff * skb)393da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
394da8fa4e3SBjoern A. Zeeb 				     struct sk_buff *skb)
395da8fa4e3SBjoern A. Zeeb {
396da8fa4e3SBjoern A. Zeeb 	const void **tb;
397da8fa4e3SBjoern A. Zeeb 	const void *data;
398da8fa4e3SBjoern A. Zeeb 	int ret, len;
399da8fa4e3SBjoern A. Zeeb 
400da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
401da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
402da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
403da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
404da8fa4e3SBjoern A. Zeeb 		return ret;
405da8fa4e3SBjoern A. Zeeb 	}
406da8fa4e3SBjoern A. Zeeb 
407da8fa4e3SBjoern A. Zeeb 	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
408da8fa4e3SBjoern A. Zeeb 	if (!data) {
409da8fa4e3SBjoern A. Zeeb 		kfree(tb);
410da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
411da8fa4e3SBjoern A. Zeeb 	}
412da8fa4e3SBjoern A. Zeeb 	len = ath10k_wmi_tlv_len(data);
413da8fa4e3SBjoern A. Zeeb 
414da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len);
415da8fa4e3SBjoern A. Zeeb 	trace_ath10k_wmi_diag(ar, data, len);
416da8fa4e3SBjoern A. Zeeb 
417da8fa4e3SBjoern A. Zeeb 	kfree(tb);
418da8fa4e3SBjoern A. Zeeb 	return 0;
419da8fa4e3SBjoern A. Zeeb }
420da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_p2p_noa(struct ath10k * ar,struct sk_buff * skb)421da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_event_p2p_noa(struct ath10k *ar,
422da8fa4e3SBjoern A. Zeeb 					struct sk_buff *skb)
423da8fa4e3SBjoern A. Zeeb {
424da8fa4e3SBjoern A. Zeeb 	const void **tb;
425da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_p2p_noa_ev *ev;
426da8fa4e3SBjoern A. Zeeb 	const struct wmi_p2p_noa_info *noa;
427da8fa4e3SBjoern A. Zeeb 	int ret, vdev_id;
428da8fa4e3SBjoern A. Zeeb 
429da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
430da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
431da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
432da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
433da8fa4e3SBjoern A. Zeeb 		return ret;
434da8fa4e3SBjoern A. Zeeb 	}
435da8fa4e3SBjoern A. Zeeb 
436da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT];
437da8fa4e3SBjoern A. Zeeb 	noa = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO];
438da8fa4e3SBjoern A. Zeeb 
439da8fa4e3SBjoern A. Zeeb 	if (!ev || !noa) {
440da8fa4e3SBjoern A. Zeeb 		kfree(tb);
441da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
442da8fa4e3SBjoern A. Zeeb 	}
443da8fa4e3SBjoern A. Zeeb 
444da8fa4e3SBjoern A. Zeeb 	vdev_id = __le32_to_cpu(ev->vdev_id);
445da8fa4e3SBjoern A. Zeeb 
446da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
447da8fa4e3SBjoern A. Zeeb 		   "wmi tlv p2p noa vdev_id %i descriptors %u\n",
448da8fa4e3SBjoern A. Zeeb 		   vdev_id, noa->num_descriptors);
449da8fa4e3SBjoern A. Zeeb 
450da8fa4e3SBjoern A. Zeeb 	ath10k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
451da8fa4e3SBjoern A. Zeeb 	kfree(tb);
452da8fa4e3SBjoern A. Zeeb 	return 0;
453da8fa4e3SBjoern A. Zeeb }
454da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_tx_pause(struct ath10k * ar,struct sk_buff * skb)455da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
456da8fa4e3SBjoern A. Zeeb 					 struct sk_buff *skb)
457da8fa4e3SBjoern A. Zeeb {
458da8fa4e3SBjoern A. Zeeb 	const void **tb;
459da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_tx_pause_ev *ev;
460da8fa4e3SBjoern A. Zeeb 	int ret, vdev_id;
461da8fa4e3SBjoern A. Zeeb 	u32 pause_id, action, vdev_map, peer_id, tid_map;
462da8fa4e3SBjoern A. Zeeb 
463da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
464da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
465da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
466da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
467da8fa4e3SBjoern A. Zeeb 		return ret;
468da8fa4e3SBjoern A. Zeeb 	}
469da8fa4e3SBjoern A. Zeeb 
470da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT];
471da8fa4e3SBjoern A. Zeeb 	if (!ev) {
472da8fa4e3SBjoern A. Zeeb 		kfree(tb);
473da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
474da8fa4e3SBjoern A. Zeeb 	}
475da8fa4e3SBjoern A. Zeeb 
476da8fa4e3SBjoern A. Zeeb 	pause_id = __le32_to_cpu(ev->pause_id);
477da8fa4e3SBjoern A. Zeeb 	action = __le32_to_cpu(ev->action);
478da8fa4e3SBjoern A. Zeeb 	vdev_map = __le32_to_cpu(ev->vdev_map);
479da8fa4e3SBjoern A. Zeeb 	peer_id = __le32_to_cpu(ev->peer_id);
480da8fa4e3SBjoern A. Zeeb 	tid_map = __le32_to_cpu(ev->tid_map);
481da8fa4e3SBjoern A. Zeeb 
482da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
483da8fa4e3SBjoern A. Zeeb 		   "wmi tlv tx pause pause_id %u action %u vdev_map 0x%08x peer_id %u tid_map 0x%08x\n",
484da8fa4e3SBjoern A. Zeeb 		   pause_id, action, vdev_map, peer_id, tid_map);
485da8fa4e3SBjoern A. Zeeb 
486da8fa4e3SBjoern A. Zeeb 	switch (pause_id) {
487da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_MCC:
488da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
489da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
490da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_AP_PS:
491da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
492da8fa4e3SBjoern A. Zeeb 		for (vdev_id = 0; vdev_map; vdev_id++) {
493da8fa4e3SBjoern A. Zeeb 			if (!(vdev_map & BIT(vdev_id)))
494da8fa4e3SBjoern A. Zeeb 				continue;
495da8fa4e3SBjoern A. Zeeb 
496da8fa4e3SBjoern A. Zeeb 			vdev_map &= ~BIT(vdev_id);
497da8fa4e3SBjoern A. Zeeb 			ath10k_mac_handle_tx_pause_vdev(ar, vdev_id, pause_id,
498da8fa4e3SBjoern A. Zeeb 							action);
499da8fa4e3SBjoern A. Zeeb 		}
500da8fa4e3SBjoern A. Zeeb 		break;
501da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
502da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
503da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
504da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_ID_HOST:
505da8fa4e3SBjoern A. Zeeb 		ath10k_dbg(ar, ATH10K_DBG_MAC,
506da8fa4e3SBjoern A. Zeeb 			   "mac ignoring unsupported tx pause id %d\n",
507da8fa4e3SBjoern A. Zeeb 			   pause_id);
508da8fa4e3SBjoern A. Zeeb 		break;
509da8fa4e3SBjoern A. Zeeb 	default:
510da8fa4e3SBjoern A. Zeeb 		ath10k_dbg(ar, ATH10K_DBG_MAC,
511da8fa4e3SBjoern A. Zeeb 			   "mac ignoring unknown tx pause vdev %d\n",
512da8fa4e3SBjoern A. Zeeb 			   pause_id);
513da8fa4e3SBjoern A. Zeeb 		break;
514da8fa4e3SBjoern A. Zeeb 	}
515da8fa4e3SBjoern A. Zeeb 
516da8fa4e3SBjoern A. Zeeb 	kfree(tb);
517da8fa4e3SBjoern A. Zeeb 	return 0;
518da8fa4e3SBjoern A. Zeeb }
519da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k * ar,struct sk_buff * skb)520da8fa4e3SBjoern A. Zeeb static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
521da8fa4e3SBjoern A. Zeeb 						     struct sk_buff *skb)
522da8fa4e3SBjoern A. Zeeb {
523da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_rfkill_state_change_ev *ev;
524da8fa4e3SBjoern A. Zeeb 	const void **tb;
525da8fa4e3SBjoern A. Zeeb 	bool radio;
526da8fa4e3SBjoern A. Zeeb 	int ret;
527da8fa4e3SBjoern A. Zeeb 
528da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
529da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
530da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
531da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar,
532da8fa4e3SBjoern A. Zeeb 			    "failed to parse rfkill state change event: %d\n",
533da8fa4e3SBjoern A. Zeeb 			    ret);
534da8fa4e3SBjoern A. Zeeb 		return;
535da8fa4e3SBjoern A. Zeeb 	}
536da8fa4e3SBjoern A. Zeeb 
537da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
538da8fa4e3SBjoern A. Zeeb 	if (!ev) {
539da8fa4e3SBjoern A. Zeeb 		kfree(tb);
540da8fa4e3SBjoern A. Zeeb 		return;
541da8fa4e3SBjoern A. Zeeb 	}
542da8fa4e3SBjoern A. Zeeb 
543da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_MAC,
544da8fa4e3SBjoern A. Zeeb 		   "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
545da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->gpio_pin_num),
546da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->int_type),
547da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->radio_state));
548da8fa4e3SBjoern A. Zeeb 
549da8fa4e3SBjoern A. Zeeb 	radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
550da8fa4e3SBjoern A. Zeeb 
551da8fa4e3SBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
552da8fa4e3SBjoern A. Zeeb 
553da8fa4e3SBjoern A. Zeeb 	if (!radio)
554da8fa4e3SBjoern A. Zeeb 		ar->hw_rfkill_on = true;
555da8fa4e3SBjoern A. Zeeb 
556da8fa4e3SBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
557da8fa4e3SBjoern A. Zeeb 
558da8fa4e3SBjoern A. Zeeb 	/* notify cfg80211 radio state change */
559da8fa4e3SBjoern A. Zeeb 	ath10k_mac_rfkill_enable_radio(ar, radio);
560da8fa4e3SBjoern A. Zeeb 	wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
561da8fa4e3SBjoern A. Zeeb }
562da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_temperature(struct ath10k * ar,struct sk_buff * skb)563da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
564da8fa4e3SBjoern A. Zeeb 					    struct sk_buff *skb)
565da8fa4e3SBjoern A. Zeeb {
566da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_pdev_temperature_event *ev;
567da8fa4e3SBjoern A. Zeeb 
568da8fa4e3SBjoern A. Zeeb 	ev = (struct wmi_tlv_pdev_temperature_event *)skb->data;
569da8fa4e3SBjoern A. Zeeb 	if (WARN_ON(skb->len < sizeof(*ev)))
570da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
571da8fa4e3SBjoern A. Zeeb 
572da8fa4e3SBjoern A. Zeeb 	ath10k_thermal_event_temperature(ar, __le32_to_cpu(ev->temperature));
573da8fa4e3SBjoern A. Zeeb 	return 0;
574da8fa4e3SBjoern A. Zeeb }
575da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_event_tdls_peer(struct ath10k * ar,struct sk_buff * skb)576da8fa4e3SBjoern A. Zeeb static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
577da8fa4e3SBjoern A. Zeeb {
578da8fa4e3SBjoern A. Zeeb 	struct ieee80211_sta *station;
579da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_tdls_peer_event *ev;
580da8fa4e3SBjoern A. Zeeb 	const void **tb;
581da8fa4e3SBjoern A. Zeeb 	struct ath10k_vif *arvif;
582da8fa4e3SBjoern A. Zeeb 
583da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
584da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
585da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "tdls peer failed to parse tlv");
586da8fa4e3SBjoern A. Zeeb 		return;
587da8fa4e3SBjoern A. Zeeb 	}
588da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT];
589da8fa4e3SBjoern A. Zeeb 	if (!ev) {
590da8fa4e3SBjoern A. Zeeb 		kfree(tb);
591da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "tdls peer NULL event");
592da8fa4e3SBjoern A. Zeeb 		return;
593da8fa4e3SBjoern A. Zeeb 	}
594da8fa4e3SBjoern A. Zeeb 
595da8fa4e3SBjoern A. Zeeb 	switch (__le32_to_cpu(ev->peer_reason)) {
596da8fa4e3SBjoern A. Zeeb 	case WMI_TDLS_TEARDOWN_REASON_TX:
597da8fa4e3SBjoern A. Zeeb 	case WMI_TDLS_TEARDOWN_REASON_RSSI:
598da8fa4e3SBjoern A. Zeeb 	case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
599da8fa4e3SBjoern A. Zeeb 		rcu_read_lock();
600da8fa4e3SBjoern A. Zeeb 		station = ieee80211_find_sta_by_ifaddr(ar->hw,
601da8fa4e3SBjoern A. Zeeb 						       ev->peer_macaddr.addr,
602da8fa4e3SBjoern A. Zeeb 						       NULL);
603da8fa4e3SBjoern A. Zeeb 		if (!station) {
604da8fa4e3SBjoern A. Zeeb 			ath10k_warn(ar, "did not find station from tdls peer event");
605da8fa4e3SBjoern A. Zeeb 			goto exit;
606da8fa4e3SBjoern A. Zeeb 		}
607*07724ba6SBjoern A. Zeeb 
608da8fa4e3SBjoern A. Zeeb 		arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
609*07724ba6SBjoern A. Zeeb 		if (!arvif) {
610*07724ba6SBjoern A. Zeeb 			ath10k_warn(ar, "no vif for vdev_id %d found",
611*07724ba6SBjoern A. Zeeb 				    __le32_to_cpu(ev->vdev_id));
612*07724ba6SBjoern A. Zeeb 			goto exit;
613*07724ba6SBjoern A. Zeeb 		}
614*07724ba6SBjoern A. Zeeb 
615da8fa4e3SBjoern A. Zeeb 		ieee80211_tdls_oper_request(
616da8fa4e3SBjoern A. Zeeb 					arvif->vif, station->addr,
617da8fa4e3SBjoern A. Zeeb 					NL80211_TDLS_TEARDOWN,
618da8fa4e3SBjoern A. Zeeb 					WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
619da8fa4e3SBjoern A. Zeeb 					GFP_ATOMIC
620da8fa4e3SBjoern A. Zeeb 					);
621da8fa4e3SBjoern A. Zeeb 		break;
622da8fa4e3SBjoern A. Zeeb 	default:
623da8fa4e3SBjoern A. Zeeb 		kfree(tb);
624da8fa4e3SBjoern A. Zeeb 		return;
625da8fa4e3SBjoern A. Zeeb 	}
626da8fa4e3SBjoern A. Zeeb 
627da8fa4e3SBjoern A. Zeeb exit:
628da8fa4e3SBjoern A. Zeeb 	rcu_read_unlock();
629da8fa4e3SBjoern A. Zeeb 	kfree(tb);
630da8fa4e3SBjoern A. Zeeb }
631da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k * ar,struct sk_buff * skb)632da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
633da8fa4e3SBjoern A. Zeeb 						 struct sk_buff *skb)
634da8fa4e3SBjoern A. Zeeb {
635da8fa4e3SBjoern A. Zeeb 	struct wmi_peer_delete_resp_ev_arg *arg;
636da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv_hdr;
637da8fa4e3SBjoern A. Zeeb 
638da8fa4e3SBjoern A. Zeeb 	tlv_hdr = (struct wmi_tlv *)skb->data;
639da8fa4e3SBjoern A. Zeeb 	arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value;
640da8fa4e3SBjoern A. Zeeb 
641da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id);
642da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr);
643da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n");
644da8fa4e3SBjoern A. Zeeb 
645da8fa4e3SBjoern A. Zeeb 	complete(&ar->peer_delete_done);
646da8fa4e3SBjoern A. Zeeb 
647da8fa4e3SBjoern A. Zeeb 	return 0;
648da8fa4e3SBjoern A. Zeeb }
649da8fa4e3SBjoern A. Zeeb 
650da8fa4e3SBjoern A. Zeeb /***********/
651da8fa4e3SBjoern A. Zeeb /* TLV ops */
652da8fa4e3SBjoern A. Zeeb /***********/
653da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_rx(struct ath10k * ar,struct sk_buff * skb)654da8fa4e3SBjoern A. Zeeb static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
655da8fa4e3SBjoern A. Zeeb {
656da8fa4e3SBjoern A. Zeeb 	struct wmi_cmd_hdr *cmd_hdr;
657da8fa4e3SBjoern A. Zeeb 	enum wmi_tlv_event_id id;
658da8fa4e3SBjoern A. Zeeb 	bool consumed;
659da8fa4e3SBjoern A. Zeeb 
660da8fa4e3SBjoern A. Zeeb 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
661da8fa4e3SBjoern A. Zeeb 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
662da8fa4e3SBjoern A. Zeeb 
663da8fa4e3SBjoern A. Zeeb 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
664da8fa4e3SBjoern A. Zeeb 		goto out;
665da8fa4e3SBjoern A. Zeeb 
666da8fa4e3SBjoern A. Zeeb 	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
667da8fa4e3SBjoern A. Zeeb 
668da8fa4e3SBjoern A. Zeeb 	consumed = ath10k_tm_event_wmi(ar, id, skb);
669da8fa4e3SBjoern A. Zeeb 
670da8fa4e3SBjoern A. Zeeb 	/* Ready event must be handled normally also in UTF mode so that we
671da8fa4e3SBjoern A. Zeeb 	 * know the UTF firmware has booted, others we are just bypass WMI
672da8fa4e3SBjoern A. Zeeb 	 * events to testmode.
673da8fa4e3SBjoern A. Zeeb 	 */
674da8fa4e3SBjoern A. Zeeb 	if (consumed && id != WMI_TLV_READY_EVENTID) {
675da8fa4e3SBjoern A. Zeeb 		ath10k_dbg(ar, ATH10K_DBG_WMI,
676da8fa4e3SBjoern A. Zeeb 			   "wmi tlv testmode consumed 0x%x\n", id);
677da8fa4e3SBjoern A. Zeeb 		goto out;
678da8fa4e3SBjoern A. Zeeb 	}
679da8fa4e3SBjoern A. Zeeb 
680da8fa4e3SBjoern A. Zeeb 	switch (id) {
681da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_MGMT_RX_EVENTID:
682da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_mgmt_rx(ar, skb);
683da8fa4e3SBjoern A. Zeeb 		/* mgmt_rx() owns the skb now! */
684da8fa4e3SBjoern A. Zeeb 		return;
685da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_SCAN_EVENTID:
686da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_scan(ar, skb);
687da8fa4e3SBjoern A. Zeeb 		break;
688da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_CHAN_INFO_EVENTID:
689da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_chan_info(ar, skb);
690da8fa4e3SBjoern A. Zeeb 		break;
691da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_ECHO_EVENTID:
692da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_echo(ar, skb);
693da8fa4e3SBjoern A. Zeeb 		break;
694da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_DEBUG_MESG_EVENTID:
695da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_debug_mesg(ar, skb);
696da8fa4e3SBjoern A. Zeeb 		break;
697da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_UPDATE_STATS_EVENTID:
698da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_update_stats(ar, skb);
699da8fa4e3SBjoern A. Zeeb 		break;
700da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PEER_STATS_INFO_EVENTID:
701da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_peer_stats_info(ar, skb);
702da8fa4e3SBjoern A. Zeeb 		break;
703da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_VDEV_START_RESP_EVENTID:
704da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_vdev_start_resp(ar, skb);
705da8fa4e3SBjoern A. Zeeb 		break;
706da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_VDEV_STOPPED_EVENTID:
707da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_vdev_stopped(ar, skb);
708da8fa4e3SBjoern A. Zeeb 		break;
709da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_VDEV_DELETE_RESP_EVENTID:
710da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb);
711da8fa4e3SBjoern A. Zeeb 		break;
712da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
713da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_peer_sta_kickout(ar, skb);
714da8fa4e3SBjoern A. Zeeb 		break;
715da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_HOST_SWBA_EVENTID:
716da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_host_swba(ar, skb);
717da8fa4e3SBjoern A. Zeeb 		break;
718da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TBTTOFFSET_UPDATE_EVENTID:
719da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_tbttoffset_update(ar, skb);
720da8fa4e3SBjoern A. Zeeb 		break;
721da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PHYERR_EVENTID:
722da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_phyerr(ar, skb);
723da8fa4e3SBjoern A. Zeeb 		break;
724da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_ROAM_EVENTID:
725da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_roam(ar, skb);
726da8fa4e3SBjoern A. Zeeb 		break;
727da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PROFILE_MATCH:
728da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_profile_match(ar, skb);
729da8fa4e3SBjoern A. Zeeb 		break;
730da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_DEBUG_PRINT_EVENTID:
731da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_debug_print(ar, skb);
732da8fa4e3SBjoern A. Zeeb 		break;
733da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PDEV_QVIT_EVENTID:
734da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_pdev_qvit(ar, skb);
735da8fa4e3SBjoern A. Zeeb 		break;
736da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_WLAN_PROFILE_DATA_EVENTID:
737da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_wlan_profile_data(ar, skb);
738da8fa4e3SBjoern A. Zeeb 		break;
739da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID:
740da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_rtt_measurement_report(ar, skb);
741da8fa4e3SBjoern A. Zeeb 		break;
742da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID:
743da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_tsf_measurement_report(ar, skb);
744da8fa4e3SBjoern A. Zeeb 		break;
745da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_RTT_ERROR_REPORT_EVENTID:
746da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_rtt_error_report(ar, skb);
747da8fa4e3SBjoern A. Zeeb 		break;
748da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_WOW_WAKEUP_HOST_EVENTID:
749da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_wow_wakeup_host(ar, skb);
750da8fa4e3SBjoern A. Zeeb 		break;
751da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_DCS_INTERFERENCE_EVENTID:
752da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_dcs_interference(ar, skb);
753da8fa4e3SBjoern A. Zeeb 		break;
754da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PDEV_TPC_CONFIG_EVENTID:
755da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_pdev_tpc_config(ar, skb);
756da8fa4e3SBjoern A. Zeeb 		break;
757da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PDEV_FTM_INTG_EVENTID:
758da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_pdev_ftm_intg(ar, skb);
759da8fa4e3SBjoern A. Zeeb 		break;
760da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID:
761da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_gtk_offload_status(ar, skb);
762da8fa4e3SBjoern A. Zeeb 		break;
763da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_GTK_REKEY_FAIL_EVENTID:
764da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_gtk_rekey_fail(ar, skb);
765da8fa4e3SBjoern A. Zeeb 		break;
766da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_DELBA_COMPLETE_EVENTID:
767da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_delba_complete(ar, skb);
768da8fa4e3SBjoern A. Zeeb 		break;
769da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_ADDBA_COMPLETE_EVENTID:
770da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_addba_complete(ar, skb);
771da8fa4e3SBjoern A. Zeeb 		break;
772da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID:
773da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
774da8fa4e3SBjoern A. Zeeb 		break;
775da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_SERVICE_READY_EVENTID:
776da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_service_ready(ar, skb);
777da8fa4e3SBjoern A. Zeeb 		return;
778da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_READY_EVENTID:
779da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_ready(ar, skb);
780da8fa4e3SBjoern A. Zeeb 		break;
781da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_SERVICE_AVAILABLE_EVENTID:
782da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_service_available(ar, skb);
783da8fa4e3SBjoern A. Zeeb 		break;
784da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID:
785da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_bcn_tx_status(ar, skb);
786da8fa4e3SBjoern A. Zeeb 		break;
787da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID:
788da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_diag_data(ar, skb);
789da8fa4e3SBjoern A. Zeeb 		break;
790da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_DIAG_EVENTID:
791da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_diag(ar, skb);
792da8fa4e3SBjoern A. Zeeb 		break;
793da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_P2P_NOA_EVENTID:
794da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_p2p_noa(ar, skb);
795da8fa4e3SBjoern A. Zeeb 		break;
796da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TX_PAUSE_EVENTID:
797da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_tx_pause(ar, skb);
798da8fa4e3SBjoern A. Zeeb 		break;
799da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
800da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
801da8fa4e3SBjoern A. Zeeb 		break;
802da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
803da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_temperature(ar, skb);
804da8fa4e3SBjoern A. Zeeb 		break;
805da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TDLS_PEER_EVENTID:
806da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_tdls_peer(ar, skb);
807da8fa4e3SBjoern A. Zeeb 		break;
808da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_PEER_DELETE_RESP_EVENTID:
809da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_event_peer_delete_resp(ar, skb);
810da8fa4e3SBjoern A. Zeeb 		break;
811da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
812da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_mgmt_tx_compl(ar, skb);
813da8fa4e3SBjoern A. Zeeb 		break;
814da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID:
815da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb);
816da8fa4e3SBjoern A. Zeeb 		break;
817da8fa4e3SBjoern A. Zeeb 	default:
818da8fa4e3SBjoern A. Zeeb 		ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id);
819da8fa4e3SBjoern A. Zeeb 		break;
820da8fa4e3SBjoern A. Zeeb 	}
821da8fa4e3SBjoern A. Zeeb 
822da8fa4e3SBjoern A. Zeeb out:
823da8fa4e3SBjoern A. Zeeb 	dev_kfree_skb(skb);
824da8fa4e3SBjoern A. Zeeb }
825da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_scan_ev_arg * arg)826da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
827da8fa4e3SBjoern A. Zeeb 					  struct sk_buff *skb,
828da8fa4e3SBjoern A. Zeeb 					  struct wmi_scan_ev_arg *arg)
829da8fa4e3SBjoern A. Zeeb {
830da8fa4e3SBjoern A. Zeeb 	const void **tb;
831da8fa4e3SBjoern A. Zeeb 	const struct wmi_scan_event *ev;
832da8fa4e3SBjoern A. Zeeb 	int ret;
833da8fa4e3SBjoern A. Zeeb 
834da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
835da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
836da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
837da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
838da8fa4e3SBjoern A. Zeeb 		return ret;
839da8fa4e3SBjoern A. Zeeb 	}
840da8fa4e3SBjoern A. Zeeb 
841da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_SCAN_EVENT];
842da8fa4e3SBjoern A. Zeeb 	if (!ev) {
843da8fa4e3SBjoern A. Zeeb 		kfree(tb);
844da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
845da8fa4e3SBjoern A. Zeeb 	}
846da8fa4e3SBjoern A. Zeeb 
847da8fa4e3SBjoern A. Zeeb 	arg->event_type = ev->event_type;
848da8fa4e3SBjoern A. Zeeb 	arg->reason = ev->reason;
849da8fa4e3SBjoern A. Zeeb 	arg->channel_freq = ev->channel_freq;
850da8fa4e3SBjoern A. Zeeb 	arg->scan_req_id = ev->scan_req_id;
851da8fa4e3SBjoern A. Zeeb 	arg->scan_id = ev->scan_id;
852da8fa4e3SBjoern A. Zeeb 	arg->vdev_id = ev->vdev_id;
853da8fa4e3SBjoern A. Zeeb 
854da8fa4e3SBjoern A. Zeeb 	kfree(tb);
855da8fa4e3SBjoern A. Zeeb 	return 0;
856da8fa4e3SBjoern A. Zeeb }
857da8fa4e3SBjoern A. Zeeb 
858da8fa4e3SBjoern A. Zeeb 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)859da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
860da8fa4e3SBjoern A. Zeeb 					struct wmi_tlv_mgmt_tx_compl_ev_arg *arg)
861da8fa4e3SBjoern A. Zeeb {
862da8fa4e3SBjoern A. Zeeb 	const void **tb;
863da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_mgmt_tx_compl_ev *ev;
864da8fa4e3SBjoern A. Zeeb 	int ret;
865da8fa4e3SBjoern A. Zeeb 
866da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
867da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
868da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
869da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
870da8fa4e3SBjoern A. Zeeb 		return ret;
871da8fa4e3SBjoern A. Zeeb 	}
872da8fa4e3SBjoern A. Zeeb 
873da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
874da8fa4e3SBjoern A. Zeeb 
875da8fa4e3SBjoern A. Zeeb 	arg->desc_id = ev->desc_id;
876da8fa4e3SBjoern A. Zeeb 	arg->status = ev->status;
877da8fa4e3SBjoern A. Zeeb 	arg->pdev_id = ev->pdev_id;
878da8fa4e3SBjoern A. Zeeb 	arg->ppdu_id = ev->ppdu_id;
879da8fa4e3SBjoern A. Zeeb 
880da8fa4e3SBjoern A. Zeeb 	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
881da8fa4e3SBjoern A. Zeeb 		arg->ack_rssi = ev->ack_rssi;
882da8fa4e3SBjoern A. Zeeb 
883da8fa4e3SBjoern A. Zeeb 	kfree(tb);
884da8fa4e3SBjoern A. Zeeb 	return 0;
885da8fa4e3SBjoern A. Zeeb }
886da8fa4e3SBjoern A. Zeeb 
887da8fa4e3SBjoern A. Zeeb struct wmi_tlv_tx_bundle_compl_parse {
888da8fa4e3SBjoern A. Zeeb 	const __le32 *num_reports;
889da8fa4e3SBjoern A. Zeeb 	const __le32 *desc_ids;
890da8fa4e3SBjoern A. Zeeb 	const __le32 *status;
891da8fa4e3SBjoern A. Zeeb 	const __le32 *ppdu_ids;
892da8fa4e3SBjoern A. Zeeb 	const __le32 *ack_rssi;
893da8fa4e3SBjoern A. Zeeb 	bool desc_ids_done;
894da8fa4e3SBjoern A. Zeeb 	bool status_done;
895da8fa4e3SBjoern A. Zeeb 	bool ppdu_ids_done;
896da8fa4e3SBjoern A. Zeeb 	bool ack_rssi_done;
897da8fa4e3SBjoern A. Zeeb };
898da8fa4e3SBjoern A. Zeeb 
899da8fa4e3SBjoern A. Zeeb static int
ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)900da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len,
901da8fa4e3SBjoern A. Zeeb 					  const void *ptr, void *data)
902da8fa4e3SBjoern A. Zeeb {
903da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data;
904da8fa4e3SBjoern A. Zeeb 
905da8fa4e3SBjoern A. Zeeb 	switch (tag) {
906da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT:
907da8fa4e3SBjoern A. Zeeb 		bundle_tx_compl->num_reports = ptr;
908da8fa4e3SBjoern A. Zeeb 		break;
909da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_ARRAY_UINT32:
910da8fa4e3SBjoern A. Zeeb 		if (!bundle_tx_compl->desc_ids_done) {
911da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->desc_ids_done = true;
912da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->desc_ids = ptr;
913da8fa4e3SBjoern A. Zeeb 		} else if (!bundle_tx_compl->status_done) {
914da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->status_done = true;
915da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->status = ptr;
916da8fa4e3SBjoern A. Zeeb 		} else if (!bundle_tx_compl->ppdu_ids_done) {
917da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->ppdu_ids_done = true;
918da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->ppdu_ids = ptr;
919da8fa4e3SBjoern A. Zeeb 		} else if (!bundle_tx_compl->ack_rssi_done) {
920da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->ack_rssi_done = true;
921da8fa4e3SBjoern A. Zeeb 			bundle_tx_compl->ack_rssi = ptr;
922da8fa4e3SBjoern A. Zeeb 		}
923da8fa4e3SBjoern A. Zeeb 		break;
924da8fa4e3SBjoern A. Zeeb 	default:
925da8fa4e3SBjoern A. Zeeb 		break;
926da8fa4e3SBjoern A. Zeeb 	}
927da8fa4e3SBjoern A. Zeeb 	return 0;
928da8fa4e3SBjoern A. Zeeb }
929da8fa4e3SBjoern A. Zeeb 
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)930da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
931da8fa4e3SBjoern A. Zeeb 				struct ath10k *ar, struct sk_buff *skb,
932da8fa4e3SBjoern A. Zeeb 				struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
933da8fa4e3SBjoern A. Zeeb {
934da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { };
935da8fa4e3SBjoern A. Zeeb 	int ret;
936da8fa4e3SBjoern A. Zeeb 
937da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
938da8fa4e3SBjoern A. Zeeb 				  ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse,
939da8fa4e3SBjoern A. Zeeb 				  &bundle_tx_compl);
940da8fa4e3SBjoern A. Zeeb 	if (ret) {
941da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
942da8fa4e3SBjoern A. Zeeb 		return ret;
943da8fa4e3SBjoern A. Zeeb 	}
944da8fa4e3SBjoern A. Zeeb 
945da8fa4e3SBjoern A. Zeeb 	if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids ||
946da8fa4e3SBjoern A. Zeeb 	    !bundle_tx_compl.status)
947da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
948da8fa4e3SBjoern A. Zeeb 
949da8fa4e3SBjoern A. Zeeb 	arg->num_reports = *bundle_tx_compl.num_reports;
950da8fa4e3SBjoern A. Zeeb 	arg->desc_ids = bundle_tx_compl.desc_ids;
951da8fa4e3SBjoern A. Zeeb 	arg->status = bundle_tx_compl.status;
952da8fa4e3SBjoern A. Zeeb 	arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
953da8fa4e3SBjoern A. Zeeb 
954da8fa4e3SBjoern A. Zeeb 	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
955da8fa4e3SBjoern A. Zeeb 		arg->ack_rssi = bundle_tx_compl.ack_rssi;
956da8fa4e3SBjoern A. Zeeb 
957da8fa4e3SBjoern A. Zeeb 	return 0;
958da8fa4e3SBjoern A. Zeeb }
959da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_mgmt_rx_ev_arg * arg)960da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
961da8fa4e3SBjoern A. Zeeb 					     struct sk_buff *skb,
962da8fa4e3SBjoern A. Zeeb 					     struct wmi_mgmt_rx_ev_arg *arg)
963da8fa4e3SBjoern A. Zeeb {
964da8fa4e3SBjoern A. Zeeb 	const void **tb;
965da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_mgmt_rx_ev *ev;
966da8fa4e3SBjoern A. Zeeb 	const u8 *frame;
967da8fa4e3SBjoern A. Zeeb 	u32 msdu_len;
968da8fa4e3SBjoern A. Zeeb 	int ret, i;
969da8fa4e3SBjoern A. Zeeb 
970da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
971da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
972da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
973da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
974da8fa4e3SBjoern A. Zeeb 		return ret;
975da8fa4e3SBjoern A. Zeeb 	}
976da8fa4e3SBjoern A. Zeeb 
977da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR];
978da8fa4e3SBjoern A. Zeeb 	frame = tb[WMI_TLV_TAG_ARRAY_BYTE];
979da8fa4e3SBjoern A. Zeeb 
980da8fa4e3SBjoern A. Zeeb 	if (!ev || !frame) {
981da8fa4e3SBjoern A. Zeeb 		kfree(tb);
982da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
983da8fa4e3SBjoern A. Zeeb 	}
984da8fa4e3SBjoern A. Zeeb 
985da8fa4e3SBjoern A. Zeeb 	arg->channel = ev->channel;
986da8fa4e3SBjoern A. Zeeb 	arg->buf_len = ev->buf_len;
987da8fa4e3SBjoern A. Zeeb 	arg->status = ev->status;
988da8fa4e3SBjoern A. Zeeb 	arg->snr = ev->snr;
989da8fa4e3SBjoern A. Zeeb 	arg->phy_mode = ev->phy_mode;
990da8fa4e3SBjoern A. Zeeb 	arg->rate = ev->rate;
991da8fa4e3SBjoern A. Zeeb 
992da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(ev->rssi); i++)
993da8fa4e3SBjoern A. Zeeb 		arg->rssi[i] = ev->rssi[i];
994da8fa4e3SBjoern A. Zeeb 
995da8fa4e3SBjoern A. Zeeb 	msdu_len = __le32_to_cpu(arg->buf_len);
996da8fa4e3SBjoern A. Zeeb 
997da8fa4e3SBjoern A. Zeeb 	if (skb->len < (frame - skb->data) + msdu_len) {
998da8fa4e3SBjoern A. Zeeb 		kfree(tb);
999da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1000da8fa4e3SBjoern A. Zeeb 	}
1001da8fa4e3SBjoern A. Zeeb 
1002da8fa4e3SBjoern A. Zeeb 	/* shift the sk_buff to point to `frame` */
1003da8fa4e3SBjoern A. Zeeb 	skb_trim(skb, 0);
1004da8fa4e3SBjoern A. Zeeb 	skb_put(skb, frame - skb->data);
1005da8fa4e3SBjoern A. Zeeb 	skb_pull(skb, frame - skb->data);
1006da8fa4e3SBjoern A. Zeeb 	skb_put(skb, msdu_len);
1007da8fa4e3SBjoern A. Zeeb 
1008da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1009da8fa4e3SBjoern A. Zeeb 	return 0;
1010da8fa4e3SBjoern A. Zeeb }
1011da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_ch_info_ev_arg * arg)1012da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar,
1013da8fa4e3SBjoern A. Zeeb 					     struct sk_buff *skb,
1014da8fa4e3SBjoern A. Zeeb 					     struct wmi_ch_info_ev_arg *arg)
1015da8fa4e3SBjoern A. Zeeb {
1016da8fa4e3SBjoern A. Zeeb 	const void **tb;
1017da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_chan_info_event *ev;
1018da8fa4e3SBjoern A. Zeeb 	int ret;
1019da8fa4e3SBjoern A. Zeeb 
1020da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1021da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1022da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1023da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1024da8fa4e3SBjoern A. Zeeb 		return ret;
1025da8fa4e3SBjoern A. Zeeb 	}
1026da8fa4e3SBjoern A. Zeeb 
1027da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT];
1028da8fa4e3SBjoern A. Zeeb 	if (!ev) {
1029da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1030da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1031da8fa4e3SBjoern A. Zeeb 	}
1032da8fa4e3SBjoern A. Zeeb 
1033da8fa4e3SBjoern A. Zeeb 	arg->err_code = ev->err_code;
1034da8fa4e3SBjoern A. Zeeb 	arg->freq = ev->freq;
1035da8fa4e3SBjoern A. Zeeb 	arg->cmd_flags = ev->cmd_flags;
1036da8fa4e3SBjoern A. Zeeb 	arg->noise_floor = ev->noise_floor;
1037da8fa4e3SBjoern A. Zeeb 	arg->rx_clear_count = ev->rx_clear_count;
1038da8fa4e3SBjoern A. Zeeb 	arg->cycle_count = ev->cycle_count;
1039da8fa4e3SBjoern A. Zeeb 	if (test_bit(ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL,
1040da8fa4e3SBjoern A. Zeeb 		     ar->running_fw->fw_file.fw_features))
1041da8fa4e3SBjoern A. Zeeb 		arg->mac_clk_mhz = ev->mac_clk_mhz;
1042da8fa4e3SBjoern A. Zeeb 
1043da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1044da8fa4e3SBjoern A. Zeeb 	return 0;
1045da8fa4e3SBjoern A. Zeeb }
1046da8fa4e3SBjoern A. Zeeb 
1047da8fa4e3SBjoern A. Zeeb static int
ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_vdev_start_ev_arg * arg)1048da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
1049da8fa4e3SBjoern A. Zeeb 				     struct wmi_vdev_start_ev_arg *arg)
1050da8fa4e3SBjoern A. Zeeb {
1051da8fa4e3SBjoern A. Zeeb 	const void **tb;
1052da8fa4e3SBjoern A. Zeeb 	const struct wmi_vdev_start_response_event *ev;
1053da8fa4e3SBjoern A. Zeeb 	int ret;
1054da8fa4e3SBjoern A. Zeeb 
1055da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1056da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1057da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1058da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1059da8fa4e3SBjoern A. Zeeb 		return ret;
1060da8fa4e3SBjoern A. Zeeb 	}
1061da8fa4e3SBjoern A. Zeeb 
1062da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT];
1063da8fa4e3SBjoern A. Zeeb 	if (!ev) {
1064da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1065da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1066da8fa4e3SBjoern A. Zeeb 	}
1067da8fa4e3SBjoern A. Zeeb 
1068da8fa4e3SBjoern A. Zeeb 	skb_pull(skb, sizeof(*ev));
1069da8fa4e3SBjoern A. Zeeb 	arg->vdev_id = ev->vdev_id;
1070da8fa4e3SBjoern A. Zeeb 	arg->req_id = ev->req_id;
1071da8fa4e3SBjoern A. Zeeb 	arg->resp_type = ev->resp_type;
1072da8fa4e3SBjoern A. Zeeb 	arg->status = ev->status;
1073da8fa4e3SBjoern A. Zeeb 
1074da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1075da8fa4e3SBjoern A. Zeeb 	return 0;
1076da8fa4e3SBjoern A. Zeeb }
1077da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_peer_kick_ev_arg * arg)1078da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k *ar,
1079da8fa4e3SBjoern A. Zeeb 					       struct sk_buff *skb,
1080da8fa4e3SBjoern A. Zeeb 					       struct wmi_peer_kick_ev_arg *arg)
1081da8fa4e3SBjoern A. Zeeb {
1082da8fa4e3SBjoern A. Zeeb 	const void **tb;
1083da8fa4e3SBjoern A. Zeeb 	const struct wmi_peer_sta_kickout_event *ev;
1084da8fa4e3SBjoern A. Zeeb 	int ret;
1085da8fa4e3SBjoern A. Zeeb 
1086da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1087da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1088da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1089da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1090da8fa4e3SBjoern A. Zeeb 		return ret;
1091da8fa4e3SBjoern A. Zeeb 	}
1092da8fa4e3SBjoern A. Zeeb 
1093da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT];
1094da8fa4e3SBjoern A. Zeeb 	if (!ev) {
1095da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1096da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1097da8fa4e3SBjoern A. Zeeb 	}
1098da8fa4e3SBjoern A. Zeeb 
1099da8fa4e3SBjoern A. Zeeb 	arg->mac_addr = ev->peer_macaddr.addr;
1100da8fa4e3SBjoern A. Zeeb 
1101da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1102da8fa4e3SBjoern A. Zeeb 	return 0;
1103da8fa4e3SBjoern A. Zeeb }
1104da8fa4e3SBjoern A. Zeeb 
1105da8fa4e3SBjoern A. Zeeb struct wmi_tlv_swba_parse {
1106da8fa4e3SBjoern A. Zeeb 	const struct wmi_host_swba_event *ev;
1107da8fa4e3SBjoern A. Zeeb 	bool tim_done;
1108da8fa4e3SBjoern A. Zeeb 	bool noa_done;
1109da8fa4e3SBjoern A. Zeeb 	size_t n_tim;
1110da8fa4e3SBjoern A. Zeeb 	size_t n_noa;
1111da8fa4e3SBjoern A. Zeeb 	struct wmi_swba_ev_arg *arg;
1112da8fa4e3SBjoern A. Zeeb };
1113da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_swba_tim_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1114da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
1115da8fa4e3SBjoern A. Zeeb 					 const void *ptr, void *data)
1116da8fa4e3SBjoern A. Zeeb {
1117da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_swba_parse *swba = data;
1118da8fa4e3SBjoern A. Zeeb 	struct wmi_tim_info_arg *tim_info_arg;
1119da8fa4e3SBjoern A. Zeeb 	const struct wmi_tim_info *tim_info_ev = ptr;
1120da8fa4e3SBjoern A. Zeeb 
1121da8fa4e3SBjoern A. Zeeb 	if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO)
1122da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1123da8fa4e3SBjoern A. Zeeb 
1124da8fa4e3SBjoern A. Zeeb 	if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info))
1125da8fa4e3SBjoern A. Zeeb 		return -ENOBUFS;
1126da8fa4e3SBjoern A. Zeeb 
1127da8fa4e3SBjoern A. Zeeb 	if (__le32_to_cpu(tim_info_ev->tim_len) >
1128da8fa4e3SBjoern A. Zeeb 	     sizeof(tim_info_ev->tim_bitmap)) {
1129da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "refusing to parse invalid swba structure\n");
1130da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1131da8fa4e3SBjoern A. Zeeb 	}
1132da8fa4e3SBjoern A. Zeeb 
1133da8fa4e3SBjoern A. Zeeb 	tim_info_arg = &swba->arg->tim_info[swba->n_tim];
1134da8fa4e3SBjoern A. Zeeb 	tim_info_arg->tim_len = tim_info_ev->tim_len;
1135da8fa4e3SBjoern A. Zeeb 	tim_info_arg->tim_mcast = tim_info_ev->tim_mcast;
1136da8fa4e3SBjoern A. Zeeb 	tim_info_arg->tim_bitmap = tim_info_ev->tim_bitmap;
1137da8fa4e3SBjoern A. Zeeb 	tim_info_arg->tim_changed = tim_info_ev->tim_changed;
1138da8fa4e3SBjoern A. Zeeb 	tim_info_arg->tim_num_ps_pending = tim_info_ev->tim_num_ps_pending;
1139da8fa4e3SBjoern A. Zeeb 
1140da8fa4e3SBjoern A. Zeeb 	swba->n_tim++;
1141da8fa4e3SBjoern A. Zeeb 
1142da8fa4e3SBjoern A. Zeeb 	return 0;
1143da8fa4e3SBjoern A. Zeeb }
1144da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_swba_noa_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1145da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_swba_noa_parse(struct ath10k *ar, u16 tag, u16 len,
1146da8fa4e3SBjoern A. Zeeb 					 const void *ptr, void *data)
1147da8fa4e3SBjoern A. Zeeb {
1148da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_swba_parse *swba = data;
1149da8fa4e3SBjoern A. Zeeb 
1150da8fa4e3SBjoern A. Zeeb 	if (tag != WMI_TLV_TAG_STRUCT_P2P_NOA_INFO)
1151da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1152da8fa4e3SBjoern A. Zeeb 
1153da8fa4e3SBjoern A. Zeeb 	if (swba->n_noa >= ARRAY_SIZE(swba->arg->noa_info))
1154da8fa4e3SBjoern A. Zeeb 		return -ENOBUFS;
1155da8fa4e3SBjoern A. Zeeb 
1156da8fa4e3SBjoern A. Zeeb 	swba->arg->noa_info[swba->n_noa++] = ptr;
1157da8fa4e3SBjoern A. Zeeb 	return 0;
1158da8fa4e3SBjoern A. Zeeb }
1159da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_swba_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1160da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_swba_parse(struct ath10k *ar, u16 tag, u16 len,
1161da8fa4e3SBjoern A. Zeeb 				     const void *ptr, void *data)
1162da8fa4e3SBjoern A. Zeeb {
1163da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_swba_parse *swba = data;
1164da8fa4e3SBjoern A. Zeeb 	int ret;
1165da8fa4e3SBjoern A. Zeeb 
1166da8fa4e3SBjoern A. Zeeb 	switch (tag) {
1167da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT:
1168da8fa4e3SBjoern A. Zeeb 		swba->ev = ptr;
1169da8fa4e3SBjoern A. Zeeb 		break;
1170da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_ARRAY_STRUCT:
1171da8fa4e3SBjoern A. Zeeb 		if (!swba->tim_done) {
1172da8fa4e3SBjoern A. Zeeb 			swba->tim_done = true;
1173da8fa4e3SBjoern A. Zeeb 			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
1174da8fa4e3SBjoern A. Zeeb 						  ath10k_wmi_tlv_swba_tim_parse,
1175da8fa4e3SBjoern A. Zeeb 						  swba);
1176da8fa4e3SBjoern A. Zeeb 			if (ret)
1177da8fa4e3SBjoern A. Zeeb 				return ret;
1178da8fa4e3SBjoern A. Zeeb 		} else if (!swba->noa_done) {
1179da8fa4e3SBjoern A. Zeeb 			swba->noa_done = true;
1180da8fa4e3SBjoern A. Zeeb 			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
1181da8fa4e3SBjoern A. Zeeb 						  ath10k_wmi_tlv_swba_noa_parse,
1182da8fa4e3SBjoern A. Zeeb 						  swba);
1183da8fa4e3SBjoern A. Zeeb 			if (ret)
1184da8fa4e3SBjoern A. Zeeb 				return ret;
1185da8fa4e3SBjoern A. Zeeb 		}
1186da8fa4e3SBjoern A. Zeeb 		break;
1187da8fa4e3SBjoern A. Zeeb 	default:
1188da8fa4e3SBjoern A. Zeeb 		break;
1189da8fa4e3SBjoern A. Zeeb 	}
1190da8fa4e3SBjoern A. Zeeb 	return 0;
1191da8fa4e3SBjoern A. Zeeb }
1192da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_swba_ev_arg * arg)1193da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
1194da8fa4e3SBjoern A. Zeeb 					  struct sk_buff *skb,
1195da8fa4e3SBjoern A. Zeeb 					  struct wmi_swba_ev_arg *arg)
1196da8fa4e3SBjoern A. Zeeb {
1197da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_swba_parse swba = { .arg = arg };
1198da8fa4e3SBjoern A. Zeeb 	u32 map;
1199da8fa4e3SBjoern A. Zeeb 	size_t n_vdevs;
1200da8fa4e3SBjoern A. Zeeb 	int ret;
1201da8fa4e3SBjoern A. Zeeb 
1202da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1203da8fa4e3SBjoern A. Zeeb 				  ath10k_wmi_tlv_swba_parse, &swba);
1204da8fa4e3SBjoern A. Zeeb 	if (ret) {
1205da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1206da8fa4e3SBjoern A. Zeeb 		return ret;
1207da8fa4e3SBjoern A. Zeeb 	}
1208da8fa4e3SBjoern A. Zeeb 
1209da8fa4e3SBjoern A. Zeeb 	if (!swba.ev)
1210da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1211da8fa4e3SBjoern A. Zeeb 
1212da8fa4e3SBjoern A. Zeeb 	arg->vdev_map = swba.ev->vdev_map;
1213da8fa4e3SBjoern A. Zeeb 
1214da8fa4e3SBjoern A. Zeeb 	for (map = __le32_to_cpu(arg->vdev_map), n_vdevs = 0; map; map >>= 1)
1215da8fa4e3SBjoern A. Zeeb 		if (map & BIT(0))
1216da8fa4e3SBjoern A. Zeeb 			n_vdevs++;
1217da8fa4e3SBjoern A. Zeeb 
1218da8fa4e3SBjoern A. Zeeb 	if (n_vdevs != swba.n_tim ||
1219da8fa4e3SBjoern A. Zeeb 	    n_vdevs != swba.n_noa)
1220da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1221da8fa4e3SBjoern A. Zeeb 
1222da8fa4e3SBjoern A. Zeeb 	return 0;
1223da8fa4e3SBjoern A. Zeeb }
1224da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k * ar,struct sk_buff * skb,struct wmi_phyerr_hdr_arg * arg)1225da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k *ar,
1226da8fa4e3SBjoern A. Zeeb 						struct sk_buff *skb,
1227da8fa4e3SBjoern A. Zeeb 						struct wmi_phyerr_hdr_arg *arg)
1228da8fa4e3SBjoern A. Zeeb {
1229da8fa4e3SBjoern A. Zeeb 	const void **tb;
1230da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_phyerr_ev *ev;
1231da8fa4e3SBjoern A. Zeeb 	const void *phyerrs;
1232da8fa4e3SBjoern A. Zeeb 	int ret;
1233da8fa4e3SBjoern A. Zeeb 
1234da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1235da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1236da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1237da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1238da8fa4e3SBjoern A. Zeeb 		return ret;
1239da8fa4e3SBjoern A. Zeeb 	}
1240da8fa4e3SBjoern A. Zeeb 
1241da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR];
1242da8fa4e3SBjoern A. Zeeb 	phyerrs = tb[WMI_TLV_TAG_ARRAY_BYTE];
1243da8fa4e3SBjoern A. Zeeb 
1244da8fa4e3SBjoern A. Zeeb 	if (!ev || !phyerrs) {
1245da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1246da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1247da8fa4e3SBjoern A. Zeeb 	}
1248da8fa4e3SBjoern A. Zeeb 
1249da8fa4e3SBjoern A. Zeeb 	arg->num_phyerrs  = __le32_to_cpu(ev->num_phyerrs);
1250da8fa4e3SBjoern A. Zeeb 	arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
1251da8fa4e3SBjoern A. Zeeb 	arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
1252da8fa4e3SBjoern A. Zeeb 	arg->buf_len = __le32_to_cpu(ev->buf_len);
1253da8fa4e3SBjoern A. Zeeb 	arg->phyerrs = phyerrs;
1254da8fa4e3SBjoern A. Zeeb 
1255da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1256da8fa4e3SBjoern A. Zeeb 	return 0;
1257da8fa4e3SBjoern A. Zeeb }
1258da8fa4e3SBjoern A. Zeeb 
1259da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER_NS0 0x5F414351
1260da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER_NS1 0x00004C4D
1261da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER_NS2 0x00000000
1262da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER_NS3 0x00000000
1263da8fa4e3SBjoern A. Zeeb 
1264da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER0_MAJOR 1
1265da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER0_MINOR 0
1266da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER0 ((((WMI_TLV_ABI_VER0_MAJOR) << 24) & 0xFF000000) | \
1267da8fa4e3SBjoern A. Zeeb 			  (((WMI_TLV_ABI_VER0_MINOR) <<  0) & 0x00FFFFFF))
1268da8fa4e3SBjoern A. Zeeb #define WMI_TLV_ABI_VER1 53
1269da8fa4e3SBjoern A. Zeeb 
1270da8fa4e3SBjoern A. Zeeb static int
ath10k_wmi_tlv_parse_mem_reqs(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1271da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_parse_mem_reqs(struct ath10k *ar, u16 tag, u16 len,
1272da8fa4e3SBjoern A. Zeeb 			      const void *ptr, void *data)
1273da8fa4e3SBjoern A. Zeeb {
1274da8fa4e3SBjoern A. Zeeb 	struct wmi_svc_rdy_ev_arg *arg = data;
1275da8fa4e3SBjoern A. Zeeb 	int i;
1276da8fa4e3SBjoern A. Zeeb 
1277da8fa4e3SBjoern A. Zeeb 	if (tag != WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ)
1278da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1279da8fa4e3SBjoern A. Zeeb 
1280da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(arg->mem_reqs); i++) {
1281da8fa4e3SBjoern A. Zeeb 		if (!arg->mem_reqs[i]) {
1282da8fa4e3SBjoern A. Zeeb 			arg->mem_reqs[i] = ptr;
1283da8fa4e3SBjoern A. Zeeb 			return 0;
1284da8fa4e3SBjoern A. Zeeb 		}
1285da8fa4e3SBjoern A. Zeeb 	}
1286da8fa4e3SBjoern A. Zeeb 
1287da8fa4e3SBjoern A. Zeeb 	return -ENOMEM;
1288da8fa4e3SBjoern A. Zeeb }
1289da8fa4e3SBjoern A. Zeeb 
1290da8fa4e3SBjoern A. Zeeb struct wmi_tlv_svc_rdy_parse {
1291da8fa4e3SBjoern A. Zeeb 	const struct hal_reg_capabilities *reg;
1292da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_svc_rdy_ev *ev;
1293da8fa4e3SBjoern A. Zeeb 	const __le32 *svc_bmap;
1294da8fa4e3SBjoern A. Zeeb 	const struct wlan_host_mem_req *mem_reqs;
1295da8fa4e3SBjoern A. Zeeb 	bool svc_bmap_done;
1296da8fa4e3SBjoern A. Zeeb 	bool dbs_hw_mode_done;
1297da8fa4e3SBjoern A. Zeeb };
1298da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_svc_rdy_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1299da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_svc_rdy_parse(struct ath10k *ar, u16 tag, u16 len,
1300da8fa4e3SBjoern A. Zeeb 					const void *ptr, void *data)
1301da8fa4e3SBjoern A. Zeeb {
1302da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_svc_rdy_parse *svc_rdy = data;
1303da8fa4e3SBjoern A. Zeeb 
1304da8fa4e3SBjoern A. Zeeb 	switch (tag) {
1305da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT:
1306da8fa4e3SBjoern A. Zeeb 		svc_rdy->ev = ptr;
1307da8fa4e3SBjoern A. Zeeb 		break;
1308da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES:
1309da8fa4e3SBjoern A. Zeeb 		svc_rdy->reg = ptr;
1310da8fa4e3SBjoern A. Zeeb 		break;
1311da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_ARRAY_STRUCT:
1312da8fa4e3SBjoern A. Zeeb 		svc_rdy->mem_reqs = ptr;
1313da8fa4e3SBjoern A. Zeeb 		break;
1314da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_ARRAY_UINT32:
1315da8fa4e3SBjoern A. Zeeb 		if (!svc_rdy->svc_bmap_done) {
1316da8fa4e3SBjoern A. Zeeb 			svc_rdy->svc_bmap_done = true;
1317da8fa4e3SBjoern A. Zeeb 			svc_rdy->svc_bmap = ptr;
1318da8fa4e3SBjoern A. Zeeb 		} else if (!svc_rdy->dbs_hw_mode_done) {
1319da8fa4e3SBjoern A. Zeeb 			svc_rdy->dbs_hw_mode_done = true;
1320da8fa4e3SBjoern A. Zeeb 		}
1321da8fa4e3SBjoern A. Zeeb 		break;
1322da8fa4e3SBjoern A. Zeeb 	default:
1323da8fa4e3SBjoern A. Zeeb 		break;
1324da8fa4e3SBjoern A. Zeeb 	}
1325da8fa4e3SBjoern A. Zeeb 	return 0;
1326da8fa4e3SBjoern A. Zeeb }
1327da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_svc_rdy_ev_arg * arg)1328da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
1329da8fa4e3SBjoern A. Zeeb 					     struct sk_buff *skb,
1330da8fa4e3SBjoern A. Zeeb 					     struct wmi_svc_rdy_ev_arg *arg)
1331da8fa4e3SBjoern A. Zeeb {
1332da8fa4e3SBjoern A. Zeeb 	const struct hal_reg_capabilities *reg;
1333da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_svc_rdy_ev *ev;
1334da8fa4e3SBjoern A. Zeeb 	const __le32 *svc_bmap;
1335da8fa4e3SBjoern A. Zeeb 	const struct wlan_host_mem_req *mem_reqs;
1336da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_svc_rdy_parse svc_rdy = { };
1337da8fa4e3SBjoern A. Zeeb 	int ret;
1338da8fa4e3SBjoern A. Zeeb 
1339da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1340da8fa4e3SBjoern A. Zeeb 				  ath10k_wmi_tlv_svc_rdy_parse, &svc_rdy);
1341da8fa4e3SBjoern A. Zeeb 	if (ret) {
1342da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1343da8fa4e3SBjoern A. Zeeb 		return ret;
1344da8fa4e3SBjoern A. Zeeb 	}
1345da8fa4e3SBjoern A. Zeeb 
1346da8fa4e3SBjoern A. Zeeb 	ev = svc_rdy.ev;
1347da8fa4e3SBjoern A. Zeeb 	reg = svc_rdy.reg;
1348da8fa4e3SBjoern A. Zeeb 	svc_bmap = svc_rdy.svc_bmap;
1349da8fa4e3SBjoern A. Zeeb 	mem_reqs = svc_rdy.mem_reqs;
1350da8fa4e3SBjoern A. Zeeb 
1351da8fa4e3SBjoern A. Zeeb 	if (!ev || !reg || !svc_bmap || !mem_reqs)
1352da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1353da8fa4e3SBjoern A. Zeeb 
1354da8fa4e3SBjoern A. Zeeb 	/* This is an internal ABI compatibility check for WMI TLV so check it
1355da8fa4e3SBjoern A. Zeeb 	 * here instead of the generic WMI code.
1356da8fa4e3SBjoern A. Zeeb 	 */
1357da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
1358da8fa4e3SBjoern A. Zeeb 		   "wmi tlv abi 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x\n",
1359da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->abi.abi_ver0), WMI_TLV_ABI_VER0,
1360da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->abi.abi_ver_ns0), WMI_TLV_ABI_VER_NS0,
1361da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->abi.abi_ver_ns1), WMI_TLV_ABI_VER_NS1,
1362da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->abi.abi_ver_ns2), WMI_TLV_ABI_VER_NS2,
1363da8fa4e3SBjoern A. Zeeb 		   __le32_to_cpu(ev->abi.abi_ver_ns3), WMI_TLV_ABI_VER_NS3);
1364da8fa4e3SBjoern A. Zeeb 
1365da8fa4e3SBjoern A. Zeeb 	if (__le32_to_cpu(ev->abi.abi_ver0) != WMI_TLV_ABI_VER0 ||
1366da8fa4e3SBjoern A. Zeeb 	    __le32_to_cpu(ev->abi.abi_ver_ns0) != WMI_TLV_ABI_VER_NS0 ||
1367da8fa4e3SBjoern A. Zeeb 	    __le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 ||
1368da8fa4e3SBjoern A. Zeeb 	    __le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 ||
1369da8fa4e3SBjoern A. Zeeb 	    __le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) {
1370da8fa4e3SBjoern A. Zeeb 		return -ENOTSUPP;
1371da8fa4e3SBjoern A. Zeeb 	}
1372da8fa4e3SBjoern A. Zeeb 
1373da8fa4e3SBjoern A. Zeeb 	arg->min_tx_power = ev->hw_min_tx_power;
1374da8fa4e3SBjoern A. Zeeb 	arg->max_tx_power = ev->hw_max_tx_power;
1375da8fa4e3SBjoern A. Zeeb 	arg->ht_cap = ev->ht_cap_info;
1376da8fa4e3SBjoern A. Zeeb 	arg->vht_cap = ev->vht_cap_info;
1377da8fa4e3SBjoern A. Zeeb 	arg->vht_supp_mcs = ev->vht_supp_mcs;
1378da8fa4e3SBjoern A. Zeeb 	arg->sw_ver0 = ev->abi.abi_ver0;
1379da8fa4e3SBjoern A. Zeeb 	arg->sw_ver1 = ev->abi.abi_ver1;
1380da8fa4e3SBjoern A. Zeeb 	arg->fw_build = ev->fw_build_vers;
1381da8fa4e3SBjoern A. Zeeb 	arg->phy_capab = ev->phy_capability;
1382da8fa4e3SBjoern A. Zeeb 	arg->num_rf_chains = ev->num_rf_chains;
1383da8fa4e3SBjoern A. Zeeb 	arg->eeprom_rd = reg->eeprom_rd;
1384da8fa4e3SBjoern A. Zeeb 	arg->low_2ghz_chan = reg->low_2ghz_chan;
1385da8fa4e3SBjoern A. Zeeb 	arg->high_2ghz_chan = reg->high_2ghz_chan;
1386da8fa4e3SBjoern A. Zeeb 	arg->low_5ghz_chan = reg->low_5ghz_chan;
1387da8fa4e3SBjoern A. Zeeb 	arg->high_5ghz_chan = reg->high_5ghz_chan;
1388da8fa4e3SBjoern A. Zeeb 	arg->num_mem_reqs = ev->num_mem_reqs;
1389da8fa4e3SBjoern A. Zeeb 	arg->service_map = svc_bmap;
1390da8fa4e3SBjoern A. Zeeb 	arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
1391da8fa4e3SBjoern A. Zeeb 	arg->sys_cap_info = ev->sys_cap_info;
1392da8fa4e3SBjoern A. Zeeb 
1393da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1394da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
1395da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1396da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_iter(ar, (const u8 *)mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
1397da8fa4e3SBjoern A. Zeeb #endif
1398da8fa4e3SBjoern A. Zeeb 				  ath10k_wmi_tlv_parse_mem_reqs, arg);
1399da8fa4e3SBjoern A. Zeeb 	if (ret) {
1400da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse mem_reqs tlv: %d\n", ret);
1401da8fa4e3SBjoern A. Zeeb 		return ret;
1402da8fa4e3SBjoern A. Zeeb 	}
1403da8fa4e3SBjoern A. Zeeb 
1404da8fa4e3SBjoern A. Zeeb 	return 0;
1405da8fa4e3SBjoern A. Zeeb }
1406da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_rdy_ev_arg * arg)1407da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
1408da8fa4e3SBjoern A. Zeeb 					 struct sk_buff *skb,
1409da8fa4e3SBjoern A. Zeeb 					 struct wmi_rdy_ev_arg *arg)
1410da8fa4e3SBjoern A. Zeeb {
1411da8fa4e3SBjoern A. Zeeb 	const void **tb;
1412da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_rdy_ev *ev;
1413da8fa4e3SBjoern A. Zeeb 	int ret;
1414da8fa4e3SBjoern A. Zeeb 
1415da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1416da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1417da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1418da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1419da8fa4e3SBjoern A. Zeeb 		return ret;
1420da8fa4e3SBjoern A. Zeeb 	}
1421da8fa4e3SBjoern A. Zeeb 
1422da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_READY_EVENT];
1423da8fa4e3SBjoern A. Zeeb 	if (!ev) {
1424da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1425da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1426da8fa4e3SBjoern A. Zeeb 	}
1427da8fa4e3SBjoern A. Zeeb 
1428da8fa4e3SBjoern A. Zeeb 	arg->sw_version = ev->abi.abi_ver0;
1429da8fa4e3SBjoern A. Zeeb 	arg->abi_version = ev->abi.abi_ver1;
1430da8fa4e3SBjoern A. Zeeb 	arg->status = ev->status;
1431da8fa4e3SBjoern A. Zeeb 	arg->mac_addr = ev->mac_addr.addr;
1432da8fa4e3SBjoern A. Zeeb 
1433da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1434da8fa4e3SBjoern A. Zeeb 	return 0;
1435da8fa4e3SBjoern A. Zeeb }
1436da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_svc_avail_parse(struct ath10k * ar,u16 tag,u16 len,const void * ptr,void * data)1437da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len,
1438da8fa4e3SBjoern A. Zeeb 					  const void *ptr, void *data)
1439da8fa4e3SBjoern A. Zeeb {
1440da8fa4e3SBjoern A. Zeeb 	struct wmi_svc_avail_ev_arg *arg = data;
1441da8fa4e3SBjoern A. Zeeb 
1442da8fa4e3SBjoern A. Zeeb 	switch (tag) {
1443da8fa4e3SBjoern A. Zeeb 	case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT:
1444da8fa4e3SBjoern A. Zeeb 		arg->service_map_ext_valid = true;
1445da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1446da8fa4e3SBjoern A. Zeeb 		arg->service_map_ext_len = *(__le32 *)ptr;
1447da8fa4e3SBjoern A. Zeeb 		arg->service_map_ext = ptr + sizeof(__le32);
1448da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1449da8fa4e3SBjoern A. Zeeb 		arg->service_map_ext_len = *(const __le32 *)ptr;
1450da8fa4e3SBjoern A. Zeeb 		arg->service_map_ext = (const __le32 *)((const u8 *)ptr + sizeof(__le32));
1451da8fa4e3SBjoern A. Zeeb #endif
1452da8fa4e3SBjoern A. Zeeb 		return 0;
1453da8fa4e3SBjoern A. Zeeb 	default:
1454da8fa4e3SBjoern A. Zeeb 		break;
1455da8fa4e3SBjoern A. Zeeb 	}
1456da8fa4e3SBjoern A. Zeeb 
1457da8fa4e3SBjoern A. Zeeb 	return 0;
1458da8fa4e3SBjoern A. Zeeb }
1459da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k * ar,struct sk_buff * skb,struct wmi_svc_avail_ev_arg * arg)1460da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar,
1461da8fa4e3SBjoern A. Zeeb 					    struct sk_buff *skb,
1462da8fa4e3SBjoern A. Zeeb 					    struct wmi_svc_avail_ev_arg *arg)
1463da8fa4e3SBjoern A. Zeeb {
1464da8fa4e3SBjoern A. Zeeb 	int ret;
1465da8fa4e3SBjoern A. Zeeb 
1466da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
1467da8fa4e3SBjoern A. Zeeb 				  ath10k_wmi_tlv_svc_avail_parse, arg);
1468da8fa4e3SBjoern A. Zeeb 
1469da8fa4e3SBjoern A. Zeeb 	if (ret) {
1470da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse svc_avail tlv: %d\n", ret);
1471da8fa4e3SBjoern A. Zeeb 		return ret;
1472da8fa4e3SBjoern A. Zeeb 	}
1473da8fa4e3SBjoern A. Zeeb 
1474da8fa4e3SBjoern A. Zeeb 	return 0;
1475da8fa4e3SBjoern A. Zeeb }
1476da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats * src,struct ath10k_fw_stats_vdev * dst)1477da8fa4e3SBjoern A. Zeeb static void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
1478da8fa4e3SBjoern A. Zeeb 					   struct ath10k_fw_stats_vdev *dst)
1479da8fa4e3SBjoern A. Zeeb {
1480da8fa4e3SBjoern A. Zeeb 	int i;
1481da8fa4e3SBjoern A. Zeeb 
1482da8fa4e3SBjoern A. Zeeb 	dst->vdev_id = __le32_to_cpu(src->vdev_id);
1483da8fa4e3SBjoern A. Zeeb 	dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
1484da8fa4e3SBjoern A. Zeeb 	dst->data_snr = __le32_to_cpu(src->data_snr);
1485da8fa4e3SBjoern A. Zeeb 	dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
1486da8fa4e3SBjoern A. Zeeb 	dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
1487da8fa4e3SBjoern A. Zeeb 	dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
1488da8fa4e3SBjoern A. Zeeb 	dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
1489da8fa4e3SBjoern A. Zeeb 	dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
1490da8fa4e3SBjoern A. Zeeb 	dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
1491da8fa4e3SBjoern A. Zeeb 
1492da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
1493da8fa4e3SBjoern A. Zeeb 		dst->num_tx_frames[i] =
1494da8fa4e3SBjoern A. Zeeb 			__le32_to_cpu(src->num_tx_frames[i]);
1495da8fa4e3SBjoern A. Zeeb 
1496da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
1497da8fa4e3SBjoern A. Zeeb 		dst->num_tx_frames_retries[i] =
1498da8fa4e3SBjoern A. Zeeb 			__le32_to_cpu(src->num_tx_frames_retries[i]);
1499da8fa4e3SBjoern A. Zeeb 
1500da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
1501da8fa4e3SBjoern A. Zeeb 		dst->num_tx_frames_failures[i] =
1502da8fa4e3SBjoern A. Zeeb 			__le32_to_cpu(src->num_tx_frames_failures[i]);
1503da8fa4e3SBjoern A. Zeeb 
1504da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
1505da8fa4e3SBjoern A. Zeeb 		dst->tx_rate_history[i] =
1506da8fa4e3SBjoern A. Zeeb 			__le32_to_cpu(src->tx_rate_history[i]);
1507da8fa4e3SBjoern A. Zeeb 
1508da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
1509da8fa4e3SBjoern A. Zeeb 		dst->beacon_rssi_history[i] =
1510da8fa4e3SBjoern A. Zeeb 			__le32_to_cpu(src->beacon_rssi_history[i]);
1511da8fa4e3SBjoern A. Zeeb }
1512da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k * ar,struct sk_buff * skb,struct ath10k_fw_stats * stats)1513da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
1514da8fa4e3SBjoern A. Zeeb 					   struct sk_buff *skb,
1515da8fa4e3SBjoern A. Zeeb 					   struct ath10k_fw_stats *stats)
1516da8fa4e3SBjoern A. Zeeb {
1517da8fa4e3SBjoern A. Zeeb 	const void **tb;
1518da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_stats_ev *ev;
1519da8fa4e3SBjoern A. Zeeb 	u32 num_peer_stats_extd;
1520da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1521da8fa4e3SBjoern A. Zeeb 	const void *data;
1522da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1523da8fa4e3SBjoern A. Zeeb 	const u8 *data;
1524da8fa4e3SBjoern A. Zeeb #endif
1525da8fa4e3SBjoern A. Zeeb 	u32 num_pdev_stats;
1526da8fa4e3SBjoern A. Zeeb 	u32 num_vdev_stats;
1527da8fa4e3SBjoern A. Zeeb 	u32 num_peer_stats;
1528da8fa4e3SBjoern A. Zeeb 	u32 num_bcnflt_stats;
1529da8fa4e3SBjoern A. Zeeb 	u32 num_chan_stats;
1530da8fa4e3SBjoern A. Zeeb 	size_t data_len;
1531da8fa4e3SBjoern A. Zeeb 	u32 stats_id;
1532da8fa4e3SBjoern A. Zeeb 	int ret;
1533da8fa4e3SBjoern A. Zeeb 	int i;
1534da8fa4e3SBjoern A. Zeeb 
1535da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1536da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1537da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1538da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1539da8fa4e3SBjoern A. Zeeb 		return ret;
1540da8fa4e3SBjoern A. Zeeb 	}
1541da8fa4e3SBjoern A. Zeeb 
1542da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_STATS_EVENT];
1543da8fa4e3SBjoern A. Zeeb 	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
1544da8fa4e3SBjoern A. Zeeb 
1545da8fa4e3SBjoern A. Zeeb 	if (!ev || !data) {
1546da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1547da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1548da8fa4e3SBjoern A. Zeeb 	}
1549da8fa4e3SBjoern A. Zeeb 
1550da8fa4e3SBjoern A. Zeeb 	data_len = ath10k_wmi_tlv_len(data);
1551da8fa4e3SBjoern A. Zeeb 	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
1552da8fa4e3SBjoern A. Zeeb 	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
1553da8fa4e3SBjoern A. Zeeb 	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
1554da8fa4e3SBjoern A. Zeeb 	num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
1555da8fa4e3SBjoern A. Zeeb 	num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
1556da8fa4e3SBjoern A. Zeeb 	stats_id = __le32_to_cpu(ev->stats_id);
1557da8fa4e3SBjoern A. Zeeb 	num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd);
1558da8fa4e3SBjoern A. Zeeb 
1559da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
1560da8fa4e3SBjoern A. Zeeb 		   "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n",
1561da8fa4e3SBjoern A. Zeeb 		   num_pdev_stats, num_vdev_stats, num_peer_stats,
1562da8fa4e3SBjoern A. Zeeb 		   num_bcnflt_stats, num_chan_stats, num_peer_stats_extd);
1563da8fa4e3SBjoern A. Zeeb 
1564da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < num_pdev_stats; i++) {
1565da8fa4e3SBjoern A. Zeeb 		const struct wmi_pdev_stats *src;
1566da8fa4e3SBjoern A. Zeeb 		struct ath10k_fw_stats_pdev *dst;
1567da8fa4e3SBjoern A. Zeeb 
1568da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1569da8fa4e3SBjoern A. Zeeb 		src = data;
1570da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1571da8fa4e3SBjoern A. Zeeb 		src = (const void *)data;
1572da8fa4e3SBjoern A. Zeeb #endif
1573da8fa4e3SBjoern A. Zeeb 		if (data_len < sizeof(*src)) {
1574da8fa4e3SBjoern A. Zeeb 			kfree(tb);
1575da8fa4e3SBjoern A. Zeeb 			return -EPROTO;
1576da8fa4e3SBjoern A. Zeeb 		}
1577da8fa4e3SBjoern A. Zeeb 
1578da8fa4e3SBjoern A. Zeeb 		data += sizeof(*src);
1579da8fa4e3SBjoern A. Zeeb 		data_len -= sizeof(*src);
1580da8fa4e3SBjoern A. Zeeb 
1581da8fa4e3SBjoern A. Zeeb 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1582da8fa4e3SBjoern A. Zeeb 		if (!dst)
1583da8fa4e3SBjoern A. Zeeb 			continue;
1584da8fa4e3SBjoern A. Zeeb 
1585da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
1586da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
1587da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
1588da8fa4e3SBjoern A. Zeeb 		list_add_tail(&dst->list, &stats->pdevs);
1589da8fa4e3SBjoern A. Zeeb 	}
1590da8fa4e3SBjoern A. Zeeb 
1591da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < num_vdev_stats; i++) {
1592da8fa4e3SBjoern A. Zeeb 		const struct wmi_tlv_vdev_stats *src;
1593da8fa4e3SBjoern A. Zeeb 		struct ath10k_fw_stats_vdev *dst;
1594da8fa4e3SBjoern A. Zeeb 
1595da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1596da8fa4e3SBjoern A. Zeeb 		src = data;
1597da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1598da8fa4e3SBjoern A. Zeeb 		src = (const void *)data;
1599da8fa4e3SBjoern A. Zeeb #endif
1600da8fa4e3SBjoern A. Zeeb 		if (data_len < sizeof(*src)) {
1601da8fa4e3SBjoern A. Zeeb 			kfree(tb);
1602da8fa4e3SBjoern A. Zeeb 			return -EPROTO;
1603da8fa4e3SBjoern A. Zeeb 		}
1604da8fa4e3SBjoern A. Zeeb 
1605da8fa4e3SBjoern A. Zeeb 		data += sizeof(*src);
1606da8fa4e3SBjoern A. Zeeb 		data_len -= sizeof(*src);
1607da8fa4e3SBjoern A. Zeeb 
1608da8fa4e3SBjoern A. Zeeb 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1609da8fa4e3SBjoern A. Zeeb 		if (!dst)
1610da8fa4e3SBjoern A. Zeeb 			continue;
1611da8fa4e3SBjoern A. Zeeb 
1612da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_tlv_pull_vdev_stats(src, dst);
1613da8fa4e3SBjoern A. Zeeb 		list_add_tail(&dst->list, &stats->vdevs);
1614da8fa4e3SBjoern A. Zeeb 	}
1615da8fa4e3SBjoern A. Zeeb 
1616da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < num_peer_stats; i++) {
1617da8fa4e3SBjoern A. Zeeb 		const struct wmi_10x_peer_stats *src;
1618da8fa4e3SBjoern A. Zeeb 		struct ath10k_fw_stats_peer *dst;
1619da8fa4e3SBjoern A. Zeeb 
1620da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1621da8fa4e3SBjoern A. Zeeb 		src = data;
1622da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1623da8fa4e3SBjoern A. Zeeb 		src = (const void *)data;
1624da8fa4e3SBjoern A. Zeeb #endif
1625da8fa4e3SBjoern A. Zeeb 		if (data_len < sizeof(*src)) {
1626da8fa4e3SBjoern A. Zeeb 			kfree(tb);
1627da8fa4e3SBjoern A. Zeeb 			return -EPROTO;
1628da8fa4e3SBjoern A. Zeeb 		}
1629da8fa4e3SBjoern A. Zeeb 
1630da8fa4e3SBjoern A. Zeeb 		data += sizeof(*src);
1631da8fa4e3SBjoern A. Zeeb 		data_len -= sizeof(*src);
1632da8fa4e3SBjoern A. Zeeb 
1633da8fa4e3SBjoern A. Zeeb 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1634da8fa4e3SBjoern A. Zeeb 		if (!dst)
1635da8fa4e3SBjoern A. Zeeb 			continue;
1636da8fa4e3SBjoern A. Zeeb 
1637da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_pull_peer_stats(&src->old, dst);
1638da8fa4e3SBjoern A. Zeeb 		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
1639da8fa4e3SBjoern A. Zeeb 
1640da8fa4e3SBjoern A. Zeeb 		if (stats_id & WMI_TLV_STAT_PEER_EXTD) {
1641da8fa4e3SBjoern A. Zeeb 			const struct wmi_tlv_peer_stats_extd *extd;
1642da8fa4e3SBjoern A. Zeeb 			unsigned long rx_duration_high;
1643da8fa4e3SBjoern A. Zeeb 
1644da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1645da8fa4e3SBjoern A. Zeeb 			extd = data + sizeof(*src) * (num_peer_stats - i - 1)
1646da8fa4e3SBjoern A. Zeeb 			       + sizeof(*extd) * i;
1647da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1648da8fa4e3SBjoern A. Zeeb 			extd = (const void *)(data + sizeof(*src) * (num_peer_stats - i - 1)
1649da8fa4e3SBjoern A. Zeeb 			       + sizeof(*extd) * i);
1650da8fa4e3SBjoern A. Zeeb #endif
1651da8fa4e3SBjoern A. Zeeb 
1652da8fa4e3SBjoern A. Zeeb 			dst->rx_duration = __le32_to_cpu(extd->rx_duration);
1653da8fa4e3SBjoern A. Zeeb 			rx_duration_high = __le32_to_cpu
1654da8fa4e3SBjoern A. Zeeb 						(extd->rx_duration_high);
1655da8fa4e3SBjoern A. Zeeb 
1656da8fa4e3SBjoern A. Zeeb 			if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT,
1657da8fa4e3SBjoern A. Zeeb 				     &rx_duration_high)) {
1658da8fa4e3SBjoern A. Zeeb 				rx_duration_high =
1659da8fa4e3SBjoern A. Zeeb 					FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK,
1660da8fa4e3SBjoern A. Zeeb 						  rx_duration_high);
1661da8fa4e3SBjoern A. Zeeb 				dst->rx_duration |= (u64)rx_duration_high <<
1662da8fa4e3SBjoern A. Zeeb 						    WMI_TLV_PEER_RX_DURATION_SHIFT;
1663da8fa4e3SBjoern A. Zeeb 			}
1664da8fa4e3SBjoern A. Zeeb 		}
1665da8fa4e3SBjoern A. Zeeb 
1666da8fa4e3SBjoern A. Zeeb 		list_add_tail(&dst->list, &stats->peers);
1667da8fa4e3SBjoern A. Zeeb 	}
1668da8fa4e3SBjoern A. Zeeb 
1669da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1670da8fa4e3SBjoern A. Zeeb 	return 0;
1671da8fa4e3SBjoern A. Zeeb }
1672da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_roam_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_roam_ev_arg * arg)1673da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_roam_ev(struct ath10k *ar,
1674da8fa4e3SBjoern A. Zeeb 					  struct sk_buff *skb,
1675da8fa4e3SBjoern A. Zeeb 					  struct wmi_roam_ev_arg *arg)
1676da8fa4e3SBjoern A. Zeeb {
1677da8fa4e3SBjoern A. Zeeb 	const void **tb;
1678da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_roam_ev *ev;
1679da8fa4e3SBjoern A. Zeeb 	int ret;
1680da8fa4e3SBjoern A. Zeeb 
1681da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1682da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1683da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1684da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1685da8fa4e3SBjoern A. Zeeb 		return ret;
1686da8fa4e3SBjoern A. Zeeb 	}
1687da8fa4e3SBjoern A. Zeeb 
1688da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_ROAM_EVENT];
1689da8fa4e3SBjoern A. Zeeb 	if (!ev) {
1690da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1691da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1692da8fa4e3SBjoern A. Zeeb 	}
1693da8fa4e3SBjoern A. Zeeb 
1694da8fa4e3SBjoern A. Zeeb 	arg->vdev_id = ev->vdev_id;
1695da8fa4e3SBjoern A. Zeeb 	arg->reason = ev->reason;
1696da8fa4e3SBjoern A. Zeeb 	arg->rssi = ev->rssi;
1697da8fa4e3SBjoern A. Zeeb 
1698da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1699da8fa4e3SBjoern A. Zeeb 	return 0;
1700da8fa4e3SBjoern A. Zeeb }
1701da8fa4e3SBjoern A. Zeeb 
1702da8fa4e3SBjoern A. Zeeb static int
ath10k_wmi_tlv_op_pull_wow_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_wow_ev_arg * arg)1703da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_pull_wow_ev(struct ath10k *ar, struct sk_buff *skb,
1704da8fa4e3SBjoern A. Zeeb 			      struct wmi_wow_ev_arg *arg)
1705da8fa4e3SBjoern A. Zeeb {
1706da8fa4e3SBjoern A. Zeeb 	const void **tb;
1707da8fa4e3SBjoern A. Zeeb 	const struct wmi_tlv_wow_event_info *ev;
1708da8fa4e3SBjoern A. Zeeb 	int ret;
1709da8fa4e3SBjoern A. Zeeb 
1710da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1711da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1712da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1713da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1714da8fa4e3SBjoern A. Zeeb 		return ret;
1715da8fa4e3SBjoern A. Zeeb 	}
1716da8fa4e3SBjoern A. Zeeb 
1717da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO];
1718da8fa4e3SBjoern A. Zeeb 	if (!ev) {
1719da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1720da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1721da8fa4e3SBjoern A. Zeeb 	}
1722da8fa4e3SBjoern A. Zeeb 
1723da8fa4e3SBjoern A. Zeeb 	arg->vdev_id = __le32_to_cpu(ev->vdev_id);
1724da8fa4e3SBjoern A. Zeeb 	arg->flag = __le32_to_cpu(ev->flag);
1725da8fa4e3SBjoern A. Zeeb 	arg->wake_reason = __le32_to_cpu(ev->wake_reason);
1726da8fa4e3SBjoern A. Zeeb 	arg->data_len = __le32_to_cpu(ev->data_len);
1727da8fa4e3SBjoern A. Zeeb 
1728da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1729da8fa4e3SBjoern A. Zeeb 	return 0;
1730da8fa4e3SBjoern A. Zeeb }
1731da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k * ar,struct sk_buff * skb,struct wmi_echo_ev_arg * arg)1732da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k *ar,
1733da8fa4e3SBjoern A. Zeeb 					  struct sk_buff *skb,
1734da8fa4e3SBjoern A. Zeeb 					  struct wmi_echo_ev_arg *arg)
1735da8fa4e3SBjoern A. Zeeb {
1736da8fa4e3SBjoern A. Zeeb 	const void **tb;
1737da8fa4e3SBjoern A. Zeeb 	const struct wmi_echo_event *ev;
1738da8fa4e3SBjoern A. Zeeb 	int ret;
1739da8fa4e3SBjoern A. Zeeb 
1740da8fa4e3SBjoern A. Zeeb 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
1741da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(tb)) {
1742da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(tb);
1743da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
1744da8fa4e3SBjoern A. Zeeb 		return ret;
1745da8fa4e3SBjoern A. Zeeb 	}
1746da8fa4e3SBjoern A. Zeeb 
1747da8fa4e3SBjoern A. Zeeb 	ev = tb[WMI_TLV_TAG_STRUCT_ECHO_EVENT];
1748da8fa4e3SBjoern A. Zeeb 	if (!ev) {
1749da8fa4e3SBjoern A. Zeeb 		kfree(tb);
1750da8fa4e3SBjoern A. Zeeb 		return -EPROTO;
1751da8fa4e3SBjoern A. Zeeb 	}
1752da8fa4e3SBjoern A. Zeeb 
1753da8fa4e3SBjoern A. Zeeb 	arg->value = ev->value;
1754da8fa4e3SBjoern A. Zeeb 
1755da8fa4e3SBjoern A. Zeeb 	kfree(tb);
1756da8fa4e3SBjoern A. Zeeb 	return 0;
1757da8fa4e3SBjoern A. Zeeb }
1758da8fa4e3SBjoern A. Zeeb 
1759da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k * ar,u32 opt)1760da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
1761da8fa4e3SBjoern A. Zeeb {
1762da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_pdev_suspend *cmd;
1763da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
1764da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
1765da8fa4e3SBjoern A. Zeeb 
1766da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1767da8fa4e3SBjoern A. Zeeb 	if (!skb)
1768da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
1769da8fa4e3SBjoern A. Zeeb 
1770da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
1771da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD);
1772da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1773da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
1774da8fa4e3SBjoern A. Zeeb 	cmd->opt = __cpu_to_le32(opt);
1775da8fa4e3SBjoern A. Zeeb 
1776da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev suspend\n");
1777da8fa4e3SBjoern A. Zeeb 	return skb;
1778da8fa4e3SBjoern A. Zeeb }
1779da8fa4e3SBjoern A. Zeeb 
1780da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k * ar)1781da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k *ar)
1782da8fa4e3SBjoern A. Zeeb {
1783da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_resume_cmd *cmd;
1784da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
1785da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
1786da8fa4e3SBjoern A. Zeeb 
1787da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1788da8fa4e3SBjoern A. Zeeb 	if (!skb)
1789da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
1790da8fa4e3SBjoern A. Zeeb 
1791da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
1792da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD);
1793da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1794da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
1795da8fa4e3SBjoern A. Zeeb 	cmd->reserved = __cpu_to_le32(0);
1796da8fa4e3SBjoern A. Zeeb 
1797da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev resume\n");
1798da8fa4e3SBjoern A. Zeeb 	return skb;
1799da8fa4e3SBjoern A. Zeeb }
1800da8fa4e3SBjoern A. Zeeb 
1801da8fa4e3SBjoern A. Zeeb 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)1802da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
1803da8fa4e3SBjoern A. Zeeb 				  u16 rd, u16 rd2g, u16 rd5g,
1804da8fa4e3SBjoern A. Zeeb 				  u16 ctl2g, u16 ctl5g,
1805da8fa4e3SBjoern A. Zeeb 				  enum wmi_dfs_region dfs_reg)
1806da8fa4e3SBjoern A. Zeeb {
1807da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_pdev_set_rd_cmd *cmd;
1808da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
1809da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
1810da8fa4e3SBjoern A. Zeeb 
1811da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1812da8fa4e3SBjoern A. Zeeb 	if (!skb)
1813da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
1814da8fa4e3SBjoern A. Zeeb 
1815da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
1816da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD);
1817da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1818da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
1819da8fa4e3SBjoern A. Zeeb 	cmd->regd = __cpu_to_le32(rd);
1820da8fa4e3SBjoern A. Zeeb 	cmd->regd_2ghz = __cpu_to_le32(rd2g);
1821da8fa4e3SBjoern A. Zeeb 	cmd->regd_5ghz = __cpu_to_le32(rd5g);
1822da8fa4e3SBjoern A. Zeeb 	cmd->conform_limit_2ghz = __cpu_to_le32(ctl2g);
1823da8fa4e3SBjoern A. Zeeb 	cmd->conform_limit_5ghz = __cpu_to_le32(ctl5g);
1824da8fa4e3SBjoern A. Zeeb 
1825da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
1826da8fa4e3SBjoern A. Zeeb 	return skb;
1827da8fa4e3SBjoern A. Zeeb }
1828da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_txbf_conf_scheme(struct ath10k * ar)1829da8fa4e3SBjoern A. Zeeb static enum wmi_txbf_conf ath10k_wmi_tlv_txbf_conf_scheme(struct ath10k *ar)
1830da8fa4e3SBjoern A. Zeeb {
1831da8fa4e3SBjoern A. Zeeb 	return WMI_TXBF_CONF_AFTER_ASSOC;
1832da8fa4e3SBjoern A. Zeeb }
1833da8fa4e3SBjoern A. Zeeb 
1834da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k * ar,u32 param_id,u32 param_value)1835da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
1836da8fa4e3SBjoern A. Zeeb 				     u32 param_value)
1837da8fa4e3SBjoern A. Zeeb {
1838da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_pdev_set_param_cmd *cmd;
1839da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
1840da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
1841da8fa4e3SBjoern A. Zeeb 
1842da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1843da8fa4e3SBjoern A. Zeeb 	if (!skb)
1844da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
1845da8fa4e3SBjoern A. Zeeb 
1846da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
1847da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD);
1848da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1849da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
1850da8fa4e3SBjoern A. Zeeb 	cmd->param_id = __cpu_to_le32(param_id);
1851da8fa4e3SBjoern A. Zeeb 	cmd->param_value = __cpu_to_le32(param_value);
1852da8fa4e3SBjoern A. Zeeb 
1853da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n",
1854da8fa4e3SBjoern A. Zeeb 		   param_id, param_value);
1855da8fa4e3SBjoern A. Zeeb 	return skb;
1856da8fa4e3SBjoern A. Zeeb }
1857da8fa4e3SBjoern A. Zeeb 
1858da8fa4e3SBjoern A. Zeeb static void
1859da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k * ar,void * host_mem_chunks)1860da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
1861da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1862da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, u8 *host_mem_chunks)
1863da8fa4e3SBjoern A. Zeeb #endif
1864da8fa4e3SBjoern A. Zeeb {
1865da8fa4e3SBjoern A. Zeeb 	struct host_memory_chunk_tlv *chunk;
1866da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
1867da8fa4e3SBjoern A. Zeeb 	dma_addr_t paddr;
1868da8fa4e3SBjoern A. Zeeb 	int i;
1869da8fa4e3SBjoern A. Zeeb 	__le16 tlv_len, tlv_tag;
1870da8fa4e3SBjoern A. Zeeb 
1871da8fa4e3SBjoern A. Zeeb 	tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK);
1872da8fa4e3SBjoern A. Zeeb 	tlv_len = __cpu_to_le16(sizeof(*chunk));
1873da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
1874da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1875da8fa4e3SBjoern A. Zeeb 		tlv = host_mem_chunks;
1876da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1877da8fa4e3SBjoern A. Zeeb 		tlv = (void *)host_mem_chunks;
1878da8fa4e3SBjoern A. Zeeb #endif
1879da8fa4e3SBjoern A. Zeeb 		tlv->tag = tlv_tag;
1880da8fa4e3SBjoern A. Zeeb 		tlv->len = tlv_len;
1881da8fa4e3SBjoern A. Zeeb 		chunk = (void *)tlv->value;
1882da8fa4e3SBjoern A. Zeeb 
1883da8fa4e3SBjoern A. Zeeb 		chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
1884da8fa4e3SBjoern A. Zeeb 		chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
1885da8fa4e3SBjoern A. Zeeb 		chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
1886da8fa4e3SBjoern A. Zeeb 
1887da8fa4e3SBjoern A. Zeeb 		if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
1888da8fa4e3SBjoern A. Zeeb 			     ar->wmi.svc_map)) {
1889da8fa4e3SBjoern A. Zeeb 			paddr = ar->wmi.mem_chunks[i].paddr;
1890da8fa4e3SBjoern A. Zeeb 			chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr));
1891da8fa4e3SBjoern A. Zeeb 		}
1892da8fa4e3SBjoern A. Zeeb 
1893da8fa4e3SBjoern A. Zeeb 		ath10k_dbg(ar, ATH10K_DBG_WMI,
1894da8fa4e3SBjoern A. Zeeb 			   "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
1895da8fa4e3SBjoern A. Zeeb 			   i,
1896da8fa4e3SBjoern A. Zeeb 			   ar->wmi.mem_chunks[i].len,
1897da8fa4e3SBjoern A. Zeeb 			   (unsigned long long)ar->wmi.mem_chunks[i].paddr,
1898da8fa4e3SBjoern A. Zeeb 			   ar->wmi.mem_chunks[i].req_id);
1899da8fa4e3SBjoern A. Zeeb 
1900da8fa4e3SBjoern A. Zeeb 		host_mem_chunks += sizeof(*tlv);
1901da8fa4e3SBjoern A. Zeeb 		host_mem_chunks += sizeof(*chunk);
1902da8fa4e3SBjoern A. Zeeb 	}
1903da8fa4e3SBjoern A. Zeeb }
1904da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_gen_init(struct ath10k * ar)1905da8fa4e3SBjoern A. Zeeb static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
1906da8fa4e3SBjoern A. Zeeb {
1907da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
1908da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
1909da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_init_cmd *cmd;
1910da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_resource_config *cfg;
1911da8fa4e3SBjoern A. Zeeb 	void *chunks;
1912da8fa4e3SBjoern A. Zeeb 	size_t len, chunks_len;
1913da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1914da8fa4e3SBjoern A. Zeeb 	void *ptr;
1915da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1916da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
1917da8fa4e3SBjoern A. Zeeb #endif
1918da8fa4e3SBjoern A. Zeeb 
1919da8fa4e3SBjoern A. Zeeb 	chunks_len = ar->wmi.num_mem_chunks *
1920da8fa4e3SBjoern A. Zeeb 		     (sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv));
1921da8fa4e3SBjoern A. Zeeb 	len = (sizeof(*tlv) + sizeof(*cmd)) +
1922da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + sizeof(*cfg)) +
1923da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + chunks_len);
1924da8fa4e3SBjoern A. Zeeb 
1925da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
1926da8fa4e3SBjoern A. Zeeb 	if (!skb)
1927da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
1928da8fa4e3SBjoern A. Zeeb 
1929da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1930da8fa4e3SBjoern A. Zeeb 	ptr = skb->data;
1931da8fa4e3SBjoern A. Zeeb 
1932da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
1933da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1934da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
1935da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
1936da8fa4e3SBjoern A. Zeeb #endif
1937da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_INIT_CMD);
1938da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
1939da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
1940da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
1941da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
1942da8fa4e3SBjoern A. Zeeb 
1943da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1944da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
1945da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1946da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
1947da8fa4e3SBjoern A. Zeeb #endif
1948da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG);
1949da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cfg));
1950da8fa4e3SBjoern A. Zeeb 	cfg = (void *)tlv->value;
1951da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
1952da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cfg);
1953da8fa4e3SBjoern A. Zeeb 
1954da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1955da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
1956da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1957da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
1958da8fa4e3SBjoern A. Zeeb #endif
1959da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
1960da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(chunks_len);
1961da8fa4e3SBjoern A. Zeeb 	chunks = (void *)tlv->value;
1962da8fa4e3SBjoern A. Zeeb 
1963da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
1964da8fa4e3SBjoern A. Zeeb 	ptr += chunks_len;
1965da8fa4e3SBjoern A. Zeeb 
1966da8fa4e3SBjoern A. Zeeb 	cmd->abi.abi_ver0 = __cpu_to_le32(WMI_TLV_ABI_VER0);
1967da8fa4e3SBjoern A. Zeeb 	cmd->abi.abi_ver1 = __cpu_to_le32(WMI_TLV_ABI_VER1);
1968da8fa4e3SBjoern A. Zeeb 	cmd->abi.abi_ver_ns0 = __cpu_to_le32(WMI_TLV_ABI_VER_NS0);
1969da8fa4e3SBjoern A. Zeeb 	cmd->abi.abi_ver_ns1 = __cpu_to_le32(WMI_TLV_ABI_VER_NS1);
1970da8fa4e3SBjoern A. Zeeb 	cmd->abi.abi_ver_ns2 = __cpu_to_le32(WMI_TLV_ABI_VER_NS2);
1971da8fa4e3SBjoern A. Zeeb 	cmd->abi.abi_ver_ns3 = __cpu_to_le32(WMI_TLV_ABI_VER_NS3);
1972da8fa4e3SBjoern A. Zeeb 	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
1973da8fa4e3SBjoern A. Zeeb 
1974da8fa4e3SBjoern A. Zeeb 	cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1975da8fa4e3SBjoern A. Zeeb 
1976da8fa4e3SBjoern A. Zeeb 	if (ar->hw_params.num_peers)
1977da8fa4e3SBjoern A. Zeeb 		cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers);
1978da8fa4e3SBjoern A. Zeeb 	else
1979da8fa4e3SBjoern A. Zeeb 		cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
1980da8fa4e3SBjoern A. Zeeb 	cfg->ast_skid_limit = __cpu_to_le32(ar->hw_params.ast_skid_limit);
1981da8fa4e3SBjoern A. Zeeb 	cfg->num_wds_entries = __cpu_to_le32(ar->hw_params.num_wds_entries);
1982da8fa4e3SBjoern A. Zeeb 
1983da8fa4e3SBjoern A. Zeeb 	if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
1984da8fa4e3SBjoern A. Zeeb 		cfg->num_offload_peers = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1985da8fa4e3SBjoern A. Zeeb 		cfg->num_offload_reorder_bufs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1986da8fa4e3SBjoern A. Zeeb 	} else {
1987da8fa4e3SBjoern A. Zeeb 		cfg->num_offload_peers = __cpu_to_le32(0);
1988da8fa4e3SBjoern A. Zeeb 		cfg->num_offload_reorder_bufs = __cpu_to_le32(0);
1989da8fa4e3SBjoern A. Zeeb 	}
1990da8fa4e3SBjoern A. Zeeb 
1991da8fa4e3SBjoern A. Zeeb 	cfg->num_peer_keys = __cpu_to_le32(2);
1992da8fa4e3SBjoern A. Zeeb 	if (ar->hw_params.num_peers)
1993da8fa4e3SBjoern A. Zeeb 		cfg->num_tids = __cpu_to_le32(ar->hw_params.num_peers * 2);
1994da8fa4e3SBjoern A. Zeeb 	else
1995da8fa4e3SBjoern A. Zeeb 		cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
1996da8fa4e3SBjoern A. Zeeb 	cfg->tx_chain_mask = __cpu_to_le32(0x7);
1997da8fa4e3SBjoern A. Zeeb 	cfg->rx_chain_mask = __cpu_to_le32(0x7);
1998da8fa4e3SBjoern A. Zeeb 	cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
1999da8fa4e3SBjoern A. Zeeb 	cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64);
2000da8fa4e3SBjoern A. Zeeb 	cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64);
2001da8fa4e3SBjoern A. Zeeb 	cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28);
2002da8fa4e3SBjoern A. Zeeb 	cfg->rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
2003da8fa4e3SBjoern A. Zeeb 	cfg->scan_max_pending_reqs = __cpu_to_le32(4);
2004da8fa4e3SBjoern A. Zeeb 	cfg->bmiss_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
2005da8fa4e3SBjoern A. Zeeb 	cfg->roam_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
2006da8fa4e3SBjoern A. Zeeb 	cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8);
2007da8fa4e3SBjoern A. Zeeb 	cfg->num_mcast_groups = __cpu_to_le32(0);
2008da8fa4e3SBjoern A. Zeeb 	cfg->num_mcast_table_elems = __cpu_to_le32(0);
2009da8fa4e3SBjoern A. Zeeb 	cfg->mcast2ucast_mode = __cpu_to_le32(0);
2010da8fa4e3SBjoern A. Zeeb 	cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
2011da8fa4e3SBjoern A. Zeeb 	cfg->dma_burst_size = __cpu_to_le32(0);
2012da8fa4e3SBjoern A. Zeeb 	cfg->mac_aggr_delim = __cpu_to_le32(0);
2013da8fa4e3SBjoern A. Zeeb 	cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
2014da8fa4e3SBjoern A. Zeeb 	cfg->vow_config = __cpu_to_le32(0);
2015da8fa4e3SBjoern A. Zeeb 	cfg->gtk_offload_max_vdev = __cpu_to_le32(2);
2016da8fa4e3SBjoern A. Zeeb 	cfg->num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx);
2017da8fa4e3SBjoern A. Zeeb 	cfg->max_frag_entries = __cpu_to_le32(2);
2018da8fa4e3SBjoern A. Zeeb 	cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS);
2019da8fa4e3SBjoern A. Zeeb 	cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
2020da8fa4e3SBjoern A. Zeeb 	cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2);
2021da8fa4e3SBjoern A. Zeeb 	cfg->num_multicast_filter_entries = __cpu_to_le32(5);
2022da8fa4e3SBjoern A. Zeeb 	cfg->num_wow_filters = __cpu_to_le32(ar->wow.max_num_patterns);
2023da8fa4e3SBjoern A. Zeeb 	cfg->num_keep_alive_pattern = __cpu_to_le32(6);
2024da8fa4e3SBjoern A. Zeeb 	cfg->keep_alive_pattern_size = __cpu_to_le32(0);
2025da8fa4e3SBjoern A. Zeeb 	cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1);
2026da8fa4e3SBjoern A. Zeeb 	cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1);
2027da8fa4e3SBjoern A. Zeeb 	cfg->wmi_send_separate = __cpu_to_le32(0);
2028da8fa4e3SBjoern A. Zeeb 	cfg->num_ocb_vdevs = __cpu_to_le32(0);
2029da8fa4e3SBjoern A. Zeeb 	cfg->num_ocb_channels = __cpu_to_le32(0);
2030da8fa4e3SBjoern A. Zeeb 	cfg->num_ocb_schedules = __cpu_to_le32(0);
2031da8fa4e3SBjoern A. Zeeb 	cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL);
2032da8fa4e3SBjoern A. Zeeb 
2033da8fa4e3SBjoern A. Zeeb 	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
2034da8fa4e3SBjoern A. Zeeb 		cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
2035da8fa4e3SBjoern A. Zeeb 
2036da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks);
2037da8fa4e3SBjoern A. Zeeb 
2038da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
2039da8fa4e3SBjoern A. Zeeb 	return skb;
2040da8fa4e3SBjoern A. Zeeb }
2041da8fa4e3SBjoern A. Zeeb 
2042da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_start_scan(struct ath10k * ar,const struct wmi_start_scan_arg * arg)2043da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
2044da8fa4e3SBjoern A. Zeeb 				 const struct wmi_start_scan_arg *arg)
2045da8fa4e3SBjoern A. Zeeb {
2046da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_start_scan_cmd *cmd;
2047da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2048da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2049da8fa4e3SBjoern A. Zeeb 	size_t len, chan_len, ssid_len, bssid_len, ie_len;
2050da8fa4e3SBjoern A. Zeeb 	__le32 *chans;
2051da8fa4e3SBjoern A. Zeeb 	struct wmi_ssid *ssids;
2052da8fa4e3SBjoern A. Zeeb 	struct wmi_mac_addr *addrs;
2053da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2054da8fa4e3SBjoern A. Zeeb 	void *ptr;
2055da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2056da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
2057da8fa4e3SBjoern A. Zeeb #endif
2058da8fa4e3SBjoern A. Zeeb 	int i, ret;
2059da8fa4e3SBjoern A. Zeeb 
2060da8fa4e3SBjoern A. Zeeb 	ret = ath10k_wmi_start_scan_verify(arg);
2061da8fa4e3SBjoern A. Zeeb 	if (ret)
2062da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(ret);
2063da8fa4e3SBjoern A. Zeeb 
2064da8fa4e3SBjoern A. Zeeb 	chan_len = arg->n_channels * sizeof(__le32);
2065da8fa4e3SBjoern A. Zeeb 	ssid_len = arg->n_ssids * sizeof(struct wmi_ssid);
2066da8fa4e3SBjoern A. Zeeb 	bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr);
2067da8fa4e3SBjoern A. Zeeb 	ie_len = roundup(arg->ie_len, 4);
2068da8fa4e3SBjoern A. Zeeb 	len = (sizeof(*tlv) + sizeof(*cmd)) +
2069da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + chan_len +
2070da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + ssid_len +
2071da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + bssid_len +
2072da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + ie_len;
2073da8fa4e3SBjoern A. Zeeb 
2074da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
2075da8fa4e3SBjoern A. Zeeb 	if (!skb)
2076da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2077da8fa4e3SBjoern A. Zeeb 
2078da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2079da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
2080da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2081da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2082da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
2083da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2084da8fa4e3SBjoern A. Zeeb #endif
2085da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_START_SCAN_CMD);
2086da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2087da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2088da8fa4e3SBjoern A. Zeeb 
2089da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
2090da8fa4e3SBjoern A. Zeeb 	cmd->burst_duration_ms = __cpu_to_le32(arg->burst_duration_ms);
2091da8fa4e3SBjoern A. Zeeb 	cmd->num_channels = __cpu_to_le32(arg->n_channels);
2092da8fa4e3SBjoern A. Zeeb 	cmd->num_ssids = __cpu_to_le32(arg->n_ssids);
2093da8fa4e3SBjoern A. Zeeb 	cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
2094da8fa4e3SBjoern A. Zeeb 	cmd->ie_len = __cpu_to_le32(arg->ie_len);
2095da8fa4e3SBjoern A. Zeeb 	cmd->num_probes = __cpu_to_le32(3);
2096da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->mac_addr.addr, arg->mac_addr.addr);
2097da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->mac_mask.addr, arg->mac_mask.addr);
2098da8fa4e3SBjoern A. Zeeb 
2099da8fa4e3SBjoern A. Zeeb 	/* FIXME: There are some scan flag inconsistencies across firmwares,
2100da8fa4e3SBjoern A. Zeeb 	 * e.g. WMI-TLV inverts the logic behind the following flag.
2101da8fa4e3SBjoern A. Zeeb 	 */
2102da8fa4e3SBjoern A. Zeeb 	cmd->common.scan_ctrl_flags ^= __cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);
2103da8fa4e3SBjoern A. Zeeb 
2104da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2105da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
2106da8fa4e3SBjoern A. Zeeb 
2107da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2108da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2109da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2110da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2111da8fa4e3SBjoern A. Zeeb #endif
2112da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
2113da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(chan_len);
2114da8fa4e3SBjoern A. Zeeb 	chans = (void *)tlv->value;
2115da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < arg->n_channels; i++)
2116da8fa4e3SBjoern A. Zeeb 		chans[i] = __cpu_to_le32(arg->channels[i]);
2117da8fa4e3SBjoern A. Zeeb 
2118da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2119da8fa4e3SBjoern A. Zeeb 	ptr += chan_len;
2120da8fa4e3SBjoern A. Zeeb 
2121da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2122da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2123da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2124da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2125da8fa4e3SBjoern A. Zeeb #endif
2126da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
2127da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(ssid_len);
2128da8fa4e3SBjoern A. Zeeb 	ssids = (void *)tlv->value;
2129da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < arg->n_ssids; i++) {
2130da8fa4e3SBjoern A. Zeeb 		ssids[i].ssid_len = __cpu_to_le32(arg->ssids[i].len);
2131da8fa4e3SBjoern A. Zeeb 		memcpy(ssids[i].ssid, arg->ssids[i].ssid, arg->ssids[i].len);
2132da8fa4e3SBjoern A. Zeeb 	}
2133da8fa4e3SBjoern A. Zeeb 
2134da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2135da8fa4e3SBjoern A. Zeeb 	ptr += ssid_len;
2136da8fa4e3SBjoern A. Zeeb 
2137da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2138da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2139da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2140da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2141da8fa4e3SBjoern A. Zeeb #endif
2142da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
2143da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(bssid_len);
2144da8fa4e3SBjoern A. Zeeb 	addrs = (void *)tlv->value;
2145da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < arg->n_bssids; i++)
2146da8fa4e3SBjoern A. Zeeb 		ether_addr_copy(addrs[i].addr, arg->bssids[i].bssid);
2147da8fa4e3SBjoern A. Zeeb 
2148da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2149da8fa4e3SBjoern A. Zeeb 	ptr += bssid_len;
2150da8fa4e3SBjoern A. Zeeb 
2151da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2152da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2153da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2154da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2155da8fa4e3SBjoern A. Zeeb #endif
2156da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2157da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(ie_len);
2158da8fa4e3SBjoern A. Zeeb 	memcpy(tlv->value, arg->ie, arg->ie_len);
2159da8fa4e3SBjoern A. Zeeb 
2160da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2161da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2162da8fa4e3SBjoern A. Zeeb 	ptr += ie_len;
2163da8fa4e3SBjoern A. Zeeb #endif
2164da8fa4e3SBjoern A. Zeeb 
2165da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start scan\n");
2166da8fa4e3SBjoern A. Zeeb 	return skb;
2167da8fa4e3SBjoern A. Zeeb }
2168da8fa4e3SBjoern A. Zeeb 
2169da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k * ar,const struct wmi_stop_scan_arg * arg)2170da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar,
2171da8fa4e3SBjoern A. Zeeb 				const struct wmi_stop_scan_arg *arg)
2172da8fa4e3SBjoern A. Zeeb {
2173da8fa4e3SBjoern A. Zeeb 	struct wmi_stop_scan_cmd *cmd;
2174da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2175da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2176da8fa4e3SBjoern A. Zeeb 	u32 scan_id;
2177da8fa4e3SBjoern A. Zeeb 	u32 req_id;
2178da8fa4e3SBjoern A. Zeeb 
2179da8fa4e3SBjoern A. Zeeb 	if (arg->req_id > 0xFFF)
2180da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2181da8fa4e3SBjoern A. Zeeb 	if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
2182da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2183da8fa4e3SBjoern A. Zeeb 
2184da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2185da8fa4e3SBjoern A. Zeeb 	if (!skb)
2186da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2187da8fa4e3SBjoern A. Zeeb 
2188da8fa4e3SBjoern A. Zeeb 	scan_id = arg->u.scan_id;
2189da8fa4e3SBjoern A. Zeeb 	scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
2190da8fa4e3SBjoern A. Zeeb 
2191da8fa4e3SBjoern A. Zeeb 	req_id = arg->req_id;
2192da8fa4e3SBjoern A. Zeeb 	req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
2193da8fa4e3SBjoern A. Zeeb 
2194da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2195da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD);
2196da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2197da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2198da8fa4e3SBjoern A. Zeeb 	cmd->req_type = __cpu_to_le32(arg->req_type);
2199da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id);
2200da8fa4e3SBjoern A. Zeeb 	cmd->scan_id = __cpu_to_le32(scan_id);
2201da8fa4e3SBjoern A. Zeeb 	cmd->scan_req_id = __cpu_to_le32(req_id);
2202da8fa4e3SBjoern A. Zeeb 
2203da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop scan\n");
2204da8fa4e3SBjoern A. Zeeb 	return skb;
2205da8fa4e3SBjoern A. Zeeb }
2206da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k * ar,enum wmi_vdev_subtype subtype)2207da8fa4e3SBjoern A. Zeeb static int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar,
2208da8fa4e3SBjoern A. Zeeb 					      enum wmi_vdev_subtype subtype)
2209da8fa4e3SBjoern A. Zeeb {
2210da8fa4e3SBjoern A. Zeeb 	switch (subtype) {
2211da8fa4e3SBjoern A. Zeeb 	case WMI_VDEV_SUBTYPE_NONE:
2212da8fa4e3SBjoern A. Zeeb 		return WMI_TLV_VDEV_SUBTYPE_NONE;
2213da8fa4e3SBjoern A. Zeeb 	case WMI_VDEV_SUBTYPE_P2P_DEVICE:
2214da8fa4e3SBjoern A. Zeeb 		return WMI_TLV_VDEV_SUBTYPE_P2P_DEV;
2215da8fa4e3SBjoern A. Zeeb 	case WMI_VDEV_SUBTYPE_P2P_CLIENT:
2216da8fa4e3SBjoern A. Zeeb 		return WMI_TLV_VDEV_SUBTYPE_P2P_CLI;
2217da8fa4e3SBjoern A. Zeeb 	case WMI_VDEV_SUBTYPE_P2P_GO:
2218da8fa4e3SBjoern A. Zeeb 		return WMI_TLV_VDEV_SUBTYPE_P2P_GO;
2219da8fa4e3SBjoern A. Zeeb 	case WMI_VDEV_SUBTYPE_PROXY_STA:
2220da8fa4e3SBjoern A. Zeeb 		return WMI_TLV_VDEV_SUBTYPE_PROXY_STA;
2221da8fa4e3SBjoern A. Zeeb 	case WMI_VDEV_SUBTYPE_MESH_11S:
2222da8fa4e3SBjoern A. Zeeb 		return WMI_TLV_VDEV_SUBTYPE_MESH_11S;
2223da8fa4e3SBjoern A. Zeeb 	case WMI_VDEV_SUBTYPE_MESH_NON_11S:
2224da8fa4e3SBjoern A. Zeeb 		return -ENOTSUPP;
2225da8fa4e3SBjoern A. Zeeb 	}
2226da8fa4e3SBjoern A. Zeeb 	return -ENOTSUPP;
2227da8fa4e3SBjoern A. Zeeb }
2228da8fa4e3SBjoern A. Zeeb 
2229da8fa4e3SBjoern A. Zeeb 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])2230da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar,
2231da8fa4e3SBjoern A. Zeeb 				  u32 vdev_id,
2232da8fa4e3SBjoern A. Zeeb 				  enum wmi_vdev_type vdev_type,
2233da8fa4e3SBjoern A. Zeeb 				  enum wmi_vdev_subtype vdev_subtype,
2234da8fa4e3SBjoern A. Zeeb 				  const u8 mac_addr[ETH_ALEN])
2235da8fa4e3SBjoern A. Zeeb {
2236da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_create_cmd *cmd;
2237da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2238da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2239da8fa4e3SBjoern A. Zeeb 
2240da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2241da8fa4e3SBjoern A. Zeeb 	if (!skb)
2242da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2243da8fa4e3SBjoern A. Zeeb 
2244da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2245da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD);
2246da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2247da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2248da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2249da8fa4e3SBjoern A. Zeeb 	cmd->vdev_type = __cpu_to_le32(vdev_type);
2250da8fa4e3SBjoern A. Zeeb 	cmd->vdev_subtype = __cpu_to_le32(vdev_subtype);
2251da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->vdev_macaddr.addr, mac_addr);
2252da8fa4e3SBjoern A. Zeeb 
2253da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev create\n");
2254da8fa4e3SBjoern A. Zeeb 	return skb;
2255da8fa4e3SBjoern A. Zeeb }
2256da8fa4e3SBjoern A. Zeeb 
2257da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k * ar,u32 vdev_id)2258da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
2259da8fa4e3SBjoern A. Zeeb {
2260da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_delete_cmd *cmd;
2261da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2262da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2263da8fa4e3SBjoern A. Zeeb 
2264da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2265da8fa4e3SBjoern A. Zeeb 	if (!skb)
2266da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2267da8fa4e3SBjoern A. Zeeb 
2268da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2269da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD);
2270da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2271da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2272da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2273da8fa4e3SBjoern A. Zeeb 
2274da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev delete\n");
2275da8fa4e3SBjoern A. Zeeb 	return skb;
2276da8fa4e3SBjoern A. Zeeb }
2277da8fa4e3SBjoern A. Zeeb 
2278da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k * ar,const struct wmi_vdev_start_request_arg * arg,bool restart)2279da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
2280da8fa4e3SBjoern A. Zeeb 				 const struct wmi_vdev_start_request_arg *arg,
2281da8fa4e3SBjoern A. Zeeb 				 bool restart)
2282da8fa4e3SBjoern A. Zeeb {
2283da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_vdev_start_cmd *cmd;
2284da8fa4e3SBjoern A. Zeeb 	struct wmi_channel *ch;
2285da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2286da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2287da8fa4e3SBjoern A. Zeeb 	size_t len;
2288da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2289da8fa4e3SBjoern A. Zeeb 	void *ptr;
2290da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2291da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
2292da8fa4e3SBjoern A. Zeeb #endif
2293da8fa4e3SBjoern A. Zeeb 	u32 flags = 0;
2294da8fa4e3SBjoern A. Zeeb 
2295da8fa4e3SBjoern A. Zeeb 	if (WARN_ON(arg->hidden_ssid && !arg->ssid))
2296da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2297da8fa4e3SBjoern A. Zeeb 	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
2298da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2299da8fa4e3SBjoern A. Zeeb 
2300da8fa4e3SBjoern A. Zeeb 	len = (sizeof(*tlv) + sizeof(*cmd)) +
2301da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + sizeof(*ch)) +
2302da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + 0);
2303da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
2304da8fa4e3SBjoern A. Zeeb 	if (!skb)
2305da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2306da8fa4e3SBjoern A. Zeeb 
2307da8fa4e3SBjoern A. Zeeb 	if (arg->hidden_ssid)
2308da8fa4e3SBjoern A. Zeeb 		flags |= WMI_VDEV_START_HIDDEN_SSID;
2309da8fa4e3SBjoern A. Zeeb 	if (arg->pmf_enabled)
2310da8fa4e3SBjoern A. Zeeb 		flags |= WMI_VDEV_START_PMF_ENABLED;
2311da8fa4e3SBjoern A. Zeeb 
2312da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2313da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
2314da8fa4e3SBjoern A. Zeeb 
2315da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2316da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2317da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
2318da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2319da8fa4e3SBjoern A. Zeeb #endif
2320da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD);
2321da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2322da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2323da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2324da8fa4e3SBjoern A. Zeeb 	cmd->bcn_intval = __cpu_to_le32(arg->bcn_intval);
2325da8fa4e3SBjoern A. Zeeb 	cmd->dtim_period = __cpu_to_le32(arg->dtim_period);
2326da8fa4e3SBjoern A. Zeeb 	cmd->flags = __cpu_to_le32(flags);
2327da8fa4e3SBjoern A. Zeeb 	cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate);
2328da8fa4e3SBjoern A. Zeeb 	cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power);
2329da8fa4e3SBjoern A. Zeeb 	cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack);
2330da8fa4e3SBjoern A. Zeeb 
2331da8fa4e3SBjoern A. Zeeb 	if (arg->ssid) {
2332da8fa4e3SBjoern A. Zeeb 		cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len);
2333da8fa4e3SBjoern A. Zeeb 		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
2334da8fa4e3SBjoern A. Zeeb 	}
2335da8fa4e3SBjoern A. Zeeb 
2336da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2337da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
2338da8fa4e3SBjoern A. Zeeb 
2339da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2340da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2341da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2342da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2343da8fa4e3SBjoern A. Zeeb #endif
2344da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
2345da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*ch));
2346da8fa4e3SBjoern A. Zeeb 	ch = (void *)tlv->value;
2347da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_put_wmi_channel(ar, ch, &arg->channel);
2348da8fa4e3SBjoern A. Zeeb 
2349da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2350da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*ch);
2351da8fa4e3SBjoern A. Zeeb 
2352da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2353da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2354da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2355da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2356da8fa4e3SBjoern A. Zeeb #endif
2357da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2358da8fa4e3SBjoern A. Zeeb 	tlv->len = 0;
2359da8fa4e3SBjoern A. Zeeb 
2360da8fa4e3SBjoern A. Zeeb 	/* Note: This is a nested TLV containing:
2361da8fa4e3SBjoern A. Zeeb 	 * [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
2362da8fa4e3SBjoern A. Zeeb 	 */
2363da8fa4e3SBjoern A. Zeeb 
2364da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2365da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2366da8fa4e3SBjoern A. Zeeb 	ptr += 0;
2367da8fa4e3SBjoern A. Zeeb #endif
2368da8fa4e3SBjoern A. Zeeb 
2369da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev start\n");
2370da8fa4e3SBjoern A. Zeeb 	return skb;
2371da8fa4e3SBjoern A. Zeeb }
2372da8fa4e3SBjoern A. Zeeb 
2373da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k * ar,u32 vdev_id)2374da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
2375da8fa4e3SBjoern A. Zeeb {
2376da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_stop_cmd *cmd;
2377da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2378da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2379da8fa4e3SBjoern A. Zeeb 
2380da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2381da8fa4e3SBjoern A. Zeeb 	if (!skb)
2382da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2383da8fa4e3SBjoern A. Zeeb 
2384da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2385da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD);
2386da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2387da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2388da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2389da8fa4e3SBjoern A. Zeeb 
2390da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev stop\n");
2391da8fa4e3SBjoern A. Zeeb 	return skb;
2392da8fa4e3SBjoern A. Zeeb }
2393da8fa4e3SBjoern A. Zeeb 
2394da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k * ar,u32 vdev_id,u32 aid,const u8 * bssid)2395da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
2396da8fa4e3SBjoern A. Zeeb 			      const u8 *bssid)
2397da8fa4e3SBjoern A. Zeeb 
2398da8fa4e3SBjoern A. Zeeb {
2399da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_up_cmd *cmd;
2400da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2401da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2402da8fa4e3SBjoern A. Zeeb 
2403da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2404da8fa4e3SBjoern A. Zeeb 	if (!skb)
2405da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2406da8fa4e3SBjoern A. Zeeb 
2407da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2408da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_UP_CMD);
2409da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2410da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2411da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2412da8fa4e3SBjoern A. Zeeb 	cmd->vdev_assoc_id = __cpu_to_le32(aid);
2413da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
2414da8fa4e3SBjoern A. Zeeb 
2415da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev up\n");
2416da8fa4e3SBjoern A. Zeeb 	return skb;
2417da8fa4e3SBjoern A. Zeeb }
2418da8fa4e3SBjoern A. Zeeb 
2419da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k * ar,u32 vdev_id)2420da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
2421da8fa4e3SBjoern A. Zeeb {
2422da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_down_cmd *cmd;
2423da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2424da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2425da8fa4e3SBjoern A. Zeeb 
2426da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2427da8fa4e3SBjoern A. Zeeb 	if (!skb)
2428da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2429da8fa4e3SBjoern A. Zeeb 
2430da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2431da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD);
2432da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2433da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2434da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2435da8fa4e3SBjoern A. Zeeb 
2436da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev down\n");
2437da8fa4e3SBjoern A. Zeeb 	return skb;
2438da8fa4e3SBjoern A. Zeeb }
2439da8fa4e3SBjoern A. Zeeb 
2440da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k * ar,u32 vdev_id,u32 param_id,u32 param_value)2441da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
2442da8fa4e3SBjoern A. Zeeb 				     u32 param_id, u32 param_value)
2443da8fa4e3SBjoern A. Zeeb {
2444da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_set_param_cmd *cmd;
2445da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2446da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2447da8fa4e3SBjoern A. Zeeb 
2448da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2449da8fa4e3SBjoern A. Zeeb 	if (!skb)
2450da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2451da8fa4e3SBjoern A. Zeeb 
2452da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2453da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD);
2454da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2455da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2456da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2457da8fa4e3SBjoern A. Zeeb 	cmd->param_id = __cpu_to_le32(param_id);
2458da8fa4e3SBjoern A. Zeeb 	cmd->param_value = __cpu_to_le32(param_value);
2459da8fa4e3SBjoern A. Zeeb 
2460da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n",
2461da8fa4e3SBjoern A. Zeeb 		   vdev_id, param_id, param_value);
2462da8fa4e3SBjoern A. Zeeb 	return skb;
2463da8fa4e3SBjoern A. Zeeb }
2464da8fa4e3SBjoern A. Zeeb 
2465da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k * ar,const struct wmi_vdev_install_key_arg * arg)2466da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
2467da8fa4e3SBjoern A. Zeeb 				       const struct wmi_vdev_install_key_arg *arg)
2468da8fa4e3SBjoern A. Zeeb {
2469da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_install_key_cmd *cmd;
2470da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2471da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2472da8fa4e3SBjoern A. Zeeb 	size_t len;
2473da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2474da8fa4e3SBjoern A. Zeeb 	void *ptr;
2475da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2476da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
2477da8fa4e3SBjoern A. Zeeb #endif
2478da8fa4e3SBjoern A. Zeeb 
2479da8fa4e3SBjoern A. Zeeb 	if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
2480da8fa4e3SBjoern A. Zeeb 	    arg->key_data)
2481da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2482da8fa4e3SBjoern A. Zeeb 	if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
2483da8fa4e3SBjoern A. Zeeb 	    !arg->key_data)
2484da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2485da8fa4e3SBjoern A. Zeeb 
2486da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
2487da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + roundup(arg->key_len, sizeof(__le32));
2488da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
2489da8fa4e3SBjoern A. Zeeb 	if (!skb)
2490da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2491da8fa4e3SBjoern A. Zeeb 
2492da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2493da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
2494da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2495da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2496da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
2497da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2498da8fa4e3SBjoern A. Zeeb #endif
2499da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD);
2500da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2501da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2502da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2503da8fa4e3SBjoern A. Zeeb 	cmd->key_idx = __cpu_to_le32(arg->key_idx);
2504da8fa4e3SBjoern A. Zeeb 	cmd->key_flags = __cpu_to_le32(arg->key_flags);
2505da8fa4e3SBjoern A. Zeeb 	cmd->key_cipher = __cpu_to_le32(arg->key_cipher);
2506da8fa4e3SBjoern A. Zeeb 	cmd->key_len = __cpu_to_le32(arg->key_len);
2507da8fa4e3SBjoern A. Zeeb 	cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len);
2508da8fa4e3SBjoern A. Zeeb 	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
2509da8fa4e3SBjoern A. Zeeb 
2510da8fa4e3SBjoern A. Zeeb 	if (arg->macaddr)
2511da8fa4e3SBjoern A. Zeeb 		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
2512da8fa4e3SBjoern A. Zeeb 
2513da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2514da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
2515da8fa4e3SBjoern A. Zeeb 
2516da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2517da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2518da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2519da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2520da8fa4e3SBjoern A. Zeeb #endif
2521da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2522da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(roundup(arg->key_len, sizeof(__le32)));
2523da8fa4e3SBjoern A. Zeeb 	if (arg->key_data)
2524da8fa4e3SBjoern A. Zeeb 		memcpy(tlv->value, arg->key_data, arg->key_len);
2525da8fa4e3SBjoern A. Zeeb 
2526da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2527da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2528da8fa4e3SBjoern A. Zeeb 	ptr += roundup(arg->key_len, sizeof(__le32));
2529da8fa4e3SBjoern A. Zeeb #endif
2530da8fa4e3SBjoern A. Zeeb 
2531da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev install key\n");
2532da8fa4e3SBjoern A. Zeeb 	return skb;
2533da8fa4e3SBjoern A. Zeeb }
2534da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_put_uapsd_ac(struct ath10k * ar,void * ptr,const struct wmi_sta_uapsd_auto_trig_arg * arg)2535da8fa4e3SBjoern A. Zeeb static void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr,
2536da8fa4e3SBjoern A. Zeeb 					 const struct wmi_sta_uapsd_auto_trig_arg *arg)
2537da8fa4e3SBjoern A. Zeeb {
2538da8fa4e3SBjoern A. Zeeb 	struct wmi_sta_uapsd_auto_trig_param *ac;
2539da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2540da8fa4e3SBjoern A. Zeeb 
2541da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2542da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM);
2543da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*ac));
2544da8fa4e3SBjoern A. Zeeb 	ac = (void *)tlv->value;
2545da8fa4e3SBjoern A. Zeeb 
2546da8fa4e3SBjoern A. Zeeb 	ac->wmm_ac = __cpu_to_le32(arg->wmm_ac);
2547da8fa4e3SBjoern A. Zeeb 	ac->user_priority = __cpu_to_le32(arg->user_priority);
2548da8fa4e3SBjoern A. Zeeb 	ac->service_interval = __cpu_to_le32(arg->service_interval);
2549da8fa4e3SBjoern A. Zeeb 	ac->suspend_interval = __cpu_to_le32(arg->suspend_interval);
2550da8fa4e3SBjoern A. Zeeb 	ac->delay_interval = __cpu_to_le32(arg->delay_interval);
2551da8fa4e3SBjoern A. Zeeb 
2552da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
2553da8fa4e3SBjoern A. Zeeb 		   "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n",
2554da8fa4e3SBjoern A. Zeeb 		   ac->wmm_ac, ac->user_priority, ac->service_interval,
2555da8fa4e3SBjoern A. Zeeb 		   ac->suspend_interval, ac->delay_interval);
2556da8fa4e3SBjoern A. Zeeb 
2557da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2558da8fa4e3SBjoern A. Zeeb 	return ptr + sizeof(*tlv) + sizeof(*ac);
2559da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2560da8fa4e3SBjoern A. Zeeb 	return (u8 *)ptr + sizeof(*tlv) + sizeof(*ac);
2561da8fa4e3SBjoern A. Zeeb #endif
2562da8fa4e3SBjoern A. Zeeb }
2563da8fa4e3SBjoern A. Zeeb 
2564da8fa4e3SBjoern A. Zeeb 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)2565da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id,
2566da8fa4e3SBjoern A. Zeeb 				     const u8 peer_addr[ETH_ALEN],
2567da8fa4e3SBjoern A. Zeeb 				     const struct wmi_sta_uapsd_auto_trig_arg *args,
2568da8fa4e3SBjoern A. Zeeb 				     u32 num_ac)
2569da8fa4e3SBjoern A. Zeeb {
2570da8fa4e3SBjoern A. Zeeb 	struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd;
2571da8fa4e3SBjoern A. Zeeb 	struct wmi_sta_uapsd_auto_trig_param *ac;
2572da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2573da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2574da8fa4e3SBjoern A. Zeeb 	size_t len;
2575da8fa4e3SBjoern A. Zeeb 	size_t ac_tlv_len;
2576da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2577da8fa4e3SBjoern A. Zeeb 	void *ptr;
2578da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2579da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
2580da8fa4e3SBjoern A. Zeeb #endif
2581da8fa4e3SBjoern A. Zeeb 	int i;
2582da8fa4e3SBjoern A. Zeeb 
2583da8fa4e3SBjoern A. Zeeb 	ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac));
2584da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
2585da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + ac_tlv_len;
2586da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
2587da8fa4e3SBjoern A. Zeeb 	if (!skb)
2588da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2589da8fa4e3SBjoern A. Zeeb 
2590da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2591da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
2592da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2593da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2594da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
2595da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2596da8fa4e3SBjoern A. Zeeb #endif
2597da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD);
2598da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2599da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2600da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2601da8fa4e3SBjoern A. Zeeb 	cmd->num_ac = __cpu_to_le32(num_ac);
2602da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2603da8fa4e3SBjoern A. Zeeb 
2604da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2605da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
2606da8fa4e3SBjoern A. Zeeb 
2607da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2608da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2609da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2610da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2611da8fa4e3SBjoern A. Zeeb #endif
2612da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2613da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(ac_tlv_len);
2614da8fa4e3SBjoern A. Zeeb 	ac = (void *)tlv->value;
2615da8fa4e3SBjoern A. Zeeb 
2616da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2617da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < num_ac; i++)
2618da8fa4e3SBjoern A. Zeeb 		ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]);
2619da8fa4e3SBjoern A. Zeeb 
2620da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n");
2621da8fa4e3SBjoern A. Zeeb 	return skb;
2622da8fa4e3SBjoern A. Zeeb }
2623da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_put_wmm(void * ptr,const struct wmi_wmm_params_arg * arg)2624da8fa4e3SBjoern A. Zeeb static void *ath10k_wmi_tlv_put_wmm(void *ptr,
2625da8fa4e3SBjoern A. Zeeb 				    const struct wmi_wmm_params_arg *arg)
2626da8fa4e3SBjoern A. Zeeb {
2627da8fa4e3SBjoern A. Zeeb 	struct wmi_wmm_params *wmm;
2628da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2629da8fa4e3SBjoern A. Zeeb 
2630da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2631da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS);
2632da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*wmm));
2633da8fa4e3SBjoern A. Zeeb 	wmm = (void *)tlv->value;
2634da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_set_wmm_param(wmm, arg);
2635da8fa4e3SBjoern A. Zeeb 
2636da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2637da8fa4e3SBjoern A. Zeeb 	return ptr + sizeof(*tlv) + sizeof(*wmm);
2638da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2639da8fa4e3SBjoern A. Zeeb 	return (u8 *)ptr + sizeof(*tlv) + sizeof(*wmm);
2640da8fa4e3SBjoern A. Zeeb #endif
2641da8fa4e3SBjoern A. Zeeb }
2642da8fa4e3SBjoern A. Zeeb 
2643da8fa4e3SBjoern A. Zeeb 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)2644da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
2645da8fa4e3SBjoern A. Zeeb 				    const struct wmi_wmm_params_all_arg *arg)
2646da8fa4e3SBjoern A. Zeeb {
2647da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_vdev_set_wmm_cmd *cmd;
2648da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2649da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2650da8fa4e3SBjoern A. Zeeb 	size_t len;
2651da8fa4e3SBjoern A. Zeeb 	void *ptr;
2652da8fa4e3SBjoern A. Zeeb 
2653da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
2654da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
2655da8fa4e3SBjoern A. Zeeb 	if (!skb)
2656da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2657da8fa4e3SBjoern A. Zeeb 
2658da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
2659da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2660da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD);
2661da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2662da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2663da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2664da8fa4e3SBjoern A. Zeeb 
2665da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[0].params, &arg->ac_be);
2666da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[1].params, &arg->ac_bk);
2667da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[2].params, &arg->ac_vi);
2668da8fa4e3SBjoern A. Zeeb 	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[3].params, &arg->ac_vo);
2669da8fa4e3SBjoern A. Zeeb 
2670da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n");
2671da8fa4e3SBjoern A. Zeeb 	return skb;
2672da8fa4e3SBjoern A. Zeeb }
2673da8fa4e3SBjoern A. Zeeb 
2674da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k * ar,const struct wmi_sta_keepalive_arg * arg)2675da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar,
2676da8fa4e3SBjoern A. Zeeb 				    const struct wmi_sta_keepalive_arg *arg)
2677da8fa4e3SBjoern A. Zeeb {
2678da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_sta_keepalive_cmd *cmd;
2679da8fa4e3SBjoern A. Zeeb 	struct wmi_sta_keepalive_arp_resp *arp;
2680da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2681da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2682da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2683da8fa4e3SBjoern A. Zeeb 	void *ptr;
2684da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2685da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
2686da8fa4e3SBjoern A. Zeeb #endif
2687da8fa4e3SBjoern A. Zeeb 	size_t len;
2688da8fa4e3SBjoern A. Zeeb 
2689da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
2690da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + sizeof(*arp);
2691da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
2692da8fa4e3SBjoern A. Zeeb 	if (!skb)
2693da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2694da8fa4e3SBjoern A. Zeeb 
2695da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2696da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
2697da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2698da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2699da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
2700da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2701da8fa4e3SBjoern A. Zeeb #endif
2702da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD);
2703da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2704da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2705da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2706da8fa4e3SBjoern A. Zeeb 	cmd->enabled = __cpu_to_le32(arg->enabled);
2707da8fa4e3SBjoern A. Zeeb 	cmd->method = __cpu_to_le32(arg->method);
2708da8fa4e3SBjoern A. Zeeb 	cmd->interval = __cpu_to_le32(arg->interval);
2709da8fa4e3SBjoern A. Zeeb 
2710da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2711da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
2712da8fa4e3SBjoern A. Zeeb 
2713da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2714da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2715da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2716da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2717da8fa4e3SBjoern A. Zeeb #endif
2718da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE);
2719da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*arp));
2720da8fa4e3SBjoern A. Zeeb 	arp = (void *)tlv->value;
2721da8fa4e3SBjoern A. Zeeb 
2722da8fa4e3SBjoern A. Zeeb 	arp->src_ip4_addr = arg->src_ip4_addr;
2723da8fa4e3SBjoern A. Zeeb 	arp->dest_ip4_addr = arg->dest_ip4_addr;
2724da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
2725da8fa4e3SBjoern A. Zeeb 
2726da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d interval %d\n",
2727da8fa4e3SBjoern A. Zeeb 		   arg->vdev_id, arg->enabled, arg->method, arg->interval);
2728da8fa4e3SBjoern A. Zeeb 	return skb;
2729da8fa4e3SBjoern A. Zeeb }
2730da8fa4e3SBjoern A. Zeeb 
2731da8fa4e3SBjoern A. Zeeb 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)2732da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
2733da8fa4e3SBjoern A. Zeeb 				  const u8 peer_addr[ETH_ALEN],
2734da8fa4e3SBjoern A. Zeeb 				  enum wmi_peer_type peer_type)
2735da8fa4e3SBjoern A. Zeeb {
2736da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_peer_create_cmd *cmd;
2737da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2738da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2739da8fa4e3SBjoern A. Zeeb 
2740da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2741da8fa4e3SBjoern A. Zeeb 	if (!skb)
2742da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2743da8fa4e3SBjoern A. Zeeb 
2744da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2745da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD);
2746da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2747da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2748da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2749da8fa4e3SBjoern A. Zeeb 	cmd->peer_type = __cpu_to_le32(peer_type);
2750da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->peer_addr.addr, peer_addr);
2751da8fa4e3SBjoern A. Zeeb 
2752da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer create\n");
2753da8fa4e3SBjoern A. Zeeb 	return skb;
2754da8fa4e3SBjoern A. Zeeb }
2755da8fa4e3SBjoern A. Zeeb 
2756da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k * ar,u32 vdev_id,const u8 peer_addr[ETH_ALEN])2757da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
2758da8fa4e3SBjoern A. Zeeb 				  const u8 peer_addr[ETH_ALEN])
2759da8fa4e3SBjoern A. Zeeb {
2760da8fa4e3SBjoern A. Zeeb 	struct wmi_peer_delete_cmd *cmd;
2761da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2762da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2763da8fa4e3SBjoern A. Zeeb 
2764da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2765da8fa4e3SBjoern A. Zeeb 	if (!skb)
2766da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2767da8fa4e3SBjoern A. Zeeb 
2768da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2769da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD);
2770da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2771da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2772da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2773da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2774da8fa4e3SBjoern A. Zeeb 
2775da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete\n");
2776da8fa4e3SBjoern A. Zeeb 	return skb;
2777da8fa4e3SBjoern A. Zeeb }
2778da8fa4e3SBjoern A. Zeeb 
2779da8fa4e3SBjoern A. Zeeb 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)2780da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
2781da8fa4e3SBjoern A. Zeeb 				 const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
2782da8fa4e3SBjoern A. Zeeb {
2783da8fa4e3SBjoern A. Zeeb 	struct wmi_peer_flush_tids_cmd *cmd;
2784da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2785da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2786da8fa4e3SBjoern A. Zeeb 
2787da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2788da8fa4e3SBjoern A. Zeeb 	if (!skb)
2789da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2790da8fa4e3SBjoern A. Zeeb 
2791da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2792da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD);
2793da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2794da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2795da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2796da8fa4e3SBjoern A. Zeeb 	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
2797da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2798da8fa4e3SBjoern A. Zeeb 
2799da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer flush\n");
2800da8fa4e3SBjoern A. Zeeb 	return skb;
2801da8fa4e3SBjoern A. Zeeb }
2802da8fa4e3SBjoern A. Zeeb 
2803da8fa4e3SBjoern A. Zeeb 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)2804da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
2805da8fa4e3SBjoern A. Zeeb 				     const u8 *peer_addr,
2806da8fa4e3SBjoern A. Zeeb 				     enum wmi_peer_param param_id,
2807da8fa4e3SBjoern A. Zeeb 				     u32 param_value)
2808da8fa4e3SBjoern A. Zeeb {
2809da8fa4e3SBjoern A. Zeeb 	struct wmi_peer_set_param_cmd *cmd;
2810da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2811da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2812da8fa4e3SBjoern A. Zeeb 
2813da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2814da8fa4e3SBjoern A. Zeeb 	if (!skb)
2815da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2816da8fa4e3SBjoern A. Zeeb 
2817da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2818da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD);
2819da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2820da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2821da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2822da8fa4e3SBjoern A. Zeeb 	cmd->param_id = __cpu_to_le32(param_id);
2823da8fa4e3SBjoern A. Zeeb 	cmd->param_value = __cpu_to_le32(param_value);
2824da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
2825da8fa4e3SBjoern A. Zeeb 
2826da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
2827da8fa4e3SBjoern A. Zeeb 		   "wmi tlv vdev %d peer %pM set param %d value 0x%x\n",
2828da8fa4e3SBjoern A. Zeeb 		   vdev_id, peer_addr, param_id, param_value);
2829da8fa4e3SBjoern A. Zeeb 	return skb;
2830da8fa4e3SBjoern A. Zeeb }
2831da8fa4e3SBjoern A. Zeeb 
2832da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k * ar,const struct wmi_peer_assoc_complete_arg * arg)2833da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k *ar,
2834da8fa4e3SBjoern A. Zeeb 				 const struct wmi_peer_assoc_complete_arg *arg)
2835da8fa4e3SBjoern A. Zeeb {
2836da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_peer_assoc_cmd *cmd;
2837da8fa4e3SBjoern A. Zeeb 	struct wmi_vht_rate_set *vht_rate;
2838da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2839da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2840da8fa4e3SBjoern A. Zeeb 	size_t len, legacy_rate_len, ht_rate_len;
2841da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2842da8fa4e3SBjoern A. Zeeb 	void *ptr;
2843da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2844da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
2845da8fa4e3SBjoern A. Zeeb #endif
2846da8fa4e3SBjoern A. Zeeb 
2847da8fa4e3SBjoern A. Zeeb 	if (arg->peer_mpdu_density > 16)
2848da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2849da8fa4e3SBjoern A. Zeeb 	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
2850da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2851da8fa4e3SBjoern A. Zeeb 	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
2852da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
2853da8fa4e3SBjoern A. Zeeb 
2854da8fa4e3SBjoern A. Zeeb 	legacy_rate_len = roundup(arg->peer_legacy_rates.num_rates,
2855da8fa4e3SBjoern A. Zeeb 				  sizeof(__le32));
2856da8fa4e3SBjoern A. Zeeb 	ht_rate_len = roundup(arg->peer_ht_rates.num_rates, sizeof(__le32));
2857da8fa4e3SBjoern A. Zeeb 	len = (sizeof(*tlv) + sizeof(*cmd)) +
2858da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + legacy_rate_len) +
2859da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + ht_rate_len) +
2860da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + sizeof(*vht_rate));
2861da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
2862da8fa4e3SBjoern A. Zeeb 	if (!skb)
2863da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2864da8fa4e3SBjoern A. Zeeb 
2865da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2866da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
2867da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2868da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2869da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
2870da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2871da8fa4e3SBjoern A. Zeeb #endif
2872da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD);
2873da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2874da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2875da8fa4e3SBjoern A. Zeeb 
2876da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
2877da8fa4e3SBjoern A. Zeeb 	cmd->new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
2878da8fa4e3SBjoern A. Zeeb 	cmd->assoc_id = __cpu_to_le32(arg->peer_aid);
2879da8fa4e3SBjoern A. Zeeb 	cmd->flags = __cpu_to_le32(arg->peer_flags);
2880da8fa4e3SBjoern A. Zeeb 	cmd->caps = __cpu_to_le32(arg->peer_caps);
2881da8fa4e3SBjoern A. Zeeb 	cmd->listen_intval = __cpu_to_le32(arg->peer_listen_intval);
2882da8fa4e3SBjoern A. Zeeb 	cmd->ht_caps = __cpu_to_le32(arg->peer_ht_caps);
2883da8fa4e3SBjoern A. Zeeb 	cmd->max_mpdu = __cpu_to_le32(arg->peer_max_mpdu);
2884da8fa4e3SBjoern A. Zeeb 	cmd->mpdu_density = __cpu_to_le32(arg->peer_mpdu_density);
2885da8fa4e3SBjoern A. Zeeb 	cmd->rate_caps = __cpu_to_le32(arg->peer_rate_caps);
2886da8fa4e3SBjoern A. Zeeb 	cmd->nss = __cpu_to_le32(arg->peer_num_spatial_streams);
2887da8fa4e3SBjoern A. Zeeb 	cmd->vht_caps = __cpu_to_le32(arg->peer_vht_caps);
2888da8fa4e3SBjoern A. Zeeb 	cmd->phy_mode = __cpu_to_le32(arg->peer_phymode);
2889da8fa4e3SBjoern A. Zeeb 	cmd->num_legacy_rates = __cpu_to_le32(arg->peer_legacy_rates.num_rates);
2890da8fa4e3SBjoern A. Zeeb 	cmd->num_ht_rates = __cpu_to_le32(arg->peer_ht_rates.num_rates);
2891da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->mac_addr.addr, arg->addr);
2892da8fa4e3SBjoern A. Zeeb 
2893da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2894da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
2895da8fa4e3SBjoern A. Zeeb 
2896da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2897da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2898da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2899da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2900da8fa4e3SBjoern A. Zeeb #endif
2901da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2902da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(legacy_rate_len);
2903da8fa4e3SBjoern A. Zeeb 	memcpy(tlv->value, arg->peer_legacy_rates.rates,
2904da8fa4e3SBjoern A. Zeeb 	       arg->peer_legacy_rates.num_rates);
2905da8fa4e3SBjoern A. Zeeb 
2906da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2907da8fa4e3SBjoern A. Zeeb 	ptr += legacy_rate_len;
2908da8fa4e3SBjoern A. Zeeb 
2909da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2910da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2911da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2912da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2913da8fa4e3SBjoern A. Zeeb #endif
2914da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2915da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(ht_rate_len);
2916da8fa4e3SBjoern A. Zeeb 	memcpy(tlv->value, arg->peer_ht_rates.rates,
2917da8fa4e3SBjoern A. Zeeb 	       arg->peer_ht_rates.num_rates);
2918da8fa4e3SBjoern A. Zeeb 
2919da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2920da8fa4e3SBjoern A. Zeeb 	ptr += ht_rate_len;
2921da8fa4e3SBjoern A. Zeeb 
2922da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2923da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
2924da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
2925da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
2926da8fa4e3SBjoern A. Zeeb #endif
2927da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VHT_RATE_SET);
2928da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*vht_rate));
2929da8fa4e3SBjoern A. Zeeb 	vht_rate = (void *)tlv->value;
2930da8fa4e3SBjoern A. Zeeb 
2931da8fa4e3SBjoern A. Zeeb 	vht_rate->rx_max_rate = __cpu_to_le32(arg->peer_vht_rates.rx_max_rate);
2932da8fa4e3SBjoern A. Zeeb 	vht_rate->rx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set);
2933da8fa4e3SBjoern A. Zeeb 	vht_rate->tx_max_rate = __cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
2934da8fa4e3SBjoern A. Zeeb 	vht_rate->tx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
2935da8fa4e3SBjoern A. Zeeb 
2936da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
2937da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
2938da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*vht_rate);
2939da8fa4e3SBjoern A. Zeeb #endif
2940da8fa4e3SBjoern A. Zeeb 
2941da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer assoc\n");
2942da8fa4e3SBjoern A. Zeeb 	return skb;
2943da8fa4e3SBjoern A. Zeeb }
2944da8fa4e3SBjoern A. Zeeb 
2945da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k * ar,u32 vdev_id,enum wmi_sta_ps_mode psmode)2946da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
2947da8fa4e3SBjoern A. Zeeb 				 enum wmi_sta_ps_mode psmode)
2948da8fa4e3SBjoern A. Zeeb {
2949da8fa4e3SBjoern A. Zeeb 	struct wmi_sta_powersave_mode_cmd *cmd;
2950da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2951da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2952da8fa4e3SBjoern A. Zeeb 
2953da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2954da8fa4e3SBjoern A. Zeeb 	if (!skb)
2955da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2956da8fa4e3SBjoern A. Zeeb 
2957da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2958da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD);
2959da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2960da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2961da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2962da8fa4e3SBjoern A. Zeeb 	cmd->sta_ps_mode = __cpu_to_le32(psmode);
2963da8fa4e3SBjoern A. Zeeb 
2964da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set psmode\n");
2965da8fa4e3SBjoern A. Zeeb 	return skb;
2966da8fa4e3SBjoern A. Zeeb }
2967da8fa4e3SBjoern A. Zeeb 
2968da8fa4e3SBjoern A. Zeeb 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)2969da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
2970da8fa4e3SBjoern A. Zeeb 				 enum wmi_sta_powersave_param param_id,
2971da8fa4e3SBjoern A. Zeeb 				 u32 param_value)
2972da8fa4e3SBjoern A. Zeeb {
2973da8fa4e3SBjoern A. Zeeb 	struct wmi_sta_powersave_param_cmd *cmd;
2974da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2975da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
2976da8fa4e3SBjoern A. Zeeb 
2977da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2978da8fa4e3SBjoern A. Zeeb 	if (!skb)
2979da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
2980da8fa4e3SBjoern A. Zeeb 
2981da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
2982da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD);
2983da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
2984da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
2985da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
2986da8fa4e3SBjoern A. Zeeb 	cmd->param_id = __cpu_to_le32(param_id);
2987da8fa4e3SBjoern A. Zeeb 	cmd->param_value = __cpu_to_le32(param_value);
2988da8fa4e3SBjoern A. Zeeb 
2989da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set sta ps\n");
2990da8fa4e3SBjoern A. Zeeb 	return skb;
2991da8fa4e3SBjoern A. Zeeb }
2992da8fa4e3SBjoern A. Zeeb 
2993da8fa4e3SBjoern A. Zeeb 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)2994da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
2995da8fa4e3SBjoern A. Zeeb 				enum wmi_ap_ps_peer_param param_id, u32 value)
2996da8fa4e3SBjoern A. Zeeb {
2997da8fa4e3SBjoern A. Zeeb 	struct wmi_ap_ps_peer_cmd *cmd;
2998da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
2999da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3000da8fa4e3SBjoern A. Zeeb 
3001da8fa4e3SBjoern A. Zeeb 	if (!mac)
3002da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
3003da8fa4e3SBjoern A. Zeeb 
3004da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3005da8fa4e3SBjoern A. Zeeb 	if (!skb)
3006da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3007da8fa4e3SBjoern A. Zeeb 
3008da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3009da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD);
3010da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3011da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3012da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3013da8fa4e3SBjoern A. Zeeb 	cmd->param_id = __cpu_to_le32(param_id);
3014da8fa4e3SBjoern A. Zeeb 	cmd->param_value = __cpu_to_le32(value);
3015da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->peer_macaddr.addr, mac);
3016da8fa4e3SBjoern A. Zeeb 
3017da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv ap ps param\n");
3018da8fa4e3SBjoern A. Zeeb 	return skb;
3019da8fa4e3SBjoern A. Zeeb }
3020da8fa4e3SBjoern A. Zeeb 
3021da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k * ar,const struct wmi_scan_chan_list_arg * arg)3022da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
3023da8fa4e3SBjoern A. Zeeb 				     const struct wmi_scan_chan_list_arg *arg)
3024da8fa4e3SBjoern A. Zeeb {
3025da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_scan_chan_list_cmd *cmd;
3026da8fa4e3SBjoern A. Zeeb 	struct wmi_channel *ci;
3027da8fa4e3SBjoern A. Zeeb 	struct wmi_channel_arg *ch;
3028da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3029da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3030da8fa4e3SBjoern A. Zeeb 	size_t chans_len, len;
3031da8fa4e3SBjoern A. Zeeb 	int i;
3032da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3033da8fa4e3SBjoern A. Zeeb 	void *ptr, *chans;
3034da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3035da8fa4e3SBjoern A. Zeeb 	u8 *ptr, *chans;
3036da8fa4e3SBjoern A. Zeeb #endif
3037da8fa4e3SBjoern A. Zeeb 
3038da8fa4e3SBjoern A. Zeeb 	chans_len = arg->n_channels * (sizeof(*tlv) + sizeof(*ci));
3039da8fa4e3SBjoern A. Zeeb 	len = (sizeof(*tlv) + sizeof(*cmd)) +
3040da8fa4e3SBjoern A. Zeeb 	      (sizeof(*tlv) + chans_len);
3041da8fa4e3SBjoern A. Zeeb 
3042da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3043da8fa4e3SBjoern A. Zeeb 	if (!skb)
3044da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3045da8fa4e3SBjoern A. Zeeb 
3046da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3047da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3048da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3049da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3050da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3051da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3052da8fa4e3SBjoern A. Zeeb #endif
3053da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD);
3054da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3055da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3056da8fa4e3SBjoern A. Zeeb 	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
3057da8fa4e3SBjoern A. Zeeb 
3058da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3059da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3060da8fa4e3SBjoern A. Zeeb 
3061da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3062da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3063da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3064da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3065da8fa4e3SBjoern A. Zeeb #endif
3066da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3067da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(chans_len);
3068da8fa4e3SBjoern A. Zeeb 	chans = (void *)tlv->value;
3069da8fa4e3SBjoern A. Zeeb 
3070da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < arg->n_channels; i++) {
3071da8fa4e3SBjoern A. Zeeb 		ch = &arg->channels[i];
3072da8fa4e3SBjoern A. Zeeb 
3073da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3074da8fa4e3SBjoern A. Zeeb 		tlv = chans;
3075da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3076da8fa4e3SBjoern A. Zeeb 		tlv = (void *)chans;
3077da8fa4e3SBjoern A. Zeeb #endif
3078da8fa4e3SBjoern A. Zeeb 		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
3079da8fa4e3SBjoern A. Zeeb 		tlv->len = __cpu_to_le16(sizeof(*ci));
3080da8fa4e3SBjoern A. Zeeb 		ci = (void *)tlv->value;
3081da8fa4e3SBjoern A. Zeeb 
3082da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_put_wmi_channel(ar, ci, ch);
3083da8fa4e3SBjoern A. Zeeb 
3084da8fa4e3SBjoern A. Zeeb 		chans += sizeof(*tlv);
3085da8fa4e3SBjoern A. Zeeb 		chans += sizeof(*ci);
3086da8fa4e3SBjoern A. Zeeb 	}
3087da8fa4e3SBjoern A. Zeeb 
3088da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3089da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3090da8fa4e3SBjoern A. Zeeb 	ptr += chans_len;
3091da8fa4e3SBjoern A. Zeeb #endif
3092da8fa4e3SBjoern A. Zeeb 
3093da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan chan list\n");
3094da8fa4e3SBjoern A. Zeeb 	return skb;
3095da8fa4e3SBjoern A. Zeeb }
3096da8fa4e3SBjoern A. Zeeb 
3097da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_scan_prob_req_oui(struct ath10k * ar,u32 prob_req_oui)3098da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_scan_prob_req_oui(struct ath10k *ar, u32 prob_req_oui)
3099da8fa4e3SBjoern A. Zeeb {
3100da8fa4e3SBjoern A. Zeeb 	struct wmi_scan_prob_req_oui_cmd *cmd;
3101da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3102da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3103da8fa4e3SBjoern A. Zeeb 
3104da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3105da8fa4e3SBjoern A. Zeeb 	if (!skb)
3106da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3107da8fa4e3SBjoern A. Zeeb 
3108da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3109da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_PROB_REQ_OUI_CMD);
3110da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3111da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3112da8fa4e3SBjoern A. Zeeb 	cmd->prob_req_oui = __cpu_to_le32(prob_req_oui);
3113da8fa4e3SBjoern A. Zeeb 
3114da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan prob req oui\n");
3115da8fa4e3SBjoern A. Zeeb 	return skb;
3116da8fa4e3SBjoern A. Zeeb }
3117da8fa4e3SBjoern A. Zeeb 
3118da8fa4e3SBjoern A. Zeeb 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)3119da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
3120da8fa4e3SBjoern A. Zeeb 				 const void *bcn, size_t bcn_len,
3121da8fa4e3SBjoern A. Zeeb 				 u32 bcn_paddr, bool dtim_zero,
3122da8fa4e3SBjoern A. Zeeb 				 bool deliver_cab)
3123da8fa4e3SBjoern A. Zeeb 
3124da8fa4e3SBjoern A. Zeeb {
3125da8fa4e3SBjoern A. Zeeb 	struct wmi_bcn_tx_ref_cmd *cmd;
3126da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3127da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3128da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3129da8fa4e3SBjoern A. Zeeb 	struct ieee80211_hdr *hdr;
3130da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3131da8fa4e3SBjoern A. Zeeb 	const struct ieee80211_hdr *hdr;
3132da8fa4e3SBjoern A. Zeeb #endif
3133da8fa4e3SBjoern A. Zeeb 	u16 fc;
3134da8fa4e3SBjoern A. Zeeb 
3135da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3136da8fa4e3SBjoern A. Zeeb 	if (!skb)
3137da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3138da8fa4e3SBjoern A. Zeeb 
3139da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3140da8fa4e3SBjoern A. Zeeb 	hdr = (struct ieee80211_hdr *)bcn;
3141da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3142da8fa4e3SBjoern A. Zeeb 	hdr = (const struct ieee80211_hdr *)bcn;
3143da8fa4e3SBjoern A. Zeeb #endif
3144da8fa4e3SBjoern A. Zeeb 	fc = le16_to_cpu(hdr->frame_control);
3145da8fa4e3SBjoern A. Zeeb 
3146da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3147da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD);
3148da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3149da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3150da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3151da8fa4e3SBjoern A. Zeeb 	cmd->data_len = __cpu_to_le32(bcn_len);
3152da8fa4e3SBjoern A. Zeeb 	cmd->data_ptr = __cpu_to_le32(bcn_paddr);
3153da8fa4e3SBjoern A. Zeeb 	cmd->msdu_id = 0;
3154da8fa4e3SBjoern A. Zeeb 	cmd->frame_control = __cpu_to_le32(fc);
3155da8fa4e3SBjoern A. Zeeb 	cmd->flags = 0;
3156da8fa4e3SBjoern A. Zeeb 
3157da8fa4e3SBjoern A. Zeeb 	if (dtim_zero)
3158da8fa4e3SBjoern A. Zeeb 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
3159da8fa4e3SBjoern A. Zeeb 
3160da8fa4e3SBjoern A. Zeeb 	if (deliver_cab)
3161da8fa4e3SBjoern A. Zeeb 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
3162da8fa4e3SBjoern A. Zeeb 
3163da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n");
3164da8fa4e3SBjoern A. Zeeb 	return skb;
3165da8fa4e3SBjoern A. Zeeb }
3166da8fa4e3SBjoern A. Zeeb 
3167da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k * ar,const struct wmi_wmm_params_all_arg * arg)3168da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
3169da8fa4e3SBjoern A. Zeeb 				   const struct wmi_wmm_params_all_arg *arg)
3170da8fa4e3SBjoern A. Zeeb {
3171da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_pdev_set_wmm_cmd *cmd;
3172da8fa4e3SBjoern A. Zeeb 	struct wmi_wmm_params *wmm;
3173da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3174da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3175da8fa4e3SBjoern A. Zeeb 	size_t len;
3176da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3177da8fa4e3SBjoern A. Zeeb 	void *ptr;
3178da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3179da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3180da8fa4e3SBjoern A. Zeeb #endif
3181da8fa4e3SBjoern A. Zeeb 
3182da8fa4e3SBjoern A. Zeeb 	len = (sizeof(*tlv) + sizeof(*cmd)) +
3183da8fa4e3SBjoern A. Zeeb 	      (4 * (sizeof(*tlv) + sizeof(*wmm)));
3184da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3185da8fa4e3SBjoern A. Zeeb 	if (!skb)
3186da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3187da8fa4e3SBjoern A. Zeeb 
3188da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3189da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3190da8fa4e3SBjoern A. Zeeb 
3191da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3192da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3193da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3194da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3195da8fa4e3SBjoern A. Zeeb #endif
3196da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD);
3197da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3198da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3199da8fa4e3SBjoern A. Zeeb 
3200da8fa4e3SBjoern A. Zeeb 	/* nothing to set here */
3201da8fa4e3SBjoern A. Zeeb 
3202da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3203da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3204da8fa4e3SBjoern A. Zeeb 
3205da8fa4e3SBjoern A. Zeeb 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be);
3206da8fa4e3SBjoern A. Zeeb 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk);
3207da8fa4e3SBjoern A. Zeeb 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi);
3208da8fa4e3SBjoern A. Zeeb 	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo);
3209da8fa4e3SBjoern A. Zeeb 
3210da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set wmm\n");
3211da8fa4e3SBjoern A. Zeeb 	return skb;
3212da8fa4e3SBjoern A. Zeeb }
3213da8fa4e3SBjoern A. Zeeb 
3214da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_request_stats(struct ath10k * ar,u32 stats_mask)3215da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
3216da8fa4e3SBjoern A. Zeeb {
3217da8fa4e3SBjoern A. Zeeb 	struct wmi_request_stats_cmd *cmd;
3218da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3219da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3220da8fa4e3SBjoern A. Zeeb 
3221da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3222da8fa4e3SBjoern A. Zeeb 	if (!skb)
3223da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3224da8fa4e3SBjoern A. Zeeb 
3225da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3226da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
3227da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3228da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3229da8fa4e3SBjoern A. Zeeb 	cmd->stats_id = __cpu_to_le32(stats_mask);
3230da8fa4e3SBjoern A. Zeeb 
3231da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
3232da8fa4e3SBjoern A. Zeeb 	return skb;
3233da8fa4e3SBjoern A. Zeeb }
3234da8fa4e3SBjoern A. Zeeb 
3235da8fa4e3SBjoern A. Zeeb 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)3236da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_request_peer_stats_info(struct ath10k *ar,
3237da8fa4e3SBjoern A. Zeeb 					      u32 vdev_id,
3238da8fa4e3SBjoern A. Zeeb 					      enum wmi_peer_stats_info_request_type type,
3239da8fa4e3SBjoern A. Zeeb 					      u8 *addr,
3240da8fa4e3SBjoern A. Zeeb 					      u32 reset)
3241da8fa4e3SBjoern A. Zeeb {
3242da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_request_peer_stats_info *cmd;
3243da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3244da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3245da8fa4e3SBjoern A. Zeeb 
3246da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3247da8fa4e3SBjoern A. Zeeb 	if (!skb)
3248da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3249da8fa4e3SBjoern A. Zeeb 
3250da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3251da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_PEER_STATS_INFO_CMD);
3252da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3253da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3254da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3255da8fa4e3SBjoern A. Zeeb 	cmd->request_type = __cpu_to_le32(type);
3256da8fa4e3SBjoern A. Zeeb 
3257da8fa4e3SBjoern A. Zeeb 	if (type == WMI_REQUEST_ONE_PEER_STATS_INFO)
3258da8fa4e3SBjoern A. Zeeb 		ether_addr_copy(cmd->peer_macaddr.addr, addr);
3259da8fa4e3SBjoern A. Zeeb 
3260da8fa4e3SBjoern A. Zeeb 	cmd->reset_after_request = __cpu_to_le32(reset);
3261da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request peer stats info\n");
3262da8fa4e3SBjoern A. Zeeb 	return skb;
3263da8fa4e3SBjoern A. Zeeb }
3264da8fa4e3SBjoern A. Zeeb 
3265da8fa4e3SBjoern A. Zeeb static int
ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k * ar,struct sk_buff * msdu)3266da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
3267da8fa4e3SBjoern A. Zeeb 				       struct sk_buff *msdu)
3268da8fa4e3SBjoern A. Zeeb {
3269da8fa4e3SBjoern A. Zeeb 	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
3270da8fa4e3SBjoern A. Zeeb 	struct ath10k_wmi *wmi = &ar->wmi;
3271da8fa4e3SBjoern A. Zeeb 
3272da8fa4e3SBjoern A. Zeeb 	idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
3273da8fa4e3SBjoern A. Zeeb 
3274da8fa4e3SBjoern A. Zeeb 	return 0;
3275da8fa4e3SBjoern A. Zeeb }
3276da8fa4e3SBjoern A. Zeeb 
3277da8fa4e3SBjoern A. Zeeb static int
ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k * ar,struct sk_buff * skb,dma_addr_t paddr)3278da8fa4e3SBjoern A. Zeeb ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
3279da8fa4e3SBjoern A. Zeeb 				 dma_addr_t paddr)
3280da8fa4e3SBjoern A. Zeeb {
3281da8fa4e3SBjoern A. Zeeb 	struct ath10k_wmi *wmi = &ar->wmi;
3282da8fa4e3SBjoern A. Zeeb 	struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
3283da8fa4e3SBjoern A. Zeeb 	int ret;
3284da8fa4e3SBjoern A. Zeeb 
3285da8fa4e3SBjoern A. Zeeb 	pkt_addr = kmalloc(sizeof(*pkt_addr), GFP_ATOMIC);
3286da8fa4e3SBjoern A. Zeeb 	if (!pkt_addr)
3287da8fa4e3SBjoern A. Zeeb 		return -ENOMEM;
3288da8fa4e3SBjoern A. Zeeb 
3289da8fa4e3SBjoern A. Zeeb 	pkt_addr->vaddr = skb;
3290da8fa4e3SBjoern A. Zeeb 	pkt_addr->paddr = paddr;
3291da8fa4e3SBjoern A. Zeeb 
3292da8fa4e3SBjoern A. Zeeb 	spin_lock_bh(&ar->data_lock);
3293da8fa4e3SBjoern A. Zeeb 	ret = idr_alloc(&wmi->mgmt_pending_tx, pkt_addr, 0,
3294da8fa4e3SBjoern A. Zeeb 			wmi->mgmt_max_num_pending_tx, GFP_ATOMIC);
3295da8fa4e3SBjoern A. Zeeb 	spin_unlock_bh(&ar->data_lock);
3296da8fa4e3SBjoern A. Zeeb 
3297da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx alloc msdu_id ret %d\n", ret);
3298da8fa4e3SBjoern A. Zeeb 	return ret;
3299da8fa4e3SBjoern A. Zeeb }
3300da8fa4e3SBjoern A. Zeeb 
3301da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k * ar,struct sk_buff * msdu,dma_addr_t paddr)3302da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
3303da8fa4e3SBjoern A. Zeeb 				   dma_addr_t paddr)
3304da8fa4e3SBjoern A. Zeeb {
3305da8fa4e3SBjoern A. Zeeb 	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
3306da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_mgmt_tx_cmd *cmd;
3307da8fa4e3SBjoern A. Zeeb 	struct ieee80211_hdr *hdr;
3308da8fa4e3SBjoern A. Zeeb 	struct ath10k_vif *arvif;
3309da8fa4e3SBjoern A. Zeeb 	u32 buf_len = msdu->len;
3310da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3311da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3312da8fa4e3SBjoern A. Zeeb 	int len, desc_id;
3313da8fa4e3SBjoern A. Zeeb 	u32 vdev_id;
3314da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3315da8fa4e3SBjoern A. Zeeb 	void *ptr;
3316da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3317da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3318da8fa4e3SBjoern A. Zeeb #endif
3319da8fa4e3SBjoern A. Zeeb 
3320da8fa4e3SBjoern A. Zeeb 	if (!cb->vif)
3321da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
3322da8fa4e3SBjoern A. Zeeb 
3323da8fa4e3SBjoern A. Zeeb 	hdr = (struct ieee80211_hdr *)msdu->data;
3324da8fa4e3SBjoern A. Zeeb 	arvif = (void *)cb->vif->drv_priv;
3325da8fa4e3SBjoern A. Zeeb 	vdev_id = arvif->vdev_id;
3326da8fa4e3SBjoern A. Zeeb 
3327da8fa4e3SBjoern A. Zeeb 	if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
3328da8fa4e3SBjoern A. Zeeb 			 (!(ieee80211_is_nullfunc(hdr->frame_control) ||
3329da8fa4e3SBjoern A. Zeeb 			 ieee80211_is_qos_nullfunc(hdr->frame_control)))))
3330da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
3331da8fa4e3SBjoern A. Zeeb 
3332da8fa4e3SBjoern A. Zeeb 	len = sizeof(*cmd) + 2 * sizeof(*tlv);
3333da8fa4e3SBjoern A. Zeeb 
3334da8fa4e3SBjoern A. Zeeb 	if ((ieee80211_is_action(hdr->frame_control) ||
3335da8fa4e3SBjoern A. Zeeb 	     ieee80211_is_deauth(hdr->frame_control) ||
3336da8fa4e3SBjoern A. Zeeb 	     ieee80211_is_disassoc(hdr->frame_control)) &&
3337da8fa4e3SBjoern A. Zeeb 	     ieee80211_has_protected(hdr->frame_control)) {
3338da8fa4e3SBjoern A. Zeeb 		skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
3339da8fa4e3SBjoern A. Zeeb 		buf_len += IEEE80211_CCMP_MIC_LEN;
3340da8fa4e3SBjoern A. Zeeb 	}
3341da8fa4e3SBjoern A. Zeeb 
3342da8fa4e3SBjoern A. Zeeb 	buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN);
3343da8fa4e3SBjoern A. Zeeb 	buf_len = round_up(buf_len, 4);
3344da8fa4e3SBjoern A. Zeeb 
3345da8fa4e3SBjoern A. Zeeb 	len += buf_len;
3346da8fa4e3SBjoern A. Zeeb 	len = round_up(len, 4);
3347da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3348da8fa4e3SBjoern A. Zeeb 	if (!skb)
3349da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3350da8fa4e3SBjoern A. Zeeb 
3351da8fa4e3SBjoern A. Zeeb 	desc_id = ath10k_wmi_mgmt_tx_alloc_msdu_id(ar, msdu, paddr);
3352da8fa4e3SBjoern A. Zeeb 	if (desc_id < 0)
3353da8fa4e3SBjoern A. Zeeb 		goto err_free_skb;
3354da8fa4e3SBjoern A. Zeeb 
3355da8fa4e3SBjoern A. Zeeb 	cb->msdu_id = desc_id;
3356da8fa4e3SBjoern A. Zeeb 
3357da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3358da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3359da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3360da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3361da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3362da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3363da8fa4e3SBjoern A. Zeeb #endif
3364da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
3365da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3366da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3367da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3368da8fa4e3SBjoern A. Zeeb 	cmd->desc_id = __cpu_to_le32(desc_id);
3369da8fa4e3SBjoern A. Zeeb 	cmd->chanfreq = 0;
3370da8fa4e3SBjoern A. Zeeb 	cmd->buf_len = __cpu_to_le32(buf_len);
3371da8fa4e3SBjoern A. Zeeb 	cmd->frame_len = __cpu_to_le32(msdu->len);
3372da8fa4e3SBjoern A. Zeeb 	cmd->paddr = __cpu_to_le64(paddr);
3373da8fa4e3SBjoern A. Zeeb 
3374da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3375da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3376da8fa4e3SBjoern A. Zeeb 
3377da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3378da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3379da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3380da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3381da8fa4e3SBjoern A. Zeeb #endif
3382da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3383da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(buf_len);
3384da8fa4e3SBjoern A. Zeeb 
3385da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3386da8fa4e3SBjoern A. Zeeb 	memcpy(ptr, msdu->data, buf_len);
3387da8fa4e3SBjoern A. Zeeb 
3388da8fa4e3SBjoern A. Zeeb 	return skb;
3389da8fa4e3SBjoern A. Zeeb 
3390da8fa4e3SBjoern A. Zeeb err_free_skb:
3391da8fa4e3SBjoern A. Zeeb 	dev_kfree_skb(skb);
3392da8fa4e3SBjoern A. Zeeb 	return ERR_PTR(desc_id);
3393da8fa4e3SBjoern A. Zeeb }
3394da8fa4e3SBjoern A. Zeeb 
3395da8fa4e3SBjoern A. Zeeb 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)3396da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
3397da8fa4e3SBjoern A. Zeeb 				    enum wmi_force_fw_hang_type type,
3398da8fa4e3SBjoern A. Zeeb 				    u32 delay_ms)
3399da8fa4e3SBjoern A. Zeeb {
3400da8fa4e3SBjoern A. Zeeb 	struct wmi_force_fw_hang_cmd *cmd;
3401da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3402da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3403da8fa4e3SBjoern A. Zeeb 
3404da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3405da8fa4e3SBjoern A. Zeeb 	if (!skb)
3406da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3407da8fa4e3SBjoern A. Zeeb 
3408da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3409da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD);
3410da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3411da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3412da8fa4e3SBjoern A. Zeeb 	cmd->type = __cpu_to_le32(type);
3413da8fa4e3SBjoern A. Zeeb 	cmd->delay_ms = __cpu_to_le32(delay_ms);
3414da8fa4e3SBjoern A. Zeeb 
3415da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv force fw hang\n");
3416da8fa4e3SBjoern A. Zeeb 	return skb;
3417da8fa4e3SBjoern A. Zeeb }
3418da8fa4e3SBjoern A. Zeeb 
3419da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k * ar,u64 module_enable,u32 log_level)3420da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u64 module_enable,
3421da8fa4e3SBjoern A. Zeeb 				 u32 log_level)
3422da8fa4e3SBjoern A. Zeeb {
3423da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_dbglog_cmd *cmd;
3424da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3425da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3426da8fa4e3SBjoern A. Zeeb 	size_t len, bmap_len;
3427da8fa4e3SBjoern A. Zeeb 	u32 value;
3428da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3429da8fa4e3SBjoern A. Zeeb 	void *ptr;
3430da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3431da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3432da8fa4e3SBjoern A. Zeeb #endif
3433da8fa4e3SBjoern A. Zeeb 
3434da8fa4e3SBjoern A. Zeeb 	if (module_enable) {
3435da8fa4e3SBjoern A. Zeeb 		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
3436da8fa4e3SBjoern A. Zeeb 				module_enable,
3437da8fa4e3SBjoern A. Zeeb 				WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE);
3438da8fa4e3SBjoern A. Zeeb 	} else {
3439da8fa4e3SBjoern A. Zeeb 		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
3440da8fa4e3SBjoern A. Zeeb 				WMI_TLV_DBGLOG_ALL_MODULES,
3441da8fa4e3SBjoern A. Zeeb 				WMI_TLV_DBGLOG_LOG_LEVEL_WARN);
3442da8fa4e3SBjoern A. Zeeb 	}
3443da8fa4e3SBjoern A. Zeeb 
3444da8fa4e3SBjoern A. Zeeb 	bmap_len = 0;
3445da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) + sizeof(*tlv) + bmap_len;
3446da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3447da8fa4e3SBjoern A. Zeeb 	if (!skb)
3448da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3449da8fa4e3SBjoern A. Zeeb 
3450da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3451da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3452da8fa4e3SBjoern A. Zeeb 
3453da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3454da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3455da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3456da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3457da8fa4e3SBjoern A. Zeeb #endif
3458da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD);
3459da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3460da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3461da8fa4e3SBjoern A. Zeeb 	cmd->param = __cpu_to_le32(WMI_TLV_DBGLOG_PARAM_LOG_LEVEL);
3462da8fa4e3SBjoern A. Zeeb 	cmd->value = __cpu_to_le32(value);
3463da8fa4e3SBjoern A. Zeeb 
3464da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3465da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3466da8fa4e3SBjoern A. Zeeb 
3467da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3468da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3469da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3470da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3471da8fa4e3SBjoern A. Zeeb #endif
3472da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3473da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(bmap_len);
3474da8fa4e3SBjoern A. Zeeb 
3475da8fa4e3SBjoern A. Zeeb 	/* nothing to do here */
3476da8fa4e3SBjoern A. Zeeb 
3477da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3478da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3479da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(bmap_len);
3480da8fa4e3SBjoern A. Zeeb #endif
3481da8fa4e3SBjoern A. Zeeb 
3482da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv dbglog value 0x%08x\n", value);
3483da8fa4e3SBjoern A. Zeeb 	return skb;
3484da8fa4e3SBjoern A. Zeeb }
3485da8fa4e3SBjoern A. Zeeb 
3486da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k * ar,u32 filter)3487da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
3488da8fa4e3SBjoern A. Zeeb {
3489da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_pktlog_enable *cmd;
3490da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3491da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3492da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3493da8fa4e3SBjoern A. Zeeb 	void *ptr;
3494da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3495da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3496da8fa4e3SBjoern A. Zeeb #endif
3497da8fa4e3SBjoern A. Zeeb 	size_t len;
3498da8fa4e3SBjoern A. Zeeb 
3499da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
3500da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3501da8fa4e3SBjoern A. Zeeb 	if (!skb)
3502da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3503da8fa4e3SBjoern A. Zeeb 
3504da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3505da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3506da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3507da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3508da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3509da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3510da8fa4e3SBjoern A. Zeeb #endif
3511da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD);
3512da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3513da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3514da8fa4e3SBjoern A. Zeeb 	cmd->filter = __cpu_to_le32(filter);
3515da8fa4e3SBjoern A. Zeeb 
3516da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3517da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3518da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3519da8fa4e3SBjoern A. Zeeb #endif
3520da8fa4e3SBjoern A. Zeeb 
3521da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog enable filter 0x%08x\n",
3522da8fa4e3SBjoern A. Zeeb 		   filter);
3523da8fa4e3SBjoern A. Zeeb 	return skb;
3524da8fa4e3SBjoern A. Zeeb }
3525da8fa4e3SBjoern A. Zeeb 
3526da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_get_temperature(struct ath10k * ar)3527da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pdev_get_temperature(struct ath10k *ar)
3528da8fa4e3SBjoern A. Zeeb {
3529da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_pdev_get_temp_cmd *cmd;
3530da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3531da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3532da8fa4e3SBjoern A. Zeeb 
3533da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3534da8fa4e3SBjoern A. Zeeb 	if (!skb)
3535da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3536da8fa4e3SBjoern A. Zeeb 
3537da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3538da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_GET_TEMPERATURE_CMD);
3539da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3540da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3541da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev get temperature tlv\n");
3542da8fa4e3SBjoern A. Zeeb 	return skb;
3543da8fa4e3SBjoern A. Zeeb }
3544da8fa4e3SBjoern A. Zeeb 
3545da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k * ar)3546da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar)
3547da8fa4e3SBjoern A. Zeeb {
3548da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_pktlog_disable *cmd;
3549da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3550da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3551da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3552da8fa4e3SBjoern A. Zeeb 	void *ptr;
3553da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3554da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3555da8fa4e3SBjoern A. Zeeb #endif
3556da8fa4e3SBjoern A. Zeeb 	size_t len;
3557da8fa4e3SBjoern A. Zeeb 
3558da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
3559da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3560da8fa4e3SBjoern A. Zeeb 	if (!skb)
3561da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3562da8fa4e3SBjoern A. Zeeb 
3563da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3564da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3565da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3566da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3567da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3568da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3569da8fa4e3SBjoern A. Zeeb #endif
3570da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD);
3571da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3572da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3573da8fa4e3SBjoern A. Zeeb 
3574da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3575da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3576da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3577da8fa4e3SBjoern A. Zeeb #endif
3578da8fa4e3SBjoern A. Zeeb 
3579da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog disable\n");
3580da8fa4e3SBjoern A. Zeeb 	return skb;
3581da8fa4e3SBjoern A. Zeeb }
3582da8fa4e3SBjoern A. Zeeb 
3583da8fa4e3SBjoern A. Zeeb 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)3584da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id,
3585da8fa4e3SBjoern A. Zeeb 			       u32 tim_ie_offset, struct sk_buff *bcn,
3586da8fa4e3SBjoern A. Zeeb 			       u32 prb_caps, u32 prb_erp, void *prb_ies,
3587da8fa4e3SBjoern A. Zeeb 			       size_t prb_ies_len)
3588da8fa4e3SBjoern A. Zeeb {
3589da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_bcn_tmpl_cmd *cmd;
3590da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_bcn_prb_info *info;
3591da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3592da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3593da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3594da8fa4e3SBjoern A. Zeeb 	void *ptr;
3595da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3596da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3597da8fa4e3SBjoern A. Zeeb #endif
3598da8fa4e3SBjoern A. Zeeb 	size_t len;
3599da8fa4e3SBjoern A. Zeeb 
3600da8fa4e3SBjoern A. Zeeb 	if (WARN_ON(prb_ies_len > 0 && !prb_ies))
3601da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-EINVAL);
3602da8fa4e3SBjoern A. Zeeb 
3603da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
3604da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + sizeof(*info) + prb_ies_len +
3605da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + roundup(bcn->len, 4);
3606da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3607da8fa4e3SBjoern A. Zeeb 	if (!skb)
3608da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3609da8fa4e3SBjoern A. Zeeb 
3610da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3611da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3612da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3613da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3614da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3615da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3616da8fa4e3SBjoern A. Zeeb #endif
3617da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD);
3618da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3619da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3620da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3621da8fa4e3SBjoern A. Zeeb 	cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset);
3622da8fa4e3SBjoern A. Zeeb 	cmd->buf_len = __cpu_to_le32(bcn->len);
3623da8fa4e3SBjoern A. Zeeb 
3624da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3625da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3626da8fa4e3SBjoern A. Zeeb 
3627da8fa4e3SBjoern A. Zeeb 	/* FIXME: prb_ies_len should be probably aligned to 4byte boundary but
3628da8fa4e3SBjoern A. Zeeb 	 * then it is then impossible to pass original ie len.
3629da8fa4e3SBjoern A. Zeeb 	 * This chunk is not used yet so if setting probe resp template yields
3630da8fa4e3SBjoern A. Zeeb 	 * problems with beaconing or crashes firmware look here.
3631da8fa4e3SBjoern A. Zeeb 	 */
3632da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3633da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3634da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3635da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3636da8fa4e3SBjoern A. Zeeb #endif
3637da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
3638da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len);
3639da8fa4e3SBjoern A. Zeeb 	info = (void *)tlv->value;
3640da8fa4e3SBjoern A. Zeeb 	info->caps = __cpu_to_le32(prb_caps);
3641da8fa4e3SBjoern A. Zeeb 	info->erp = __cpu_to_le32(prb_erp);
3642da8fa4e3SBjoern A. Zeeb 	memcpy(info->ies, prb_ies, prb_ies_len);
3643da8fa4e3SBjoern A. Zeeb 
3644da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3645da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*info);
3646da8fa4e3SBjoern A. Zeeb 	ptr += prb_ies_len;
3647da8fa4e3SBjoern A. Zeeb 
3648da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3649da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3650da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3651da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3652da8fa4e3SBjoern A. Zeeb #endif
3653da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3654da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(roundup(bcn->len, 4));
3655da8fa4e3SBjoern A. Zeeb 	memcpy(tlv->value, bcn->data, bcn->len);
3656da8fa4e3SBjoern A. Zeeb 
3657da8fa4e3SBjoern A. Zeeb 	/* FIXME: Adjust TSF? */
3658da8fa4e3SBjoern A. Zeeb 
3659da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n",
3660da8fa4e3SBjoern A. Zeeb 		   vdev_id);
3661da8fa4e3SBjoern A. Zeeb 	return skb;
3662da8fa4e3SBjoern A. Zeeb }
3663da8fa4e3SBjoern A. Zeeb 
3664da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k * ar,u32 vdev_id,struct sk_buff * prb)3665da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id,
3666da8fa4e3SBjoern A. Zeeb 			       struct sk_buff *prb)
3667da8fa4e3SBjoern A. Zeeb {
3668da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_prb_tmpl_cmd *cmd;
3669da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_bcn_prb_info *info;
3670da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3671da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3672da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3673da8fa4e3SBjoern A. Zeeb 	void *ptr;
3674da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3675da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3676da8fa4e3SBjoern A. Zeeb #endif
3677da8fa4e3SBjoern A. Zeeb 	size_t len;
3678da8fa4e3SBjoern A. Zeeb 
3679da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
3680da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + sizeof(*info) +
3681da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + roundup(prb->len, 4);
3682da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3683da8fa4e3SBjoern A. Zeeb 	if (!skb)
3684da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3685da8fa4e3SBjoern A. Zeeb 
3686da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3687da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3688da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3689da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3690da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3691da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3692da8fa4e3SBjoern A. Zeeb #endif
3693da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD);
3694da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3695da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3696da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3697da8fa4e3SBjoern A. Zeeb 	cmd->buf_len = __cpu_to_le32(prb->len);
3698da8fa4e3SBjoern A. Zeeb 
3699da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3700da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3701da8fa4e3SBjoern A. Zeeb 
3702da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3703da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3704da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3705da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3706da8fa4e3SBjoern A. Zeeb #endif
3707da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
3708da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*info));
3709da8fa4e3SBjoern A. Zeeb 	info = (void *)tlv->value;
3710da8fa4e3SBjoern A. Zeeb 	info->caps = 0;
3711da8fa4e3SBjoern A. Zeeb 	info->erp = 0;
3712da8fa4e3SBjoern A. Zeeb 
3713da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3714da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*info);
3715da8fa4e3SBjoern A. Zeeb 
3716da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3717da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3718da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3719da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3720da8fa4e3SBjoern A. Zeeb #endif
3721da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3722da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(roundup(prb->len, 4));
3723da8fa4e3SBjoern A. Zeeb 	memcpy(tlv->value, prb->data, prb->len);
3724da8fa4e3SBjoern A. Zeeb 
3725da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n",
3726da8fa4e3SBjoern A. Zeeb 		   vdev_id);
3727da8fa4e3SBjoern A. Zeeb 	return skb;
3728da8fa4e3SBjoern A. Zeeb }
3729da8fa4e3SBjoern A. Zeeb 
3730da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k * ar,u32 vdev_id,const u8 * p2p_ie)3731da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id,
3732da8fa4e3SBjoern A. Zeeb 				    const u8 *p2p_ie)
3733da8fa4e3SBjoern A. Zeeb {
3734da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_p2p_go_bcn_ie *cmd;
3735da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3736da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3737da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3738da8fa4e3SBjoern A. Zeeb 	void *ptr;
3739da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3740da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3741da8fa4e3SBjoern A. Zeeb #endif
3742da8fa4e3SBjoern A. Zeeb 	size_t len;
3743da8fa4e3SBjoern A. Zeeb 
3744da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
3745da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4);
3746da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3747da8fa4e3SBjoern A. Zeeb 	if (!skb)
3748da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3749da8fa4e3SBjoern A. Zeeb 
3750da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3751da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3752da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3753da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3754da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3755da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3756da8fa4e3SBjoern A. Zeeb #endif
3757da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE);
3758da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3759da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3760da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3761da8fa4e3SBjoern A. Zeeb 	cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2);
3762da8fa4e3SBjoern A. Zeeb 
3763da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3764da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3765da8fa4e3SBjoern A. Zeeb 
3766da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3767da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3768da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3769da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3770da8fa4e3SBjoern A. Zeeb #endif
3771da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3772da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4));
3773da8fa4e3SBjoern A. Zeeb 	memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2);
3774da8fa4e3SBjoern A. Zeeb 
3775da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3776da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3777da8fa4e3SBjoern A. Zeeb 	ptr += roundup(p2p_ie[1] + 2, 4);
3778da8fa4e3SBjoern A. Zeeb #endif
3779da8fa4e3SBjoern A. Zeeb 
3780da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n",
3781da8fa4e3SBjoern A. Zeeb 		   vdev_id);
3782da8fa4e3SBjoern A. Zeeb 	return skb;
3783da8fa4e3SBjoern A. Zeeb }
3784da8fa4e3SBjoern A. Zeeb 
3785da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k * ar,u32 vdev_id,enum wmi_tdls_state state)3786da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
3787da8fa4e3SBjoern A. Zeeb 					   enum wmi_tdls_state state)
3788da8fa4e3SBjoern A. Zeeb {
3789da8fa4e3SBjoern A. Zeeb 	struct wmi_tdls_set_state_cmd *cmd;
3790da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3791da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3792da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3793da8fa4e3SBjoern A. Zeeb 	void *ptr;
3794da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3795da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3796da8fa4e3SBjoern A. Zeeb #endif
3797da8fa4e3SBjoern A. Zeeb 	size_t len;
3798da8fa4e3SBjoern A. Zeeb 	/* Set to options from wmi_tlv_tdls_options,
3799da8fa4e3SBjoern A. Zeeb 	 * for now none of them are enabled.
3800da8fa4e3SBjoern A. Zeeb 	 */
3801da8fa4e3SBjoern A. Zeeb 	u32 options = 0;
3802da8fa4e3SBjoern A. Zeeb 
3803da8fa4e3SBjoern A. Zeeb 	if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
3804da8fa4e3SBjoern A. Zeeb 		options |=  WMI_TLV_TDLS_BUFFER_STA_EN;
3805da8fa4e3SBjoern A. Zeeb 
3806da8fa4e3SBjoern A. Zeeb 	/* WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL means firm will handle TDLS
3807da8fa4e3SBjoern A. Zeeb 	 * link inactivity detecting logic.
3808da8fa4e3SBjoern A. Zeeb 	 */
3809da8fa4e3SBjoern A. Zeeb 	if (state == WMI_TDLS_ENABLE_ACTIVE)
3810da8fa4e3SBjoern A. Zeeb 		state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
3811da8fa4e3SBjoern A. Zeeb 
3812da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
3813da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3814da8fa4e3SBjoern A. Zeeb 	if (!skb)
3815da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3816da8fa4e3SBjoern A. Zeeb 
3817da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3818da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3819da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3820da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3821da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3822da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3823da8fa4e3SBjoern A. Zeeb #endif
3824da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_SET_STATE_CMD);
3825da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3826da8fa4e3SBjoern A. Zeeb 
3827da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3828da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
3829da8fa4e3SBjoern A. Zeeb 	cmd->state = __cpu_to_le32(state);
3830da8fa4e3SBjoern A. Zeeb 	cmd->notification_interval_ms = __cpu_to_le32(5000);
3831da8fa4e3SBjoern A. Zeeb 	cmd->tx_discovery_threshold = __cpu_to_le32(100);
3832da8fa4e3SBjoern A. Zeeb 	cmd->tx_teardown_threshold = __cpu_to_le32(5);
3833da8fa4e3SBjoern A. Zeeb 	cmd->rssi_teardown_threshold = __cpu_to_le32(-75);
3834da8fa4e3SBjoern A. Zeeb 	cmd->rssi_delta = __cpu_to_le32(-20);
3835da8fa4e3SBjoern A. Zeeb 	cmd->tdls_options = __cpu_to_le32(options);
3836da8fa4e3SBjoern A. Zeeb 	cmd->tdls_peer_traffic_ind_window = __cpu_to_le32(2);
3837da8fa4e3SBjoern A. Zeeb 	cmd->tdls_peer_traffic_response_timeout_ms = __cpu_to_le32(5000);
3838da8fa4e3SBjoern A. Zeeb 	cmd->tdls_puapsd_mask = __cpu_to_le32(0xf);
3839da8fa4e3SBjoern A. Zeeb 	cmd->tdls_puapsd_inactivity_time_ms = __cpu_to_le32(0);
3840da8fa4e3SBjoern A. Zeeb 	cmd->tdls_puapsd_rx_frame_threshold = __cpu_to_le32(10);
3841da8fa4e3SBjoern A. Zeeb 
3842da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3843da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3844da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3845da8fa4e3SBjoern A. Zeeb #endif
3846da8fa4e3SBjoern A. Zeeb 
3847da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv update fw tdls state %d for vdev %i\n",
3848da8fa4e3SBjoern A. Zeeb 		   state, vdev_id);
3849da8fa4e3SBjoern A. Zeeb 	return skb;
3850da8fa4e3SBjoern A. Zeeb }
3851da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_prepare_peer_qos(u8 uapsd_queues,u8 sp)3852da8fa4e3SBjoern A. Zeeb static u32 ath10k_wmi_tlv_prepare_peer_qos(u8 uapsd_queues, u8 sp)
3853da8fa4e3SBjoern A. Zeeb {
3854da8fa4e3SBjoern A. Zeeb 	u32 peer_qos = 0;
3855da8fa4e3SBjoern A. Zeeb 
3856da8fa4e3SBjoern A. Zeeb 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
3857da8fa4e3SBjoern A. Zeeb 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VO;
3858da8fa4e3SBjoern A. Zeeb 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
3859da8fa4e3SBjoern A. Zeeb 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_VI;
3860da8fa4e3SBjoern A. Zeeb 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
3861da8fa4e3SBjoern A. Zeeb 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BK;
3862da8fa4e3SBjoern A. Zeeb 	if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
3863da8fa4e3SBjoern A. Zeeb 		peer_qos |= WMI_TLV_TDLS_PEER_QOS_AC_BE;
3864da8fa4e3SBjoern A. Zeeb 
3865da8fa4e3SBjoern A. Zeeb 	peer_qos |= SM(sp, WMI_TLV_TDLS_PEER_SP);
3866da8fa4e3SBjoern A. Zeeb 
3867da8fa4e3SBjoern A. Zeeb 	return peer_qos;
3868da8fa4e3SBjoern A. Zeeb }
3869da8fa4e3SBjoern A. Zeeb 
3870da8fa4e3SBjoern A. Zeeb 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)3871da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar,
3872da8fa4e3SBjoern A. Zeeb 				       const struct wmi_tdls_peer_update_cmd_arg *arg,
3873da8fa4e3SBjoern A. Zeeb 				       const struct wmi_tdls_peer_capab_arg *cap,
3874da8fa4e3SBjoern A. Zeeb 				       const struct wmi_channel_arg *chan_arg)
3875da8fa4e3SBjoern A. Zeeb {
3876da8fa4e3SBjoern A. Zeeb 	struct wmi_tdls_peer_update_cmd *cmd;
3877da8fa4e3SBjoern A. Zeeb 	struct wmi_tdls_peer_capab *peer_cap;
3878da8fa4e3SBjoern A. Zeeb 	struct wmi_channel *chan;
3879da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3880da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3881da8fa4e3SBjoern A. Zeeb 	u32 peer_qos;
3882da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3883da8fa4e3SBjoern A. Zeeb 	void *ptr;
3884da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3885da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
3886da8fa4e3SBjoern A. Zeeb #endif
3887da8fa4e3SBjoern A. Zeeb 	int len;
3888da8fa4e3SBjoern A. Zeeb 	int i;
3889da8fa4e3SBjoern A. Zeeb 
3890da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
3891da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + sizeof(*peer_cap) +
3892da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + cap->peer_chan_len * sizeof(*chan);
3893da8fa4e3SBjoern A. Zeeb 
3894da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
3895da8fa4e3SBjoern A. Zeeb 	if (!skb)
3896da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3897da8fa4e3SBjoern A. Zeeb 
3898da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3899da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
3900da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3901da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3902da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
3903da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3904da8fa4e3SBjoern A. Zeeb #endif
3905da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_UPDATE_CMD);
3906da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3907da8fa4e3SBjoern A. Zeeb 
3908da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3909da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
3910da8fa4e3SBjoern A. Zeeb 	ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
3911da8fa4e3SBjoern A. Zeeb 	cmd->peer_state = __cpu_to_le32(arg->peer_state);
3912da8fa4e3SBjoern A. Zeeb 
3913da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3914da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
3915da8fa4e3SBjoern A. Zeeb 
3916da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3917da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3918da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3919da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3920da8fa4e3SBjoern A. Zeeb #endif
3921da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_TDLS_PEER_CAPABILITIES);
3922da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*peer_cap));
3923da8fa4e3SBjoern A. Zeeb 	peer_cap = (void *)tlv->value;
3924da8fa4e3SBjoern A. Zeeb 	peer_qos = ath10k_wmi_tlv_prepare_peer_qos(cap->peer_uapsd_queues,
3925da8fa4e3SBjoern A. Zeeb 						   cap->peer_max_sp);
3926da8fa4e3SBjoern A. Zeeb 	peer_cap->peer_qos = __cpu_to_le32(peer_qos);
3927da8fa4e3SBjoern A. Zeeb 	peer_cap->buff_sta_support = __cpu_to_le32(cap->buff_sta_support);
3928da8fa4e3SBjoern A. Zeeb 	peer_cap->off_chan_support = __cpu_to_le32(cap->off_chan_support);
3929da8fa4e3SBjoern A. Zeeb 	peer_cap->peer_curr_operclass = __cpu_to_le32(cap->peer_curr_operclass);
3930da8fa4e3SBjoern A. Zeeb 	peer_cap->self_curr_operclass = __cpu_to_le32(cap->self_curr_operclass);
3931da8fa4e3SBjoern A. Zeeb 	peer_cap->peer_chan_len = __cpu_to_le32(cap->peer_chan_len);
3932da8fa4e3SBjoern A. Zeeb 	peer_cap->peer_operclass_len = __cpu_to_le32(cap->peer_operclass_len);
3933da8fa4e3SBjoern A. Zeeb 
3934da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++)
3935da8fa4e3SBjoern A. Zeeb 		peer_cap->peer_operclass[i] = cap->peer_operclass[i];
3936da8fa4e3SBjoern A. Zeeb 
3937da8fa4e3SBjoern A. Zeeb 	peer_cap->is_peer_responder = __cpu_to_le32(cap->is_peer_responder);
3938da8fa4e3SBjoern A. Zeeb 	peer_cap->pref_offchan_num = __cpu_to_le32(cap->pref_offchan_num);
3939da8fa4e3SBjoern A. Zeeb 	peer_cap->pref_offchan_bw = __cpu_to_le32(cap->pref_offchan_bw);
3940da8fa4e3SBjoern A. Zeeb 
3941da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3942da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*peer_cap);
3943da8fa4e3SBjoern A. Zeeb 
3944da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3945da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
3946da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3947da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
3948da8fa4e3SBjoern A. Zeeb #endif
3949da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3950da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(cap->peer_chan_len * sizeof(*chan));
3951da8fa4e3SBjoern A. Zeeb 
3952da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
3953da8fa4e3SBjoern A. Zeeb 
3954da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < cap->peer_chan_len; i++) {
3955da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
3956da8fa4e3SBjoern A. Zeeb 		tlv = ptr;
3957da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
3958da8fa4e3SBjoern A. Zeeb 		tlv = (void *)ptr;
3959da8fa4e3SBjoern A. Zeeb #endif
3960da8fa4e3SBjoern A. Zeeb 		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
3961da8fa4e3SBjoern A. Zeeb 		tlv->len = __cpu_to_le16(sizeof(*chan));
3962da8fa4e3SBjoern A. Zeeb 		chan = (void *)tlv->value;
3963da8fa4e3SBjoern A. Zeeb 		ath10k_wmi_put_wmi_channel(ar, chan, &chan_arg[i]);
3964da8fa4e3SBjoern A. Zeeb 
3965da8fa4e3SBjoern A. Zeeb 		ptr += sizeof(*tlv);
3966da8fa4e3SBjoern A. Zeeb 		ptr += sizeof(*chan);
3967da8fa4e3SBjoern A. Zeeb 	}
3968da8fa4e3SBjoern A. Zeeb 
3969da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
3970da8fa4e3SBjoern A. Zeeb 		   "wmi tlv tdls peer update vdev %i state %d n_chans %u\n",
3971da8fa4e3SBjoern A. Zeeb 		   arg->vdev_id, arg->peer_state, cap->peer_chan_len);
3972da8fa4e3SBjoern A. Zeeb 	return skb;
3973da8fa4e3SBjoern A. Zeeb }
3974da8fa4e3SBjoern A. Zeeb 
3975da8fa4e3SBjoern A. Zeeb 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)3976da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period,
3977da8fa4e3SBjoern A. Zeeb 					  u32 duration, u32 next_offset,
3978da8fa4e3SBjoern A. Zeeb 					  u32 enabled)
3979da8fa4e3SBjoern A. Zeeb {
3980da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_set_quiet_cmd *cmd;
3981da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
3982da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
3983da8fa4e3SBjoern A. Zeeb 
3984da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
3985da8fa4e3SBjoern A. Zeeb 	if (!skb)
3986da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
3987da8fa4e3SBjoern A. Zeeb 
3988da8fa4e3SBjoern A. Zeeb 	tlv = (void *)skb->data;
3989da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_QUIET_CMD);
3990da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
3991da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
3992da8fa4e3SBjoern A. Zeeb 
3993da8fa4e3SBjoern A. Zeeb 	/* vdev_id is not in use, set to 0 */
3994da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(0);
3995da8fa4e3SBjoern A. Zeeb 	cmd->period = __cpu_to_le32(period);
3996da8fa4e3SBjoern A. Zeeb 	cmd->duration = __cpu_to_le32(duration);
3997da8fa4e3SBjoern A. Zeeb 	cmd->next_start = __cpu_to_le32(next_offset);
3998da8fa4e3SBjoern A. Zeeb 	cmd->enabled = __cpu_to_le32(enabled);
3999da8fa4e3SBjoern A. Zeeb 
4000da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI,
4001da8fa4e3SBjoern A. Zeeb 		   "wmi tlv quiet param: period %u duration %u enabled %d\n",
4002da8fa4e3SBjoern A. Zeeb 		   period, duration, enabled);
4003da8fa4e3SBjoern A. Zeeb 	return skb;
4004da8fa4e3SBjoern A. Zeeb }
4005da8fa4e3SBjoern A. Zeeb 
4006da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k * ar)4007da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar)
4008da8fa4e3SBjoern A. Zeeb {
4009da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_enable_cmd *cmd;
4010da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4011da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4012da8fa4e3SBjoern A. Zeeb 	size_t len;
4013da8fa4e3SBjoern A. Zeeb 
4014da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4015da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4016da8fa4e3SBjoern A. Zeeb 	if (!skb)
4017da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4018da8fa4e3SBjoern A. Zeeb 
4019da8fa4e3SBjoern A. Zeeb 	tlv = (struct wmi_tlv *)skb->data;
4020da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ENABLE_CMD);
4021da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4022da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4023da8fa4e3SBjoern A. Zeeb 
4024da8fa4e3SBjoern A. Zeeb 	cmd->enable = __cpu_to_le32(1);
4025da8fa4e3SBjoern A. Zeeb 	if (!ar->bus_param.link_can_suspend)
4026da8fa4e3SBjoern A. Zeeb 		cmd->pause_iface_config = __cpu_to_le32(WOW_IFACE_PAUSE_DISABLED);
4027da8fa4e3SBjoern A. Zeeb 
4028da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow enable\n");
4029da8fa4e3SBjoern A. Zeeb 	return skb;
4030da8fa4e3SBjoern A. Zeeb }
4031da8fa4e3SBjoern A. Zeeb 
4032da8fa4e3SBjoern A. Zeeb 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)4033da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_wow_add_wakeup_event(struct ath10k *ar,
4034da8fa4e3SBjoern A. Zeeb 					   u32 vdev_id,
4035da8fa4e3SBjoern A. Zeeb 					   enum wmi_wow_wakeup_event event,
4036da8fa4e3SBjoern A. Zeeb 					   u32 enable)
4037da8fa4e3SBjoern A. Zeeb {
4038da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_add_del_event_cmd *cmd;
4039da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4040da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4041da8fa4e3SBjoern A. Zeeb 	size_t len;
4042da8fa4e3SBjoern A. Zeeb 
4043da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4044da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4045da8fa4e3SBjoern A. Zeeb 	if (!skb)
4046da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4047da8fa4e3SBjoern A. Zeeb 
4048da8fa4e3SBjoern A. Zeeb 	tlv = (struct wmi_tlv *)skb->data;
4049da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_DEL_EVT_CMD);
4050da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4051da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4052da8fa4e3SBjoern A. Zeeb 
4053da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4054da8fa4e3SBjoern A. Zeeb 	cmd->is_add = __cpu_to_le32(enable);
4055da8fa4e3SBjoern A. Zeeb 	cmd->event_bitmap = __cpu_to_le32(1 << event);
4056da8fa4e3SBjoern A. Zeeb 
4057da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
4058da8fa4e3SBjoern A. Zeeb 		   wow_wakeup_event(event), enable, vdev_id);
4059da8fa4e3SBjoern A. Zeeb 	return skb;
4060da8fa4e3SBjoern A. Zeeb }
4061da8fa4e3SBjoern A. Zeeb 
4062da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_gen_wow_host_wakeup_ind(struct ath10k * ar)4063da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_gen_wow_host_wakeup_ind(struct ath10k *ar)
4064da8fa4e3SBjoern A. Zeeb {
4065da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_host_wakeup_ind *cmd;
4066da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4067da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4068da8fa4e3SBjoern A. Zeeb 	size_t len;
4069da8fa4e3SBjoern A. Zeeb 
4070da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4071da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4072da8fa4e3SBjoern A. Zeeb 	if (!skb)
4073da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4074da8fa4e3SBjoern A. Zeeb 
4075da8fa4e3SBjoern A. Zeeb 	tlv = (struct wmi_tlv *)skb->data;
4076da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_HOSTWAKEUP_FROM_SLEEP_CMD);
4077da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4078da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4079da8fa4e3SBjoern A. Zeeb 
4080da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
4081da8fa4e3SBjoern A. Zeeb 	return skb;
4082da8fa4e3SBjoern A. Zeeb }
4083da8fa4e3SBjoern A. Zeeb 
4084da8fa4e3SBjoern A. Zeeb 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)4085da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_wow_add_pattern(struct ath10k *ar, u32 vdev_id,
4086da8fa4e3SBjoern A. Zeeb 				      u32 pattern_id, const u8 *pattern,
4087da8fa4e3SBjoern A. Zeeb 				      const u8 *bitmask, int pattern_len,
4088da8fa4e3SBjoern A. Zeeb 				      int pattern_offset)
4089da8fa4e3SBjoern A. Zeeb {
4090da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_add_pattern_cmd *cmd;
4091da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_bitmap_pattern *bitmap;
4092da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4093da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4094da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4095da8fa4e3SBjoern A. Zeeb 	void *ptr;
4096da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4097da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
4098da8fa4e3SBjoern A. Zeeb #endif
4099da8fa4e3SBjoern A. Zeeb 	size_t len;
4100da8fa4e3SBjoern A. Zeeb 
4101da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
4102da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) +			/* array struct */
4103da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + sizeof(*bitmap) +  /* bitmap */
4104da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) +			/* empty ipv4 sync */
4105da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) +			/* empty ipv6 sync */
4106da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) +			/* empty magic */
4107da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) +			/* empty info timeout */
4108da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) + sizeof(u32);	/* ratelimit interval */
4109da8fa4e3SBjoern A. Zeeb 
4110da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4111da8fa4e3SBjoern A. Zeeb 	if (!skb)
4112da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4113da8fa4e3SBjoern A. Zeeb 
4114da8fa4e3SBjoern A. Zeeb 	/* cmd */
4115da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4116da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
4117da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4118da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4119da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
4120da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4121da8fa4e3SBjoern A. Zeeb #endif
4122da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_ADD_PATTERN_CMD);
4123da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4124da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4125da8fa4e3SBjoern A. Zeeb 
4126da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4127da8fa4e3SBjoern A. Zeeb 	cmd->pattern_id = __cpu_to_le32(pattern_id);
4128da8fa4e3SBjoern A. Zeeb 	cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
4129da8fa4e3SBjoern A. Zeeb 
4130da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4131da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
4132da8fa4e3SBjoern A. Zeeb 
4133da8fa4e3SBjoern A. Zeeb 	/* bitmap */
4134da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4135da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4136da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4137da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4138da8fa4e3SBjoern A. Zeeb #endif
4139da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4140da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*tlv) + sizeof(*bitmap));
4141da8fa4e3SBjoern A. Zeeb 
4142da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4143da8fa4e3SBjoern A. Zeeb 
4144da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4145da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4146da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4147da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4148da8fa4e3SBjoern A. Zeeb #endif
4149da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_BITMAP_PATTERN_T);
4150da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*bitmap));
4151da8fa4e3SBjoern A. Zeeb 	bitmap = (void *)tlv->value;
4152da8fa4e3SBjoern A. Zeeb 
4153da8fa4e3SBjoern A. Zeeb 	memcpy(bitmap->patternbuf, pattern, pattern_len);
4154da8fa4e3SBjoern A. Zeeb 	memcpy(bitmap->bitmaskbuf, bitmask, pattern_len);
4155da8fa4e3SBjoern A. Zeeb 	bitmap->pattern_offset = __cpu_to_le32(pattern_offset);
4156da8fa4e3SBjoern A. Zeeb 	bitmap->pattern_len = __cpu_to_le32(pattern_len);
4157da8fa4e3SBjoern A. Zeeb 	bitmap->bitmask_len = __cpu_to_le32(pattern_len);
4158da8fa4e3SBjoern A. Zeeb 	bitmap->pattern_id = __cpu_to_le32(pattern_id);
4159da8fa4e3SBjoern A. Zeeb 
4160da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4161da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*bitmap);
4162da8fa4e3SBjoern A. Zeeb 
4163da8fa4e3SBjoern A. Zeeb 	/* ipv4 sync */
4164da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4165da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4166da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4167da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4168da8fa4e3SBjoern A. Zeeb #endif
4169da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4170da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(0);
4171da8fa4e3SBjoern A. Zeeb 
4172da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4173da8fa4e3SBjoern A. Zeeb 
4174da8fa4e3SBjoern A. Zeeb 	/* ipv6 sync */
4175da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4176da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4177da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4178da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4179da8fa4e3SBjoern A. Zeeb #endif
4180da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4181da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(0);
4182da8fa4e3SBjoern A. Zeeb 
4183da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4184da8fa4e3SBjoern A. Zeeb 
4185da8fa4e3SBjoern A. Zeeb 	/* magic */
4186da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4187da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4188da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4189da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4190da8fa4e3SBjoern A. Zeeb #endif
4191da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4192da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(0);
4193da8fa4e3SBjoern A. Zeeb 
4194da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4195da8fa4e3SBjoern A. Zeeb 
4196da8fa4e3SBjoern A. Zeeb 	/* pattern info timeout */
4197da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4198da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4199da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4200da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4201da8fa4e3SBjoern A. Zeeb #endif
4202da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
4203da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(0);
4204da8fa4e3SBjoern A. Zeeb 
4205da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4206da8fa4e3SBjoern A. Zeeb 
4207da8fa4e3SBjoern A. Zeeb 	/* ratelimit interval */
4208da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4209da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4210da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4211da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4212da8fa4e3SBjoern A. Zeeb #endif
4213da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
4214da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(u32));
4215da8fa4e3SBjoern A. Zeeb 
4216da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d, pattern_offset %d\n",
4217da8fa4e3SBjoern A. Zeeb 		   vdev_id, pattern_id, pattern_offset);
4218da8fa4e3SBjoern A. Zeeb 	return skb;
4219da8fa4e3SBjoern A. Zeeb }
4220da8fa4e3SBjoern A. Zeeb 
4221da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k * ar,u32 vdev_id,u32 pattern_id)4222da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
4223da8fa4e3SBjoern A. Zeeb 				      u32 pattern_id)
4224da8fa4e3SBjoern A. Zeeb {
4225da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_del_pattern_cmd *cmd;
4226da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4227da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4228da8fa4e3SBjoern A. Zeeb 	size_t len;
4229da8fa4e3SBjoern A. Zeeb 
4230da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4231da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4232da8fa4e3SBjoern A. Zeeb 	if (!skb)
4233da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4234da8fa4e3SBjoern A. Zeeb 
4235da8fa4e3SBjoern A. Zeeb 	tlv = (struct wmi_tlv *)skb->data;
4236da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WOW_DEL_PATTERN_CMD);
4237da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4238da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4239da8fa4e3SBjoern A. Zeeb 
4240da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4241da8fa4e3SBjoern A. Zeeb 	cmd->pattern_id = __cpu_to_le32(pattern_id);
4242da8fa4e3SBjoern A. Zeeb 	cmd->pattern_type = __cpu_to_le32(WOW_BITMAP_PATTERN);
4243da8fa4e3SBjoern A. Zeeb 
4244da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
4245da8fa4e3SBjoern A. Zeeb 		   vdev_id, pattern_id);
4246da8fa4e3SBjoern A. Zeeb 	return skb;
4247da8fa4e3SBjoern A. Zeeb }
4248da8fa4e3SBjoern A. Zeeb 
4249da8fa4e3SBjoern A. Zeeb /* Request FW to start PNO operation */
4250da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k * ar,u32 vdev_id,struct wmi_pno_scan_req * pno)4251da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
4252da8fa4e3SBjoern A. Zeeb 				       u32 vdev_id,
4253da8fa4e3SBjoern A. Zeeb 				       struct wmi_pno_scan_req *pno)
4254da8fa4e3SBjoern A. Zeeb {
4255da8fa4e3SBjoern A. Zeeb 	struct nlo_configured_parameters *nlo_list;
4256da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_nlo_config_cmd *cmd;
4257da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4258da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4259da8fa4e3SBjoern A. Zeeb 	__le32 *channel_list;
4260da8fa4e3SBjoern A. Zeeb 	u16 tlv_len;
4261da8fa4e3SBjoern A. Zeeb 	size_t len;
4262da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4263da8fa4e3SBjoern A. Zeeb 	void *ptr;
4264da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4265da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
4266da8fa4e3SBjoern A. Zeeb #endif
4267da8fa4e3SBjoern A. Zeeb 	u32 i;
4268da8fa4e3SBjoern A. Zeeb 
4269da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
4270da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) +
4271da8fa4e3SBjoern A. Zeeb 	      /* TLV place holder for array of structures
4272da8fa4e3SBjoern A. Zeeb 	       * nlo_configured_parameters(nlo_list)
4273da8fa4e3SBjoern A. Zeeb 	       */
4274da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv);
4275da8fa4e3SBjoern A. Zeeb 	      /* TLV place holder for array of uint32 channel_list */
4276da8fa4e3SBjoern A. Zeeb 
4277da8fa4e3SBjoern A. Zeeb 	len += sizeof(u32) * min_t(u8, pno->a_networks[0].channel_count,
4278da8fa4e3SBjoern A. Zeeb 				   WMI_NLO_MAX_CHAN);
4279da8fa4e3SBjoern A. Zeeb 	len += sizeof(struct nlo_configured_parameters) *
4280da8fa4e3SBjoern A. Zeeb 				min_t(u8, pno->uc_networks_count, WMI_NLO_MAX_SSIDS);
4281da8fa4e3SBjoern A. Zeeb 
4282da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4283da8fa4e3SBjoern A. Zeeb 	if (!skb)
4284da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4285da8fa4e3SBjoern A. Zeeb 
4286da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4287da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
4288da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4289da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4290da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
4291da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4292da8fa4e3SBjoern A. Zeeb #endif
4293da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
4294da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4295da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4296da8fa4e3SBjoern A. Zeeb 
4297da8fa4e3SBjoern A. Zeeb 	/* wmi_tlv_wow_nlo_config_cmd parameters*/
4298da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(pno->vdev_id);
4299da8fa4e3SBjoern A. Zeeb 	cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);
4300da8fa4e3SBjoern A. Zeeb 
4301da8fa4e3SBjoern A. Zeeb 	/* current FW does not support min-max range for dwell time */
4302da8fa4e3SBjoern A. Zeeb 	cmd->active_dwell_time = __cpu_to_le32(pno->active_max_time);
4303da8fa4e3SBjoern A. Zeeb 	cmd->passive_dwell_time = __cpu_to_le32(pno->passive_max_time);
4304da8fa4e3SBjoern A. Zeeb 
4305da8fa4e3SBjoern A. Zeeb 	if (pno->do_passive_scan)
4306da8fa4e3SBjoern A. Zeeb 		cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);
4307da8fa4e3SBjoern A. Zeeb 
4308da8fa4e3SBjoern A. Zeeb 	/* copy scan interval */
4309da8fa4e3SBjoern A. Zeeb 	cmd->fast_scan_period = __cpu_to_le32(pno->fast_scan_period);
4310da8fa4e3SBjoern A. Zeeb 	cmd->slow_scan_period = __cpu_to_le32(pno->slow_scan_period);
4311da8fa4e3SBjoern A. Zeeb 	cmd->fast_scan_max_cycles = __cpu_to_le32(pno->fast_scan_max_cycles);
4312da8fa4e3SBjoern A. Zeeb 	cmd->delay_start_time = __cpu_to_le32(pno->delay_start_time);
4313da8fa4e3SBjoern A. Zeeb 
4314da8fa4e3SBjoern A. Zeeb 	if (pno->enable_pno_scan_randomization) {
4315da8fa4e3SBjoern A. Zeeb 		cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |
4316da8fa4e3SBjoern A. Zeeb 				WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);
4317da8fa4e3SBjoern A. Zeeb 		ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);
4318da8fa4e3SBjoern A. Zeeb 		ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);
4319da8fa4e3SBjoern A. Zeeb 	}
4320da8fa4e3SBjoern A. Zeeb 
4321da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4322da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
4323da8fa4e3SBjoern A. Zeeb 
4324da8fa4e3SBjoern A. Zeeb 	/* nlo_configured_parameters(nlo_list) */
4325da8fa4e3SBjoern A. Zeeb 	cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
4326da8fa4e3SBjoern A. Zeeb 					       WMI_NLO_MAX_SSIDS));
4327da8fa4e3SBjoern A. Zeeb 	tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
4328da8fa4e3SBjoern A. Zeeb 		sizeof(struct nlo_configured_parameters);
4329da8fa4e3SBjoern A. Zeeb 
4330da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4331da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4332da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4333da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4334da8fa4e3SBjoern A. Zeeb #endif
4335da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4336da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(tlv_len);
4337da8fa4e3SBjoern A. Zeeb 
4338da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4339da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4340da8fa4e3SBjoern A. Zeeb 	nlo_list = ptr;
4341da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4342da8fa4e3SBjoern A. Zeeb 	nlo_list = (void *)ptr;
4343da8fa4e3SBjoern A. Zeeb #endif
4344da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < __le32_to_cpu(cmd->no_of_ssids); i++) {
4345da8fa4e3SBjoern A. Zeeb 		tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);
4346da8fa4e3SBjoern A. Zeeb 		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
4347da8fa4e3SBjoern A. Zeeb 		tlv->len = __cpu_to_le16(sizeof(struct nlo_configured_parameters) -
4348da8fa4e3SBjoern A. Zeeb 					 sizeof(*tlv));
4349da8fa4e3SBjoern A. Zeeb 
4350da8fa4e3SBjoern A. Zeeb 		/* copy ssid and it's length */
4351da8fa4e3SBjoern A. Zeeb 		nlo_list[i].ssid.valid = __cpu_to_le32(true);
4352da8fa4e3SBjoern A. Zeeb 		nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len;
4353da8fa4e3SBjoern A. Zeeb 		memcpy(nlo_list[i].ssid.ssid.ssid,
4354da8fa4e3SBjoern A. Zeeb 		       pno->a_networks[i].ssid.ssid,
4355da8fa4e3SBjoern A. Zeeb 		       __le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));
4356da8fa4e3SBjoern A. Zeeb 
4357da8fa4e3SBjoern A. Zeeb 		/* copy rssi threshold */
4358da8fa4e3SBjoern A. Zeeb 		if (pno->a_networks[i].rssi_threshold &&
4359da8fa4e3SBjoern A. Zeeb 		    pno->a_networks[i].rssi_threshold > -300) {
4360da8fa4e3SBjoern A. Zeeb 			nlo_list[i].rssi_cond.valid = __cpu_to_le32(true);
4361da8fa4e3SBjoern A. Zeeb 			nlo_list[i].rssi_cond.rssi =
4362da8fa4e3SBjoern A. Zeeb 				__cpu_to_le32(pno->a_networks[i].rssi_threshold);
4363da8fa4e3SBjoern A. Zeeb 		}
4364da8fa4e3SBjoern A. Zeeb 
4365da8fa4e3SBjoern A. Zeeb 		nlo_list[i].bcast_nw_type.valid = __cpu_to_le32(true);
4366da8fa4e3SBjoern A. Zeeb 		nlo_list[i].bcast_nw_type.bcast_nw_type =
4367da8fa4e3SBjoern A. Zeeb 			__cpu_to_le32(pno->a_networks[i].bcast_nw_type);
4368da8fa4e3SBjoern A. Zeeb 	}
4369da8fa4e3SBjoern A. Zeeb 
4370da8fa4e3SBjoern A. Zeeb 	ptr += __le32_to_cpu(cmd->no_of_ssids) * sizeof(struct nlo_configured_parameters);
4371da8fa4e3SBjoern A. Zeeb 
4372da8fa4e3SBjoern A. Zeeb 	/* copy channel info */
4373da8fa4e3SBjoern A. Zeeb 	cmd->num_of_channels = __cpu_to_le32(min_t(u8,
4374da8fa4e3SBjoern A. Zeeb 						   pno->a_networks[0].channel_count,
4375da8fa4e3SBjoern A. Zeeb 						   WMI_NLO_MAX_CHAN));
4376da8fa4e3SBjoern A. Zeeb 
4377da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4378da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4379da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4380da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4381da8fa4e3SBjoern A. Zeeb #endif
4382da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
4383da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(__le32_to_cpu(cmd->num_of_channels) *
4384da8fa4e3SBjoern A. Zeeb 				 sizeof(u_int32_t));
4385da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4386da8fa4e3SBjoern A. Zeeb 
4387da8fa4e3SBjoern A. Zeeb 	channel_list = (__le32 *)ptr;
4388da8fa4e3SBjoern A. Zeeb 	for (i = 0; i < __le32_to_cpu(cmd->num_of_channels); i++)
4389da8fa4e3SBjoern A. Zeeb 		channel_list[i] = __cpu_to_le32(pno->a_networks[0].channels[i]);
4390da8fa4e3SBjoern A. Zeeb 
4391da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
4392da8fa4e3SBjoern A. Zeeb 		   vdev_id);
4393da8fa4e3SBjoern A. Zeeb 
4394da8fa4e3SBjoern A. Zeeb 	return skb;
4395da8fa4e3SBjoern A. Zeeb }
4396da8fa4e3SBjoern A. Zeeb 
4397da8fa4e3SBjoern A. Zeeb /* Request FW to stop ongoing PNO operation */
ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k * ar,u32 vdev_id)4398da8fa4e3SBjoern A. Zeeb static struct sk_buff *ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k *ar,
4399da8fa4e3SBjoern A. Zeeb 							     u32 vdev_id)
4400da8fa4e3SBjoern A. Zeeb {
4401da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_wow_nlo_config_cmd *cmd;
4402da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4403da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4404da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4405da8fa4e3SBjoern A. Zeeb 	void *ptr;
4406da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4407da8fa4e3SBjoern A. Zeeb 	u8 *ptr;
4408da8fa4e3SBjoern A. Zeeb #endif
4409da8fa4e3SBjoern A. Zeeb 	size_t len;
4410da8fa4e3SBjoern A. Zeeb 
4411da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd) +
4412da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv) +
4413da8fa4e3SBjoern A. Zeeb 	      /* TLV place holder for array of structures
4414da8fa4e3SBjoern A. Zeeb 	       * nlo_configured_parameters(nlo_list)
4415da8fa4e3SBjoern A. Zeeb 	       */
4416da8fa4e3SBjoern A. Zeeb 	      sizeof(*tlv);
4417da8fa4e3SBjoern A. Zeeb 	      /* TLV place holder for array of uint32 channel_list */
4418da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4419da8fa4e3SBjoern A. Zeeb 	if (!skb)
4420da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4421da8fa4e3SBjoern A. Zeeb 
4422da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4423da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
4424da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4425da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4426da8fa4e3SBjoern A. Zeeb 	ptr = (u8 *)skb->data;
4427da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4428da8fa4e3SBjoern A. Zeeb #endif
4429da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
4430da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4431da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4432da8fa4e3SBjoern A. Zeeb 
4433da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4434da8fa4e3SBjoern A. Zeeb 	cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_STOP);
4435da8fa4e3SBjoern A. Zeeb 
4436da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4437da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
4438da8fa4e3SBjoern A. Zeeb 
4439da8fa4e3SBjoern A. Zeeb 	/* nlo_configured_parameters(nlo_list) */
4440da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4441da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4442da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4443da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4444da8fa4e3SBjoern A. Zeeb #endif
4445da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
4446da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(0);
4447da8fa4e3SBjoern A. Zeeb 
4448da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4449da8fa4e3SBjoern A. Zeeb 
4450da8fa4e3SBjoern A. Zeeb 	/* channel list */
4451da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4452da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4453da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
4454da8fa4e3SBjoern A. Zeeb 	tlv = (void *)ptr;
4455da8fa4e3SBjoern A. Zeeb #endif
4456da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
4457da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(0);
4458da8fa4e3SBjoern A. Zeeb 
4459da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop pno config vdev_id %d\n", vdev_id);
4460da8fa4e3SBjoern A. Zeeb 	return skb;
4461da8fa4e3SBjoern A. Zeeb }
4462da8fa4e3SBjoern A. Zeeb 
4463da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_config_pno(struct ath10k * ar,u32 vdev_id,struct wmi_pno_scan_req * pno_scan)4464da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_config_pno(struct ath10k *ar, u32 vdev_id,
4465da8fa4e3SBjoern A. Zeeb 				 struct wmi_pno_scan_req *pno_scan)
4466da8fa4e3SBjoern A. Zeeb {
4467da8fa4e3SBjoern A. Zeeb 	if (pno_scan->enable)
4468da8fa4e3SBjoern A. Zeeb 		return ath10k_wmi_tlv_op_gen_config_pno_start(ar, vdev_id, pno_scan);
4469da8fa4e3SBjoern A. Zeeb 	else
4470da8fa4e3SBjoern A. Zeeb 		return ath10k_wmi_tlv_op_gen_config_pno_stop(ar, vdev_id);
4471da8fa4e3SBjoern A. Zeeb }
4472da8fa4e3SBjoern A. Zeeb 
4473da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k * ar,bool enable)4474da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
4475da8fa4e3SBjoern A. Zeeb {
4476da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv_adaptive_qcs *cmd;
4477da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4478da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4479da8fa4e3SBjoern A. Zeeb 	void *ptr;
4480da8fa4e3SBjoern A. Zeeb 	size_t len;
4481da8fa4e3SBjoern A. Zeeb 
4482da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4483da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4484da8fa4e3SBjoern A. Zeeb 	if (!skb)
4485da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4486da8fa4e3SBjoern A. Zeeb 
4487da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
4488da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4489da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESMGR_ADAPTIVE_OCS_CMD);
4490da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4491da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4492da8fa4e3SBjoern A. Zeeb 	cmd->enable = __cpu_to_le32(enable ? 1 : 0);
4493da8fa4e3SBjoern A. Zeeb 
4494da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4495da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4496da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
4497da8fa4e3SBjoern A. Zeeb #endif
4498da8fa4e3SBjoern A. Zeeb 
4499da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv adaptive qcs %d\n", enable);
4500da8fa4e3SBjoern A. Zeeb 	return skb;
4501da8fa4e3SBjoern A. Zeeb }
4502da8fa4e3SBjoern A. Zeeb 
4503da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_echo(struct ath10k * ar,u32 value)4504da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value)
4505da8fa4e3SBjoern A. Zeeb {
4506da8fa4e3SBjoern A. Zeeb 	struct wmi_echo_cmd *cmd;
4507da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4508da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4509da8fa4e3SBjoern A. Zeeb 	void *ptr;
4510da8fa4e3SBjoern A. Zeeb 	size_t len;
4511da8fa4e3SBjoern A. Zeeb 
4512da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4513da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4514da8fa4e3SBjoern A. Zeeb 	if (!skb)
4515da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4516da8fa4e3SBjoern A. Zeeb 
4517da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
4518da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4519da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_ECHO_CMD);
4520da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4521da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4522da8fa4e3SBjoern A. Zeeb 	cmd->value = cpu_to_le32(value);
4523da8fa4e3SBjoern A. Zeeb 
4524da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
4525da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*tlv);
4526da8fa4e3SBjoern A. Zeeb 	ptr += sizeof(*cmd);
4527da8fa4e3SBjoern A. Zeeb #endif
4528da8fa4e3SBjoern A. Zeeb 
4529da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv echo value 0x%08x\n", value);
4530da8fa4e3SBjoern A. Zeeb 	return skb;
4531da8fa4e3SBjoern A. Zeeb }
4532da8fa4e3SBjoern A. Zeeb 
4533da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k * ar,const struct wmi_vdev_spectral_conf_arg * arg)4534da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k *ar,
4535da8fa4e3SBjoern A. Zeeb 					 const struct wmi_vdev_spectral_conf_arg *arg)
4536da8fa4e3SBjoern A. Zeeb {
4537da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_spectral_conf_cmd *cmd;
4538da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4539da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4540da8fa4e3SBjoern A. Zeeb 	void *ptr;
4541da8fa4e3SBjoern A. Zeeb 	size_t len;
4542da8fa4e3SBjoern A. Zeeb 
4543da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4544da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4545da8fa4e3SBjoern A. Zeeb 	if (!skb)
4546da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4547da8fa4e3SBjoern A. Zeeb 
4548da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
4549da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4550da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD);
4551da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4552da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4553da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
4554da8fa4e3SBjoern A. Zeeb 	cmd->scan_count = __cpu_to_le32(arg->scan_count);
4555da8fa4e3SBjoern A. Zeeb 	cmd->scan_period = __cpu_to_le32(arg->scan_period);
4556da8fa4e3SBjoern A. Zeeb 	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
4557da8fa4e3SBjoern A. Zeeb 	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
4558da8fa4e3SBjoern A. Zeeb 	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
4559da8fa4e3SBjoern A. Zeeb 	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
4560da8fa4e3SBjoern A. Zeeb 	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
4561da8fa4e3SBjoern A. Zeeb 	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
4562da8fa4e3SBjoern A. Zeeb 	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
4563da8fa4e3SBjoern A. Zeeb 	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
4564da8fa4e3SBjoern A. Zeeb 	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
4565da8fa4e3SBjoern A. Zeeb 	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
4566da8fa4e3SBjoern A. Zeeb 	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
4567da8fa4e3SBjoern A. Zeeb 	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
4568da8fa4e3SBjoern A. Zeeb 	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
4569da8fa4e3SBjoern A. Zeeb 	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
4570da8fa4e3SBjoern A. Zeeb 	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
4571da8fa4e3SBjoern A. Zeeb 	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
4572da8fa4e3SBjoern A. Zeeb 
4573da8fa4e3SBjoern A. Zeeb 	return skb;
4574da8fa4e3SBjoern A. Zeeb }
4575da8fa4e3SBjoern A. Zeeb 
4576da8fa4e3SBjoern A. Zeeb static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k * ar,u32 vdev_id,u32 trigger,u32 enable)4577da8fa4e3SBjoern A. Zeeb ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
4578da8fa4e3SBjoern A. Zeeb 					   u32 trigger, u32 enable)
4579da8fa4e3SBjoern A. Zeeb {
4580da8fa4e3SBjoern A. Zeeb 	struct wmi_vdev_spectral_enable_cmd *cmd;
4581da8fa4e3SBjoern A. Zeeb 	struct sk_buff *skb;
4582da8fa4e3SBjoern A. Zeeb 	struct wmi_tlv *tlv;
4583da8fa4e3SBjoern A. Zeeb 	void *ptr;
4584da8fa4e3SBjoern A. Zeeb 	size_t len;
4585da8fa4e3SBjoern A. Zeeb 
4586da8fa4e3SBjoern A. Zeeb 	len = sizeof(*tlv) + sizeof(*cmd);
4587da8fa4e3SBjoern A. Zeeb 	skb = ath10k_wmi_alloc_skb(ar, len);
4588da8fa4e3SBjoern A. Zeeb 	if (!skb)
4589da8fa4e3SBjoern A. Zeeb 		return ERR_PTR(-ENOMEM);
4590da8fa4e3SBjoern A. Zeeb 
4591da8fa4e3SBjoern A. Zeeb 	ptr = (void *)skb->data;
4592da8fa4e3SBjoern A. Zeeb 	tlv = ptr;
4593da8fa4e3SBjoern A. Zeeb 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD);
4594da8fa4e3SBjoern A. Zeeb 	tlv->len = __cpu_to_le16(sizeof(*cmd));
4595da8fa4e3SBjoern A. Zeeb 	cmd = (void *)tlv->value;
4596da8fa4e3SBjoern A. Zeeb 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4597da8fa4e3SBjoern A. Zeeb 	cmd->trigger_cmd = __cpu_to_le32(trigger);
4598da8fa4e3SBjoern A. Zeeb 	cmd->enable_cmd = __cpu_to_le32(enable);
4599da8fa4e3SBjoern A. Zeeb 
4600da8fa4e3SBjoern A. Zeeb 	return skb;
4601da8fa4e3SBjoern A. Zeeb }
4602da8fa4e3SBjoern A. Zeeb 
4603da8fa4e3SBjoern A. Zeeb /****************/
4604da8fa4e3SBjoern A. Zeeb /* TLV mappings */
4605da8fa4e3SBjoern A. Zeeb /****************/
4606da8fa4e3SBjoern A. Zeeb 
4607da8fa4e3SBjoern A. Zeeb static struct wmi_cmd_map wmi_tlv_cmd_map = {
4608da8fa4e3SBjoern A. Zeeb 	.init_cmdid = WMI_TLV_INIT_CMDID,
4609da8fa4e3SBjoern A. Zeeb 	.start_scan_cmdid = WMI_TLV_START_SCAN_CMDID,
4610da8fa4e3SBjoern A. Zeeb 	.stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
4611da8fa4e3SBjoern A. Zeeb 	.scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
4612da8fa4e3SBjoern A. Zeeb 	.scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
4613da8fa4e3SBjoern A. Zeeb 	.scan_prob_req_oui_cmdid = WMI_TLV_SCAN_PROB_REQ_OUI_CMDID,
4614da8fa4e3SBjoern A. Zeeb 	.pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
4615da8fa4e3SBjoern A. Zeeb 	.pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
4616da8fa4e3SBjoern A. Zeeb 	.pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
4617da8fa4e3SBjoern A. Zeeb 	.pdev_pktlog_enable_cmdid = WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID,
4618da8fa4e3SBjoern A. Zeeb 	.pdev_pktlog_disable_cmdid = WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID,
4619da8fa4e3SBjoern A. Zeeb 	.pdev_set_wmm_params_cmdid = WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID,
4620da8fa4e3SBjoern A. Zeeb 	.pdev_set_ht_cap_ie_cmdid = WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID,
4621da8fa4e3SBjoern A. Zeeb 	.pdev_set_vht_cap_ie_cmdid = WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID,
4622da8fa4e3SBjoern A. Zeeb 	.pdev_set_dscp_tid_map_cmdid = WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID,
4623da8fa4e3SBjoern A. Zeeb 	.pdev_set_quiet_mode_cmdid = WMI_TLV_PDEV_SET_QUIET_MODE_CMDID,
4624da8fa4e3SBjoern A. Zeeb 	.pdev_green_ap_ps_enable_cmdid = WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID,
4625da8fa4e3SBjoern A. Zeeb 	.pdev_get_tpc_config_cmdid = WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID,
4626da8fa4e3SBjoern A. Zeeb 	.pdev_set_base_macaddr_cmdid = WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID,
4627da8fa4e3SBjoern A. Zeeb 	.vdev_create_cmdid = WMI_TLV_VDEV_CREATE_CMDID,
4628da8fa4e3SBjoern A. Zeeb 	.vdev_delete_cmdid = WMI_TLV_VDEV_DELETE_CMDID,
4629da8fa4e3SBjoern A. Zeeb 	.vdev_start_request_cmdid = WMI_TLV_VDEV_START_REQUEST_CMDID,
4630da8fa4e3SBjoern A. Zeeb 	.vdev_restart_request_cmdid = WMI_TLV_VDEV_RESTART_REQUEST_CMDID,
4631da8fa4e3SBjoern A. Zeeb 	.vdev_up_cmdid = WMI_TLV_VDEV_UP_CMDID,
4632da8fa4e3SBjoern A. Zeeb 	.vdev_stop_cmdid = WMI_TLV_VDEV_STOP_CMDID,
4633da8fa4e3SBjoern A. Zeeb 	.vdev_down_cmdid = WMI_TLV_VDEV_DOWN_CMDID,
4634da8fa4e3SBjoern A. Zeeb 	.vdev_set_param_cmdid = WMI_TLV_VDEV_SET_PARAM_CMDID,
4635da8fa4e3SBjoern A. Zeeb 	.vdev_install_key_cmdid = WMI_TLV_VDEV_INSTALL_KEY_CMDID,
4636da8fa4e3SBjoern A. Zeeb 	.peer_create_cmdid = WMI_TLV_PEER_CREATE_CMDID,
4637da8fa4e3SBjoern A. Zeeb 	.peer_delete_cmdid = WMI_TLV_PEER_DELETE_CMDID,
4638da8fa4e3SBjoern A. Zeeb 	.peer_flush_tids_cmdid = WMI_TLV_PEER_FLUSH_TIDS_CMDID,
4639da8fa4e3SBjoern A. Zeeb 	.peer_set_param_cmdid = WMI_TLV_PEER_SET_PARAM_CMDID,
4640da8fa4e3SBjoern A. Zeeb 	.peer_assoc_cmdid = WMI_TLV_PEER_ASSOC_CMDID,
4641da8fa4e3SBjoern A. Zeeb 	.peer_add_wds_entry_cmdid = WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID,
4642da8fa4e3SBjoern A. Zeeb 	.peer_remove_wds_entry_cmdid = WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID,
4643da8fa4e3SBjoern A. Zeeb 	.peer_mcast_group_cmdid = WMI_TLV_PEER_MCAST_GROUP_CMDID,
4644da8fa4e3SBjoern A. Zeeb 	.bcn_tx_cmdid = WMI_TLV_BCN_TX_CMDID,
4645da8fa4e3SBjoern A. Zeeb 	.pdev_send_bcn_cmdid = WMI_TLV_PDEV_SEND_BCN_CMDID,
4646da8fa4e3SBjoern A. Zeeb 	.bcn_tmpl_cmdid = WMI_TLV_BCN_TMPL_CMDID,
4647da8fa4e3SBjoern A. Zeeb 	.bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID,
4648da8fa4e3SBjoern A. Zeeb 	.prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
4649da8fa4e3SBjoern A. Zeeb 	.mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID,
4650da8fa4e3SBjoern A. Zeeb 	.mgmt_tx_send_cmdid = WMI_TLV_MGMT_TX_SEND_CMD,
4651da8fa4e3SBjoern A. Zeeb 	.prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID,
4652da8fa4e3SBjoern A. Zeeb 	.addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID,
4653da8fa4e3SBjoern A. Zeeb 	.addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID,
4654da8fa4e3SBjoern A. Zeeb 	.addba_status_cmdid = WMI_TLV_ADDBA_STATUS_CMDID,
4655da8fa4e3SBjoern A. Zeeb 	.delba_send_cmdid = WMI_TLV_DELBA_SEND_CMDID,
4656da8fa4e3SBjoern A. Zeeb 	.addba_set_resp_cmdid = WMI_TLV_ADDBA_SET_RESP_CMDID,
4657da8fa4e3SBjoern A. Zeeb 	.send_singleamsdu_cmdid = WMI_TLV_SEND_SINGLEAMSDU_CMDID,
4658da8fa4e3SBjoern A. Zeeb 	.sta_powersave_mode_cmdid = WMI_TLV_STA_POWERSAVE_MODE_CMDID,
4659da8fa4e3SBjoern A. Zeeb 	.sta_powersave_param_cmdid = WMI_TLV_STA_POWERSAVE_PARAM_CMDID,
4660da8fa4e3SBjoern A. Zeeb 	.sta_mimo_ps_mode_cmdid = WMI_TLV_STA_MIMO_PS_MODE_CMDID,
4661da8fa4e3SBjoern A. Zeeb 	.pdev_dfs_enable_cmdid = WMI_TLV_PDEV_DFS_ENABLE_CMDID,
4662da8fa4e3SBjoern A. Zeeb 	.pdev_dfs_disable_cmdid = WMI_TLV_PDEV_DFS_DISABLE_CMDID,
4663da8fa4e3SBjoern A. Zeeb 	.roam_scan_mode = WMI_TLV_ROAM_SCAN_MODE,
4664da8fa4e3SBjoern A. Zeeb 	.roam_scan_rssi_threshold = WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD,
4665da8fa4e3SBjoern A. Zeeb 	.roam_scan_period = WMI_TLV_ROAM_SCAN_PERIOD,
4666da8fa4e3SBjoern A. Zeeb 	.roam_scan_rssi_change_threshold =
4667da8fa4e3SBjoern A. Zeeb 				WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
4668da8fa4e3SBjoern A. Zeeb 	.roam_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
4669da8fa4e3SBjoern A. Zeeb 	.ofl_scan_add_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
4670da8fa4e3SBjoern A. Zeeb 	.ofl_scan_remove_ap_profile = WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE,
4671da8fa4e3SBjoern A. Zeeb 	.ofl_scan_period = WMI_TLV_OFL_SCAN_PERIOD,
4672da8fa4e3SBjoern A. Zeeb 	.p2p_dev_set_device_info = WMI_TLV_P2P_DEV_SET_DEVICE_INFO,
4673da8fa4e3SBjoern A. Zeeb 	.p2p_dev_set_discoverability = WMI_TLV_P2P_DEV_SET_DISCOVERABILITY,
4674da8fa4e3SBjoern A. Zeeb 	.p2p_go_set_beacon_ie = WMI_TLV_P2P_GO_SET_BEACON_IE,
4675da8fa4e3SBjoern A. Zeeb 	.p2p_go_set_probe_resp_ie = WMI_TLV_P2P_GO_SET_PROBE_RESP_IE,
4676da8fa4e3SBjoern A. Zeeb 	.p2p_set_vendor_ie_data_cmdid = WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID,
4677da8fa4e3SBjoern A. Zeeb 	.ap_ps_peer_param_cmdid = WMI_TLV_AP_PS_PEER_PARAM_CMDID,
4678da8fa4e3SBjoern A. Zeeb 	.ap_ps_peer_uapsd_coex_cmdid = WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID,
4679da8fa4e3SBjoern A. Zeeb 	.peer_rate_retry_sched_cmdid = WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID,
4680da8fa4e3SBjoern A. Zeeb 	.wlan_profile_trigger_cmdid = WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID,
4681da8fa4e3SBjoern A. Zeeb 	.wlan_profile_set_hist_intvl_cmdid =
4682da8fa4e3SBjoern A. Zeeb 				WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
4683da8fa4e3SBjoern A. Zeeb 	.wlan_profile_get_profile_data_cmdid =
4684da8fa4e3SBjoern A. Zeeb 				WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
4685da8fa4e3SBjoern A. Zeeb 	.wlan_profile_enable_profile_id_cmdid =
4686da8fa4e3SBjoern A. Zeeb 				WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
4687da8fa4e3SBjoern A. Zeeb 	.wlan_profile_list_profile_id_cmdid =
4688da8fa4e3SBjoern A. Zeeb 				WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
4689da8fa4e3SBjoern A. Zeeb 	.pdev_suspend_cmdid = WMI_TLV_PDEV_SUSPEND_CMDID,
4690da8fa4e3SBjoern A. Zeeb 	.pdev_resume_cmdid = WMI_TLV_PDEV_RESUME_CMDID,
4691da8fa4e3SBjoern A. Zeeb 	.add_bcn_filter_cmdid = WMI_TLV_ADD_BCN_FILTER_CMDID,
4692da8fa4e3SBjoern A. Zeeb 	.rmv_bcn_filter_cmdid = WMI_TLV_RMV_BCN_FILTER_CMDID,
4693da8fa4e3SBjoern A. Zeeb 	.wow_add_wake_pattern_cmdid = WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID,
4694da8fa4e3SBjoern A. Zeeb 	.wow_del_wake_pattern_cmdid = WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID,
4695da8fa4e3SBjoern A. Zeeb 	.wow_enable_disable_wake_event_cmdid =
4696da8fa4e3SBjoern A. Zeeb 				WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
4697da8fa4e3SBjoern A. Zeeb 	.wow_enable_cmdid = WMI_TLV_WOW_ENABLE_CMDID,
4698da8fa4e3SBjoern A. Zeeb 	.wow_hostwakeup_from_sleep_cmdid =
4699da8fa4e3SBjoern A. Zeeb 				WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
4700da8fa4e3SBjoern A. Zeeb 	.rtt_measreq_cmdid = WMI_TLV_RTT_MEASREQ_CMDID,
4701da8fa4e3SBjoern A. Zeeb 	.rtt_tsf_cmdid = WMI_TLV_RTT_TSF_CMDID,
4702da8fa4e3SBjoern A. Zeeb 	.vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID,
4703da8fa4e3SBjoern A. Zeeb 	.vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID,
4704da8fa4e3SBjoern A. Zeeb 	.request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID,
4705da8fa4e3SBjoern A. Zeeb 	.request_peer_stats_info_cmdid = WMI_TLV_REQUEST_PEER_STATS_INFO_CMDID,
4706da8fa4e3SBjoern A. Zeeb 	.set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID,
4707da8fa4e3SBjoern A. Zeeb 	.network_list_offload_config_cmdid =
4708da8fa4e3SBjoern A. Zeeb 				WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID,
4709da8fa4e3SBjoern A. Zeeb 	.gtk_offload_cmdid = WMI_TLV_GTK_OFFLOAD_CMDID,
4710da8fa4e3SBjoern A. Zeeb 	.csa_offload_enable_cmdid = WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID,
4711da8fa4e3SBjoern A. Zeeb 	.csa_offload_chanswitch_cmdid = WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID,
4712da8fa4e3SBjoern A. Zeeb 	.chatter_set_mode_cmdid = WMI_TLV_CHATTER_SET_MODE_CMDID,
4713da8fa4e3SBjoern A. Zeeb 	.peer_tid_addba_cmdid = WMI_TLV_PEER_TID_ADDBA_CMDID,
4714da8fa4e3SBjoern A. Zeeb 	.peer_tid_delba_cmdid = WMI_TLV_PEER_TID_DELBA_CMDID,
4715da8fa4e3SBjoern A. Zeeb 	.sta_dtim_ps_method_cmdid = WMI_TLV_STA_DTIM_PS_METHOD_CMDID,
4716da8fa4e3SBjoern A. Zeeb 	.sta_uapsd_auto_trig_cmdid = WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID,
4717da8fa4e3SBjoern A. Zeeb 	.sta_keepalive_cmd = WMI_TLV_STA_KEEPALIVE_CMDID,
4718da8fa4e3SBjoern A. Zeeb 	.echo_cmdid = WMI_TLV_ECHO_CMDID,
4719da8fa4e3SBjoern A. Zeeb 	.pdev_utf_cmdid = WMI_TLV_PDEV_UTF_CMDID,
4720da8fa4e3SBjoern A. Zeeb 	.dbglog_cfg_cmdid = WMI_TLV_DBGLOG_CFG_CMDID,
4721da8fa4e3SBjoern A. Zeeb 	.pdev_qvit_cmdid = WMI_TLV_PDEV_QVIT_CMDID,
4722da8fa4e3SBjoern A. Zeeb 	.pdev_ftm_intg_cmdid = WMI_TLV_PDEV_FTM_INTG_CMDID,
4723da8fa4e3SBjoern A. Zeeb 	.vdev_set_keepalive_cmdid = WMI_TLV_VDEV_SET_KEEPALIVE_CMDID,
4724da8fa4e3SBjoern A. Zeeb 	.vdev_get_keepalive_cmdid = WMI_TLV_VDEV_GET_KEEPALIVE_CMDID,
4725da8fa4e3SBjoern A. Zeeb 	.force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID,
4726da8fa4e3SBjoern A. Zeeb 	.gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID,
4727da8fa4e3SBjoern A. Zeeb 	.gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID,
4728da8fa4e3SBjoern A. Zeeb 	.pdev_get_temperature_cmdid = WMI_TLV_PDEV_GET_TEMPERATURE_CMDID,
4729da8fa4e3SBjoern A. Zeeb 	.vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
4730da8fa4e3SBjoern A. Zeeb 	.tdls_set_state_cmdid = WMI_TLV_TDLS_SET_STATE_CMDID,
4731da8fa4e3SBjoern A. Zeeb 	.tdls_peer_update_cmdid = WMI_TLV_TDLS_PEER_UPDATE_CMDID,
4732da8fa4e3SBjoern A. Zeeb 	.adaptive_qcs_cmdid = WMI_TLV_RESMGR_ADAPTIVE_OCS_CMDID,
4733da8fa4e3SBjoern A. Zeeb 	.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
4734da8fa4e3SBjoern A. Zeeb 	.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
4735da8fa4e3SBjoern A. Zeeb 	.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
4736da8fa4e3SBjoern A. Zeeb 	.wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
4737da8fa4e3SBjoern A. Zeeb 	.wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
4738da8fa4e3SBjoern A. Zeeb 	.wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
4739da8fa4e3SBjoern A. Zeeb 	.wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
4740da8fa4e3SBjoern A. Zeeb 	.peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
4741da8fa4e3SBjoern A. Zeeb 	.peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
4742da8fa4e3SBjoern A. Zeeb 	.rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
4743da8fa4e3SBjoern A. Zeeb 	.oem_req_cmdid = WMI_CMD_UNSUPPORTED,
4744da8fa4e3SBjoern A. Zeeb 	.nan_cmdid = WMI_CMD_UNSUPPORTED,
4745da8fa4e3SBjoern A. Zeeb 	.vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
4746da8fa4e3SBjoern A. Zeeb 	.qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
4747da8fa4e3SBjoern A. Zeeb 	.pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
4748da8fa4e3SBjoern A. Zeeb 	.pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
4749da8fa4e3SBjoern A. Zeeb 	.peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
4750da8fa4e3SBjoern A. Zeeb 	.peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
4751da8fa4e3SBjoern A. Zeeb 	.peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
4752da8fa4e3SBjoern A. Zeeb 	.pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
4753da8fa4e3SBjoern A. Zeeb 	.pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
4754da8fa4e3SBjoern A. Zeeb 	.pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
4755da8fa4e3SBjoern A. Zeeb 	.pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
4756da8fa4e3SBjoern A. Zeeb 	.pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
4757da8fa4e3SBjoern A. Zeeb 	.pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
4758da8fa4e3SBjoern A. Zeeb 	.tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
4759da8fa4e3SBjoern A. Zeeb 	.fwtest_cmdid = WMI_CMD_UNSUPPORTED,
4760da8fa4e3SBjoern A. Zeeb 	.vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
4761da8fa4e3SBjoern A. Zeeb 	.peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
4762da8fa4e3SBjoern A. Zeeb 	.pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
4763da8fa4e3SBjoern A. Zeeb 	.pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
4764da8fa4e3SBjoern A. Zeeb 	.pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
4765da8fa4e3SBjoern A. Zeeb };
4766da8fa4e3SBjoern A. Zeeb 
4767da8fa4e3SBjoern A. Zeeb static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
4768da8fa4e3SBjoern A. Zeeb 	.tx_chain_mask = WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK,
4769da8fa4e3SBjoern A. Zeeb 	.rx_chain_mask = WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK,
4770da8fa4e3SBjoern A. Zeeb 	.txpower_limit2g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G,
4771da8fa4e3SBjoern A. Zeeb 	.txpower_limit5g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G,
4772da8fa4e3SBjoern A. Zeeb 	.txpower_scale = WMI_TLV_PDEV_PARAM_TXPOWER_SCALE,
4773da8fa4e3SBjoern A. Zeeb 	.beacon_gen_mode = WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE,
4774da8fa4e3SBjoern A. Zeeb 	.beacon_tx_mode = WMI_TLV_PDEV_PARAM_BEACON_TX_MODE,
4775da8fa4e3SBjoern A. Zeeb 	.resmgr_offchan_mode = WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
4776da8fa4e3SBjoern A. Zeeb 	.protection_mode = WMI_TLV_PDEV_PARAM_PROTECTION_MODE,
4777da8fa4e3SBjoern A. Zeeb 	.dynamic_bw = WMI_TLV_PDEV_PARAM_DYNAMIC_BW,
4778da8fa4e3SBjoern A. Zeeb 	.non_agg_sw_retry_th = WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
4779da8fa4e3SBjoern A. Zeeb 	.agg_sw_retry_th = WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH,
4780da8fa4e3SBjoern A. Zeeb 	.sta_kickout_th = WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH,
4781da8fa4e3SBjoern A. Zeeb 	.ac_aggrsize_scaling = WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING,
4782da8fa4e3SBjoern A. Zeeb 	.ltr_enable = WMI_TLV_PDEV_PARAM_LTR_ENABLE,
4783da8fa4e3SBjoern A. Zeeb 	.ltr_ac_latency_be = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE,
4784da8fa4e3SBjoern A. Zeeb 	.ltr_ac_latency_bk = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK,
4785da8fa4e3SBjoern A. Zeeb 	.ltr_ac_latency_vi = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI,
4786da8fa4e3SBjoern A. Zeeb 	.ltr_ac_latency_vo = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO,
4787da8fa4e3SBjoern A. Zeeb 	.ltr_ac_latency_timeout = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
4788da8fa4e3SBjoern A. Zeeb 	.ltr_sleep_override = WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
4789da8fa4e3SBjoern A. Zeeb 	.ltr_rx_override = WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE,
4790da8fa4e3SBjoern A. Zeeb 	.ltr_tx_activity_timeout = WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
4791da8fa4e3SBjoern A. Zeeb 	.l1ss_enable = WMI_TLV_PDEV_PARAM_L1SS_ENABLE,
4792da8fa4e3SBjoern A. Zeeb 	.dsleep_enable = WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE,
4793da8fa4e3SBjoern A. Zeeb 	.pcielp_txbuf_flush = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
4794da8fa4e3SBjoern A. Zeeb 	.pcielp_txbuf_watermark = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
4795da8fa4e3SBjoern A. Zeeb 	.pcielp_txbuf_tmo_en = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
4796da8fa4e3SBjoern A. Zeeb 	.pcielp_txbuf_tmo_value = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
4797da8fa4e3SBjoern A. Zeeb 	.pdev_stats_update_period = WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
4798da8fa4e3SBjoern A. Zeeb 	.vdev_stats_update_period = WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
4799da8fa4e3SBjoern A. Zeeb 	.peer_stats_update_period = WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
4800da8fa4e3SBjoern A. Zeeb 	.bcnflt_stats_update_period =
4801da8fa4e3SBjoern A. Zeeb 				WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
4802da8fa4e3SBjoern A. Zeeb 	.pmf_qos = WMI_TLV_PDEV_PARAM_PMF_QOS,
4803da8fa4e3SBjoern A. Zeeb 	.arp_ac_override = WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE,
4804da8fa4e3SBjoern A. Zeeb 	.dcs = WMI_TLV_PDEV_PARAM_DCS,
4805da8fa4e3SBjoern A. Zeeb 	.ani_enable = WMI_TLV_PDEV_PARAM_ANI_ENABLE,
4806da8fa4e3SBjoern A. Zeeb 	.ani_poll_period = WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD,
4807da8fa4e3SBjoern A. Zeeb 	.ani_listen_period = WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD,
4808da8fa4e3SBjoern A. Zeeb 	.ani_ofdm_level = WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL,
4809da8fa4e3SBjoern A. Zeeb 	.ani_cck_level = WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL,
4810da8fa4e3SBjoern A. Zeeb 	.dyntxchain = WMI_TLV_PDEV_PARAM_DYNTXCHAIN,
4811da8fa4e3SBjoern A. Zeeb 	.proxy_sta = WMI_TLV_PDEV_PARAM_PROXY_STA,
4812da8fa4e3SBjoern A. Zeeb 	.idle_ps_config = WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG,
4813da8fa4e3SBjoern A. Zeeb 	.power_gating_sleep = WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP,
4814da8fa4e3SBjoern A. Zeeb 	.fast_channel_reset = WMI_TLV_PDEV_PARAM_UNSUPPORTED,
4815da8fa4e3SBjoern A. Zeeb 	.burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR,
4816da8fa4e3SBjoern A. Zeeb 	.burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE,
4817da8fa4e3SBjoern A. Zeeb 	.cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
4818da8fa4e3SBjoern A. Zeeb 	.aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
4819da8fa4e3SBjoern A. Zeeb 	.rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4820da8fa4e3SBjoern A. Zeeb 	.smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
4821da8fa4e3SBjoern A. Zeeb 	.igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
4822da8fa4e3SBjoern A. Zeeb 	.igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
4823da8fa4e3SBjoern A. Zeeb 	.antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
4824da8fa4e3SBjoern A. Zeeb 	.rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
4825da8fa4e3SBjoern A. Zeeb 	.set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
4826da8fa4e3SBjoern A. Zeeb 	.proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4827da8fa4e3SBjoern A. Zeeb 	.set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
4828da8fa4e3SBjoern A. Zeeb 	.set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
4829da8fa4e3SBjoern A. Zeeb 	.remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
4830da8fa4e3SBjoern A. Zeeb 	.peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
4831da8fa4e3SBjoern A. Zeeb 	.igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
4832da8fa4e3SBjoern A. Zeeb 	.block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
4833da8fa4e3SBjoern A. Zeeb 	.set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4834da8fa4e3SBjoern A. Zeeb 	.set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4835da8fa4e3SBjoern A. Zeeb 	.set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4836da8fa4e3SBjoern A. Zeeb 	.txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4837da8fa4e3SBjoern A. Zeeb 	.set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4838da8fa4e3SBjoern A. Zeeb 	.set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
4839da8fa4e3SBjoern A. Zeeb 	.en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
4840da8fa4e3SBjoern A. Zeeb 	.mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
4841da8fa4e3SBjoern A. Zeeb 	.noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
4842da8fa4e3SBjoern A. Zeeb 	.noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
4843da8fa4e3SBjoern A. Zeeb 	.dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
4844da8fa4e3SBjoern A. Zeeb 	.set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
4845da8fa4e3SBjoern A. Zeeb 	.atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
4846da8fa4e3SBjoern A. Zeeb 	.atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
4847da8fa4e3SBjoern A. Zeeb 	.ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
4848da8fa4e3SBjoern A. Zeeb 	.mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
4849da8fa4e3SBjoern A. Zeeb 	.sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
4850da8fa4e3SBjoern A. Zeeb 	.signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
4851da8fa4e3SBjoern A. Zeeb 	.signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
4852da8fa4e3SBjoern A. Zeeb 	.enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
4853da8fa4e3SBjoern A. Zeeb 	.enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
4854da8fa4e3SBjoern A. Zeeb 	.cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
4855da8fa4e3SBjoern A. Zeeb 	.rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
4856da8fa4e3SBjoern A. Zeeb 	.pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
4857da8fa4e3SBjoern A. Zeeb 	.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
4858da8fa4e3SBjoern A. Zeeb 	.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
4859da8fa4e3SBjoern A. Zeeb 	.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
4860da8fa4e3SBjoern A. Zeeb 	.rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
4861da8fa4e3SBjoern A. Zeeb 	.rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
4862da8fa4e3SBjoern A. Zeeb 	.peer_stats_info_enable = WMI_TLV_PDEV_PARAM_PEER_STATS_INFO_ENABLE,
4863da8fa4e3SBjoern A. Zeeb };
4864da8fa4e3SBjoern A. Zeeb 
4865da8fa4e3SBjoern A. Zeeb static struct wmi_peer_param_map wmi_tlv_peer_param_map = {
4866da8fa4e3SBjoern A. Zeeb 	.smps_state = WMI_TLV_PEER_SMPS_STATE,
4867da8fa4e3SBjoern A. Zeeb 	.ampdu = WMI_TLV_PEER_AMPDU,
4868da8fa4e3SBjoern A. Zeeb 	.authorize = WMI_TLV_PEER_AUTHORIZE,
4869da8fa4e3SBjoern A. Zeeb 	.chan_width = WMI_TLV_PEER_CHAN_WIDTH,
4870da8fa4e3SBjoern A. Zeeb 	.nss = WMI_TLV_PEER_NSS,
4871da8fa4e3SBjoern A. Zeeb 	.use_4addr = WMI_TLV_PEER_USE_4ADDR,
4872da8fa4e3SBjoern A. Zeeb 	.membership = WMI_TLV_PEER_MEMBERSHIP,
4873da8fa4e3SBjoern A. Zeeb 	.user_pos = WMI_TLV_PEER_USERPOS,
4874da8fa4e3SBjoern A. Zeeb 	.crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED,
4875da8fa4e3SBjoern A. Zeeb 	.tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR,
4876da8fa4e3SBjoern A. Zeeb 	.set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S,
4877da8fa4e3SBjoern A. Zeeb 	.ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH,
4878da8fa4e3SBjoern A. Zeeb 	.phymode = WMI_TLV_PEER_PHYMODE,
4879da8fa4e3SBjoern A. Zeeb 	.use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR,
4880da8fa4e3SBjoern A. Zeeb 	.dummy_var = WMI_TLV_PEER_DUMMY_VAR,
4881da8fa4e3SBjoern A. Zeeb };
4882da8fa4e3SBjoern A. Zeeb 
4883da8fa4e3SBjoern A. Zeeb static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
4884da8fa4e3SBjoern A. Zeeb 	.rts_threshold = WMI_TLV_VDEV_PARAM_RTS_THRESHOLD,
4885da8fa4e3SBjoern A. Zeeb 	.fragmentation_threshold = WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
4886da8fa4e3SBjoern A. Zeeb 	.beacon_interval = WMI_TLV_VDEV_PARAM_BEACON_INTERVAL,
4887da8fa4e3SBjoern A. Zeeb 	.listen_interval = WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL,
4888da8fa4e3SBjoern A. Zeeb 	.multicast_rate = WMI_TLV_VDEV_PARAM_MULTICAST_RATE,
4889da8fa4e3SBjoern A. Zeeb 	.mgmt_tx_rate = WMI_TLV_VDEV_PARAM_MGMT_TX_RATE,
4890da8fa4e3SBjoern A. Zeeb 	.slot_time = WMI_TLV_VDEV_PARAM_SLOT_TIME,
4891da8fa4e3SBjoern A. Zeeb 	.preamble = WMI_TLV_VDEV_PARAM_PREAMBLE,
4892da8fa4e3SBjoern A. Zeeb 	.swba_time = WMI_TLV_VDEV_PARAM_SWBA_TIME,
4893da8fa4e3SBjoern A. Zeeb 	.wmi_vdev_stats_update_period = WMI_TLV_VDEV_STATS_UPDATE_PERIOD,
4894da8fa4e3SBjoern A. Zeeb 	.wmi_vdev_pwrsave_ageout_time = WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME,
4895da8fa4e3SBjoern A. Zeeb 	.wmi_vdev_host_swba_interval = WMI_TLV_VDEV_HOST_SWBA_INTERVAL,
4896da8fa4e3SBjoern A. Zeeb 	.dtim_period = WMI_TLV_VDEV_PARAM_DTIM_PERIOD,
4897da8fa4e3SBjoern A. Zeeb 	.wmi_vdev_oc_scheduler_air_time_limit =
4898da8fa4e3SBjoern A. Zeeb 				WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
4899da8fa4e3SBjoern A. Zeeb 	.wds = WMI_TLV_VDEV_PARAM_WDS,
4900da8fa4e3SBjoern A. Zeeb 	.atim_window = WMI_TLV_VDEV_PARAM_ATIM_WINDOW,
4901da8fa4e3SBjoern A. Zeeb 	.bmiss_count_max = WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX,
4902da8fa4e3SBjoern A. Zeeb 	.bmiss_first_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT,
4903da8fa4e3SBjoern A. Zeeb 	.bmiss_final_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT,
4904da8fa4e3SBjoern A. Zeeb 	.feature_wmm = WMI_TLV_VDEV_PARAM_FEATURE_WMM,
4905da8fa4e3SBjoern A. Zeeb 	.chwidth = WMI_TLV_VDEV_PARAM_CHWIDTH,
4906da8fa4e3SBjoern A. Zeeb 	.chextoffset = WMI_TLV_VDEV_PARAM_CHEXTOFFSET,
4907da8fa4e3SBjoern A. Zeeb 	.disable_htprotection =	WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION,
4908da8fa4e3SBjoern A. Zeeb 	.sta_quickkickout = WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT,
4909da8fa4e3SBjoern A. Zeeb 	.mgmt_rate = WMI_TLV_VDEV_PARAM_MGMT_RATE,
4910da8fa4e3SBjoern A. Zeeb 	.protection_mode = WMI_TLV_VDEV_PARAM_PROTECTION_MODE,
4911da8fa4e3SBjoern A. Zeeb 	.fixed_rate = WMI_TLV_VDEV_PARAM_FIXED_RATE,
4912da8fa4e3SBjoern A. Zeeb 	.sgi = WMI_TLV_VDEV_PARAM_SGI,
4913da8fa4e3SBjoern A. Zeeb 	.ldpc = WMI_TLV_VDEV_PARAM_LDPC,
4914da8fa4e3SBjoern A. Zeeb 	.tx_stbc = WMI_TLV_VDEV_PARAM_TX_STBC,
4915da8fa4e3SBjoern A. Zeeb 	.rx_stbc = WMI_TLV_VDEV_PARAM_RX_STBC,
4916da8fa4e3SBjoern A. Zeeb 	.intra_bss_fwd = WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD,
4917da8fa4e3SBjoern A. Zeeb 	.def_keyid = WMI_TLV_VDEV_PARAM_DEF_KEYID,
4918da8fa4e3SBjoern A. Zeeb 	.nss = WMI_TLV_VDEV_PARAM_NSS,
4919da8fa4e3SBjoern A. Zeeb 	.bcast_data_rate = WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE,
4920da8fa4e3SBjoern A. Zeeb 	.mcast_data_rate = WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE,
4921da8fa4e3SBjoern A. Zeeb 	.mcast_indicate = WMI_TLV_VDEV_PARAM_MCAST_INDICATE,
4922da8fa4e3SBjoern A. Zeeb 	.dhcp_indicate = WMI_TLV_VDEV_PARAM_DHCP_INDICATE,
4923da8fa4e3SBjoern A. Zeeb 	.unknown_dest_indicate = WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
4924da8fa4e3SBjoern A. Zeeb 	.ap_keepalive_min_idle_inactive_time_secs =
4925da8fa4e3SBjoern A. Zeeb 		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
4926da8fa4e3SBjoern A. Zeeb 	.ap_keepalive_max_idle_inactive_time_secs =
4927da8fa4e3SBjoern A. Zeeb 		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
4928da8fa4e3SBjoern A. Zeeb 	.ap_keepalive_max_unresponsive_time_secs =
4929da8fa4e3SBjoern A. Zeeb 		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
4930da8fa4e3SBjoern A. Zeeb 	.ap_enable_nawds = WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS,
4931da8fa4e3SBjoern A. Zeeb 	.mcast2ucast_set = WMI_TLV_VDEV_PARAM_UNSUPPORTED,
4932da8fa4e3SBjoern A. Zeeb 	.enable_rtscts = WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS,
4933da8fa4e3SBjoern A. Zeeb 	.txbf = WMI_TLV_VDEV_PARAM_TXBF,
4934da8fa4e3SBjoern A. Zeeb 	.packet_powersave = WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE,
4935da8fa4e3SBjoern A. Zeeb 	.drop_unencry = WMI_TLV_VDEV_PARAM_DROP_UNENCRY,
4936da8fa4e3SBjoern A. Zeeb 	.tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
4937da8fa4e3SBjoern A. Zeeb 	.ap_detect_out_of_sync_sleeping_sta_time_secs =
4938da8fa4e3SBjoern A. Zeeb 					WMI_TLV_VDEV_PARAM_UNSUPPORTED,
4939da8fa4e3SBjoern A. Zeeb 	.rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
4940da8fa4e3SBjoern A. Zeeb 	.cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
4941da8fa4e3SBjoern A. Zeeb 	.mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
4942da8fa4e3SBjoern A. Zeeb 	.rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
4943da8fa4e3SBjoern A. Zeeb 	.vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
4944da8fa4e3SBjoern A. Zeeb 	.vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
4945da8fa4e3SBjoern A. Zeeb 	.early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
4946da8fa4e3SBjoern A. Zeeb 	.early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
4947da8fa4e3SBjoern A. Zeeb 	.early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
4948da8fa4e3SBjoern A. Zeeb 	.early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
4949da8fa4e3SBjoern A. Zeeb 	.early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
4950da8fa4e3SBjoern A. Zeeb 	.early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
4951da8fa4e3SBjoern A. Zeeb 	.proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
4952da8fa4e3SBjoern A. Zeeb 	.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
4953da8fa4e3SBjoern A. Zeeb 	.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
4954da8fa4e3SBjoern A. Zeeb 	.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
4955da8fa4e3SBjoern A. Zeeb };
4956da8fa4e3SBjoern A. Zeeb 
4957da8fa4e3SBjoern A. Zeeb static const struct wmi_ops wmi_tlv_ops = {
4958da8fa4e3SBjoern A. Zeeb 	.rx = ath10k_wmi_tlv_op_rx,
4959da8fa4e3SBjoern A. Zeeb 	.map_svc = wmi_tlv_svc_map,
4960da8fa4e3SBjoern A. Zeeb 	.map_svc_ext = wmi_tlv_svc_map_ext,
4961da8fa4e3SBjoern A. Zeeb 
4962da8fa4e3SBjoern A. Zeeb 	.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
4963da8fa4e3SBjoern A. Zeeb 	.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
4964da8fa4e3SBjoern A. Zeeb 	.pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev,
4965da8fa4e3SBjoern A. Zeeb 	.pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev,
4966da8fa4e3SBjoern A. Zeeb 	.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
4967da8fa4e3SBjoern A. Zeeb 	.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
4968da8fa4e3SBjoern A. Zeeb 	.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
4969da8fa4e3SBjoern A. Zeeb 	.pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
4970da8fa4e3SBjoern A. Zeeb 	.pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
4971da8fa4e3SBjoern A. Zeeb 	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
4972da8fa4e3SBjoern A. Zeeb 	.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
4973da8fa4e3SBjoern A. Zeeb 	.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
4974da8fa4e3SBjoern A. Zeeb 	.pull_svc_avail = ath10k_wmi_tlv_op_pull_svc_avail,
4975da8fa4e3SBjoern A. Zeeb 	.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
4976da8fa4e3SBjoern A. Zeeb 	.pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
4977da8fa4e3SBjoern A. Zeeb 	.pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
4978da8fa4e3SBjoern A. Zeeb 	.pull_echo_ev = ath10k_wmi_tlv_op_pull_echo_ev,
4979da8fa4e3SBjoern A. Zeeb 	.get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
4980da8fa4e3SBjoern A. Zeeb 
4981da8fa4e3SBjoern A. Zeeb 	.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
4982da8fa4e3SBjoern A. Zeeb 	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
4983da8fa4e3SBjoern A. Zeeb 	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
4984da8fa4e3SBjoern A. Zeeb 	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
4985da8fa4e3SBjoern A. Zeeb 	.gen_init = ath10k_wmi_tlv_op_gen_init,
4986da8fa4e3SBjoern A. Zeeb 	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
4987da8fa4e3SBjoern A. Zeeb 	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
4988da8fa4e3SBjoern A. Zeeb 	.gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
4989da8fa4e3SBjoern A. Zeeb 	.gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
4990da8fa4e3SBjoern A. Zeeb 	.gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
4991da8fa4e3SBjoern A. Zeeb 	.gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
4992da8fa4e3SBjoern A. Zeeb 	.gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
4993da8fa4e3SBjoern A. Zeeb 	.gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
4994da8fa4e3SBjoern A. Zeeb 	.gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
4995da8fa4e3SBjoern A. Zeeb 	.gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
4996da8fa4e3SBjoern A. Zeeb 	.gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
4997da8fa4e3SBjoern A. Zeeb 	.gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
4998da8fa4e3SBjoern A. Zeeb 	.gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
4999da8fa4e3SBjoern A. Zeeb 	.gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
5000da8fa4e3SBjoern A. Zeeb 	.gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
5001da8fa4e3SBjoern A. Zeeb 	.gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
5002da8fa4e3SBjoern A. Zeeb 	.gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
5003da8fa4e3SBjoern A. Zeeb 	.gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
5004da8fa4e3SBjoern A. Zeeb 	.gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
5005da8fa4e3SBjoern A. Zeeb 	.gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
5006da8fa4e3SBjoern A. Zeeb 	.gen_scan_prob_req_oui = ath10k_wmi_tlv_op_gen_scan_prob_req_oui,
5007da8fa4e3SBjoern A. Zeeb 	.gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
5008da8fa4e3SBjoern A. Zeeb 	.gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
5009da8fa4e3SBjoern A. Zeeb 	.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
5010da8fa4e3SBjoern A. Zeeb 	.gen_request_peer_stats_info = ath10k_wmi_tlv_op_gen_request_peer_stats_info,
5011da8fa4e3SBjoern A. Zeeb 	.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
5012da8fa4e3SBjoern A. Zeeb 	/* .gen_mgmt_tx = not implemented; HTT is used */
5013da8fa4e3SBjoern A. Zeeb 	.gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send,
5014da8fa4e3SBjoern A. Zeeb 	.cleanup_mgmt_tx_send = ath10k_wmi_tlv_op_cleanup_mgmt_tx_send,
5015da8fa4e3SBjoern A. Zeeb 	.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
5016da8fa4e3SBjoern A. Zeeb 	.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
5017da8fa4e3SBjoern A. Zeeb 	.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
5018da8fa4e3SBjoern A. Zeeb 	.gen_pdev_set_quiet_mode = ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode,
5019da8fa4e3SBjoern A. Zeeb 	.gen_pdev_get_temperature = ath10k_wmi_tlv_op_gen_pdev_get_temperature,
5020da8fa4e3SBjoern A. Zeeb 	/* .gen_addba_clear_resp not implemented */
5021da8fa4e3SBjoern A. Zeeb 	/* .gen_addba_send not implemented */
5022da8fa4e3SBjoern A. Zeeb 	/* .gen_addba_set_resp not implemented */
5023da8fa4e3SBjoern A. Zeeb 	/* .gen_delba_send not implemented */
5024da8fa4e3SBjoern A. Zeeb 	.gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
5025da8fa4e3SBjoern A. Zeeb 	.gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
5026da8fa4e3SBjoern A. Zeeb 	.gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
5027da8fa4e3SBjoern A. Zeeb 	.gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
5028da8fa4e3SBjoern A. Zeeb 	.gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
5029da8fa4e3SBjoern A. Zeeb 	.gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
5030da8fa4e3SBjoern A. Zeeb 	.gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
5031da8fa4e3SBjoern A. Zeeb 	.gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
5032da8fa4e3SBjoern A. Zeeb 	.gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
5033da8fa4e3SBjoern A. Zeeb 	.gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
5034da8fa4e3SBjoern A. Zeeb 	.gen_wow_config_pno = ath10k_wmi_tlv_op_gen_config_pno,
5035da8fa4e3SBjoern A. Zeeb 	.gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
5036da8fa4e3SBjoern A. Zeeb 	.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
5037da8fa4e3SBjoern A. Zeeb 	.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
5038da8fa4e3SBjoern A. Zeeb 	.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
5039da8fa4e3SBjoern A. Zeeb 	.get_vdev_subtype = ath10k_wmi_tlv_op_get_vdev_subtype,
5040da8fa4e3SBjoern A. Zeeb 	.gen_echo = ath10k_wmi_tlv_op_gen_echo,
5041da8fa4e3SBjoern A. Zeeb 	.gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
5042da8fa4e3SBjoern A. Zeeb 	.gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
5043da8fa4e3SBjoern A. Zeeb };
5044da8fa4e3SBjoern A. Zeeb 
5045da8fa4e3SBjoern A. Zeeb static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
5046da8fa4e3SBjoern A. Zeeb 	.auth = WMI_TLV_PEER_AUTH,
5047da8fa4e3SBjoern A. Zeeb 	.qos = WMI_TLV_PEER_QOS,
5048da8fa4e3SBjoern A. Zeeb 	.need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
5049da8fa4e3SBjoern A. Zeeb 	.need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
5050da8fa4e3SBjoern A. Zeeb 	.apsd = WMI_TLV_PEER_APSD,
5051da8fa4e3SBjoern A. Zeeb 	.ht = WMI_TLV_PEER_HT,
5052da8fa4e3SBjoern A. Zeeb 	.bw40 = WMI_TLV_PEER_40MHZ,
5053da8fa4e3SBjoern A. Zeeb 	.stbc = WMI_TLV_PEER_STBC,
5054da8fa4e3SBjoern A. Zeeb 	.ldbc = WMI_TLV_PEER_LDPC,
5055da8fa4e3SBjoern A. Zeeb 	.dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
5056da8fa4e3SBjoern A. Zeeb 	.static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
5057da8fa4e3SBjoern A. Zeeb 	.spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
5058da8fa4e3SBjoern A. Zeeb 	.vht = WMI_TLV_PEER_VHT,
5059da8fa4e3SBjoern A. Zeeb 	.bw80 = WMI_TLV_PEER_80MHZ,
5060da8fa4e3SBjoern A. Zeeb 	.pmf = WMI_TLV_PEER_PMF,
5061da8fa4e3SBjoern A. Zeeb 	.bw160 = WMI_TLV_PEER_160MHZ,
5062da8fa4e3SBjoern A. Zeeb };
5063da8fa4e3SBjoern A. Zeeb 
5064da8fa4e3SBjoern A. Zeeb /************/
5065da8fa4e3SBjoern A. Zeeb /* TLV init */
5066da8fa4e3SBjoern A. Zeeb /************/
5067da8fa4e3SBjoern A. Zeeb 
ath10k_wmi_tlv_attach(struct ath10k * ar)5068da8fa4e3SBjoern A. Zeeb void ath10k_wmi_tlv_attach(struct ath10k *ar)
5069da8fa4e3SBjoern A. Zeeb {
5070da8fa4e3SBjoern A. Zeeb 	ar->wmi.cmd = &wmi_tlv_cmd_map;
5071da8fa4e3SBjoern A. Zeeb 	ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
5072da8fa4e3SBjoern A. Zeeb 	ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
5073da8fa4e3SBjoern A. Zeeb 	ar->wmi.peer_param = &wmi_tlv_peer_param_map;
5074da8fa4e3SBjoern A. Zeeb 	ar->wmi.ops = &wmi_tlv_ops;
5075da8fa4e3SBjoern A. Zeeb 	ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
5076da8fa4e3SBjoern A. Zeeb }
5077