1/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2014 Qualcomm Atheros, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include "core.h"
18#include "debug.h"
19#include "hw.h"
20#include "wmi.h"
21#include "wmi-ops.h"
22#include "wmi-tlv.h"
23
24/***************/
25/* TLV helpers */
26/**************/
27
28struct wmi_tlv_policy {
29	size_t min_len;
30};
31
32static const struct wmi_tlv_policy wmi_tlv_policies[] = {
33	[WMI_TLV_TAG_ARRAY_BYTE]
34		= { .min_len = sizeof(u8) },
35	[WMI_TLV_TAG_ARRAY_UINT32]
36		= { .min_len = sizeof(u32) },
37	[WMI_TLV_TAG_STRUCT_SCAN_EVENT]
38		= { .min_len = sizeof(struct wmi_scan_event) },
39	[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR]
40		= { .min_len = sizeof(struct wmi_tlv_mgmt_rx_ev) },
41	[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT]
42		= { .min_len = sizeof(struct wmi_chan_info_event) },
43	[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT]
44		= { .min_len = sizeof(struct wmi_vdev_start_response_event) },
45	[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT]
46		= { .min_len = sizeof(struct wmi_peer_sta_kickout_event) },
47	[WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT]
48		= { .min_len = sizeof(struct wmi_host_swba_event) },
49	[WMI_TLV_TAG_STRUCT_TIM_INFO]
50		= { .min_len = sizeof(struct wmi_tim_info) },
51	[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO]
52		= { .min_len = sizeof(struct wmi_p2p_noa_info) },
53	[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT]
54		= { .min_len = sizeof(struct wmi_tlv_svc_rdy_ev) },
55	[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES]
56		= { .min_len = sizeof(struct hal_reg_capabilities) },
57	[WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ]
58		= { .min_len = sizeof(struct wlan_host_mem_req) },
59	[WMI_TLV_TAG_STRUCT_READY_EVENT]
60		= { .min_len = sizeof(struct wmi_tlv_rdy_ev) },
61	[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]
62		= { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
63	[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
64		= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
65};
66
67static int
68ath10k_wmi_tlv_iter(struct ath10k *ar, const void *ptr, size_t len,
69		    int (*iter)(struct ath10k *ar, u16 tag, u16 len,
70				const void *ptr, void *data),
71		    void *data)
72{
73	const void *begin = ptr;
74	const struct wmi_tlv *tlv;
75	u16 tlv_tag, tlv_len;
76	int ret;
77
78	while (len > 0) {
79		if (len < sizeof(*tlv)) {
80			ath10k_dbg(ar, ATH10K_DBG_WMI,
81				   "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
82				   ptr - begin, len, sizeof(*tlv));
83			return -EINVAL;
84		}
85
86		tlv = ptr;
87		tlv_tag = __le16_to_cpu(tlv->tag);
88		tlv_len = __le16_to_cpu(tlv->len);
89		ptr += sizeof(*tlv);
90		len -= sizeof(*tlv);
91
92		if (tlv_len > len) {
93			ath10k_dbg(ar, ATH10K_DBG_WMI,
94				   "wmi tlv parse failure of tag %hhu at byte %zd (%zu bytes left, %hhu expected)\n",
95				   tlv_tag, ptr - begin, len, tlv_len);
96			return -EINVAL;
97		}
98
99		if (tlv_tag < ARRAY_SIZE(wmi_tlv_policies) &&
100		    wmi_tlv_policies[tlv_tag].min_len &&
101		    wmi_tlv_policies[tlv_tag].min_len > tlv_len) {
102			ath10k_dbg(ar, ATH10K_DBG_WMI,
103				   "wmi tlv parse failure of tag %hhu at byte %zd (%hhu bytes is less than min length %zu)\n",
104				   tlv_tag, ptr - begin, tlv_len,
105				   wmi_tlv_policies[tlv_tag].min_len);
106			return -EINVAL;
107		}
108
109		ret = iter(ar, tlv_tag, tlv_len, ptr, data);
110		if (ret)
111			return ret;
112
113		ptr += tlv_len;
114		len -= tlv_len;
115	}
116
117	return 0;
118}
119
120static int ath10k_wmi_tlv_iter_parse(struct ath10k *ar, u16 tag, u16 len,
121				     const void *ptr, void *data)
122{
123	const void **tb = data;
124
125	if (tag < WMI_TLV_TAG_MAX)
126		tb[tag] = ptr;
127
128	return 0;
129}
130
131static int ath10k_wmi_tlv_parse(struct ath10k *ar, const void **tb,
132				const void *ptr, size_t len)
133{
134	return ath10k_wmi_tlv_iter(ar, ptr, len, ath10k_wmi_tlv_iter_parse,
135				   (void *)tb);
136}
137
138static const void **
139ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
140			   size_t len, gfp_t gfp)
141{
142	const void **tb;
143	int ret;
144
145	tb = kzalloc(sizeof(*tb) * WMI_TLV_TAG_MAX, gfp);
146	if (!tb)
147		return ERR_PTR(-ENOMEM);
148
149	ret = ath10k_wmi_tlv_parse(ar, tb, ptr, len);
150	if (ret) {
151		kfree(tb);
152		return ERR_PTR(ret);
153	}
154
155	return tb;
156}
157
158static u16 ath10k_wmi_tlv_len(const void *ptr)
159{
160	return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len);
161}
162
163/**************/
164/* TLV events */
165/**************/
166static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
167					      struct sk_buff *skb)
168{
169	const void **tb;
170	const struct wmi_tlv_bcn_tx_status_ev *ev;
171	u32 vdev_id, tx_status;
172	int ret;
173
174	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
175	if (IS_ERR(tb)) {
176		ret = PTR_ERR(tb);
177		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
178		return ret;
179	}
180
181	ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT];
182	if (!ev) {
183		kfree(tb);
184		return -EPROTO;
185	}
186
187	tx_status = __le32_to_cpu(ev->tx_status);
188	vdev_id = __le32_to_cpu(ev->vdev_id);
189
190	switch (tx_status) {
191	case WMI_TLV_BCN_TX_STATUS_OK:
192		break;
193	case WMI_TLV_BCN_TX_STATUS_XRETRY:
194	case WMI_TLV_BCN_TX_STATUS_DROP:
195	case WMI_TLV_BCN_TX_STATUS_FILTERED:
196		/* FIXME: It's probably worth telling mac80211 to stop the
197		 * interface as it is crippled.
198		 */
199		ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d",
200			    vdev_id, tx_status);
201		break;
202	}
203
204	kfree(tb);
205	return 0;
206}
207
208static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
209					  struct sk_buff *skb)
210{
211	const void **tb;
212	const struct wmi_tlv_diag_data_ev *ev;
213	const struct wmi_tlv_diag_item *item;
214	const void *data;
215	int ret, num_items, len;
216
217	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
218	if (IS_ERR(tb)) {
219		ret = PTR_ERR(tb);
220		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
221		return ret;
222	}
223
224	ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT];
225	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
226	if (!ev || !data) {
227		kfree(tb);
228		return -EPROTO;
229	}
230
231	num_items = __le32_to_cpu(ev->num_items);
232	len = ath10k_wmi_tlv_len(data);
233
234	while (num_items--) {
235		if (len == 0)
236			break;
237		if (len < sizeof(*item)) {
238			ath10k_warn(ar, "failed to parse diag data: can't fit item header\n");
239			break;
240		}
241
242		item = data;
243
244		if (len < sizeof(*item) + __le16_to_cpu(item->len)) {
245			ath10k_warn(ar, "failed to parse diag data: item is too long\n");
246			break;
247		}
248
249		trace_ath10k_wmi_diag_container(ar,
250						item->type,
251						__le32_to_cpu(item->timestamp),
252						__le32_to_cpu(item->code),
253						__le16_to_cpu(item->len),
254						item->payload);
255
256		len -= sizeof(*item);
257		len -= roundup(__le16_to_cpu(item->len), 4);
258
259		data += sizeof(*item);
260		data += roundup(__le16_to_cpu(item->len), 4);
261	}
262
263	if (num_items != -1 || len != 0)
264		ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n",
265			    num_items, len);
266
267	kfree(tb);
268	return 0;
269}
270
271static int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
272				     struct sk_buff *skb)
273{
274	const void **tb;
275	const void *data;
276	int ret, len;
277
278	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
279	if (IS_ERR(tb)) {
280		ret = PTR_ERR(tb);
281		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
282		return ret;
283	}
284
285	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
286	if (!data) {
287		kfree(tb);
288		return -EPROTO;
289	}
290	len = ath10k_wmi_tlv_len(data);
291
292	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len);
293	trace_ath10k_wmi_diag(ar, data, len);
294
295	kfree(tb);
296	return 0;
297}
298
299/***********/
300/* TLV ops */
301/***********/
302
303static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
304{
305	struct wmi_cmd_hdr *cmd_hdr;
306	enum wmi_tlv_event_id id;
307
308	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
309	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
310
311	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
312		return;
313
314	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
315
316	switch (id) {
317	case WMI_TLV_MGMT_RX_EVENTID:
318		ath10k_wmi_event_mgmt_rx(ar, skb);
319		/* mgmt_rx() owns the skb now! */
320		return;
321	case WMI_TLV_SCAN_EVENTID:
322		ath10k_wmi_event_scan(ar, skb);
323		break;
324	case WMI_TLV_CHAN_INFO_EVENTID:
325		ath10k_wmi_event_chan_info(ar, skb);
326		break;
327	case WMI_TLV_ECHO_EVENTID:
328		ath10k_wmi_event_echo(ar, skb);
329		break;
330	case WMI_TLV_DEBUG_MESG_EVENTID:
331		ath10k_wmi_event_debug_mesg(ar, skb);
332		break;
333	case WMI_TLV_UPDATE_STATS_EVENTID:
334		ath10k_wmi_event_update_stats(ar, skb);
335		break;
336	case WMI_TLV_VDEV_START_RESP_EVENTID:
337		ath10k_wmi_event_vdev_start_resp(ar, skb);
338		break;
339	case WMI_TLV_VDEV_STOPPED_EVENTID:
340		ath10k_wmi_event_vdev_stopped(ar, skb);
341		break;
342	case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
343		ath10k_wmi_event_peer_sta_kickout(ar, skb);
344		break;
345	case WMI_TLV_HOST_SWBA_EVENTID:
346		ath10k_wmi_event_host_swba(ar, skb);
347		break;
348	case WMI_TLV_TBTTOFFSET_UPDATE_EVENTID:
349		ath10k_wmi_event_tbttoffset_update(ar, skb);
350		break;
351	case WMI_TLV_PHYERR_EVENTID:
352		ath10k_wmi_event_phyerr(ar, skb);
353		break;
354	case WMI_TLV_ROAM_EVENTID:
355		ath10k_wmi_event_roam(ar, skb);
356		break;
357	case WMI_TLV_PROFILE_MATCH:
358		ath10k_wmi_event_profile_match(ar, skb);
359		break;
360	case WMI_TLV_DEBUG_PRINT_EVENTID:
361		ath10k_wmi_event_debug_print(ar, skb);
362		break;
363	case WMI_TLV_PDEV_QVIT_EVENTID:
364		ath10k_wmi_event_pdev_qvit(ar, skb);
365		break;
366	case WMI_TLV_WLAN_PROFILE_DATA_EVENTID:
367		ath10k_wmi_event_wlan_profile_data(ar, skb);
368		break;
369	case WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID:
370		ath10k_wmi_event_rtt_measurement_report(ar, skb);
371		break;
372	case WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID:
373		ath10k_wmi_event_tsf_measurement_report(ar, skb);
374		break;
375	case WMI_TLV_RTT_ERROR_REPORT_EVENTID:
376		ath10k_wmi_event_rtt_error_report(ar, skb);
377		break;
378	case WMI_TLV_WOW_WAKEUP_HOST_EVENTID:
379		ath10k_wmi_event_wow_wakeup_host(ar, skb);
380		break;
381	case WMI_TLV_DCS_INTERFERENCE_EVENTID:
382		ath10k_wmi_event_dcs_interference(ar, skb);
383		break;
384	case WMI_TLV_PDEV_TPC_CONFIG_EVENTID:
385		ath10k_wmi_event_pdev_tpc_config(ar, skb);
386		break;
387	case WMI_TLV_PDEV_FTM_INTG_EVENTID:
388		ath10k_wmi_event_pdev_ftm_intg(ar, skb);
389		break;
390	case WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID:
391		ath10k_wmi_event_gtk_offload_status(ar, skb);
392		break;
393	case WMI_TLV_GTK_REKEY_FAIL_EVENTID:
394		ath10k_wmi_event_gtk_rekey_fail(ar, skb);
395		break;
396	case WMI_TLV_TX_DELBA_COMPLETE_EVENTID:
397		ath10k_wmi_event_delba_complete(ar, skb);
398		break;
399	case WMI_TLV_TX_ADDBA_COMPLETE_EVENTID:
400		ath10k_wmi_event_addba_complete(ar, skb);
401		break;
402	case WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID:
403		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
404		break;
405	case WMI_TLV_SERVICE_READY_EVENTID:
406		ath10k_wmi_event_service_ready(ar, skb);
407		break;
408	case WMI_TLV_READY_EVENTID:
409		ath10k_wmi_event_ready(ar, skb);
410		break;
411	case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID:
412		ath10k_wmi_tlv_event_bcn_tx_status(ar, skb);
413		break;
414	case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID:
415		ath10k_wmi_tlv_event_diag_data(ar, skb);
416		break;
417	case WMI_TLV_DIAG_EVENTID:
418		ath10k_wmi_tlv_event_diag(ar, skb);
419		break;
420	default:
421		ath10k_warn(ar, "Unknown eventid: %d\n", id);
422		break;
423	}
424
425	dev_kfree_skb(skb);
426}
427
428static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
429					  struct sk_buff *skb,
430					  struct wmi_scan_ev_arg *arg)
431{
432	const void **tb;
433	const struct wmi_scan_event *ev;
434	int ret;
435
436	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
437	if (IS_ERR(tb)) {
438		ret = PTR_ERR(tb);
439		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
440		return ret;
441	}
442
443	ev = tb[WMI_TLV_TAG_STRUCT_SCAN_EVENT];
444	if (!ev) {
445		kfree(tb);
446		return -EPROTO;
447	}
448
449	arg->event_type = ev->event_type;
450	arg->reason = ev->reason;
451	arg->channel_freq = ev->channel_freq;
452	arg->scan_req_id = ev->scan_req_id;
453	arg->scan_id = ev->scan_id;
454	arg->vdev_id = ev->vdev_id;
455
456	kfree(tb);
457	return 0;
458}
459
460static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
461					     struct sk_buff *skb,
462					     struct wmi_mgmt_rx_ev_arg *arg)
463{
464	const void **tb;
465	const struct wmi_tlv_mgmt_rx_ev *ev;
466	const u8 *frame;
467	u32 msdu_len;
468	int ret;
469
470	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
471	if (IS_ERR(tb)) {
472		ret = PTR_ERR(tb);
473		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
474		return ret;
475	}
476
477	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR];
478	frame = tb[WMI_TLV_TAG_ARRAY_BYTE];
479
480	if (!ev || !frame) {
481		kfree(tb);
482		return -EPROTO;
483	}
484
485	arg->channel = ev->channel;
486	arg->buf_len = ev->buf_len;
487	arg->status = ev->status;
488	arg->snr = ev->snr;
489	arg->phy_mode = ev->phy_mode;
490	arg->rate = ev->rate;
491
492	msdu_len = __le32_to_cpu(arg->buf_len);
493
494	if (skb->len < (frame - skb->data) + msdu_len) {
495		kfree(tb);
496		return -EPROTO;
497	}
498
499	/* shift the sk_buff to point to `frame` */
500	skb_trim(skb, 0);
501	skb_put(skb, frame - skb->data);
502	skb_pull(skb, frame - skb->data);
503	skb_put(skb, msdu_len);
504
505	kfree(tb);
506	return 0;
507}
508
509static int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar,
510					     struct sk_buff *skb,
511					     struct wmi_ch_info_ev_arg *arg)
512{
513	const void **tb;
514	const struct wmi_chan_info_event *ev;
515	int ret;
516
517	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
518	if (IS_ERR(tb)) {
519		ret = PTR_ERR(tb);
520		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
521		return ret;
522	}
523
524	ev = tb[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT];
525	if (!ev) {
526		kfree(tb);
527		return -EPROTO;
528	}
529
530	arg->err_code = ev->err_code;
531	arg->freq = ev->freq;
532	arg->cmd_flags = ev->cmd_flags;
533	arg->noise_floor = ev->noise_floor;
534	arg->rx_clear_count = ev->rx_clear_count;
535	arg->cycle_count = ev->cycle_count;
536
537	kfree(tb);
538	return 0;
539}
540
541static int
542ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
543				     struct wmi_vdev_start_ev_arg *arg)
544{
545	const void **tb;
546	const struct wmi_vdev_start_response_event *ev;
547	int ret;
548
549	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
550	if (IS_ERR(tb)) {
551		ret = PTR_ERR(tb);
552		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
553		return ret;
554	}
555
556	ev = tb[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT];
557	if (!ev) {
558		kfree(tb);
559		return -EPROTO;
560	}
561
562	skb_pull(skb, sizeof(*ev));
563	arg->vdev_id = ev->vdev_id;
564	arg->req_id = ev->req_id;
565	arg->resp_type = ev->resp_type;
566	arg->status = ev->status;
567
568	kfree(tb);
569	return 0;
570}
571
572static int ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k *ar,
573					       struct sk_buff *skb,
574					       struct wmi_peer_kick_ev_arg *arg)
575{
576	const void **tb;
577	const struct wmi_peer_sta_kickout_event *ev;
578	int ret;
579
580	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
581	if (IS_ERR(tb)) {
582		ret = PTR_ERR(tb);
583		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
584		return ret;
585	}
586
587	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT];
588	if (!ev) {
589		kfree(tb);
590		return -EPROTO;
591	}
592
593	arg->mac_addr = ev->peer_macaddr.addr;
594
595	kfree(tb);
596	return 0;
597}
598
599struct wmi_tlv_swba_parse {
600	const struct wmi_host_swba_event *ev;
601	bool tim_done;
602	bool noa_done;
603	size_t n_tim;
604	size_t n_noa;
605	struct wmi_swba_ev_arg *arg;
606};
607
608static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
609					 const void *ptr, void *data)
610{
611	struct wmi_tlv_swba_parse *swba = data;
612
613	if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO)
614		return -EPROTO;
615
616	if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info))
617		return -ENOBUFS;
618
619	swba->arg->tim_info[swba->n_tim++] = ptr;
620	return 0;
621}
622
623static int ath10k_wmi_tlv_swba_noa_parse(struct ath10k *ar, u16 tag, u16 len,
624					 const void *ptr, void *data)
625{
626	struct wmi_tlv_swba_parse *swba = data;
627
628	if (tag != WMI_TLV_TAG_STRUCT_P2P_NOA_INFO)
629		return -EPROTO;
630
631	if (swba->n_noa >= ARRAY_SIZE(swba->arg->noa_info))
632		return -ENOBUFS;
633
634	swba->arg->noa_info[swba->n_noa++] = ptr;
635	return 0;
636}
637
638static int ath10k_wmi_tlv_swba_parse(struct ath10k *ar, u16 tag, u16 len,
639				     const void *ptr, void *data)
640{
641	struct wmi_tlv_swba_parse *swba = data;
642	int ret;
643
644	switch (tag) {
645	case WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT:
646		swba->ev = ptr;
647		break;
648	case WMI_TLV_TAG_ARRAY_STRUCT:
649		if (!swba->tim_done) {
650			swba->tim_done = true;
651			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
652						  ath10k_wmi_tlv_swba_tim_parse,
653						  swba);
654			if (ret)
655				return ret;
656		} else if (!swba->noa_done) {
657			swba->noa_done = true;
658			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
659						  ath10k_wmi_tlv_swba_noa_parse,
660						  swba);
661			if (ret)
662				return ret;
663		}
664		break;
665	default:
666		break;
667	}
668	return 0;
669}
670
671static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
672					  struct sk_buff *skb,
673					  struct wmi_swba_ev_arg *arg)
674{
675	struct wmi_tlv_swba_parse swba = { .arg = arg };
676	u32 map;
677	size_t n_vdevs;
678	int ret;
679
680	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
681				  ath10k_wmi_tlv_swba_parse, &swba);
682	if (ret) {
683		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
684		return ret;
685	}
686
687	if (!swba.ev)
688		return -EPROTO;
689
690	arg->vdev_map = swba.ev->vdev_map;
691
692	for (map = __le32_to_cpu(arg->vdev_map), n_vdevs = 0; map; map >>= 1)
693		if (map & BIT(0))
694			n_vdevs++;
695
696	if (n_vdevs != swba.n_tim ||
697	    n_vdevs != swba.n_noa)
698		return -EPROTO;
699
700	return 0;
701}
702
703static int ath10k_wmi_tlv_op_pull_phyerr_ev(struct ath10k *ar,
704					    struct sk_buff *skb,
705					    struct wmi_phyerr_ev_arg *arg)
706{
707	const void **tb;
708	const struct wmi_tlv_phyerr_ev *ev;
709	const void *phyerrs;
710	int ret;
711
712	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
713	if (IS_ERR(tb)) {
714		ret = PTR_ERR(tb);
715		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
716		return ret;
717	}
718
719	ev = tb[WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR];
720	phyerrs = tb[WMI_TLV_TAG_ARRAY_BYTE];
721
722	if (!ev || !phyerrs) {
723		kfree(tb);
724		return -EPROTO;
725	}
726
727	arg->num_phyerrs  = ev->num_phyerrs;
728	arg->tsf_l32 = ev->tsf_l32;
729	arg->tsf_u32 = ev->tsf_u32;
730	arg->buf_len = ev->buf_len;
731	arg->phyerrs = phyerrs;
732
733	kfree(tb);
734	return 0;
735}
736
737#define WMI_TLV_ABI_VER_NS0 0x5F414351
738#define WMI_TLV_ABI_VER_NS1 0x00004C4D
739#define WMI_TLV_ABI_VER_NS2 0x00000000
740#define WMI_TLV_ABI_VER_NS3 0x00000000
741
742#define WMI_TLV_ABI_VER0_MAJOR 1
743#define WMI_TLV_ABI_VER0_MINOR 0
744#define WMI_TLV_ABI_VER0 ((((WMI_TLV_ABI_VER0_MAJOR) << 24) & 0xFF000000) | \
745			  (((WMI_TLV_ABI_VER0_MINOR) <<  0) & 0x00FFFFFF))
746#define WMI_TLV_ABI_VER1 53
747
748static int
749ath10k_wmi_tlv_parse_mem_reqs(struct ath10k *ar, u16 tag, u16 len,
750			      const void *ptr, void *data)
751{
752	struct wmi_svc_rdy_ev_arg *arg = data;
753	int i;
754
755	if (tag != WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ)
756		return -EPROTO;
757
758	for (i = 0; i < ARRAY_SIZE(arg->mem_reqs); i++) {
759		if (!arg->mem_reqs[i]) {
760			arg->mem_reqs[i] = ptr;
761			return 0;
762		}
763	}
764
765	return -ENOMEM;
766}
767
768static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
769					     struct sk_buff *skb,
770					     struct wmi_svc_rdy_ev_arg *arg)
771{
772	const void **tb;
773	const struct hal_reg_capabilities *reg;
774	const struct wmi_tlv_svc_rdy_ev *ev;
775	const __le32 *svc_bmap;
776	const struct wlan_host_mem_req *mem_reqs;
777	int ret;
778
779	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
780	if (IS_ERR(tb)) {
781		ret = PTR_ERR(tb);
782		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
783		return ret;
784	}
785
786	ev = tb[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT];
787	reg = tb[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES];
788	svc_bmap = tb[WMI_TLV_TAG_ARRAY_UINT32];
789	mem_reqs = tb[WMI_TLV_TAG_ARRAY_STRUCT];
790
791	if (!ev || !reg || !svc_bmap || !mem_reqs) {
792		kfree(tb);
793		return -EPROTO;
794	}
795
796	/* This is an internal ABI compatibility check for WMI TLV so check it
797	 * here instead of the generic WMI code.
798	 */
799	ath10k_dbg(ar, ATH10K_DBG_WMI,
800		   "wmi tlv abi 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x\n",
801		   __le32_to_cpu(ev->abi.abi_ver0), WMI_TLV_ABI_VER0,
802		   __le32_to_cpu(ev->abi.abi_ver_ns0), WMI_TLV_ABI_VER_NS0,
803		   __le32_to_cpu(ev->abi.abi_ver_ns1), WMI_TLV_ABI_VER_NS1,
804		   __le32_to_cpu(ev->abi.abi_ver_ns2), WMI_TLV_ABI_VER_NS2,
805		   __le32_to_cpu(ev->abi.abi_ver_ns3), WMI_TLV_ABI_VER_NS3);
806
807	if (__le32_to_cpu(ev->abi.abi_ver0) != WMI_TLV_ABI_VER0 ||
808	    __le32_to_cpu(ev->abi.abi_ver_ns0) != WMI_TLV_ABI_VER_NS0 ||
809	    __le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 ||
810	    __le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 ||
811	    __le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) {
812		kfree(tb);
813		return -ENOTSUPP;
814	}
815
816	arg->min_tx_power = ev->hw_min_tx_power;
817	arg->max_tx_power = ev->hw_max_tx_power;
818	arg->ht_cap = ev->ht_cap_info;
819	arg->vht_cap = ev->vht_cap_info;
820	arg->sw_ver0 = ev->abi.abi_ver0;
821	arg->sw_ver1 = ev->abi.abi_ver1;
822	arg->fw_build = ev->fw_build_vers;
823	arg->phy_capab = ev->phy_capability;
824	arg->num_rf_chains = ev->num_rf_chains;
825	arg->eeprom_rd = reg->eeprom_rd;
826	arg->num_mem_reqs = ev->num_mem_reqs;
827	arg->service_map = svc_bmap;
828	arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
829
830	ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
831				  ath10k_wmi_tlv_parse_mem_reqs, arg);
832	if (ret) {
833		kfree(tb);
834		ath10k_warn(ar, "failed to parse mem_reqs tlv: %d\n", ret);
835		return ret;
836	}
837
838	kfree(tb);
839	return 0;
840}
841
842static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
843					 struct sk_buff *skb,
844					 struct wmi_rdy_ev_arg *arg)
845{
846	const void **tb;
847	const struct wmi_tlv_rdy_ev *ev;
848	int ret;
849
850	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
851	if (IS_ERR(tb)) {
852		ret = PTR_ERR(tb);
853		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
854		return ret;
855	}
856
857	ev = tb[WMI_TLV_TAG_STRUCT_READY_EVENT];
858	if (!ev) {
859		kfree(tb);
860		return -EPROTO;
861	}
862
863	arg->sw_version = ev->abi.abi_ver0;
864	arg->abi_version = ev->abi.abi_ver1;
865	arg->status = ev->status;
866	arg->mac_addr = ev->mac_addr.addr;
867
868	kfree(tb);
869	return 0;
870}
871
872static void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
873					   struct ath10k_fw_stats_vdev *dst)
874{
875	int i;
876
877	dst->vdev_id = __le32_to_cpu(src->vdev_id);
878	dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
879	dst->data_snr = __le32_to_cpu(src->data_snr);
880	dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
881	dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
882	dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
883	dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
884	dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
885	dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
886
887	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
888		dst->num_tx_frames[i] =
889			__le32_to_cpu(src->num_tx_frames[i]);
890
891	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
892		dst->num_tx_frames_retries[i] =
893			__le32_to_cpu(src->num_tx_frames_retries[i]);
894
895	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
896		dst->num_tx_frames_failures[i] =
897			__le32_to_cpu(src->num_tx_frames_failures[i]);
898
899	for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
900		dst->tx_rate_history[i] =
901			__le32_to_cpu(src->tx_rate_history[i]);
902
903	for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
904		dst->beacon_rssi_history[i] =
905			__le32_to_cpu(src->beacon_rssi_history[i]);
906}
907
908static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
909					   struct sk_buff *skb,
910					   struct ath10k_fw_stats *stats)
911{
912	const void **tb;
913	const struct wmi_tlv_stats_ev *ev;
914	const void *data;
915	u32 num_pdev_stats;
916	u32 num_vdev_stats;
917	u32 num_peer_stats;
918	u32 num_bcnflt_stats;
919	u32 num_chan_stats;
920	size_t data_len;
921	int ret;
922	int i;
923
924	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
925	if (IS_ERR(tb)) {
926		ret = PTR_ERR(tb);
927		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
928		return ret;
929	}
930
931	ev = tb[WMI_TLV_TAG_STRUCT_STATS_EVENT];
932	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
933
934	if (!ev || !data) {
935		kfree(tb);
936		return -EPROTO;
937	}
938
939	data_len = ath10k_wmi_tlv_len(data);
940	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
941	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
942	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
943	num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
944	num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
945
946	ath10k_dbg(ar, ATH10K_DBG_WMI,
947		   "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n",
948		   num_pdev_stats, num_vdev_stats, num_peer_stats,
949		   num_bcnflt_stats, num_chan_stats);
950
951	for (i = 0; i < num_pdev_stats; i++) {
952		const struct wmi_pdev_stats *src;
953		struct ath10k_fw_stats_pdev *dst;
954
955		src = data;
956		if (data_len < sizeof(*src))
957			return -EPROTO;
958
959		data += sizeof(*src);
960		data_len -= sizeof(*src);
961
962		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
963		if (!dst)
964			continue;
965
966		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
967		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
968		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
969		list_add_tail(&dst->list, &stats->pdevs);
970	}
971
972	for (i = 0; i < num_vdev_stats; i++) {
973		const struct wmi_tlv_vdev_stats *src;
974		struct ath10k_fw_stats_vdev *dst;
975
976		src = data;
977		if (data_len < sizeof(*src))
978			return -EPROTO;
979
980		data += sizeof(*src);
981		data_len -= sizeof(*src);
982
983		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
984		if (!dst)
985			continue;
986
987		ath10k_wmi_tlv_pull_vdev_stats(src, dst);
988		list_add_tail(&dst->list, &stats->vdevs);
989	}
990
991	for (i = 0; i < num_peer_stats; i++) {
992		const struct wmi_10x_peer_stats *src;
993		struct ath10k_fw_stats_peer *dst;
994
995		src = data;
996		if (data_len < sizeof(*src))
997			return -EPROTO;
998
999		data += sizeof(*src);
1000		data_len -= sizeof(*src);
1001
1002		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1003		if (!dst)
1004			continue;
1005
1006		ath10k_wmi_pull_peer_stats(&src->old, dst);
1007		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
1008		list_add_tail(&dst->list, &stats->peers);
1009	}
1010
1011	kfree(tb);
1012	return 0;
1013}
1014
1015static struct sk_buff *
1016ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
1017{
1018	struct wmi_tlv_pdev_suspend *cmd;
1019	struct wmi_tlv *tlv;
1020	struct sk_buff *skb;
1021
1022	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1023	if (!skb)
1024		return ERR_PTR(-ENOMEM);
1025
1026	tlv = (void *)skb->data;
1027	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD);
1028	tlv->len = __cpu_to_le16(sizeof(*cmd));
1029	cmd = (void *)tlv->value;
1030	cmd->opt = __cpu_to_le32(opt);
1031
1032	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev suspend\n");
1033	return skb;
1034}
1035
1036static struct sk_buff *
1037ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k *ar)
1038{
1039	struct wmi_tlv_resume_cmd *cmd;
1040	struct wmi_tlv *tlv;
1041	struct sk_buff *skb;
1042
1043	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1044	if (!skb)
1045		return ERR_PTR(-ENOMEM);
1046
1047	tlv = (void *)skb->data;
1048	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD);
1049	tlv->len = __cpu_to_le16(sizeof(*cmd));
1050	cmd = (void *)tlv->value;
1051	cmd->reserved = __cpu_to_le32(0);
1052
1053	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev resume\n");
1054	return skb;
1055}
1056
1057static struct sk_buff *
1058ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
1059				  u16 rd, u16 rd2g, u16 rd5g,
1060				  u16 ctl2g, u16 ctl5g,
1061				  enum wmi_dfs_region dfs_reg)
1062{
1063	struct wmi_tlv_pdev_set_rd_cmd *cmd;
1064	struct wmi_tlv *tlv;
1065	struct sk_buff *skb;
1066
1067	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1068	if (!skb)
1069		return ERR_PTR(-ENOMEM);
1070
1071	tlv = (void *)skb->data;
1072	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD);
1073	tlv->len = __cpu_to_le16(sizeof(*cmd));
1074	cmd = (void *)tlv->value;
1075	cmd->regd = __cpu_to_le32(rd);
1076	cmd->regd_2ghz = __cpu_to_le32(rd2g);
1077	cmd->regd_5ghz = __cpu_to_le32(rd5g);
1078	cmd->conform_limit_2ghz = __cpu_to_le32(rd2g);
1079	cmd->conform_limit_5ghz = __cpu_to_le32(rd5g);
1080
1081	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
1082	return skb;
1083}
1084
1085static struct sk_buff *
1086ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
1087				     u32 param_value)
1088{
1089	struct wmi_tlv_pdev_set_param_cmd *cmd;
1090	struct wmi_tlv *tlv;
1091	struct sk_buff *skb;
1092
1093	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1094	if (!skb)
1095		return ERR_PTR(-ENOMEM);
1096
1097	tlv = (void *)skb->data;
1098	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD);
1099	tlv->len = __cpu_to_le16(sizeof(*cmd));
1100	cmd = (void *)tlv->value;
1101	cmd->param_id = __cpu_to_le32(param_id);
1102	cmd->param_value = __cpu_to_le32(param_value);
1103
1104	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n");
1105	return skb;
1106}
1107
1108static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
1109{
1110	struct sk_buff *skb;
1111	struct wmi_tlv *tlv;
1112	struct wmi_tlv_init_cmd *cmd;
1113	struct wmi_tlv_resource_config *cfg;
1114	struct wmi_host_mem_chunks *chunks;
1115	size_t len, chunks_len;
1116	void *ptr;
1117
1118	chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk);
1119	len = (sizeof(*tlv) + sizeof(*cmd)) +
1120	      (sizeof(*tlv) + sizeof(*cfg)) +
1121	      (sizeof(*tlv) + chunks_len);
1122
1123	skb = ath10k_wmi_alloc_skb(ar, len);
1124	if (!skb)
1125		return ERR_PTR(-ENOMEM);
1126
1127	ptr = skb->data;
1128
1129	tlv = ptr;
1130	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_INIT_CMD);
1131	tlv->len = __cpu_to_le16(sizeof(*cmd));
1132	cmd = (void *)tlv->value;
1133	ptr += sizeof(*tlv);
1134	ptr += sizeof(*cmd);
1135
1136	tlv = ptr;
1137	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG);
1138	tlv->len = __cpu_to_le16(sizeof(*cfg));
1139	cfg = (void *)tlv->value;
1140	ptr += sizeof(*tlv);
1141	ptr += sizeof(*cfg);
1142
1143	tlv = ptr;
1144	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
1145	tlv->len = __cpu_to_le16(chunks_len);
1146	chunks = (void *)tlv->value;
1147
1148	ptr += sizeof(*tlv);
1149	ptr += chunks_len;
1150
1151	cmd->abi.abi_ver0 = __cpu_to_le32(WMI_TLV_ABI_VER0);
1152	cmd->abi.abi_ver1 = __cpu_to_le32(WMI_TLV_ABI_VER1);
1153	cmd->abi.abi_ver_ns0 = __cpu_to_le32(WMI_TLV_ABI_VER_NS0);
1154	cmd->abi.abi_ver_ns1 = __cpu_to_le32(WMI_TLV_ABI_VER_NS1);
1155	cmd->abi.abi_ver_ns2 = __cpu_to_le32(WMI_TLV_ABI_VER_NS2);
1156	cmd->abi.abi_ver_ns3 = __cpu_to_le32(WMI_TLV_ABI_VER_NS3);
1157	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
1158
1159	cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
1160	cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
1161
1162	if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
1163		cfg->num_offload_peers = __cpu_to_le32(3);
1164		cfg->num_offload_reorder_bufs = __cpu_to_le32(3);
1165	} else {
1166		cfg->num_offload_peers = __cpu_to_le32(0);
1167		cfg->num_offload_reorder_bufs = __cpu_to_le32(0);
1168	}
1169
1170	cfg->num_peer_keys = __cpu_to_le32(2);
1171	cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
1172	cfg->ast_skid_limit = __cpu_to_le32(0x10);
1173	cfg->tx_chain_mask = __cpu_to_le32(0x7);
1174	cfg->rx_chain_mask = __cpu_to_le32(0x7);
1175	cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
1176	cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64);
1177	cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64);
1178	cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28);
1179	cfg->rx_decap_mode = __cpu_to_le32(1);
1180	cfg->scan_max_pending_reqs = __cpu_to_le32(4);
1181	cfg->bmiss_offload_max_vdev = __cpu_to_le32(3);
1182	cfg->roam_offload_max_vdev = __cpu_to_le32(3);
1183	cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8);
1184	cfg->num_mcast_groups = __cpu_to_le32(0);
1185	cfg->num_mcast_table_elems = __cpu_to_le32(0);
1186	cfg->mcast2ucast_mode = __cpu_to_le32(0);
1187	cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
1188	cfg->num_wds_entries = __cpu_to_le32(0x20);
1189	cfg->dma_burst_size = __cpu_to_le32(0);
1190	cfg->mac_aggr_delim = __cpu_to_le32(0);
1191	cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
1192	cfg->vow_config = __cpu_to_le32(0);
1193	cfg->gtk_offload_max_vdev = __cpu_to_le32(2);
1194	cfg->num_msdu_desc = __cpu_to_le32(TARGET_TLV_NUM_MSDU_DESC);
1195	cfg->max_frag_entries = __cpu_to_le32(2);
1196	cfg->num_tdls_vdevs = __cpu_to_le32(1);
1197	cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
1198	cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2);
1199	cfg->num_multicast_filter_entries = __cpu_to_le32(5);
1200	cfg->num_wow_filters = __cpu_to_le32(0x16);
1201	cfg->num_keep_alive_pattern = __cpu_to_le32(6);
1202	cfg->keep_alive_pattern_size = __cpu_to_le32(0);
1203	cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1);
1204	cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1);
1205
1206	ath10k_wmi_put_host_mem_chunks(ar, chunks);
1207
1208	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
1209	return skb;
1210}
1211
1212static struct sk_buff *
1213ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
1214				 const struct wmi_start_scan_arg *arg)
1215{
1216	struct wmi_tlv_start_scan_cmd *cmd;
1217	struct wmi_tlv *tlv;
1218	struct sk_buff *skb;
1219	size_t len, chan_len, ssid_len, bssid_len, ie_len;
1220	__le32 *chans;
1221	struct wmi_ssid *ssids;
1222	struct wmi_mac_addr *addrs;
1223	void *ptr;
1224	int i, ret;
1225
1226	ret = ath10k_wmi_start_scan_verify(arg);
1227	if (ret)
1228		return ERR_PTR(ret);
1229
1230	chan_len = arg->n_channels * sizeof(__le32);
1231	ssid_len = arg->n_ssids * sizeof(struct wmi_ssid);
1232	bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr);
1233	ie_len = roundup(arg->ie_len, 4);
1234	len = (sizeof(*tlv) + sizeof(*cmd)) +
1235	      (arg->n_channels ? sizeof(*tlv) + chan_len : 0) +
1236	      (arg->n_ssids ? sizeof(*tlv) + ssid_len : 0) +
1237	      (arg->n_bssids ? sizeof(*tlv) + bssid_len : 0) +
1238	      (arg->ie_len ? sizeof(*tlv) + ie_len : 0);
1239
1240	skb = ath10k_wmi_alloc_skb(ar, len);
1241	if (!skb)
1242		return ERR_PTR(-ENOMEM);
1243
1244	ptr = (void *)skb->data;
1245	tlv = ptr;
1246	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_START_SCAN_CMD);
1247	tlv->len = __cpu_to_le16(sizeof(*cmd));
1248	cmd = (void *)tlv->value;
1249
1250	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
1251	cmd->burst_duration_ms = __cpu_to_le32(0);
1252	cmd->num_channels = __cpu_to_le32(arg->n_channels);
1253	cmd->num_ssids = __cpu_to_le32(arg->n_ssids);
1254	cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
1255	cmd->ie_len = __cpu_to_le32(arg->ie_len);
1256	cmd->num_probes = __cpu_to_le32(3);
1257
1258	/* FIXME: There are some scan flag inconsistencies across firmwares,
1259	 * e.g. WMI-TLV inverts the logic behind the following flag.
1260	 */
1261	cmd->common.scan_ctrl_flags ^= __cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);
1262
1263	ptr += sizeof(*tlv);
1264	ptr += sizeof(*cmd);
1265
1266	tlv = ptr;
1267	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
1268	tlv->len = __cpu_to_le16(chan_len);
1269	chans = (void *)tlv->value;
1270	for (i = 0; i < arg->n_channels; i++)
1271		chans[i] = __cpu_to_le32(arg->channels[i]);
1272
1273	ptr += sizeof(*tlv);
1274	ptr += chan_len;
1275
1276	tlv = ptr;
1277	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
1278	tlv->len = __cpu_to_le16(ssid_len);
1279	ssids = (void *)tlv->value;
1280	for (i = 0; i < arg->n_ssids; i++) {
1281		ssids[i].ssid_len = __cpu_to_le32(arg->ssids[i].len);
1282		memcpy(ssids[i].ssid, arg->ssids[i].ssid, arg->ssids[i].len);
1283	}
1284
1285	ptr += sizeof(*tlv);
1286	ptr += ssid_len;
1287
1288	tlv = ptr;
1289	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
1290	tlv->len = __cpu_to_le16(bssid_len);
1291	addrs = (void *)tlv->value;
1292	for (i = 0; i < arg->n_bssids; i++)
1293		ether_addr_copy(addrs[i].addr, arg->bssids[i].bssid);
1294
1295	ptr += sizeof(*tlv);
1296	ptr += bssid_len;
1297
1298	tlv = ptr;
1299	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
1300	tlv->len = __cpu_to_le16(ie_len);
1301	memcpy(tlv->value, arg->ie, arg->ie_len);
1302
1303	ptr += sizeof(*tlv);
1304	ptr += ie_len;
1305
1306	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start scan\n");
1307	return skb;
1308}
1309
1310static struct sk_buff *
1311ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar,
1312				const struct wmi_stop_scan_arg *arg)
1313{
1314	struct wmi_stop_scan_cmd *cmd;
1315	struct wmi_tlv *tlv;
1316	struct sk_buff *skb;
1317	u32 scan_id;
1318	u32 req_id;
1319
1320	if (arg->req_id > 0xFFF)
1321		return ERR_PTR(-EINVAL);
1322	if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
1323		return ERR_PTR(-EINVAL);
1324
1325	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1326	if (!skb)
1327		return ERR_PTR(-ENOMEM);
1328
1329	scan_id = arg->u.scan_id;
1330	scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
1331
1332	req_id = arg->req_id;
1333	req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
1334
1335	tlv = (void *)skb->data;
1336	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD);
1337	tlv->len = __cpu_to_le16(sizeof(*cmd));
1338	cmd = (void *)tlv->value;
1339	cmd->req_type = __cpu_to_le32(arg->req_type);
1340	cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id);
1341	cmd->scan_id = __cpu_to_le32(scan_id);
1342	cmd->scan_req_id = __cpu_to_le32(req_id);
1343
1344	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop scan\n");
1345	return skb;
1346}
1347
1348static struct sk_buff *
1349ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar,
1350				  u32 vdev_id,
1351				  enum wmi_vdev_type vdev_type,
1352				  enum wmi_vdev_subtype vdev_subtype,
1353				  const u8 mac_addr[ETH_ALEN])
1354{
1355	struct wmi_vdev_create_cmd *cmd;
1356	struct wmi_tlv *tlv;
1357	struct sk_buff *skb;
1358
1359	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1360	if (!skb)
1361		return ERR_PTR(-ENOMEM);
1362
1363	tlv = (void *)skb->data;
1364	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD);
1365	tlv->len = __cpu_to_le16(sizeof(*cmd));
1366	cmd = (void *)tlv->value;
1367	cmd->vdev_id = __cpu_to_le32(vdev_id);
1368	cmd->vdev_type = __cpu_to_le32(vdev_type);
1369	cmd->vdev_subtype = __cpu_to_le32(vdev_subtype);
1370	ether_addr_copy(cmd->vdev_macaddr.addr, mac_addr);
1371
1372	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev create\n");
1373	return skb;
1374}
1375
1376static struct sk_buff *
1377ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
1378{
1379	struct wmi_vdev_delete_cmd *cmd;
1380	struct wmi_tlv *tlv;
1381	struct sk_buff *skb;
1382
1383	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1384	if (!skb)
1385		return ERR_PTR(-ENOMEM);
1386
1387	tlv = (void *)skb->data;
1388	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD);
1389	tlv->len = __cpu_to_le16(sizeof(*cmd));
1390	cmd = (void *)tlv->value;
1391	cmd->vdev_id = __cpu_to_le32(vdev_id);
1392
1393	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev delete\n");
1394	return skb;
1395}
1396
1397static struct sk_buff *
1398ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
1399				 const struct wmi_vdev_start_request_arg *arg,
1400				 bool restart)
1401{
1402	struct wmi_tlv_vdev_start_cmd *cmd;
1403	struct wmi_channel *ch;
1404	struct wmi_p2p_noa_descriptor *noa;
1405	struct wmi_tlv *tlv;
1406	struct sk_buff *skb;
1407	size_t len;
1408	void *ptr;
1409	u32 flags = 0;
1410
1411	if (WARN_ON(arg->ssid && arg->ssid_len == 0))
1412		return ERR_PTR(-EINVAL);
1413	if (WARN_ON(arg->hidden_ssid && !arg->ssid))
1414		return ERR_PTR(-EINVAL);
1415	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
1416		return ERR_PTR(-EINVAL);
1417
1418	len = (sizeof(*tlv) + sizeof(*cmd)) +
1419	      (sizeof(*tlv) + sizeof(*ch)) +
1420	      (sizeof(*tlv) + 0);
1421	skb = ath10k_wmi_alloc_skb(ar, len);
1422	if (!skb)
1423		return ERR_PTR(-ENOMEM);
1424
1425	if (arg->hidden_ssid)
1426		flags |= WMI_VDEV_START_HIDDEN_SSID;
1427	if (arg->pmf_enabled)
1428		flags |= WMI_VDEV_START_PMF_ENABLED;
1429
1430	ptr = (void *)skb->data;
1431
1432	tlv = ptr;
1433	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD);
1434	tlv->len = __cpu_to_le16(sizeof(*cmd));
1435	cmd = (void *)tlv->value;
1436	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
1437	cmd->bcn_intval = __cpu_to_le32(arg->bcn_intval);
1438	cmd->dtim_period = __cpu_to_le32(arg->dtim_period);
1439	cmd->flags = __cpu_to_le32(flags);
1440	cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate);
1441	cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power);
1442	cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack);
1443
1444	if (arg->ssid) {
1445		cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len);
1446		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
1447	}
1448
1449	ptr += sizeof(*tlv);
1450	ptr += sizeof(*cmd);
1451
1452	tlv = ptr;
1453	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
1454	tlv->len = __cpu_to_le16(sizeof(*ch));
1455	ch = (void *)tlv->value;
1456	ath10k_wmi_put_wmi_channel(ch, &arg->channel);
1457
1458	ptr += sizeof(*tlv);
1459	ptr += sizeof(*ch);
1460
1461	tlv = ptr;
1462	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
1463	tlv->len = 0;
1464	noa = (void *)tlv->value;
1465
1466	/* Note: This is a nested TLV containing:
1467	 * [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
1468	 */
1469
1470	ptr += sizeof(*tlv);
1471	ptr += 0;
1472
1473	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev start\n");
1474	return skb;
1475}
1476
1477static struct sk_buff *
1478ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
1479{
1480	struct wmi_vdev_stop_cmd *cmd;
1481	struct wmi_tlv *tlv;
1482	struct sk_buff *skb;
1483
1484	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1485	if (!skb)
1486		return ERR_PTR(-ENOMEM);
1487
1488	tlv = (void *)skb->data;
1489	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD);
1490	tlv->len = __cpu_to_le16(sizeof(*cmd));
1491	cmd = (void *)tlv->value;
1492	cmd->vdev_id = __cpu_to_le32(vdev_id);
1493
1494	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev stop\n");
1495	return skb;
1496}
1497
1498static struct sk_buff *
1499ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
1500			      const u8 *bssid)
1501
1502{
1503	struct wmi_vdev_up_cmd *cmd;
1504	struct wmi_tlv *tlv;
1505	struct sk_buff *skb;
1506
1507	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1508	if (!skb)
1509		return ERR_PTR(-ENOMEM);
1510
1511	tlv = (void *)skb->data;
1512	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_UP_CMD);
1513	tlv->len = __cpu_to_le16(sizeof(*cmd));
1514	cmd = (void *)tlv->value;
1515	cmd->vdev_id = __cpu_to_le32(vdev_id);
1516	cmd->vdev_assoc_id = __cpu_to_le32(aid);
1517	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
1518
1519	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev up\n");
1520	return skb;
1521}
1522
1523static struct sk_buff *
1524ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
1525{
1526	struct wmi_vdev_down_cmd *cmd;
1527	struct wmi_tlv *tlv;
1528	struct sk_buff *skb;
1529
1530	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1531	if (!skb)
1532		return ERR_PTR(-ENOMEM);
1533
1534	tlv = (void *)skb->data;
1535	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD);
1536	tlv->len = __cpu_to_le16(sizeof(*cmd));
1537	cmd = (void *)tlv->value;
1538	cmd->vdev_id = __cpu_to_le32(vdev_id);
1539
1540	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev down\n");
1541	return skb;
1542}
1543
1544static struct sk_buff *
1545ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
1546				     u32 param_id, u32 param_value)
1547{
1548	struct wmi_vdev_set_param_cmd *cmd;
1549	struct wmi_tlv *tlv;
1550	struct sk_buff *skb;
1551
1552	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1553	if (!skb)
1554		return ERR_PTR(-ENOMEM);
1555
1556	tlv = (void *)skb->data;
1557	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD);
1558	tlv->len = __cpu_to_le16(sizeof(*cmd));
1559	cmd = (void *)tlv->value;
1560	cmd->vdev_id = __cpu_to_le32(vdev_id);
1561	cmd->param_id = __cpu_to_le32(param_id);
1562	cmd->param_value = __cpu_to_le32(param_value);
1563
1564	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n");
1565	return skb;
1566}
1567
1568static struct sk_buff *
1569ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
1570				       const struct wmi_vdev_install_key_arg *arg)
1571{
1572	struct wmi_vdev_install_key_cmd *cmd;
1573	struct wmi_tlv *tlv;
1574	struct sk_buff *skb;
1575	size_t len;
1576	void *ptr;
1577
1578	if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL)
1579		return ERR_PTR(-EINVAL);
1580	if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL)
1581		return ERR_PTR(-EINVAL);
1582
1583	len = sizeof(*tlv) + sizeof(*cmd) +
1584	      sizeof(*tlv) + roundup(arg->key_len, sizeof(__le32));
1585	skb = ath10k_wmi_alloc_skb(ar, len);
1586	if (!skb)
1587		return ERR_PTR(-ENOMEM);
1588
1589	ptr = (void *)skb->data;
1590	tlv = ptr;
1591	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD);
1592	tlv->len = __cpu_to_le16(sizeof(*cmd));
1593	cmd = (void *)tlv->value;
1594	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
1595	cmd->key_idx = __cpu_to_le32(arg->key_idx);
1596	cmd->key_flags = __cpu_to_le32(arg->key_flags);
1597	cmd->key_cipher = __cpu_to_le32(arg->key_cipher);
1598	cmd->key_len = __cpu_to_le32(arg->key_len);
1599	cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len);
1600	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
1601
1602	if (arg->macaddr)
1603		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
1604
1605	ptr += sizeof(*tlv);
1606	ptr += sizeof(*cmd);
1607
1608	tlv = ptr;
1609	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
1610	tlv->len = __cpu_to_le16(roundup(arg->key_len, sizeof(__le32)));
1611	if (arg->key_data)
1612		memcpy(tlv->value, arg->key_data, arg->key_len);
1613
1614	ptr += sizeof(*tlv);
1615	ptr += roundup(arg->key_len, sizeof(__le32));
1616
1617	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev install key\n");
1618	return skb;
1619}
1620
1621static void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr,
1622					 const struct wmi_sta_uapsd_auto_trig_arg *arg)
1623{
1624	struct wmi_sta_uapsd_auto_trig_param *ac;
1625	struct wmi_tlv *tlv;
1626
1627	tlv = ptr;
1628	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM);
1629	tlv->len = __cpu_to_le16(sizeof(*ac));
1630	ac = (void *)tlv->value;
1631
1632	ac->wmm_ac = __cpu_to_le32(arg->wmm_ac);
1633	ac->user_priority = __cpu_to_le32(arg->user_priority);
1634	ac->service_interval = __cpu_to_le32(arg->service_interval);
1635	ac->suspend_interval = __cpu_to_le32(arg->suspend_interval);
1636	ac->delay_interval = __cpu_to_le32(arg->delay_interval);
1637
1638	ath10k_dbg(ar, ATH10K_DBG_WMI,
1639		   "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n",
1640		   ac->wmm_ac, ac->user_priority, ac->service_interval,
1641		   ac->suspend_interval, ac->delay_interval);
1642
1643	return ptr + sizeof(*tlv) + sizeof(*ac);
1644}
1645
1646static struct sk_buff *
1647ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id,
1648				     const u8 peer_addr[ETH_ALEN],
1649				     const struct wmi_sta_uapsd_auto_trig_arg *args,
1650				     u32 num_ac)
1651{
1652	struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd;
1653	struct wmi_sta_uapsd_auto_trig_param *ac;
1654	struct wmi_tlv *tlv;
1655	struct sk_buff *skb;
1656	size_t len;
1657	size_t ac_tlv_len;
1658	void *ptr;
1659	int i;
1660
1661	ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac));
1662	len = sizeof(*tlv) + sizeof(*cmd) +
1663	      sizeof(*tlv) + ac_tlv_len;
1664	skb = ath10k_wmi_alloc_skb(ar, len);
1665	if (!skb)
1666		return ERR_PTR(-ENOMEM);
1667
1668	ptr = (void *)skb->data;
1669	tlv = ptr;
1670	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD);
1671	tlv->len = __cpu_to_le16(sizeof(*cmd));
1672	cmd = (void *)tlv->value;
1673	cmd->vdev_id = __cpu_to_le32(vdev_id);
1674	cmd->num_ac = __cpu_to_le32(num_ac);
1675	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
1676
1677	ptr += sizeof(*tlv);
1678	ptr += sizeof(*cmd);
1679
1680	tlv = ptr;
1681	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
1682	tlv->len = __cpu_to_le16(ac_tlv_len);
1683	ac = (void *)tlv->value;
1684
1685	ptr += sizeof(*tlv);
1686	for (i = 0; i < num_ac; i++)
1687		ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]);
1688
1689	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n");
1690	return skb;
1691}
1692
1693static void *ath10k_wmi_tlv_put_wmm(void *ptr,
1694				    const struct wmi_wmm_params_arg *arg)
1695{
1696	struct wmi_wmm_params *wmm;
1697	struct wmi_tlv *tlv;
1698
1699	tlv = ptr;
1700	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS);
1701	tlv->len = __cpu_to_le16(sizeof(*wmm));
1702	wmm = (void *)tlv->value;
1703	ath10k_wmi_set_wmm_param(wmm, arg);
1704
1705	return ptr + sizeof(*tlv) + sizeof(*wmm);
1706}
1707
1708static struct sk_buff *
1709ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
1710				    const struct wmi_wmm_params_all_arg *arg)
1711{
1712	struct wmi_tlv_vdev_set_wmm_cmd *cmd;
1713	struct wmi_tlv *tlv;
1714	struct sk_buff *skb;
1715	size_t len;
1716	void *ptr;
1717
1718	len = sizeof(*tlv) + sizeof(*cmd);
1719	skb = ath10k_wmi_alloc_skb(ar, len);
1720	if (!skb)
1721		return ERR_PTR(-ENOMEM);
1722
1723	ptr = (void *)skb->data;
1724	tlv = ptr;
1725	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD);
1726	tlv->len = __cpu_to_le16(sizeof(*cmd));
1727	cmd = (void *)tlv->value;
1728	cmd->vdev_id = __cpu_to_le32(vdev_id);
1729
1730	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[0].params, &arg->ac_be);
1731	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[1].params, &arg->ac_bk);
1732	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[2].params, &arg->ac_vi);
1733	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[3].params, &arg->ac_vo);
1734
1735	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n");
1736	return skb;
1737}
1738
1739static struct sk_buff *
1740ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar,
1741				    const struct wmi_sta_keepalive_arg *arg)
1742{
1743	struct wmi_tlv_sta_keepalive_cmd *cmd;
1744	struct wmi_sta_keepalive_arp_resp *arp;
1745	struct sk_buff *skb;
1746	struct wmi_tlv *tlv;
1747	void *ptr;
1748	size_t len;
1749
1750	len = sizeof(*tlv) + sizeof(*cmd) +
1751	      sizeof(*tlv) + sizeof(*arp);
1752	skb = ath10k_wmi_alloc_skb(ar, len);
1753	if (!skb)
1754		return ERR_PTR(-ENOMEM);
1755
1756	ptr = (void *)skb->data;
1757	tlv = ptr;
1758	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD);
1759	tlv->len = __cpu_to_le16(sizeof(*cmd));
1760	cmd = (void *)tlv->value;
1761	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
1762	cmd->enabled = __cpu_to_le32(arg->enabled);
1763	cmd->method = __cpu_to_le32(arg->method);
1764	cmd->interval = __cpu_to_le32(arg->interval);
1765
1766	ptr += sizeof(*tlv);
1767	ptr += sizeof(*cmd);
1768
1769	tlv = ptr;
1770	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE);
1771	tlv->len = __cpu_to_le16(sizeof(*arp));
1772	arp = (void *)tlv->value;
1773
1774	arp->src_ip4_addr = arg->src_ip4_addr;
1775	arp->dest_ip4_addr = arg->dest_ip4_addr;
1776	ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
1777
1778	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d inverval %d\n",
1779		   arg->vdev_id, arg->enabled, arg->method, arg->interval);
1780	return skb;
1781}
1782
1783static struct sk_buff *
1784ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
1785				  const u8 peer_addr[ETH_ALEN])
1786{
1787	struct wmi_tlv_peer_create_cmd *cmd;
1788	struct wmi_tlv *tlv;
1789	struct sk_buff *skb;
1790
1791	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1792	if (!skb)
1793		return ERR_PTR(-ENOMEM);
1794
1795	tlv = (void *)skb->data;
1796	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD);
1797	tlv->len = __cpu_to_le16(sizeof(*cmd));
1798	cmd = (void *)tlv->value;
1799	cmd->vdev_id = __cpu_to_le32(vdev_id);
1800	cmd->peer_type = __cpu_to_le32(WMI_TLV_PEER_TYPE_DEFAULT); /* FIXME */
1801	ether_addr_copy(cmd->peer_addr.addr, peer_addr);
1802
1803	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer create\n");
1804	return skb;
1805}
1806
1807static struct sk_buff *
1808ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
1809				  const u8 peer_addr[ETH_ALEN])
1810{
1811	struct wmi_peer_delete_cmd *cmd;
1812	struct wmi_tlv *tlv;
1813	struct sk_buff *skb;
1814
1815	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1816	if (!skb)
1817		return ERR_PTR(-ENOMEM);
1818
1819	tlv = (void *)skb->data;
1820	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD);
1821	tlv->len = __cpu_to_le16(sizeof(*cmd));
1822	cmd = (void *)tlv->value;
1823	cmd->vdev_id = __cpu_to_le32(vdev_id);
1824	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
1825
1826	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete\n");
1827	return skb;
1828}
1829
1830static struct sk_buff *
1831ath10k_wmi_tlv_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
1832				 const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
1833{
1834	struct wmi_peer_flush_tids_cmd *cmd;
1835	struct wmi_tlv *tlv;
1836	struct sk_buff *skb;
1837
1838	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1839	if (!skb)
1840		return ERR_PTR(-ENOMEM);
1841
1842	tlv = (void *)skb->data;
1843	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD);
1844	tlv->len = __cpu_to_le16(sizeof(*cmd));
1845	cmd = (void *)tlv->value;
1846	cmd->vdev_id = __cpu_to_le32(vdev_id);
1847	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
1848	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
1849
1850	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer flush\n");
1851	return skb;
1852}
1853
1854static struct sk_buff *
1855ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
1856				     const u8 *peer_addr,
1857				     enum wmi_peer_param param_id,
1858				     u32 param_value)
1859{
1860	struct wmi_peer_set_param_cmd *cmd;
1861	struct wmi_tlv *tlv;
1862	struct sk_buff *skb;
1863
1864	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1865	if (!skb)
1866		return ERR_PTR(-ENOMEM);
1867
1868	tlv = (void *)skb->data;
1869	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD);
1870	tlv->len = __cpu_to_le16(sizeof(*cmd));
1871	cmd = (void *)tlv->value;
1872	cmd->vdev_id = __cpu_to_le32(vdev_id);
1873	cmd->param_id = __cpu_to_le32(param_id);
1874	cmd->param_value = __cpu_to_le32(param_value);
1875	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
1876
1877	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n");
1878	return skb;
1879}
1880
1881static struct sk_buff *
1882ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k *ar,
1883				 const struct wmi_peer_assoc_complete_arg *arg)
1884{
1885	struct wmi_tlv_peer_assoc_cmd *cmd;
1886	struct wmi_vht_rate_set *vht_rate;
1887	struct wmi_tlv *tlv;
1888	struct sk_buff *skb;
1889	size_t len, legacy_rate_len, ht_rate_len;
1890	void *ptr;
1891
1892	if (arg->peer_mpdu_density > 16)
1893		return ERR_PTR(-EINVAL);
1894	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
1895		return ERR_PTR(-EINVAL);
1896	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
1897		return ERR_PTR(-EINVAL);
1898
1899	legacy_rate_len = roundup(arg->peer_legacy_rates.num_rates,
1900				  sizeof(__le32));
1901	ht_rate_len = roundup(arg->peer_ht_rates.num_rates, sizeof(__le32));
1902	len = (sizeof(*tlv) + sizeof(*cmd)) +
1903	      (sizeof(*tlv) + legacy_rate_len) +
1904	      (sizeof(*tlv) + ht_rate_len) +
1905	      (sizeof(*tlv) + sizeof(*vht_rate));
1906	skb = ath10k_wmi_alloc_skb(ar, len);
1907	if (!skb)
1908		return ERR_PTR(-ENOMEM);
1909
1910	ptr = (void *)skb->data;
1911	tlv = ptr;
1912	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD);
1913	tlv->len = __cpu_to_le16(sizeof(*cmd));
1914	cmd = (void *)tlv->value;
1915
1916	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
1917	cmd->new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
1918	cmd->assoc_id = __cpu_to_le32(arg->peer_aid);
1919	cmd->flags = __cpu_to_le32(arg->peer_flags);
1920	cmd->caps = __cpu_to_le32(arg->peer_caps);
1921	cmd->listen_intval = __cpu_to_le32(arg->peer_listen_intval);
1922	cmd->ht_caps = __cpu_to_le32(arg->peer_ht_caps);
1923	cmd->max_mpdu = __cpu_to_le32(arg->peer_max_mpdu);
1924	cmd->mpdu_density = __cpu_to_le32(arg->peer_mpdu_density);
1925	cmd->rate_caps = __cpu_to_le32(arg->peer_rate_caps);
1926	cmd->nss = __cpu_to_le32(arg->peer_num_spatial_streams);
1927	cmd->vht_caps = __cpu_to_le32(arg->peer_vht_caps);
1928	cmd->phy_mode = __cpu_to_le32(arg->peer_phymode);
1929	cmd->num_legacy_rates = __cpu_to_le32(arg->peer_legacy_rates.num_rates);
1930	cmd->num_ht_rates = __cpu_to_le32(arg->peer_ht_rates.num_rates);
1931	ether_addr_copy(cmd->mac_addr.addr, arg->addr);
1932
1933	ptr += sizeof(*tlv);
1934	ptr += sizeof(*cmd);
1935
1936	tlv = ptr;
1937	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
1938	tlv->len = __cpu_to_le16(legacy_rate_len);
1939	memcpy(tlv->value, arg->peer_legacy_rates.rates,
1940	       arg->peer_legacy_rates.num_rates);
1941
1942	ptr += sizeof(*tlv);
1943	ptr += legacy_rate_len;
1944
1945	tlv = ptr;
1946	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
1947	tlv->len = __cpu_to_le16(ht_rate_len);
1948	memcpy(tlv->value, arg->peer_ht_rates.rates,
1949	       arg->peer_ht_rates.num_rates);
1950
1951	ptr += sizeof(*tlv);
1952	ptr += ht_rate_len;
1953
1954	tlv = ptr;
1955	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VHT_RATE_SET);
1956	tlv->len = __cpu_to_le16(sizeof(*vht_rate));
1957	vht_rate = (void *)tlv->value;
1958
1959	vht_rate->rx_max_rate = __cpu_to_le32(arg->peer_vht_rates.rx_max_rate);
1960	vht_rate->rx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set);
1961	vht_rate->tx_max_rate = __cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
1962	vht_rate->tx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
1963
1964	ptr += sizeof(*tlv);
1965	ptr += sizeof(*vht_rate);
1966
1967	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer assoc\n");
1968	return skb;
1969}
1970
1971static struct sk_buff *
1972ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
1973				 enum wmi_sta_ps_mode psmode)
1974{
1975	struct wmi_sta_powersave_mode_cmd *cmd;
1976	struct wmi_tlv *tlv;
1977	struct sk_buff *skb;
1978
1979	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
1980	if (!skb)
1981		return ERR_PTR(-ENOMEM);
1982
1983	tlv = (void *)skb->data;
1984	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD);
1985	tlv->len = __cpu_to_le16(sizeof(*cmd));
1986	cmd = (void *)tlv->value;
1987	cmd->vdev_id = __cpu_to_le32(vdev_id);
1988	cmd->sta_ps_mode = __cpu_to_le32(psmode);
1989
1990	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set psmode\n");
1991	return skb;
1992}
1993
1994static struct sk_buff *
1995ath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
1996				 enum wmi_sta_powersave_param param_id,
1997				 u32 param_value)
1998{
1999	struct wmi_sta_powersave_param_cmd *cmd;
2000	struct wmi_tlv *tlv;
2001	struct sk_buff *skb;
2002
2003	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2004	if (!skb)
2005		return ERR_PTR(-ENOMEM);
2006
2007	tlv = (void *)skb->data;
2008	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD);
2009	tlv->len = __cpu_to_le16(sizeof(*cmd));
2010	cmd = (void *)tlv->value;
2011	cmd->vdev_id = __cpu_to_le32(vdev_id);
2012	cmd->param_id = __cpu_to_le32(param_id);
2013	cmd->param_value = __cpu_to_le32(param_value);
2014
2015	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set sta ps\n");
2016	return skb;
2017}
2018
2019static struct sk_buff *
2020ath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
2021				enum wmi_ap_ps_peer_param param_id, u32 value)
2022{
2023	struct wmi_ap_ps_peer_cmd *cmd;
2024	struct wmi_tlv *tlv;
2025	struct sk_buff *skb;
2026
2027	if (!mac)
2028		return ERR_PTR(-EINVAL);
2029
2030	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
2031	if (!skb)
2032		return ERR_PTR(-ENOMEM);
2033
2034	tlv = (void *)skb->data;
2035	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD);
2036	tlv->len = __cpu_to_le16(sizeof(*cmd));
2037	cmd = (void *)tlv->value;
2038	cmd->vdev_id = __cpu_to_le32(vdev_id);
2039	cmd->param_id = __cpu_to_le32(param_id);
2040	cmd->param_value = __cpu_to_le32(value);
2041	ether_addr_copy(cmd->peer_macaddr.addr, mac);
2042
2043	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv ap ps param\n");
2044	return skb;
2045}
2046
2047static struct sk_buff *
2048ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
2049				     const struct wmi_scan_chan_list_arg *arg)
2050{
2051	struct wmi_tlv_scan_chan_list_cmd *cmd;
2052	struct wmi_channel *ci;
2053	struct wmi_channel_arg *ch;
2054	struct wmi_tlv *tlv;
2055	struct sk_buff *skb;
2056	size_t chans_len, len;
2057	int i;
2058	void *ptr, *chans;
2059
2060	chans_len = arg->n_channels * (sizeof(*tlv) + sizeof(*ci));
2061	len = (sizeof(*tlv) + sizeof(*cmd)) +
2062	      (sizeof(*tlv) + chans_len);
2063
2064	skb = ath10k_wmi_alloc_skb(ar, len);
2065	if (!skb)
2066		return ERR_PTR(-ENOMEM);
2067
2068	ptr = (void *)skb->data;
2069	tlv = ptr;
2070	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD);
2071	tlv->len = __cpu_to_le16(sizeof(*cmd));
2072	cmd = (void *)tlv->value;
2073	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
2074
2075	ptr += sizeof(*tlv);
2076	ptr += sizeof(*cmd);
2077
2078	tlv = ptr;
2079	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
2080	tlv->len = __cpu_to_le16(chans_len);
2081	chans = (void *)tlv->value;
2082
2083	for (i = 0; i < arg->n_channels; i++) {
2084		ch = &arg->channels[i];
2085
2086		tlv = chans;
2087		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
2088		tlv->len = __cpu_to_le16(sizeof(*ci));
2089		ci = (void *)tlv->value;
2090
2091		ath10k_wmi_put_wmi_channel(ci, ch);
2092
2093		chans += sizeof(*tlv);
2094		chans += sizeof(*ci);
2095	}
2096
2097	ptr += sizeof(*tlv);
2098	ptr += chans_len;
2099
2100	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan chan list\n");
2101	return skb;
2102}
2103
2104static struct sk_buff *
2105ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
2106				 const void *bcn, size_t bcn_len,
2107				 u32 bcn_paddr, bool dtim_zero,
2108				 bool deliver_cab)
2109
2110{
2111	struct wmi_bcn_tx_ref_cmd *cmd;
2112	struct wmi_tlv *tlv;
2113	struct sk_buff *skb;
2114	struct ieee80211_hdr *hdr;
2115	u16 fc;
2116
2117	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2118	if (!skb)
2119		return ERR_PTR(-ENOMEM);
2120
2121	hdr = (struct ieee80211_hdr *)bcn;
2122	fc = le16_to_cpu(hdr->frame_control);
2123
2124	tlv = (void *)skb->data;
2125	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD);
2126	tlv->len = __cpu_to_le16(sizeof(*cmd));
2127	cmd = (void *)tlv->value;
2128	cmd->vdev_id = __cpu_to_le32(vdev_id);
2129	cmd->data_len = __cpu_to_le32(bcn_len);
2130	cmd->data_ptr = __cpu_to_le32(bcn_paddr);
2131	cmd->msdu_id = 0;
2132	cmd->frame_control = __cpu_to_le32(fc);
2133	cmd->flags = 0;
2134
2135	if (dtim_zero)
2136		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
2137
2138	if (deliver_cab)
2139		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
2140
2141	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n");
2142	return skb;
2143}
2144
2145static struct sk_buff *
2146ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
2147				   const struct wmi_wmm_params_all_arg *arg)
2148{
2149	struct wmi_tlv_pdev_set_wmm_cmd *cmd;
2150	struct wmi_wmm_params *wmm;
2151	struct wmi_tlv *tlv;
2152	struct sk_buff *skb;
2153	size_t len;
2154	void *ptr;
2155
2156	len = (sizeof(*tlv) + sizeof(*cmd)) +
2157	      (4 * (sizeof(*tlv) + sizeof(*wmm)));
2158	skb = ath10k_wmi_alloc_skb(ar, len);
2159	if (!skb)
2160		return ERR_PTR(-ENOMEM);
2161
2162	ptr = (void *)skb->data;
2163
2164	tlv = ptr;
2165	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD);
2166	tlv->len = __cpu_to_le16(sizeof(*cmd));
2167	cmd = (void *)tlv->value;
2168
2169	/* nothing to set here */
2170
2171	ptr += sizeof(*tlv);
2172	ptr += sizeof(*cmd);
2173
2174	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be);
2175	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk);
2176	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi);
2177	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo);
2178
2179	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set wmm\n");
2180	return skb;
2181}
2182
2183static struct sk_buff *
2184ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
2185{
2186	struct wmi_request_stats_cmd *cmd;
2187	struct wmi_tlv *tlv;
2188	struct sk_buff *skb;
2189
2190	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2191	if (!skb)
2192		return ERR_PTR(-ENOMEM);
2193
2194	tlv = (void *)skb->data;
2195	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
2196	tlv->len = __cpu_to_le16(sizeof(*cmd));
2197	cmd = (void *)tlv->value;
2198	cmd->stats_id = __cpu_to_le32(stats_mask);
2199
2200	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
2201	return skb;
2202}
2203
2204static struct sk_buff *
2205ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
2206				    enum wmi_force_fw_hang_type type,
2207				    u32 delay_ms)
2208{
2209	struct wmi_force_fw_hang_cmd *cmd;
2210	struct wmi_tlv *tlv;
2211	struct sk_buff *skb;
2212
2213	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
2214	if (!skb)
2215		return ERR_PTR(-ENOMEM);
2216
2217	tlv = (void *)skb->data;
2218	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD);
2219	tlv->len = __cpu_to_le16(sizeof(*cmd));
2220	cmd = (void *)tlv->value;
2221	cmd->type = __cpu_to_le32(type);
2222	cmd->delay_ms = __cpu_to_le32(delay_ms);
2223
2224	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv force fw hang\n");
2225	return skb;
2226}
2227
2228static struct sk_buff *
2229ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable,
2230				 u32 log_level) {
2231	struct wmi_tlv_dbglog_cmd *cmd;
2232	struct wmi_tlv *tlv;
2233	struct sk_buff *skb;
2234	size_t len, bmap_len;
2235	u32 value;
2236	void *ptr;
2237
2238	if (module_enable) {
2239		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
2240				module_enable,
2241				WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE);
2242	} else {
2243		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
2244				WMI_TLV_DBGLOG_ALL_MODULES,
2245				WMI_TLV_DBGLOG_LOG_LEVEL_WARN);
2246	}
2247
2248	bmap_len = 0;
2249	len = sizeof(*tlv) + sizeof(*cmd) + sizeof(*tlv) + bmap_len;
2250	skb = ath10k_wmi_alloc_skb(ar, len);
2251	if (!skb)
2252		return ERR_PTR(-ENOMEM);
2253
2254	ptr = (void *)skb->data;
2255
2256	tlv = ptr;
2257	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD);
2258	tlv->len = __cpu_to_le16(sizeof(*cmd));
2259	cmd = (void *)tlv->value;
2260	cmd->param = __cpu_to_le32(WMI_TLV_DBGLOG_PARAM_LOG_LEVEL);
2261	cmd->value = __cpu_to_le32(value);
2262
2263	ptr += sizeof(*tlv);
2264	ptr += sizeof(*cmd);
2265
2266	tlv = ptr;
2267	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
2268	tlv->len = __cpu_to_le16(bmap_len);
2269
2270	/* nothing to do here */
2271
2272	ptr += sizeof(*tlv);
2273	ptr += sizeof(bmap_len);
2274
2275	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv dbglog value 0x%08x\n", value);
2276	return skb;
2277}
2278
2279static struct sk_buff *
2280ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
2281{
2282	struct wmi_tlv_pktlog_enable *cmd;
2283	struct wmi_tlv *tlv;
2284	struct sk_buff *skb;
2285	void *ptr;
2286	size_t len;
2287
2288	len = sizeof(*tlv) + sizeof(*cmd);
2289	skb = ath10k_wmi_alloc_skb(ar, len);
2290	if (!skb)
2291		return ERR_PTR(-ENOMEM);
2292
2293	ptr = (void *)skb->data;
2294	tlv = ptr;
2295	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD);
2296	tlv->len = __cpu_to_le16(sizeof(*cmd));
2297	cmd = (void *)tlv->value;
2298	cmd->filter = __cpu_to_le32(filter);
2299
2300	ptr += sizeof(*tlv);
2301	ptr += sizeof(*cmd);
2302
2303	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog enable filter 0x%08x\n",
2304		   filter);
2305	return skb;
2306}
2307
2308static struct sk_buff *
2309ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar)
2310{
2311	struct wmi_tlv_pktlog_disable *cmd;
2312	struct wmi_tlv *tlv;
2313	struct sk_buff *skb;
2314	void *ptr;
2315	size_t len;
2316
2317	len = sizeof(*tlv) + sizeof(*cmd);
2318	skb = ath10k_wmi_alloc_skb(ar, len);
2319	if (!skb)
2320		return ERR_PTR(-ENOMEM);
2321
2322	ptr = (void *)skb->data;
2323	tlv = ptr;
2324	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD);
2325	tlv->len = __cpu_to_le16(sizeof(*cmd));
2326	cmd = (void *)tlv->value;
2327
2328	ptr += sizeof(*tlv);
2329	ptr += sizeof(*cmd);
2330
2331	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog disable\n");
2332	return skb;
2333}
2334
2335static struct sk_buff *
2336ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id,
2337			       u32 tim_ie_offset, struct sk_buff *bcn,
2338			       u32 prb_caps, u32 prb_erp, void *prb_ies,
2339			       size_t prb_ies_len)
2340{
2341	struct wmi_tlv_bcn_tmpl_cmd *cmd;
2342	struct wmi_tlv_bcn_prb_info *info;
2343	struct wmi_tlv *tlv;
2344	struct sk_buff *skb;
2345	void *ptr;
2346	size_t len;
2347
2348	if (WARN_ON(prb_ies_len > 0 && !prb_ies))
2349		return ERR_PTR(-EINVAL);
2350
2351	len = sizeof(*tlv) + sizeof(*cmd) +
2352	      sizeof(*tlv) + sizeof(*info) + prb_ies_len +
2353	      sizeof(*tlv) + roundup(bcn->len, 4);
2354	skb = ath10k_wmi_alloc_skb(ar, len);
2355	if (!skb)
2356		return ERR_PTR(-ENOMEM);
2357
2358	ptr = (void *)skb->data;
2359	tlv = ptr;
2360	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD);
2361	tlv->len = __cpu_to_le16(sizeof(*cmd));
2362	cmd = (void *)tlv->value;
2363	cmd->vdev_id = __cpu_to_le32(vdev_id);
2364	cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset);
2365	cmd->buf_len = __cpu_to_le32(bcn->len);
2366
2367	ptr += sizeof(*tlv);
2368	ptr += sizeof(*cmd);
2369
2370	/* FIXME: prb_ies_len should be probably aligned to 4byte boundary but
2371	 * then it is then impossible to pass original ie len.
2372	 * This chunk is not used yet so if setting probe resp template yields
2373	 * problems with beaconing or crashes firmware look here.
2374	 */
2375	tlv = ptr;
2376	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
2377	tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len);
2378	info = (void *)tlv->value;
2379	info->caps = __cpu_to_le32(prb_caps);
2380	info->erp = __cpu_to_le32(prb_erp);
2381	memcpy(info->ies, prb_ies, prb_ies_len);
2382
2383	ptr += sizeof(*tlv);
2384	ptr += sizeof(*info);
2385	ptr += prb_ies_len;
2386
2387	tlv = ptr;
2388	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2389	tlv->len = __cpu_to_le16(roundup(bcn->len, 4));
2390	memcpy(tlv->value, bcn->data, bcn->len);
2391
2392	/* FIXME: Adjust TSF? */
2393
2394	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n",
2395		   vdev_id);
2396	return skb;
2397}
2398
2399static struct sk_buff *
2400ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id,
2401			       struct sk_buff *prb)
2402{
2403	struct wmi_tlv_prb_tmpl_cmd *cmd;
2404	struct wmi_tlv_bcn_prb_info *info;
2405	struct wmi_tlv *tlv;
2406	struct sk_buff *skb;
2407	void *ptr;
2408	size_t len;
2409
2410	len = sizeof(*tlv) + sizeof(*cmd) +
2411	      sizeof(*tlv) + sizeof(*info) +
2412	      sizeof(*tlv) + roundup(prb->len, 4);
2413	skb = ath10k_wmi_alloc_skb(ar, len);
2414	if (!skb)
2415		return ERR_PTR(-ENOMEM);
2416
2417	ptr = (void *)skb->data;
2418	tlv = ptr;
2419	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD);
2420	tlv->len = __cpu_to_le16(sizeof(*cmd));
2421	cmd = (void *)tlv->value;
2422	cmd->vdev_id = __cpu_to_le32(vdev_id);
2423	cmd->buf_len = __cpu_to_le32(prb->len);
2424
2425	ptr += sizeof(*tlv);
2426	ptr += sizeof(*cmd);
2427
2428	tlv = ptr;
2429	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
2430	tlv->len = __cpu_to_le16(sizeof(*info));
2431	info = (void *)tlv->value;
2432	info->caps = 0;
2433	info->erp = 0;
2434
2435	ptr += sizeof(*tlv);
2436	ptr += sizeof(*info);
2437
2438	tlv = ptr;
2439	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2440	tlv->len = __cpu_to_le16(roundup(prb->len, 4));
2441	memcpy(tlv->value, prb->data, prb->len);
2442
2443	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n",
2444		   vdev_id);
2445	return skb;
2446}
2447
2448static struct sk_buff *
2449ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id,
2450				    const u8 *p2p_ie)
2451{
2452	struct wmi_tlv_p2p_go_bcn_ie *cmd;
2453	struct wmi_tlv *tlv;
2454	struct sk_buff *skb;
2455	void *ptr;
2456	size_t len;
2457
2458	len = sizeof(*tlv) + sizeof(*cmd) +
2459	      sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4);
2460	skb = ath10k_wmi_alloc_skb(ar, len);
2461	if (!skb)
2462		return ERR_PTR(-ENOMEM);
2463
2464	ptr = (void *)skb->data;
2465	tlv = ptr;
2466	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE);
2467	tlv->len = __cpu_to_le16(sizeof(*cmd));
2468	cmd = (void *)tlv->value;
2469	cmd->vdev_id = __cpu_to_le32(vdev_id);
2470	cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2);
2471
2472	ptr += sizeof(*tlv);
2473	ptr += sizeof(*cmd);
2474
2475	tlv = ptr;
2476	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
2477	tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4));
2478	memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2);
2479
2480	ptr += sizeof(*tlv);
2481	ptr += roundup(p2p_ie[1] + 2, 4);
2482
2483	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n",
2484		   vdev_id);
2485	return skb;
2486}
2487
2488/****************/
2489/* TLV mappings */
2490/****************/
2491
2492static struct wmi_cmd_map wmi_tlv_cmd_map = {
2493	.init_cmdid = WMI_TLV_INIT_CMDID,
2494	.start_scan_cmdid = WMI_TLV_START_SCAN_CMDID,
2495	.stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
2496	.scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
2497	.scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
2498	.pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
2499	.pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
2500	.pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
2501	.pdev_pktlog_enable_cmdid = WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID,
2502	.pdev_pktlog_disable_cmdid = WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID,
2503	.pdev_set_wmm_params_cmdid = WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID,
2504	.pdev_set_ht_cap_ie_cmdid = WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID,
2505	.pdev_set_vht_cap_ie_cmdid = WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID,
2506	.pdev_set_dscp_tid_map_cmdid = WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID,
2507	.pdev_set_quiet_mode_cmdid = WMI_TLV_PDEV_SET_QUIET_MODE_CMDID,
2508	.pdev_green_ap_ps_enable_cmdid = WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID,
2509	.pdev_get_tpc_config_cmdid = WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID,
2510	.pdev_set_base_macaddr_cmdid = WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID,
2511	.vdev_create_cmdid = WMI_TLV_VDEV_CREATE_CMDID,
2512	.vdev_delete_cmdid = WMI_TLV_VDEV_DELETE_CMDID,
2513	.vdev_start_request_cmdid = WMI_TLV_VDEV_START_REQUEST_CMDID,
2514	.vdev_restart_request_cmdid = WMI_TLV_VDEV_RESTART_REQUEST_CMDID,
2515	.vdev_up_cmdid = WMI_TLV_VDEV_UP_CMDID,
2516	.vdev_stop_cmdid = WMI_TLV_VDEV_STOP_CMDID,
2517	.vdev_down_cmdid = WMI_TLV_VDEV_DOWN_CMDID,
2518	.vdev_set_param_cmdid = WMI_TLV_VDEV_SET_PARAM_CMDID,
2519	.vdev_install_key_cmdid = WMI_TLV_VDEV_INSTALL_KEY_CMDID,
2520	.peer_create_cmdid = WMI_TLV_PEER_CREATE_CMDID,
2521	.peer_delete_cmdid = WMI_TLV_PEER_DELETE_CMDID,
2522	.peer_flush_tids_cmdid = WMI_TLV_PEER_FLUSH_TIDS_CMDID,
2523	.peer_set_param_cmdid = WMI_TLV_PEER_SET_PARAM_CMDID,
2524	.peer_assoc_cmdid = WMI_TLV_PEER_ASSOC_CMDID,
2525	.peer_add_wds_entry_cmdid = WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID,
2526	.peer_remove_wds_entry_cmdid = WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID,
2527	.peer_mcast_group_cmdid = WMI_TLV_PEER_MCAST_GROUP_CMDID,
2528	.bcn_tx_cmdid = WMI_TLV_BCN_TX_CMDID,
2529	.pdev_send_bcn_cmdid = WMI_TLV_PDEV_SEND_BCN_CMDID,
2530	.bcn_tmpl_cmdid = WMI_TLV_BCN_TMPL_CMDID,
2531	.bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID,
2532	.prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
2533	.mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID,
2534	.prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID,
2535	.addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID,
2536	.addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID,
2537	.addba_status_cmdid = WMI_TLV_ADDBA_STATUS_CMDID,
2538	.delba_send_cmdid = WMI_TLV_DELBA_SEND_CMDID,
2539	.addba_set_resp_cmdid = WMI_TLV_ADDBA_SET_RESP_CMDID,
2540	.send_singleamsdu_cmdid = WMI_TLV_SEND_SINGLEAMSDU_CMDID,
2541	.sta_powersave_mode_cmdid = WMI_TLV_STA_POWERSAVE_MODE_CMDID,
2542	.sta_powersave_param_cmdid = WMI_TLV_STA_POWERSAVE_PARAM_CMDID,
2543	.sta_mimo_ps_mode_cmdid = WMI_TLV_STA_MIMO_PS_MODE_CMDID,
2544	.pdev_dfs_enable_cmdid = WMI_TLV_PDEV_DFS_ENABLE_CMDID,
2545	.pdev_dfs_disable_cmdid = WMI_TLV_PDEV_DFS_DISABLE_CMDID,
2546	.roam_scan_mode = WMI_TLV_ROAM_SCAN_MODE,
2547	.roam_scan_rssi_threshold = WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD,
2548	.roam_scan_period = WMI_TLV_ROAM_SCAN_PERIOD,
2549	.roam_scan_rssi_change_threshold =
2550				WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
2551	.roam_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
2552	.ofl_scan_add_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
2553	.ofl_scan_remove_ap_profile = WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE,
2554	.ofl_scan_period = WMI_TLV_OFL_SCAN_PERIOD,
2555	.p2p_dev_set_device_info = WMI_TLV_P2P_DEV_SET_DEVICE_INFO,
2556	.p2p_dev_set_discoverability = WMI_TLV_P2P_DEV_SET_DISCOVERABILITY,
2557	.p2p_go_set_beacon_ie = WMI_TLV_P2P_GO_SET_BEACON_IE,
2558	.p2p_go_set_probe_resp_ie = WMI_TLV_P2P_GO_SET_PROBE_RESP_IE,
2559	.p2p_set_vendor_ie_data_cmdid = WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID,
2560	.ap_ps_peer_param_cmdid = WMI_TLV_AP_PS_PEER_PARAM_CMDID,
2561	.ap_ps_peer_uapsd_coex_cmdid = WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID,
2562	.peer_rate_retry_sched_cmdid = WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID,
2563	.wlan_profile_trigger_cmdid = WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID,
2564	.wlan_profile_set_hist_intvl_cmdid =
2565				WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
2566	.wlan_profile_get_profile_data_cmdid =
2567				WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
2568	.wlan_profile_enable_profile_id_cmdid =
2569				WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
2570	.wlan_profile_list_profile_id_cmdid =
2571				WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
2572	.pdev_suspend_cmdid = WMI_TLV_PDEV_SUSPEND_CMDID,
2573	.pdev_resume_cmdid = WMI_TLV_PDEV_RESUME_CMDID,
2574	.add_bcn_filter_cmdid = WMI_TLV_ADD_BCN_FILTER_CMDID,
2575	.rmv_bcn_filter_cmdid = WMI_TLV_RMV_BCN_FILTER_CMDID,
2576	.wow_add_wake_pattern_cmdid = WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID,
2577	.wow_del_wake_pattern_cmdid = WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID,
2578	.wow_enable_disable_wake_event_cmdid =
2579				WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
2580	.wow_enable_cmdid = WMI_TLV_WOW_ENABLE_CMDID,
2581	.wow_hostwakeup_from_sleep_cmdid =
2582				WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
2583	.rtt_measreq_cmdid = WMI_TLV_RTT_MEASREQ_CMDID,
2584	.rtt_tsf_cmdid = WMI_TLV_RTT_TSF_CMDID,
2585	.vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID,
2586	.vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID,
2587	.request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID,
2588	.set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID,
2589	.network_list_offload_config_cmdid =
2590				WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID,
2591	.gtk_offload_cmdid = WMI_TLV_GTK_OFFLOAD_CMDID,
2592	.csa_offload_enable_cmdid = WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID,
2593	.csa_offload_chanswitch_cmdid = WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID,
2594	.chatter_set_mode_cmdid = WMI_TLV_CHATTER_SET_MODE_CMDID,
2595	.peer_tid_addba_cmdid = WMI_TLV_PEER_TID_ADDBA_CMDID,
2596	.peer_tid_delba_cmdid = WMI_TLV_PEER_TID_DELBA_CMDID,
2597	.sta_dtim_ps_method_cmdid = WMI_TLV_STA_DTIM_PS_METHOD_CMDID,
2598	.sta_uapsd_auto_trig_cmdid = WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID,
2599	.sta_keepalive_cmd = WMI_TLV_STA_KEEPALIVE_CMDID,
2600	.echo_cmdid = WMI_TLV_ECHO_CMDID,
2601	.pdev_utf_cmdid = WMI_TLV_PDEV_UTF_CMDID,
2602	.dbglog_cfg_cmdid = WMI_TLV_DBGLOG_CFG_CMDID,
2603	.pdev_qvit_cmdid = WMI_TLV_PDEV_QVIT_CMDID,
2604	.pdev_ftm_intg_cmdid = WMI_TLV_PDEV_FTM_INTG_CMDID,
2605	.vdev_set_keepalive_cmdid = WMI_TLV_VDEV_SET_KEEPALIVE_CMDID,
2606	.vdev_get_keepalive_cmdid = WMI_TLV_VDEV_GET_KEEPALIVE_CMDID,
2607	.force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID,
2608	.gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID,
2609	.gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID,
2610	.pdev_get_temperature_cmdid = WMI_TLV_CMD_UNSUPPORTED,
2611	.vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
2612};
2613
2614static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
2615	.tx_chain_mask = WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK,
2616	.rx_chain_mask = WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK,
2617	.txpower_limit2g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G,
2618	.txpower_limit5g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G,
2619	.txpower_scale = WMI_TLV_PDEV_PARAM_TXPOWER_SCALE,
2620	.beacon_gen_mode = WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE,
2621	.beacon_tx_mode = WMI_TLV_PDEV_PARAM_BEACON_TX_MODE,
2622	.resmgr_offchan_mode = WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
2623	.protection_mode = WMI_TLV_PDEV_PARAM_PROTECTION_MODE,
2624	.dynamic_bw = WMI_TLV_PDEV_PARAM_DYNAMIC_BW,
2625	.non_agg_sw_retry_th = WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
2626	.agg_sw_retry_th = WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH,
2627	.sta_kickout_th = WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH,
2628	.ac_aggrsize_scaling = WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING,
2629	.ltr_enable = WMI_TLV_PDEV_PARAM_LTR_ENABLE,
2630	.ltr_ac_latency_be = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE,
2631	.ltr_ac_latency_bk = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK,
2632	.ltr_ac_latency_vi = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI,
2633	.ltr_ac_latency_vo = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO,
2634	.ltr_ac_latency_timeout = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
2635	.ltr_sleep_override = WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
2636	.ltr_rx_override = WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE,
2637	.ltr_tx_activity_timeout = WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
2638	.l1ss_enable = WMI_TLV_PDEV_PARAM_L1SS_ENABLE,
2639	.dsleep_enable = WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE,
2640	.pcielp_txbuf_flush = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
2641	.pcielp_txbuf_watermark = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
2642	.pcielp_txbuf_tmo_en = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
2643	.pcielp_txbuf_tmo_value = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
2644	.pdev_stats_update_period = WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
2645	.vdev_stats_update_period = WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
2646	.peer_stats_update_period = WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
2647	.bcnflt_stats_update_period =
2648				WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
2649	.pmf_qos = WMI_TLV_PDEV_PARAM_PMF_QOS,
2650	.arp_ac_override = WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE,
2651	.dcs = WMI_TLV_PDEV_PARAM_DCS,
2652	.ani_enable = WMI_TLV_PDEV_PARAM_ANI_ENABLE,
2653	.ani_poll_period = WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD,
2654	.ani_listen_period = WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD,
2655	.ani_ofdm_level = WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL,
2656	.ani_cck_level = WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL,
2657	.dyntxchain = WMI_TLV_PDEV_PARAM_DYNTXCHAIN,
2658	.proxy_sta = WMI_TLV_PDEV_PARAM_PROXY_STA,
2659	.idle_ps_config = WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG,
2660	.power_gating_sleep = WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP,
2661	.fast_channel_reset = WMI_TLV_PDEV_PARAM_UNSUPPORTED,
2662	.burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR,
2663	.burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE,
2664	.cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
2665};
2666
2667static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
2668	.rts_threshold = WMI_TLV_VDEV_PARAM_RTS_THRESHOLD,
2669	.fragmentation_threshold = WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
2670	.beacon_interval = WMI_TLV_VDEV_PARAM_BEACON_INTERVAL,
2671	.listen_interval = WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL,
2672	.multicast_rate = WMI_TLV_VDEV_PARAM_MULTICAST_RATE,
2673	.mgmt_tx_rate = WMI_TLV_VDEV_PARAM_MGMT_TX_RATE,
2674	.slot_time = WMI_TLV_VDEV_PARAM_SLOT_TIME,
2675	.preamble = WMI_TLV_VDEV_PARAM_PREAMBLE,
2676	.swba_time = WMI_TLV_VDEV_PARAM_SWBA_TIME,
2677	.wmi_vdev_stats_update_period = WMI_TLV_VDEV_STATS_UPDATE_PERIOD,
2678	.wmi_vdev_pwrsave_ageout_time = WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME,
2679	.wmi_vdev_host_swba_interval = WMI_TLV_VDEV_HOST_SWBA_INTERVAL,
2680	.dtim_period = WMI_TLV_VDEV_PARAM_DTIM_PERIOD,
2681	.wmi_vdev_oc_scheduler_air_time_limit =
2682				WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
2683	.wds = WMI_TLV_VDEV_PARAM_WDS,
2684	.atim_window = WMI_TLV_VDEV_PARAM_ATIM_WINDOW,
2685	.bmiss_count_max = WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX,
2686	.bmiss_first_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT,
2687	.bmiss_final_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT,
2688	.feature_wmm = WMI_TLV_VDEV_PARAM_FEATURE_WMM,
2689	.chwidth = WMI_TLV_VDEV_PARAM_CHWIDTH,
2690	.chextoffset = WMI_TLV_VDEV_PARAM_CHEXTOFFSET,
2691	.disable_htprotection =	WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION,
2692	.sta_quickkickout = WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT,
2693	.mgmt_rate = WMI_TLV_VDEV_PARAM_MGMT_RATE,
2694	.protection_mode = WMI_TLV_VDEV_PARAM_PROTECTION_MODE,
2695	.fixed_rate = WMI_TLV_VDEV_PARAM_FIXED_RATE,
2696	.sgi = WMI_TLV_VDEV_PARAM_SGI,
2697	.ldpc = WMI_TLV_VDEV_PARAM_LDPC,
2698	.tx_stbc = WMI_TLV_VDEV_PARAM_TX_STBC,
2699	.rx_stbc = WMI_TLV_VDEV_PARAM_RX_STBC,
2700	.intra_bss_fwd = WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD,
2701	.def_keyid = WMI_TLV_VDEV_PARAM_DEF_KEYID,
2702	.nss = WMI_TLV_VDEV_PARAM_NSS,
2703	.bcast_data_rate = WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE,
2704	.mcast_data_rate = WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE,
2705	.mcast_indicate = WMI_TLV_VDEV_PARAM_MCAST_INDICATE,
2706	.dhcp_indicate = WMI_TLV_VDEV_PARAM_DHCP_INDICATE,
2707	.unknown_dest_indicate = WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
2708	.ap_keepalive_min_idle_inactive_time_secs =
2709		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
2710	.ap_keepalive_max_idle_inactive_time_secs =
2711		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
2712	.ap_keepalive_max_unresponsive_time_secs =
2713		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
2714	.ap_enable_nawds = WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS,
2715	.mcast2ucast_set = WMI_TLV_VDEV_PARAM_UNSUPPORTED,
2716	.enable_rtscts = WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS,
2717	.txbf = WMI_TLV_VDEV_PARAM_TXBF,
2718	.packet_powersave = WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE,
2719	.drop_unencry = WMI_TLV_VDEV_PARAM_DROP_UNENCRY,
2720	.tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
2721	.ap_detect_out_of_sync_sleeping_sta_time_secs =
2722					WMI_TLV_VDEV_PARAM_UNSUPPORTED,
2723};
2724
2725static const struct wmi_ops wmi_tlv_ops = {
2726	.rx = ath10k_wmi_tlv_op_rx,
2727	.map_svc = wmi_tlv_svc_map,
2728
2729	.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
2730	.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
2731	.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
2732	.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
2733	.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
2734	.pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
2735	.pull_phyerr = ath10k_wmi_tlv_op_pull_phyerr_ev,
2736	.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
2737	.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
2738	.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
2739
2740	.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
2741	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
2742	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
2743	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
2744	.gen_init = ath10k_wmi_tlv_op_gen_init,
2745	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
2746	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
2747	.gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
2748	.gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
2749	.gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
2750	.gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
2751	.gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
2752	.gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
2753	.gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
2754	.gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
2755	.gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
2756	.gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
2757	.gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
2758	.gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
2759	.gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
2760	.gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
2761	.gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
2762	.gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
2763	.gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
2764	.gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
2765	.gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
2766	.gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
2767	.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
2768	.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
2769	/* .gen_mgmt_tx = not implemented; HTT is used */
2770	.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
2771	.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
2772	.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
2773	/* .gen_pdev_set_quiet_mode not implemented */
2774	/* .gen_pdev_get_temperature not implemented */
2775	/* .gen_addba_clear_resp not implemented */
2776	/* .gen_addba_send not implemented */
2777	/* .gen_addba_set_resp not implemented */
2778	/* .gen_delba_send not implemented */
2779	.gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
2780	.gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
2781	.gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
2782	.gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
2783	.gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
2784};
2785
2786/************/
2787/* TLV init */
2788/************/
2789
2790void ath10k_wmi_tlv_attach(struct ath10k *ar)
2791{
2792	ar->wmi.cmd = &wmi_tlv_cmd_map;
2793	ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
2794	ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
2795	ar->wmi.ops = &wmi_tlv_ops;
2796}
2797