brintos

brintos / linux-shallow public Read only

0
0
Text · 229.6 KiB · 2cd3ff9 Raw
8087 lines · c
1// SPDX-License-Identifier: BSD-3-Clause-Clear2/*3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.5 */6#include <linux/skbuff.h>7#include <linux/ctype.h>8#include <net/mac80211.h>9#include <net/cfg80211.h>10#include <linux/completion.h>11#include <linux/if_ether.h>12#include <linux/types.h>13#include <linux/pci.h>14#include <linux/uuid.h>15#include <linux/time.h>16#include <linux/of.h>17#include "core.h"18#include "debug.h"19#include "mac.h"20#include "hw.h"21#include "peer.h"22#include "p2p.h"23 24struct ath12k_wmi_svc_ready_parse {25	bool wmi_svc_bitmap_done;26};27 28struct ath12k_wmi_dma_ring_caps_parse {29	struct ath12k_wmi_dma_ring_caps_params *dma_ring_caps;30	u32 n_dma_ring_caps;31};32 33struct ath12k_wmi_service_ext_arg {34	u32 default_conc_scan_config_bits;35	u32 default_fw_config_bits;36	struct ath12k_wmi_ppe_threshold_arg ppet;37	u32 he_cap_info;38	u32 mpdu_density;39	u32 max_bssid_rx_filters;40	u32 num_hw_modes;41	u32 num_phy;42};43 44struct ath12k_wmi_svc_rdy_ext_parse {45	struct ath12k_wmi_service_ext_arg arg;46	const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps;47	const struct ath12k_wmi_hw_mode_cap_params *hw_mode_caps;48	u32 n_hw_mode_caps;49	u32 tot_phy_id;50	struct ath12k_wmi_hw_mode_cap_params pref_hw_mode_caps;51	struct ath12k_wmi_mac_phy_caps_params *mac_phy_caps;52	u32 n_mac_phy_caps;53	const struct ath12k_wmi_soc_hal_reg_caps_params *soc_hal_reg_caps;54	const struct ath12k_wmi_hal_reg_caps_ext_params *ext_hal_reg_caps;55	u32 n_ext_hal_reg_caps;56	struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse;57	bool hw_mode_done;58	bool mac_phy_done;59	bool ext_hal_reg_done;60	bool mac_phy_chainmask_combo_done;61	bool mac_phy_chainmask_cap_done;62	bool oem_dma_ring_cap_done;63	bool dma_ring_cap_done;64};65 66struct ath12k_wmi_svc_rdy_ext2_arg {67	u32 reg_db_version;68	u32 hw_min_max_tx_power_2ghz;69	u32 hw_min_max_tx_power_5ghz;70	u32 chwidth_num_peer_caps;71	u32 preamble_puncture_bw;72	u32 max_user_per_ppdu_ofdma;73	u32 max_user_per_ppdu_mumimo;74	u32 target_cap_flags;75	u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];76	u32 max_num_linkview_peers;77	u32 max_num_msduq_supported_per_tid;78	u32 default_num_msduq_supported_per_tid;79};80 81struct ath12k_wmi_svc_rdy_ext2_parse {82	struct ath12k_wmi_svc_rdy_ext2_arg arg;83	struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse;84	bool dma_ring_cap_done;85	bool spectral_bin_scaling_done;86	bool mac_phy_caps_ext_done;87};88 89struct ath12k_wmi_rdy_parse {90	u32 num_extra_mac_addr;91};92 93struct ath12k_wmi_dma_buf_release_arg {94	struct ath12k_wmi_dma_buf_release_fixed_params fixed;95	const struct ath12k_wmi_dma_buf_release_entry_params *buf_entry;96	const struct ath12k_wmi_dma_buf_release_meta_data_params *meta_data;97	u32 num_buf_entry;98	u32 num_meta;99	bool buf_entry_done;100	bool meta_data_done;101};102 103struct ath12k_wmi_tlv_policy {104	size_t min_len;105};106 107struct wmi_tlv_mgmt_rx_parse {108	const struct ath12k_wmi_mgmt_rx_params *fixed;109	const u8 *frame_buf;110	bool frame_buf_done;111};112 113static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = {114	[WMI_TAG_ARRAY_BYTE] = { .min_len = 0 },115	[WMI_TAG_ARRAY_UINT32] = { .min_len = 0 },116	[WMI_TAG_SERVICE_READY_EVENT] = {117		.min_len = sizeof(struct wmi_service_ready_event) },118	[WMI_TAG_SERVICE_READY_EXT_EVENT] = {119		.min_len = sizeof(struct wmi_service_ready_ext_event) },120	[WMI_TAG_SOC_MAC_PHY_HW_MODE_CAPS] = {121		.min_len = sizeof(struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params) },122	[WMI_TAG_SOC_HAL_REG_CAPABILITIES] = {123		.min_len = sizeof(struct ath12k_wmi_soc_hal_reg_caps_params) },124	[WMI_TAG_VDEV_START_RESPONSE_EVENT] = {125		.min_len = sizeof(struct wmi_vdev_start_resp_event) },126	[WMI_TAG_PEER_DELETE_RESP_EVENT] = {127		.min_len = sizeof(struct wmi_peer_delete_resp_event) },128	[WMI_TAG_OFFLOAD_BCN_TX_STATUS_EVENT] = {129		.min_len = sizeof(struct wmi_bcn_tx_status_event) },130	[WMI_TAG_VDEV_STOPPED_EVENT] = {131		.min_len = sizeof(struct wmi_vdev_stopped_event) },132	[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT] = {133		.min_len = sizeof(struct wmi_reg_chan_list_cc_ext_event) },134	[WMI_TAG_MGMT_RX_HDR] = {135		.min_len = sizeof(struct ath12k_wmi_mgmt_rx_params) },136	[WMI_TAG_MGMT_TX_COMPL_EVENT] = {137		.min_len = sizeof(struct wmi_mgmt_tx_compl_event) },138	[WMI_TAG_SCAN_EVENT] = {139		.min_len = sizeof(struct wmi_scan_event) },140	[WMI_TAG_PEER_STA_KICKOUT_EVENT] = {141		.min_len = sizeof(struct wmi_peer_sta_kickout_event) },142	[WMI_TAG_ROAM_EVENT] = {143		.min_len = sizeof(struct wmi_roam_event) },144	[WMI_TAG_CHAN_INFO_EVENT] = {145		.min_len = sizeof(struct wmi_chan_info_event) },146	[WMI_TAG_PDEV_BSS_CHAN_INFO_EVENT] = {147		.min_len = sizeof(struct wmi_pdev_bss_chan_info_event) },148	[WMI_TAG_VDEV_INSTALL_KEY_COMPLETE_EVENT] = {149		.min_len = sizeof(struct wmi_vdev_install_key_compl_event) },150	[WMI_TAG_READY_EVENT] = {151		.min_len = sizeof(struct ath12k_wmi_ready_event_min_params) },152	[WMI_TAG_SERVICE_AVAILABLE_EVENT] = {153		.min_len = sizeof(struct wmi_service_available_event) },154	[WMI_TAG_PEER_ASSOC_CONF_EVENT] = {155		.min_len = sizeof(struct wmi_peer_assoc_conf_event) },156	[WMI_TAG_RFKILL_EVENT] = {157		.min_len = sizeof(struct wmi_rfkill_state_change_event) },158	[WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT] = {159		.min_len = sizeof(struct wmi_pdev_ctl_failsafe_chk_event) },160	[WMI_TAG_HOST_SWFDA_EVENT] = {161		.min_len = sizeof(struct wmi_fils_discovery_event) },162	[WMI_TAG_OFFLOAD_PRB_RSP_TX_STATUS_EVENT] = {163		.min_len = sizeof(struct wmi_probe_resp_tx_status_event) },164	[WMI_TAG_VDEV_DELETE_RESP_EVENT] = {165		.min_len = sizeof(struct wmi_vdev_delete_resp_event) },166	[WMI_TAG_TWT_ENABLE_COMPLETE_EVENT] = {167		.min_len = sizeof(struct wmi_twt_enable_event) },168	[WMI_TAG_TWT_DISABLE_COMPLETE_EVENT] = {169		.min_len = sizeof(struct wmi_twt_disable_event) },170	[WMI_TAG_P2P_NOA_INFO] = {171		.min_len = sizeof(struct ath12k_wmi_p2p_noa_info) },172	[WMI_TAG_P2P_NOA_EVENT] = {173		.min_len = sizeof(struct wmi_p2p_noa_event) },174};175 176static __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len)177{178	return le32_encode_bits(cmd, WMI_TLV_TAG) |179		le32_encode_bits(len, WMI_TLV_LEN);180}181 182static __le32 ath12k_wmi_tlv_cmd_hdr(u32 cmd, u32 len)183{184	return ath12k_wmi_tlv_hdr(cmd, len - TLV_HDR_SIZE);185}186 187void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,188			     struct ath12k_wmi_resource_config_arg *config)189{190	config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS;191	config->num_peers = ab->num_radios *192		ath12k_core_get_max_peers_per_radio(ab);193	config->num_tids = ath12k_core_get_max_num_tids(ab);194	config->num_offload_peers = TARGET_NUM_OFFLD_PEERS;195	config->num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS;196	config->num_peer_keys = TARGET_NUM_PEER_KEYS;197	config->ast_skid_limit = TARGET_AST_SKID_LIMIT;198	config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;199	config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;200	config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;201	config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;202	config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;203	config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;204 205	if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))206		config->rx_decap_mode = TARGET_DECAP_MODE_RAW;207	else208		config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;209 210	config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;211	config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;212	config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;213	config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;214	config->num_mcast_groups = TARGET_NUM_MCAST_GROUPS;215	config->num_mcast_table_elems = TARGET_NUM_MCAST_TABLE_ELEMS;216	config->mcast2ucast_mode = TARGET_MCAST2UCAST_MODE;217	config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;218	config->num_wds_entries = TARGET_NUM_WDS_ENTRIES;219	config->dma_burst_size = TARGET_DMA_BURST_SIZE;220	config->rx_skip_defrag_timeout_dup_detection_check =221		TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;222	config->vow_config = TARGET_VOW_CONFIG;223	config->gtk_offload_max_vdev = TARGET_GTK_OFFLOAD_MAX_VDEV;224	config->num_msdu_desc = TARGET_NUM_MSDU_DESC;225	config->beacon_tx_offload_max_vdev = ab->num_radios * TARGET_MAX_BCN_OFFLD;226	config->rx_batchmode = TARGET_RX_BATCHMODE;227	/* Indicates host supports peer map v3 and unmap v2 support */228	config->peer_map_unmap_version = 0x32;229	config->twt_ap_pdev_count = ab->num_radios;230	config->twt_ap_sta_count = 1000;231	config->ema_max_vap_cnt = ab->num_radios;232	config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD;233	config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt;234 235	if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map))236		config->peer_metadata_ver = ATH12K_PEER_METADATA_V1B;237}238 239void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,240			     struct ath12k_wmi_resource_config_arg *config)241{242	config->num_vdevs = 4;243	config->num_peers = 16;244	config->num_tids = 32;245 246	config->num_offload_peers = 3;247	config->num_offload_reorder_buffs = 3;248	config->num_peer_keys = TARGET_NUM_PEER_KEYS;249	config->ast_skid_limit = TARGET_AST_SKID_LIMIT;250	config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;251	config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;252	config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;253	config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;254	config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;255	config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;256	config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;257	config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;258	config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;259	config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;260	config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;261	config->num_mcast_groups = 0;262	config->num_mcast_table_elems = 0;263	config->mcast2ucast_mode = 0;264	config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;265	config->num_wds_entries = 0;266	config->dma_burst_size = 0;267	config->rx_skip_defrag_timeout_dup_detection_check = 0;268	config->vow_config = TARGET_VOW_CONFIG;269	config->gtk_offload_max_vdev = 2;270	config->num_msdu_desc = 0x400;271	config->beacon_tx_offload_max_vdev = 2;272	config->rx_batchmode = TARGET_RX_BATCHMODE;273 274	config->peer_map_unmap_version = 0x1;275	config->use_pdev_id = 1;276	config->max_frag_entries = 0xa;277	config->num_tdls_vdevs = 0x1;278	config->num_tdls_conn_table_entries = 8;279	config->beacon_tx_offload_max_vdev = 0x2;280	config->num_multicast_filter_entries = 0x20;281	config->num_wow_filters = 0x16;282	config->num_keep_alive_pattern = 0;283}284 285#define PRIMAP(_hw_mode_) \286	[_hw_mode_] = _hw_mode_##_PRI287 288static const int ath12k_hw_mode_pri_map[] = {289	PRIMAP(WMI_HOST_HW_MODE_SINGLE),290	PRIMAP(WMI_HOST_HW_MODE_DBS),291	PRIMAP(WMI_HOST_HW_MODE_SBS_PASSIVE),292	PRIMAP(WMI_HOST_HW_MODE_SBS),293	PRIMAP(WMI_HOST_HW_MODE_DBS_SBS),294	PRIMAP(WMI_HOST_HW_MODE_DBS_OR_SBS),295	/* keep last */296	PRIMAP(WMI_HOST_HW_MODE_MAX),297};298 299static int300ath12k_wmi_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,301		    int (*iter)(struct ath12k_base *ab, u16 tag, u16 len,302				const void *ptr, void *data),303		    void *data)304{305	const void *begin = ptr;306	const struct wmi_tlv *tlv;307	u16 tlv_tag, tlv_len;308	int ret;309 310	while (len > 0) {311		if (len < sizeof(*tlv)) {312			ath12k_err(ab, "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",313				   ptr - begin, len, sizeof(*tlv));314			return -EINVAL;315		}316 317		tlv = ptr;318		tlv_tag = le32_get_bits(tlv->header, WMI_TLV_TAG);319		tlv_len = le32_get_bits(tlv->header, WMI_TLV_LEN);320		ptr += sizeof(*tlv);321		len -= sizeof(*tlv);322 323		if (tlv_len > len) {324			ath12k_err(ab, "wmi tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",325				   tlv_tag, ptr - begin, len, tlv_len);326			return -EINVAL;327		}328 329		if (tlv_tag < ARRAY_SIZE(ath12k_wmi_tlv_policies) &&330		    ath12k_wmi_tlv_policies[tlv_tag].min_len &&331		    ath12k_wmi_tlv_policies[tlv_tag].min_len > tlv_len) {332			ath12k_err(ab, "wmi tlv parse failure of tag %u at byte %zd (%u bytes is less than min length %zu)\n",333				   tlv_tag, ptr - begin, tlv_len,334				   ath12k_wmi_tlv_policies[tlv_tag].min_len);335			return -EINVAL;336		}337 338		ret = iter(ab, tlv_tag, tlv_len, ptr, data);339		if (ret)340			return ret;341 342		ptr += tlv_len;343		len -= tlv_len;344	}345 346	return 0;347}348 349static int ath12k_wmi_tlv_iter_parse(struct ath12k_base *ab, u16 tag, u16 len,350				     const void *ptr, void *data)351{352	const void **tb = data;353 354	if (tag < WMI_TAG_MAX)355		tb[tag] = ptr;356 357	return 0;358}359 360static int ath12k_wmi_tlv_parse(struct ath12k_base *ar, const void **tb,361				const void *ptr, size_t len)362{363	return ath12k_wmi_tlv_iter(ar, ptr, len, ath12k_wmi_tlv_iter_parse,364				   (void *)tb);365}366 367static const void **368ath12k_wmi_tlv_parse_alloc(struct ath12k_base *ab,369			   struct sk_buff *skb, gfp_t gfp)370{371	const void **tb;372	int ret;373 374	tb = kcalloc(WMI_TAG_MAX, sizeof(*tb), gfp);375	if (!tb)376		return ERR_PTR(-ENOMEM);377 378	ret = ath12k_wmi_tlv_parse(ab, tb, skb->data, skb->len);379	if (ret) {380		kfree(tb);381		return ERR_PTR(ret);382	}383 384	return tb;385}386 387static int ath12k_wmi_cmd_send_nowait(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb,388				      u32 cmd_id)389{390	struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);391	struct ath12k_base *ab = wmi->wmi_ab->ab;392	struct wmi_cmd_hdr *cmd_hdr;393	int ret;394 395	if (!skb_push(skb, sizeof(struct wmi_cmd_hdr)))396		return -ENOMEM;397 398	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;399	cmd_hdr->cmd_id = le32_encode_bits(cmd_id, WMI_CMD_HDR_CMD_ID);400 401	memset(skb_cb, 0, sizeof(*skb_cb));402	ret = ath12k_htc_send(&ab->htc, wmi->eid, skb);403 404	if (ret)405		goto err_pull;406 407	return 0;408 409err_pull:410	skb_pull(skb, sizeof(struct wmi_cmd_hdr));411	return ret;412}413 414int ath12k_wmi_cmd_send(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb,415			u32 cmd_id)416{417	struct ath12k_wmi_base *wmi_ab = wmi->wmi_ab;418	int ret = -EOPNOTSUPP;419 420	might_sleep();421 422	wait_event_timeout(wmi_ab->tx_credits_wq, ({423		ret = ath12k_wmi_cmd_send_nowait(wmi, skb, cmd_id);424 425		if (ret && test_bit(ATH12K_FLAG_CRASH_FLUSH, &wmi_ab->ab->dev_flags))426			ret = -ESHUTDOWN;427 428		(ret != -EAGAIN);429	}), WMI_SEND_TIMEOUT_HZ);430 431	if (ret == -EAGAIN)432		ath12k_warn(wmi_ab->ab, "wmi command %d timeout\n", cmd_id);433 434	return ret;435}436 437static int ath12k_pull_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,438				     const void *ptr,439				     struct ath12k_wmi_service_ext_arg *arg)440{441	const struct wmi_service_ready_ext_event *ev = ptr;442	int i;443 444	if (!ev)445		return -EINVAL;446 447	/* Move this to host based bitmap */448	arg->default_conc_scan_config_bits =449		le32_to_cpu(ev->default_conc_scan_config_bits);450	arg->default_fw_config_bits = le32_to_cpu(ev->default_fw_config_bits);451	arg->he_cap_info = le32_to_cpu(ev->he_cap_info);452	arg->mpdu_density = le32_to_cpu(ev->mpdu_density);453	arg->max_bssid_rx_filters = le32_to_cpu(ev->max_bssid_rx_filters);454	arg->ppet.numss_m1 = le32_to_cpu(ev->ppet.numss_m1);455	arg->ppet.ru_bit_mask = le32_to_cpu(ev->ppet.ru_info);456 457	for (i = 0; i < WMI_MAX_NUM_SS; i++)458		arg->ppet.ppet16_ppet8_ru3_ru0[i] =459			le32_to_cpu(ev->ppet.ppet16_ppet8_ru3_ru0[i]);460 461	return 0;462}463 464static int465ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,466				      struct ath12k_wmi_svc_rdy_ext_parse *svc,467				      u8 hw_mode_id, u8 phy_id,468				      struct ath12k_pdev *pdev)469{470	const struct ath12k_wmi_mac_phy_caps_params *mac_caps;471	const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps = svc->hw_caps;472	const struct ath12k_wmi_hw_mode_cap_params *wmi_hw_mode_caps = svc->hw_mode_caps;473	const struct ath12k_wmi_mac_phy_caps_params *wmi_mac_phy_caps = svc->mac_phy_caps;474	struct ath12k_base *ab = wmi_handle->wmi_ab->ab;475	struct ath12k_band_cap *cap_band;476	struct ath12k_pdev_cap *pdev_cap = &pdev->cap;477	struct ath12k_fw_pdev *fw_pdev;478	u32 phy_map;479	u32 hw_idx, phy_idx = 0;480	int i;481 482	if (!hw_caps || !wmi_hw_mode_caps || !svc->soc_hal_reg_caps)483		return -EINVAL;484 485	for (hw_idx = 0; hw_idx < le32_to_cpu(hw_caps->num_hw_modes); hw_idx++) {486		if (hw_mode_id == le32_to_cpu(wmi_hw_mode_caps[hw_idx].hw_mode_id))487			break;488 489		phy_map = le32_to_cpu(wmi_hw_mode_caps[hw_idx].phy_id_map);490		phy_idx = fls(phy_map);491	}492 493	if (hw_idx == le32_to_cpu(hw_caps->num_hw_modes))494		return -EINVAL;495 496	phy_idx += phy_id;497	if (phy_id >= le32_to_cpu(svc->soc_hal_reg_caps->num_phy))498		return -EINVAL;499 500	mac_caps = wmi_mac_phy_caps + phy_idx;501 502	pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);503	pdev->hw_link_id = ath12k_wmi_mac_phy_get_hw_link_id(mac_caps);504	pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands);505	pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density);506 507	fw_pdev = &ab->fw_pdev[ab->fw_pdev_count];508	fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands);509	fw_pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);510	fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id);511	ab->fw_pdev_count++;512 513	/* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from514	 * band to band for a single radio, need to see how this should be515	 * handled.516	 */517	if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2G_CAP) {518		pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_2g);519		pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_2g);520	} else if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5G_CAP) {521		pdev_cap->vht_cap = le32_to_cpu(mac_caps->vht_cap_info_5g);522		pdev_cap->vht_mcs = le32_to_cpu(mac_caps->vht_supp_mcs_5g);523		pdev_cap->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);524		pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_5g);525		pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_5g);526	} else {527		return -EINVAL;528	}529 530	/* tx/rx chainmask reported from fw depends on the actual hw chains used,531	 * For example, for 4x4 capable macphys, first 4 chains can be used for first532	 * mac and the remaining 4 chains can be used for the second mac or vice-versa.533	 * In this case, tx/rx chainmask 0xf will be advertised for first mac and 0xf0534	 * will be advertised for second mac or vice-versa. Compute the shift value535	 * for tx/rx chainmask which will be used to advertise supported ht/vht rates to536	 * mac80211.537	 */538	pdev_cap->tx_chain_mask_shift =539			find_first_bit((unsigned long *)&pdev_cap->tx_chain_mask, 32);540	pdev_cap->rx_chain_mask_shift =541			find_first_bit((unsigned long *)&pdev_cap->rx_chain_mask, 32);542 543	if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2G_CAP) {544		cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];545		cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);546		cap_band->max_bw_supported = le32_to_cpu(mac_caps->max_bw_supported_2g);547		cap_band->ht_cap_info = le32_to_cpu(mac_caps->ht_cap_info_2g);548		cap_band->he_cap_info[0] = le32_to_cpu(mac_caps->he_cap_info_2g);549		cap_band->he_cap_info[1] = le32_to_cpu(mac_caps->he_cap_info_2g_ext);550		cap_band->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_2g);551		for (i = 0; i < WMI_MAX_HECAP_PHY_SIZE; i++)552			cap_band->he_cap_phy_info[i] =553				le32_to_cpu(mac_caps->he_cap_phy_info_2g[i]);554 555		cap_band->he_ppet.numss_m1 = le32_to_cpu(mac_caps->he_ppet2g.numss_m1);556		cap_band->he_ppet.ru_bit_mask = le32_to_cpu(mac_caps->he_ppet2g.ru_info);557 558		for (i = 0; i < WMI_MAX_NUM_SS; i++)559			cap_band->he_ppet.ppet16_ppet8_ru3_ru0[i] =560				le32_to_cpu(mac_caps->he_ppet2g.ppet16_ppet8_ru3_ru0[i]);561	}562 563	if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5G_CAP) {564		cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];565		cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);566		cap_band->max_bw_supported =567			le32_to_cpu(mac_caps->max_bw_supported_5g);568		cap_band->ht_cap_info = le32_to_cpu(mac_caps->ht_cap_info_5g);569		cap_band->he_cap_info[0] = le32_to_cpu(mac_caps->he_cap_info_5g);570		cap_band->he_cap_info[1] = le32_to_cpu(mac_caps->he_cap_info_5g_ext);571		cap_band->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);572		for (i = 0; i < WMI_MAX_HECAP_PHY_SIZE; i++)573			cap_band->he_cap_phy_info[i] =574				le32_to_cpu(mac_caps->he_cap_phy_info_5g[i]);575 576		cap_band->he_ppet.numss_m1 = le32_to_cpu(mac_caps->he_ppet5g.numss_m1);577		cap_band->he_ppet.ru_bit_mask = le32_to_cpu(mac_caps->he_ppet5g.ru_info);578 579		for (i = 0; i < WMI_MAX_NUM_SS; i++)580			cap_band->he_ppet.ppet16_ppet8_ru3_ru0[i] =581				le32_to_cpu(mac_caps->he_ppet5g.ppet16_ppet8_ru3_ru0[i]);582 583		cap_band = &pdev_cap->band[NL80211_BAND_6GHZ];584		cap_band->max_bw_supported =585			le32_to_cpu(mac_caps->max_bw_supported_5g);586		cap_band->ht_cap_info = le32_to_cpu(mac_caps->ht_cap_info_5g);587		cap_band->he_cap_info[0] = le32_to_cpu(mac_caps->he_cap_info_5g);588		cap_band->he_cap_info[1] = le32_to_cpu(mac_caps->he_cap_info_5g_ext);589		cap_band->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);590		for (i = 0; i < WMI_MAX_HECAP_PHY_SIZE; i++)591			cap_band->he_cap_phy_info[i] =592				le32_to_cpu(mac_caps->he_cap_phy_info_5g[i]);593 594		cap_band->he_ppet.numss_m1 = le32_to_cpu(mac_caps->he_ppet5g.numss_m1);595		cap_band->he_ppet.ru_bit_mask = le32_to_cpu(mac_caps->he_ppet5g.ru_info);596 597		for (i = 0; i < WMI_MAX_NUM_SS; i++)598			cap_band->he_ppet.ppet16_ppet8_ru3_ru0[i] =599				le32_to_cpu(mac_caps->he_ppet5g.ppet16_ppet8_ru3_ru0[i]);600	}601 602	return 0;603}604 605static int606ath12k_pull_reg_cap_svc_rdy_ext(struct ath12k_wmi_pdev *wmi_handle,607				const struct ath12k_wmi_soc_hal_reg_caps_params *reg_caps,608				const struct ath12k_wmi_hal_reg_caps_ext_params *ext_caps,609				u8 phy_idx,610				struct ath12k_wmi_hal_reg_capabilities_ext_arg *param)611{612	const struct ath12k_wmi_hal_reg_caps_ext_params *ext_reg_cap;613 614	if (!reg_caps || !ext_caps)615		return -EINVAL;616 617	if (phy_idx >= le32_to_cpu(reg_caps->num_phy))618		return -EINVAL;619 620	ext_reg_cap = &ext_caps[phy_idx];621 622	param->phy_id = le32_to_cpu(ext_reg_cap->phy_id);623	param->eeprom_reg_domain = le32_to_cpu(ext_reg_cap->eeprom_reg_domain);624	param->eeprom_reg_domain_ext =625		le32_to_cpu(ext_reg_cap->eeprom_reg_domain_ext);626	param->regcap1 = le32_to_cpu(ext_reg_cap->regcap1);627	param->regcap2 = le32_to_cpu(ext_reg_cap->regcap2);628	/* check if param->wireless_mode is needed */629	param->low_2ghz_chan = le32_to_cpu(ext_reg_cap->low_2ghz_chan);630	param->high_2ghz_chan = le32_to_cpu(ext_reg_cap->high_2ghz_chan);631	param->low_5ghz_chan = le32_to_cpu(ext_reg_cap->low_5ghz_chan);632	param->high_5ghz_chan = le32_to_cpu(ext_reg_cap->high_5ghz_chan);633 634	return 0;635}636 637static int ath12k_pull_service_ready_tlv(struct ath12k_base *ab,638					 const void *evt_buf,639					 struct ath12k_wmi_target_cap_arg *cap)640{641	const struct wmi_service_ready_event *ev = evt_buf;642 643	if (!ev) {644		ath12k_err(ab, "%s: failed by NULL param\n",645			   __func__);646		return -EINVAL;647	}648 649	cap->phy_capability = le32_to_cpu(ev->phy_capability);650	cap->max_frag_entry = le32_to_cpu(ev->max_frag_entry);651	cap->num_rf_chains = le32_to_cpu(ev->num_rf_chains);652	cap->ht_cap_info = le32_to_cpu(ev->ht_cap_info);653	cap->vht_cap_info = le32_to_cpu(ev->vht_cap_info);654	cap->vht_supp_mcs = le32_to_cpu(ev->vht_supp_mcs);655	cap->hw_min_tx_power = le32_to_cpu(ev->hw_min_tx_power);656	cap->hw_max_tx_power = le32_to_cpu(ev->hw_max_tx_power);657	cap->sys_cap_info = le32_to_cpu(ev->sys_cap_info);658	cap->min_pkt_size_enable = le32_to_cpu(ev->min_pkt_size_enable);659	cap->max_bcn_ie_size = le32_to_cpu(ev->max_bcn_ie_size);660	cap->max_num_scan_channels = le32_to_cpu(ev->max_num_scan_channels);661	cap->max_supported_macs = le32_to_cpu(ev->max_supported_macs);662	cap->wmi_fw_sub_feat_caps = le32_to_cpu(ev->wmi_fw_sub_feat_caps);663	cap->txrx_chainmask = le32_to_cpu(ev->txrx_chainmask);664	cap->default_dbs_hw_mode_index = le32_to_cpu(ev->default_dbs_hw_mode_index);665	cap->num_msdu_desc = le32_to_cpu(ev->num_msdu_desc);666 667	return 0;668}669 670/* Save the wmi_service_bitmap into a linear bitmap. The wmi_services in671 * wmi_service ready event are advertised in b0-b3 (LSB 4-bits) of each672 * 4-byte word.673 */674static void ath12k_wmi_service_bitmap_copy(struct ath12k_wmi_pdev *wmi,675					   const u32 *wmi_svc_bm)676{677	int i, j;678 679	for (i = 0, j = 0; i < WMI_SERVICE_BM_SIZE && j < WMI_MAX_SERVICE; i++) {680		do {681			if (wmi_svc_bm[i] & BIT(j % WMI_SERVICE_BITS_IN_SIZE32))682				set_bit(j, wmi->wmi_ab->svc_map);683		} while (++j % WMI_SERVICE_BITS_IN_SIZE32);684	}685}686 687static int ath12k_wmi_svc_rdy_parse(struct ath12k_base *ab, u16 tag, u16 len,688				    const void *ptr, void *data)689{690	struct ath12k_wmi_svc_ready_parse *svc_ready = data;691	struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];692	u16 expect_len;693 694	switch (tag) {695	case WMI_TAG_SERVICE_READY_EVENT:696		if (ath12k_pull_service_ready_tlv(ab, ptr, &ab->target_caps))697			return -EINVAL;698		break;699 700	case WMI_TAG_ARRAY_UINT32:701		if (!svc_ready->wmi_svc_bitmap_done) {702			expect_len = WMI_SERVICE_BM_SIZE * sizeof(u32);703			if (len < expect_len) {704				ath12k_warn(ab, "invalid len %d for the tag 0x%x\n",705					    len, tag);706				return -EINVAL;707			}708 709			ath12k_wmi_service_bitmap_copy(wmi_handle, ptr);710 711			svc_ready->wmi_svc_bitmap_done = true;712		}713		break;714	default:715		break;716	}717 718	return 0;719}720 721static int ath12k_service_ready_event(struct ath12k_base *ab, struct sk_buff *skb)722{723	struct ath12k_wmi_svc_ready_parse svc_ready = { };724	int ret;725 726	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,727				  ath12k_wmi_svc_rdy_parse,728				  &svc_ready);729	if (ret) {730		ath12k_warn(ab, "failed to parse tlv %d\n", ret);731		return ret;732	}733 734	return 0;735}736 737static u32 ath12k_wmi_mgmt_get_freq(struct ath12k *ar,738				    struct ieee80211_tx_info *info)739{740	struct ath12k_base *ab = ar->ab;741	u32 freq = 0;742 743	if (ab->hw_params->single_pdev_only &&744	    ar->scan.is_roc &&745	    (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))746		freq = ar->scan.roc_freq;747 748	return freq;749}750 751struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_ab, u32 len)752{753	struct sk_buff *skb;754	struct ath12k_base *ab = wmi_ab->ab;755	u32 round_len = roundup(len, 4);756 757	skb = ath12k_htc_alloc_skb(ab, WMI_SKB_HEADROOM + round_len);758	if (!skb)759		return NULL;760 761	skb_reserve(skb, WMI_SKB_HEADROOM);762	if (!IS_ALIGNED((unsigned long)skb->data, 4))763		ath12k_warn(ab, "unaligned WMI skb data\n");764 765	skb_put(skb, round_len);766	memset(skb->data, 0, round_len);767 768	return skb;769}770 771int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id,772			 struct sk_buff *frame)773{774	struct ath12k_wmi_pdev *wmi = ar->wmi;775	struct wmi_mgmt_send_cmd *cmd;776	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame);777	struct wmi_tlv *frame_tlv;778	struct sk_buff *skb;779	u32 buf_len;780	int ret, len;781 782	buf_len = min_t(int, frame->len, WMI_MGMT_SEND_DOWNLD_LEN);783 784	len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4);785 786	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);787	if (!skb)788		return -ENOMEM;789 790	cmd = (struct wmi_mgmt_send_cmd *)skb->data;791	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MGMT_TX_SEND_CMD,792						 sizeof(*cmd));793	cmd->vdev_id = cpu_to_le32(vdev_id);794	cmd->desc_id = cpu_to_le32(buf_id);795	cmd->chanfreq = cpu_to_le32(ath12k_wmi_mgmt_get_freq(ar, info));796	cmd->paddr_lo = cpu_to_le32(lower_32_bits(ATH12K_SKB_CB(frame)->paddr));797	cmd->paddr_hi = cpu_to_le32(upper_32_bits(ATH12K_SKB_CB(frame)->paddr));798	cmd->frame_len = cpu_to_le32(frame->len);799	cmd->buf_len = cpu_to_le32(buf_len);800	cmd->tx_params_valid = 0;801 802	frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));803	frame_tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, buf_len);804 805	memcpy(frame_tlv->value, frame->data, buf_len);806 807	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_MGMT_TX_SEND_CMDID);808	if (ret) {809		ath12k_warn(ar->ab,810			    "failed to submit WMI_MGMT_TX_SEND_CMDID cmd\n");811		dev_kfree_skb(skb);812	}813 814	return ret;815}816 817int ath12k_wmi_vdev_create(struct ath12k *ar, u8 *macaddr,818			   struct ath12k_wmi_vdev_create_arg *args)819{820	struct ath12k_wmi_pdev *wmi = ar->wmi;821	struct wmi_vdev_create_cmd *cmd;822	struct sk_buff *skb;823	struct ath12k_wmi_vdev_txrx_streams_params *txrx_streams;824	struct wmi_tlv *tlv;825	int ret, len;826	void *ptr;827 828	/* It can be optimized my sending tx/rx chain configuration829	 * only for supported bands instead of always sending it for830	 * both the bands.831	 */832	len = sizeof(*cmd) + TLV_HDR_SIZE +833		(WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams));834 835	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);836	if (!skb)837		return -ENOMEM;838 839	cmd = (struct wmi_vdev_create_cmd *)skb->data;840	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_CREATE_CMD,841						 sizeof(*cmd));842 843	cmd->vdev_id = cpu_to_le32(args->if_id);844	cmd->vdev_type = cpu_to_le32(args->type);845	cmd->vdev_subtype = cpu_to_le32(args->subtype);846	cmd->num_cfg_txrx_streams = cpu_to_le32(WMI_NUM_SUPPORTED_BAND_MAX);847	cmd->pdev_id = cpu_to_le32(args->pdev_id);848	cmd->mbssid_flags = cpu_to_le32(args->mbssid_flags);849	cmd->mbssid_tx_vdev_id = cpu_to_le32(args->mbssid_tx_vdev_id);850	cmd->vdev_stats_id = cpu_to_le32(args->if_stats_id);851	ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);852 853	if (args->if_stats_id != ATH12K_INVAL_VDEV_STATS_ID)854		cmd->vdev_stats_id_valid = cpu_to_le32(BIT(0));855 856	ptr = skb->data + sizeof(*cmd);857	len = WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams);858 859	tlv = ptr;860	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);861 862	ptr += TLV_HDR_SIZE;863	txrx_streams = ptr;864	len = sizeof(*txrx_streams);865	txrx_streams->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_TXRX_STREAMS,866							  len);867	txrx_streams->band = cpu_to_le32(WMI_TPC_CHAINMASK_CONFIG_BAND_2G);868	txrx_streams->supported_tx_streams =869				cpu_to_le32(args->chains[NL80211_BAND_2GHZ].tx);870	txrx_streams->supported_rx_streams =871				cpu_to_le32(args->chains[NL80211_BAND_2GHZ].rx);872 873	txrx_streams++;874	txrx_streams->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_TXRX_STREAMS,875							  len);876	txrx_streams->band = cpu_to_le32(WMI_TPC_CHAINMASK_CONFIG_BAND_5G);877	txrx_streams->supported_tx_streams =878				cpu_to_le32(args->chains[NL80211_BAND_5GHZ].tx);879	txrx_streams->supported_rx_streams =880				cpu_to_le32(args->chains[NL80211_BAND_5GHZ].rx);881 882	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,883		   "WMI vdev create: id %d type %d subtype %d macaddr %pM pdevid %d\n",884		   args->if_id, args->type, args->subtype,885		   macaddr, args->pdev_id);886 887	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_CREATE_CMDID);888	if (ret) {889		ath12k_warn(ar->ab,890			    "failed to submit WMI_VDEV_CREATE_CMDID\n");891		dev_kfree_skb(skb);892	}893 894	return ret;895}896 897int ath12k_wmi_vdev_delete(struct ath12k *ar, u8 vdev_id)898{899	struct ath12k_wmi_pdev *wmi = ar->wmi;900	struct wmi_vdev_delete_cmd *cmd;901	struct sk_buff *skb;902	int ret;903 904	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));905	if (!skb)906		return -ENOMEM;907 908	cmd = (struct wmi_vdev_delete_cmd *)skb->data;909	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_DELETE_CMD,910						 sizeof(*cmd));911	cmd->vdev_id = cpu_to_le32(vdev_id);912 913	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "WMI vdev delete id %d\n", vdev_id);914 915	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_DELETE_CMDID);916	if (ret) {917		ath12k_warn(ar->ab, "failed to submit WMI_VDEV_DELETE_CMDID\n");918		dev_kfree_skb(skb);919	}920 921	return ret;922}923 924int ath12k_wmi_vdev_stop(struct ath12k *ar, u8 vdev_id)925{926	struct ath12k_wmi_pdev *wmi = ar->wmi;927	struct wmi_vdev_stop_cmd *cmd;928	struct sk_buff *skb;929	int ret;930 931	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));932	if (!skb)933		return -ENOMEM;934 935	cmd = (struct wmi_vdev_stop_cmd *)skb->data;936 937	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_STOP_CMD,938						 sizeof(*cmd));939	cmd->vdev_id = cpu_to_le32(vdev_id);940 941	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "WMI vdev stop id 0x%x\n", vdev_id);942 943	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_STOP_CMDID);944	if (ret) {945		ath12k_warn(ar->ab, "failed to submit WMI_VDEV_STOP cmd\n");946		dev_kfree_skb(skb);947	}948 949	return ret;950}951 952int ath12k_wmi_vdev_down(struct ath12k *ar, u8 vdev_id)953{954	struct ath12k_wmi_pdev *wmi = ar->wmi;955	struct wmi_vdev_down_cmd *cmd;956	struct sk_buff *skb;957	int ret;958 959	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));960	if (!skb)961		return -ENOMEM;962 963	cmd = (struct wmi_vdev_down_cmd *)skb->data;964 965	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_DOWN_CMD,966						 sizeof(*cmd));967	cmd->vdev_id = cpu_to_le32(vdev_id);968 969	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "WMI vdev down id 0x%x\n", vdev_id);970 971	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_DOWN_CMDID);972	if (ret) {973		ath12k_warn(ar->ab, "failed to submit WMI_VDEV_DOWN cmd\n");974		dev_kfree_skb(skb);975	}976 977	return ret;978}979 980static void ath12k_wmi_put_wmi_channel(struct ath12k_wmi_channel_params *chan,981				       struct wmi_vdev_start_req_arg *arg)982{983	memset(chan, 0, sizeof(*chan));984 985	chan->mhz = cpu_to_le32(arg->freq);986	chan->band_center_freq1 = cpu_to_le32(arg->band_center_freq1);987	if (arg->mode == MODE_11AC_VHT80_80)988		chan->band_center_freq2 = cpu_to_le32(arg->band_center_freq2);989	else990		chan->band_center_freq2 = 0;991 992	chan->info |= le32_encode_bits(arg->mode, WMI_CHAN_INFO_MODE);993	if (arg->passive)994		chan->info |= cpu_to_le32(WMI_CHAN_INFO_PASSIVE);995	if (arg->allow_ibss)996		chan->info |= cpu_to_le32(WMI_CHAN_INFO_ADHOC_ALLOWED);997	if (arg->allow_ht)998		chan->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_HT);999	if (arg->allow_vht)1000		chan->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_VHT);1001	if (arg->allow_he)1002		chan->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_HE);1003	if (arg->ht40plus)1004		chan->info |= cpu_to_le32(WMI_CHAN_INFO_HT40_PLUS);1005	if (arg->chan_radar)1006		chan->info |= cpu_to_le32(WMI_CHAN_INFO_DFS);1007	if (arg->freq2_radar)1008		chan->info |= cpu_to_le32(WMI_CHAN_INFO_DFS_FREQ2);1009 1010	chan->reg_info_1 = le32_encode_bits(arg->max_power,1011					    WMI_CHAN_REG_INFO1_MAX_PWR) |1012		le32_encode_bits(arg->max_reg_power,1013				 WMI_CHAN_REG_INFO1_MAX_REG_PWR);1014 1015	chan->reg_info_2 = le32_encode_bits(arg->max_antenna_gain,1016					    WMI_CHAN_REG_INFO2_ANT_MAX) |1017		le32_encode_bits(arg->max_power, WMI_CHAN_REG_INFO2_MAX_TX_PWR);1018}1019 1020int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg,1021			  bool restart)1022{1023	struct ath12k_wmi_pdev *wmi = ar->wmi;1024	struct wmi_vdev_start_request_cmd *cmd;1025	struct sk_buff *skb;1026	struct ath12k_wmi_channel_params *chan;1027	struct wmi_tlv *tlv;1028	void *ptr;1029	int ret, len;1030 1031	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))1032		return -EINVAL;1033 1034	len = sizeof(*cmd) + sizeof(*chan) + TLV_HDR_SIZE;1035 1036	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);1037	if (!skb)1038		return -ENOMEM;1039 1040	cmd = (struct wmi_vdev_start_request_cmd *)skb->data;1041	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_START_REQUEST_CMD,1042						 sizeof(*cmd));1043	cmd->vdev_id = cpu_to_le32(arg->vdev_id);1044	cmd->beacon_interval = cpu_to_le32(arg->bcn_intval);1045	cmd->bcn_tx_rate = cpu_to_le32(arg->bcn_tx_rate);1046	cmd->dtim_period = cpu_to_le32(arg->dtim_period);1047	cmd->num_noa_descriptors = cpu_to_le32(arg->num_noa_descriptors);1048	cmd->preferred_rx_streams = cpu_to_le32(arg->pref_rx_streams);1049	cmd->preferred_tx_streams = cpu_to_le32(arg->pref_tx_streams);1050	cmd->cac_duration_ms = cpu_to_le32(arg->cac_duration_ms);1051	cmd->regdomain = cpu_to_le32(arg->regdomain);1052	cmd->he_ops = cpu_to_le32(arg->he_ops);1053	cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap);1054	cmd->mbssid_flags = cpu_to_le32(arg->mbssid_flags);1055	cmd->mbssid_tx_vdev_id = cpu_to_le32(arg->mbssid_tx_vdev_id);1056 1057	if (!restart) {1058		if (arg->ssid) {1059			cmd->ssid.ssid_len = cpu_to_le32(arg->ssid_len);1060			memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);1061		}1062		if (arg->hidden_ssid)1063			cmd->flags |= cpu_to_le32(WMI_VDEV_START_HIDDEN_SSID);1064		if (arg->pmf_enabled)1065			cmd->flags |= cpu_to_le32(WMI_VDEV_START_PMF_ENABLED);1066	}1067 1068	cmd->flags |= cpu_to_le32(WMI_VDEV_START_LDPC_RX_ENABLED);1069 1070	ptr = skb->data + sizeof(*cmd);1071	chan = ptr;1072 1073	ath12k_wmi_put_wmi_channel(chan, arg);1074 1075	chan->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_CHANNEL,1076						  sizeof(*chan));1077	ptr += sizeof(*chan);1078 1079	tlv = ptr;1080	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);1081 1082	/* Note: This is a nested TLV containing:1083	 * [wmi_tlv][ath12k_wmi_p2p_noa_descriptor][wmi_tlv]..1084	 */1085 1086	ptr += sizeof(*tlv);1087 1088	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "vdev %s id 0x%x freq 0x%x mode 0x%x\n",1089		   restart ? "restart" : "start", arg->vdev_id,1090		   arg->freq, arg->mode);1091 1092	if (restart)1093		ret = ath12k_wmi_cmd_send(wmi, skb,1094					  WMI_VDEV_RESTART_REQUEST_CMDID);1095	else1096		ret = ath12k_wmi_cmd_send(wmi, skb,1097					  WMI_VDEV_START_REQUEST_CMDID);1098	if (ret) {1099		ath12k_warn(ar->ab, "failed to submit vdev_%s cmd\n",1100			    restart ? "restart" : "start");1101		dev_kfree_skb(skb);1102	}1103 1104	return ret;1105}1106 1107int ath12k_wmi_vdev_up(struct ath12k *ar, struct ath12k_wmi_vdev_up_params *params)1108{1109	struct ath12k_wmi_pdev *wmi = ar->wmi;1110	struct wmi_vdev_up_cmd *cmd;1111	struct sk_buff *skb;1112	int ret;1113 1114	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1115	if (!skb)1116		return -ENOMEM;1117 1118	cmd = (struct wmi_vdev_up_cmd *)skb->data;1119 1120	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_UP_CMD,1121						 sizeof(*cmd));1122	cmd->vdev_id = cpu_to_le32(params->vdev_id);1123	cmd->vdev_assoc_id = cpu_to_le32(params->aid);1124 1125	ether_addr_copy(cmd->vdev_bssid.addr, params->bssid);1126 1127	if (params->tx_bssid) {1128		ether_addr_copy(cmd->tx_vdev_bssid.addr, params->tx_bssid);1129		cmd->nontx_profile_idx = cpu_to_le32(params->nontx_profile_idx);1130		cmd->nontx_profile_cnt = cpu_to_le32(params->nontx_profile_cnt);1131	}1132 1133	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1134		   "WMI mgmt vdev up id 0x%x assoc id %d bssid %pM\n",1135		   params->vdev_id, params->aid, params->bssid);1136 1137	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_UP_CMDID);1138	if (ret) {1139		ath12k_warn(ar->ab, "failed to submit WMI_VDEV_UP cmd\n");1140		dev_kfree_skb(skb);1141	}1142 1143	return ret;1144}1145 1146int ath12k_wmi_send_peer_create_cmd(struct ath12k *ar,1147				    struct ath12k_wmi_peer_create_arg *arg)1148{1149	struct ath12k_wmi_pdev *wmi = ar->wmi;1150	struct wmi_peer_create_cmd *cmd;1151	struct sk_buff *skb;1152	int ret;1153 1154	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1155	if (!skb)1156		return -ENOMEM;1157 1158	cmd = (struct wmi_peer_create_cmd *)skb->data;1159	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_CREATE_CMD,1160						 sizeof(*cmd));1161 1162	ether_addr_copy(cmd->peer_macaddr.addr, arg->peer_addr);1163	cmd->peer_type = cpu_to_le32(arg->peer_type);1164	cmd->vdev_id = cpu_to_le32(arg->vdev_id);1165 1166	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1167		   "WMI peer create vdev_id %d peer_addr %pM\n",1168		   arg->vdev_id, arg->peer_addr);1169 1170	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_CREATE_CMDID);1171	if (ret) {1172		ath12k_warn(ar->ab, "failed to submit WMI_PEER_CREATE cmd\n");1173		dev_kfree_skb(skb);1174	}1175 1176	return ret;1177}1178 1179int ath12k_wmi_send_peer_delete_cmd(struct ath12k *ar,1180				    const u8 *peer_addr, u8 vdev_id)1181{1182	struct ath12k_wmi_pdev *wmi = ar->wmi;1183	struct wmi_peer_delete_cmd *cmd;1184	struct sk_buff *skb;1185	int ret;1186 1187	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1188	if (!skb)1189		return -ENOMEM;1190 1191	cmd = (struct wmi_peer_delete_cmd *)skb->data;1192	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_DELETE_CMD,1193						 sizeof(*cmd));1194 1195	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);1196	cmd->vdev_id = cpu_to_le32(vdev_id);1197 1198	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1199		   "WMI peer delete vdev_id %d peer_addr %pM\n",1200		   vdev_id,  peer_addr);1201 1202	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_DELETE_CMDID);1203	if (ret) {1204		ath12k_warn(ar->ab, "failed to send WMI_PEER_DELETE cmd\n");1205		dev_kfree_skb(skb);1206	}1207 1208	return ret;1209}1210 1211int ath12k_wmi_send_pdev_set_regdomain(struct ath12k *ar,1212				       struct ath12k_wmi_pdev_set_regdomain_arg *arg)1213{1214	struct ath12k_wmi_pdev *wmi = ar->wmi;1215	struct wmi_pdev_set_regdomain_cmd *cmd;1216	struct sk_buff *skb;1217	int ret;1218 1219	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1220	if (!skb)1221		return -ENOMEM;1222 1223	cmd = (struct wmi_pdev_set_regdomain_cmd *)skb->data;1224	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_REGDOMAIN_CMD,1225						 sizeof(*cmd));1226 1227	cmd->reg_domain = cpu_to_le32(arg->current_rd_in_use);1228	cmd->reg_domain_2g = cpu_to_le32(arg->current_rd_2g);1229	cmd->reg_domain_5g = cpu_to_le32(arg->current_rd_5g);1230	cmd->conformance_test_limit_2g = cpu_to_le32(arg->ctl_2g);1231	cmd->conformance_test_limit_5g = cpu_to_le32(arg->ctl_5g);1232	cmd->dfs_domain = cpu_to_le32(arg->dfs_domain);1233	cmd->pdev_id = cpu_to_le32(arg->pdev_id);1234 1235	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1236		   "WMI pdev regd rd %d rd2g %d rd5g %d domain %d pdev id %d\n",1237		   arg->current_rd_in_use, arg->current_rd_2g,1238		   arg->current_rd_5g, arg->dfs_domain, arg->pdev_id);1239 1240	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_REGDOMAIN_CMDID);1241	if (ret) {1242		ath12k_warn(ar->ab,1243			    "failed to send WMI_PDEV_SET_REGDOMAIN cmd\n");1244		dev_kfree_skb(skb);1245	}1246 1247	return ret;1248}1249 1250int ath12k_wmi_set_peer_param(struct ath12k *ar, const u8 *peer_addr,1251			      u32 vdev_id, u32 param_id, u32 param_val)1252{1253	struct ath12k_wmi_pdev *wmi = ar->wmi;1254	struct wmi_peer_set_param_cmd *cmd;1255	struct sk_buff *skb;1256	int ret;1257 1258	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1259	if (!skb)1260		return -ENOMEM;1261 1262	cmd = (struct wmi_peer_set_param_cmd *)skb->data;1263	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_SET_PARAM_CMD,1264						 sizeof(*cmd));1265	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);1266	cmd->vdev_id = cpu_to_le32(vdev_id);1267	cmd->param_id = cpu_to_le32(param_id);1268	cmd->param_value = cpu_to_le32(param_val);1269 1270	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1271		   "WMI vdev %d peer 0x%pM set param %d value %d\n",1272		   vdev_id, peer_addr, param_id, param_val);1273 1274	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_SET_PARAM_CMDID);1275	if (ret) {1276		ath12k_warn(ar->ab, "failed to send WMI_PEER_SET_PARAM cmd\n");1277		dev_kfree_skb(skb);1278	}1279 1280	return ret;1281}1282 1283int ath12k_wmi_send_peer_flush_tids_cmd(struct ath12k *ar,1284					u8 peer_addr[ETH_ALEN],1285					u32 peer_tid_bitmap,1286					u8 vdev_id)1287{1288	struct ath12k_wmi_pdev *wmi = ar->wmi;1289	struct wmi_peer_flush_tids_cmd *cmd;1290	struct sk_buff *skb;1291	int ret;1292 1293	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1294	if (!skb)1295		return -ENOMEM;1296 1297	cmd = (struct wmi_peer_flush_tids_cmd *)skb->data;1298	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_FLUSH_TIDS_CMD,1299						 sizeof(*cmd));1300 1301	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);1302	cmd->peer_tid_bitmap = cpu_to_le32(peer_tid_bitmap);1303	cmd->vdev_id = cpu_to_le32(vdev_id);1304 1305	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1306		   "WMI peer flush vdev_id %d peer_addr %pM tids %08x\n",1307		   vdev_id, peer_addr, peer_tid_bitmap);1308 1309	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_FLUSH_TIDS_CMDID);1310	if (ret) {1311		ath12k_warn(ar->ab,1312			    "failed to send WMI_PEER_FLUSH_TIDS cmd\n");1313		dev_kfree_skb(skb);1314	}1315 1316	return ret;1317}1318 1319int ath12k_wmi_peer_rx_reorder_queue_setup(struct ath12k *ar,1320					   int vdev_id, const u8 *addr,1321					   dma_addr_t paddr, u8 tid,1322					   u8 ba_window_size_valid,1323					   u32 ba_window_size)1324{1325	struct wmi_peer_reorder_queue_setup_cmd *cmd;1326	struct sk_buff *skb;1327	int ret;1328 1329	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));1330	if (!skb)1331		return -ENOMEM;1332 1333	cmd = (struct wmi_peer_reorder_queue_setup_cmd *)skb->data;1334	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_REORDER_QUEUE_SETUP_CMD,1335						 sizeof(*cmd));1336 1337	ether_addr_copy(cmd->peer_macaddr.addr, addr);1338	cmd->vdev_id = cpu_to_le32(vdev_id);1339	cmd->tid = cpu_to_le32(tid);1340	cmd->queue_ptr_lo = cpu_to_le32(lower_32_bits(paddr));1341	cmd->queue_ptr_hi = cpu_to_le32(upper_32_bits(paddr));1342	cmd->queue_no = cpu_to_le32(tid);1343	cmd->ba_window_size_valid = cpu_to_le32(ba_window_size_valid);1344	cmd->ba_window_size = cpu_to_le32(ba_window_size);1345 1346	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1347		   "wmi rx reorder queue setup addr %pM vdev_id %d tid %d\n",1348		   addr, vdev_id, tid);1349 1350	ret = ath12k_wmi_cmd_send(ar->wmi, skb,1351				  WMI_PEER_REORDER_QUEUE_SETUP_CMDID);1352	if (ret) {1353		ath12k_warn(ar->ab,1354			    "failed to send WMI_PEER_REORDER_QUEUE_SETUP\n");1355		dev_kfree_skb(skb);1356	}1357 1358	return ret;1359}1360 1361int1362ath12k_wmi_rx_reord_queue_remove(struct ath12k *ar,1363				 struct ath12k_wmi_rx_reorder_queue_remove_arg *arg)1364{1365	struct ath12k_wmi_pdev *wmi = ar->wmi;1366	struct wmi_peer_reorder_queue_remove_cmd *cmd;1367	struct sk_buff *skb;1368	int ret;1369 1370	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1371	if (!skb)1372		return -ENOMEM;1373 1374	cmd = (struct wmi_peer_reorder_queue_remove_cmd *)skb->data;1375	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_REORDER_QUEUE_REMOVE_CMD,1376						 sizeof(*cmd));1377 1378	ether_addr_copy(cmd->peer_macaddr.addr, arg->peer_macaddr);1379	cmd->vdev_id = cpu_to_le32(arg->vdev_id);1380	cmd->tid_mask = cpu_to_le32(arg->peer_tid_bitmap);1381 1382	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1383		   "%s: peer_macaddr %pM vdev_id %d, tid_map %d", __func__,1384		   arg->peer_macaddr, arg->vdev_id, arg->peer_tid_bitmap);1385 1386	ret = ath12k_wmi_cmd_send(wmi, skb,1387				  WMI_PEER_REORDER_QUEUE_REMOVE_CMDID);1388	if (ret) {1389		ath12k_warn(ar->ab,1390			    "failed to send WMI_PEER_REORDER_QUEUE_REMOVE_CMDID");1391		dev_kfree_skb(skb);1392	}1393 1394	return ret;1395}1396 1397int ath12k_wmi_pdev_set_param(struct ath12k *ar, u32 param_id,1398			      u32 param_value, u8 pdev_id)1399{1400	struct ath12k_wmi_pdev *wmi = ar->wmi;1401	struct wmi_pdev_set_param_cmd *cmd;1402	struct sk_buff *skb;1403	int ret;1404 1405	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1406	if (!skb)1407		return -ENOMEM;1408 1409	cmd = (struct wmi_pdev_set_param_cmd *)skb->data;1410	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_PARAM_CMD,1411						 sizeof(*cmd));1412	cmd->pdev_id = cpu_to_le32(pdev_id);1413	cmd->param_id = cpu_to_le32(param_id);1414	cmd->param_value = cpu_to_le32(param_value);1415 1416	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1417		   "WMI pdev set param %d pdev id %d value %d\n",1418		   param_id, pdev_id, param_value);1419 1420	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_PARAM_CMDID);1421	if (ret) {1422		ath12k_warn(ar->ab, "failed to send WMI_PDEV_SET_PARAM cmd\n");1423		dev_kfree_skb(skb);1424	}1425 1426	return ret;1427}1428 1429int ath12k_wmi_pdev_set_ps_mode(struct ath12k *ar, int vdev_id, u32 enable)1430{1431	struct ath12k_wmi_pdev *wmi = ar->wmi;1432	struct wmi_pdev_set_ps_mode_cmd *cmd;1433	struct sk_buff *skb;1434	int ret;1435 1436	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1437	if (!skb)1438		return -ENOMEM;1439 1440	cmd = (struct wmi_pdev_set_ps_mode_cmd *)skb->data;1441	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_STA_POWERSAVE_MODE_CMD,1442						 sizeof(*cmd));1443	cmd->vdev_id = cpu_to_le32(vdev_id);1444	cmd->sta_ps_mode = cpu_to_le32(enable);1445 1446	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1447		   "WMI vdev set psmode %d vdev id %d\n",1448		   enable, vdev_id);1449 1450	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_STA_POWERSAVE_MODE_CMDID);1451	if (ret) {1452		ath12k_warn(ar->ab, "failed to send WMI_PDEV_SET_PARAM cmd\n");1453		dev_kfree_skb(skb);1454	}1455 1456	return ret;1457}1458 1459int ath12k_wmi_pdev_suspend(struct ath12k *ar, u32 suspend_opt,1460			    u32 pdev_id)1461{1462	struct ath12k_wmi_pdev *wmi = ar->wmi;1463	struct wmi_pdev_suspend_cmd *cmd;1464	struct sk_buff *skb;1465	int ret;1466 1467	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1468	if (!skb)1469		return -ENOMEM;1470 1471	cmd = (struct wmi_pdev_suspend_cmd *)skb->data;1472 1473	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SUSPEND_CMD,1474						 sizeof(*cmd));1475 1476	cmd->suspend_opt = cpu_to_le32(suspend_opt);1477	cmd->pdev_id = cpu_to_le32(pdev_id);1478 1479	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1480		   "WMI pdev suspend pdev_id %d\n", pdev_id);1481 1482	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PDEV_SUSPEND_CMDID);1483	if (ret) {1484		ath12k_warn(ar->ab, "failed to send WMI_PDEV_SUSPEND cmd\n");1485		dev_kfree_skb(skb);1486	}1487 1488	return ret;1489}1490 1491int ath12k_wmi_pdev_resume(struct ath12k *ar, u32 pdev_id)1492{1493	struct ath12k_wmi_pdev *wmi = ar->wmi;1494	struct wmi_pdev_resume_cmd *cmd;1495	struct sk_buff *skb;1496	int ret;1497 1498	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1499	if (!skb)1500		return -ENOMEM;1501 1502	cmd = (struct wmi_pdev_resume_cmd *)skb->data;1503 1504	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_RESUME_CMD,1505						 sizeof(*cmd));1506	cmd->pdev_id = cpu_to_le32(pdev_id);1507 1508	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1509		   "WMI pdev resume pdev id %d\n", pdev_id);1510 1511	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PDEV_RESUME_CMDID);1512	if (ret) {1513		ath12k_warn(ar->ab, "failed to send WMI_PDEV_RESUME cmd\n");1514		dev_kfree_skb(skb);1515	}1516 1517	return ret;1518}1519 1520/* TODO FW Support for the cmd is not available yet.1521 * Can be tested once the command and corresponding1522 * event is implemented in FW1523 */1524int ath12k_wmi_pdev_bss_chan_info_request(struct ath12k *ar,1525					  enum wmi_bss_chan_info_req_type type)1526{1527	struct ath12k_wmi_pdev *wmi = ar->wmi;1528	struct wmi_pdev_bss_chan_info_req_cmd *cmd;1529	struct sk_buff *skb;1530	int ret;1531 1532	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1533	if (!skb)1534		return -ENOMEM;1535 1536	cmd = (struct wmi_pdev_bss_chan_info_req_cmd *)skb->data;1537 1538	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST,1539						 sizeof(*cmd));1540	cmd->req_type = cpu_to_le32(type);1541	cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id);1542 1543	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1544		   "WMI bss chan info req type %d\n", type);1545 1546	ret = ath12k_wmi_cmd_send(wmi, skb,1547				  WMI_PDEV_BSS_CHAN_INFO_REQUEST_CMDID);1548	if (ret) {1549		ath12k_warn(ar->ab,1550			    "failed to send WMI_PDEV_BSS_CHAN_INFO_REQUEST cmd\n");1551		dev_kfree_skb(skb);1552	}1553 1554	return ret;1555}1556 1557int ath12k_wmi_send_set_ap_ps_param_cmd(struct ath12k *ar, u8 *peer_addr,1558					struct ath12k_wmi_ap_ps_arg *arg)1559{1560	struct ath12k_wmi_pdev *wmi = ar->wmi;1561	struct wmi_ap_ps_peer_cmd *cmd;1562	struct sk_buff *skb;1563	int ret;1564 1565	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1566	if (!skb)1567		return -ENOMEM;1568 1569	cmd = (struct wmi_ap_ps_peer_cmd *)skb->data;1570	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_AP_PS_PEER_CMD,1571						 sizeof(*cmd));1572 1573	cmd->vdev_id = cpu_to_le32(arg->vdev_id);1574	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);1575	cmd->param = cpu_to_le32(arg->param);1576	cmd->value = cpu_to_le32(arg->value);1577 1578	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1579		   "WMI set ap ps vdev id %d peer %pM param %d value %d\n",1580		   arg->vdev_id, peer_addr, arg->param, arg->value);1581 1582	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_AP_PS_PEER_PARAM_CMDID);1583	if (ret) {1584		ath12k_warn(ar->ab,1585			    "failed to send WMI_AP_PS_PEER_PARAM_CMDID\n");1586		dev_kfree_skb(skb);1587	}1588 1589	return ret;1590}1591 1592int ath12k_wmi_set_sta_ps_param(struct ath12k *ar, u32 vdev_id,1593				u32 param, u32 param_value)1594{1595	struct ath12k_wmi_pdev *wmi = ar->wmi;1596	struct wmi_sta_powersave_param_cmd *cmd;1597	struct sk_buff *skb;1598	int ret;1599 1600	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1601	if (!skb)1602		return -ENOMEM;1603 1604	cmd = (struct wmi_sta_powersave_param_cmd *)skb->data;1605	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_STA_POWERSAVE_PARAM_CMD,1606						 sizeof(*cmd));1607 1608	cmd->vdev_id = cpu_to_le32(vdev_id);1609	cmd->param = cpu_to_le32(param);1610	cmd->value = cpu_to_le32(param_value);1611 1612	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1613		   "WMI set sta ps vdev_id %d param %d value %d\n",1614		   vdev_id, param, param_value);1615 1616	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_STA_POWERSAVE_PARAM_CMDID);1617	if (ret) {1618		ath12k_warn(ar->ab, "failed to send WMI_STA_POWERSAVE_PARAM_CMDID");1619		dev_kfree_skb(skb);1620	}1621 1622	return ret;1623}1624 1625int ath12k_wmi_force_fw_hang_cmd(struct ath12k *ar, u32 type, u32 delay_time_ms)1626{1627	struct ath12k_wmi_pdev *wmi = ar->wmi;1628	struct wmi_force_fw_hang_cmd *cmd;1629	struct sk_buff *skb;1630	int ret, len;1631 1632	len = sizeof(*cmd);1633 1634	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);1635	if (!skb)1636		return -ENOMEM;1637 1638	cmd = (struct wmi_force_fw_hang_cmd *)skb->data;1639	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_FORCE_FW_HANG_CMD,1640						 len);1641 1642	cmd->type = cpu_to_le32(type);1643	cmd->delay_time_ms = cpu_to_le32(delay_time_ms);1644 1645	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_FORCE_FW_HANG_CMDID);1646 1647	if (ret) {1648		ath12k_warn(ar->ab, "Failed to send WMI_FORCE_FW_HANG_CMDID");1649		dev_kfree_skb(skb);1650	}1651	return ret;1652}1653 1654int ath12k_wmi_vdev_set_param_cmd(struct ath12k *ar, u32 vdev_id,1655				  u32 param_id, u32 param_value)1656{1657	struct ath12k_wmi_pdev *wmi = ar->wmi;1658	struct wmi_vdev_set_param_cmd *cmd;1659	struct sk_buff *skb;1660	int ret;1661 1662	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1663	if (!skb)1664		return -ENOMEM;1665 1666	cmd = (struct wmi_vdev_set_param_cmd *)skb->data;1667	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SET_PARAM_CMD,1668						 sizeof(*cmd));1669 1670	cmd->vdev_id = cpu_to_le32(vdev_id);1671	cmd->param_id = cpu_to_le32(param_id);1672	cmd->param_value = cpu_to_le32(param_value);1673 1674	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1675		   "WMI vdev id 0x%x set param %d value %d\n",1676		   vdev_id, param_id, param_value);1677 1678	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_SET_PARAM_CMDID);1679	if (ret) {1680		ath12k_warn(ar->ab,1681			    "failed to send WMI_VDEV_SET_PARAM_CMDID\n");1682		dev_kfree_skb(skb);1683	}1684 1685	return ret;1686}1687 1688int ath12k_wmi_send_pdev_temperature_cmd(struct ath12k *ar)1689{1690	struct ath12k_wmi_pdev *wmi = ar->wmi;1691	struct wmi_get_pdev_temperature_cmd *cmd;1692	struct sk_buff *skb;1693	int ret;1694 1695	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1696	if (!skb)1697		return -ENOMEM;1698 1699	cmd = (struct wmi_get_pdev_temperature_cmd *)skb->data;1700	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_GET_TEMPERATURE_CMD,1701						 sizeof(*cmd));1702	cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id);1703 1704	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1705		   "WMI pdev get temperature for pdev_id %d\n", ar->pdev->pdev_id);1706 1707	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PDEV_GET_TEMPERATURE_CMDID);1708	if (ret) {1709		ath12k_warn(ar->ab, "failed to send WMI_PDEV_GET_TEMPERATURE cmd\n");1710		dev_kfree_skb(skb);1711	}1712 1713	return ret;1714}1715 1716int ath12k_wmi_send_bcn_offload_control_cmd(struct ath12k *ar,1717					    u32 vdev_id, u32 bcn_ctrl_op)1718{1719	struct ath12k_wmi_pdev *wmi = ar->wmi;1720	struct wmi_bcn_offload_ctrl_cmd *cmd;1721	struct sk_buff *skb;1722	int ret;1723 1724	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));1725	if (!skb)1726		return -ENOMEM;1727 1728	cmd = (struct wmi_bcn_offload_ctrl_cmd *)skb->data;1729	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_BCN_OFFLOAD_CTRL_CMD,1730						 sizeof(*cmd));1731 1732	cmd->vdev_id = cpu_to_le32(vdev_id);1733	cmd->bcn_ctrl_op = cpu_to_le32(bcn_ctrl_op);1734 1735	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1736		   "WMI bcn ctrl offload vdev id %d ctrl_op %d\n",1737		   vdev_id, bcn_ctrl_op);1738 1739	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_BCN_OFFLOAD_CTRL_CMDID);1740	if (ret) {1741		ath12k_warn(ar->ab,1742			    "failed to send WMI_BCN_OFFLOAD_CTRL_CMDID\n");1743		dev_kfree_skb(skb);1744	}1745 1746	return ret;1747}1748 1749int ath12k_wmi_p2p_go_bcn_ie(struct ath12k *ar, u32 vdev_id,1750			     const u8 *p2p_ie)1751{1752	struct ath12k_wmi_pdev *wmi = ar->wmi;1753	struct wmi_p2p_go_set_beacon_ie_cmd *cmd;1754	size_t p2p_ie_len, aligned_len;1755	struct wmi_tlv *tlv;1756	struct sk_buff *skb;1757	void *ptr;1758	int ret, len;1759 1760	p2p_ie_len = p2p_ie[1] + 2;1761	aligned_len = roundup(p2p_ie_len, sizeof(u32));1762 1763	len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;1764 1765	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);1766	if (!skb)1767		return -ENOMEM;1768 1769	ptr = skb->data;1770	cmd = ptr;1771	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_P2P_GO_SET_BEACON_IE,1772						 sizeof(*cmd));1773	cmd->vdev_id = cpu_to_le32(vdev_id);1774	cmd->ie_buf_len = cpu_to_le32(p2p_ie_len);1775 1776	ptr += sizeof(*cmd);1777	tlv = ptr;1778	tlv->header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ARRAY_BYTE,1779					     aligned_len);1780	memcpy(tlv->value, p2p_ie, p2p_ie_len);1781 1782	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_P2P_GO_SET_BEACON_IE);1783	if (ret) {1784		ath12k_warn(ar->ab, "failed to send WMI_P2P_GO_SET_BEACON_IE\n");1785		dev_kfree_skb(skb);1786	}1787 1788	return ret;1789}1790 1791int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id,1792			struct ieee80211_mutable_offsets *offs,1793			struct sk_buff *bcn,1794			struct ath12k_wmi_bcn_tmpl_ema_arg *ema_args)1795{1796	struct ath12k_wmi_pdev *wmi = ar->wmi;1797	struct wmi_bcn_tmpl_cmd *cmd;1798	struct ath12k_wmi_bcn_prb_info_params *bcn_prb_info;1799	struct wmi_tlv *tlv;1800	struct sk_buff *skb;1801	u32 ema_params = 0;1802	void *ptr;1803	int ret, len;1804	size_t aligned_len = roundup(bcn->len, 4);1805 1806	len = sizeof(*cmd) + sizeof(*bcn_prb_info) + TLV_HDR_SIZE + aligned_len;1807 1808	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);1809	if (!skb)1810		return -ENOMEM;1811 1812	cmd = (struct wmi_bcn_tmpl_cmd *)skb->data;1813	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_BCN_TMPL_CMD,1814						 sizeof(*cmd));1815	cmd->vdev_id = cpu_to_le32(vdev_id);1816	cmd->tim_ie_offset = cpu_to_le32(offs->tim_offset);1817	cmd->csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[0]);1818	cmd->ext_csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[1]);1819	cmd->buf_len = cpu_to_le32(bcn->len);1820	cmd->mbssid_ie_offset = cpu_to_le32(offs->mbssid_off);1821	if (ema_args) {1822		u32p_replace_bits(&ema_params, ema_args->bcn_cnt, WMI_EMA_BEACON_CNT);1823		u32p_replace_bits(&ema_params, ema_args->bcn_index, WMI_EMA_BEACON_IDX);1824		if (ema_args->bcn_index == 0)1825			u32p_replace_bits(&ema_params, 1, WMI_EMA_BEACON_FIRST);1826		if (ema_args->bcn_index + 1 == ema_args->bcn_cnt)1827			u32p_replace_bits(&ema_params, 1, WMI_EMA_BEACON_LAST);1828		cmd->ema_params = cpu_to_le32(ema_params);1829	}1830 1831	ptr = skb->data + sizeof(*cmd);1832 1833	bcn_prb_info = ptr;1834	len = sizeof(*bcn_prb_info);1835	bcn_prb_info->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_BCN_PRB_INFO,1836							  len);1837	bcn_prb_info->caps = 0;1838	bcn_prb_info->erp = 0;1839 1840	ptr += sizeof(*bcn_prb_info);1841 1842	tlv = ptr;1843	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, aligned_len);1844	memcpy(tlv->value, bcn->data, bcn->len);1845 1846	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_BCN_TMPL_CMDID);1847	if (ret) {1848		ath12k_warn(ar->ab, "failed to send WMI_BCN_TMPL_CMDID\n");1849		dev_kfree_skb(skb);1850	}1851 1852	return ret;1853}1854 1855int ath12k_wmi_vdev_install_key(struct ath12k *ar,1856				struct wmi_vdev_install_key_arg *arg)1857{1858	struct ath12k_wmi_pdev *wmi = ar->wmi;1859	struct wmi_vdev_install_key_cmd *cmd;1860	struct wmi_tlv *tlv;1861	struct sk_buff *skb;1862	int ret, len, key_len_aligned;1863 1864	/* WMI_TAG_ARRAY_BYTE needs to be aligned with 4, the actual key1865	 * length is specified in cmd->key_len.1866	 */1867	key_len_aligned = roundup(arg->key_len, 4);1868 1869	len = sizeof(*cmd) + TLV_HDR_SIZE + key_len_aligned;1870 1871	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);1872	if (!skb)1873		return -ENOMEM;1874 1875	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;1876	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_INSTALL_KEY_CMD,1877						 sizeof(*cmd));1878	cmd->vdev_id = cpu_to_le32(arg->vdev_id);1879	ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);1880	cmd->key_idx = cpu_to_le32(arg->key_idx);1881	cmd->key_flags = cpu_to_le32(arg->key_flags);1882	cmd->key_cipher = cpu_to_le32(arg->key_cipher);1883	cmd->key_len = cpu_to_le32(arg->key_len);1884	cmd->key_txmic_len = cpu_to_le32(arg->key_txmic_len);1885	cmd->key_rxmic_len = cpu_to_le32(arg->key_rxmic_len);1886 1887	if (arg->key_rsc_counter)1888		cmd->key_rsc_counter = cpu_to_le64(arg->key_rsc_counter);1889 1890	tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));1891	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, key_len_aligned);1892	memcpy(tlv->value, arg->key_data, arg->key_len);1893 1894	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1895		   "WMI vdev install key idx %d cipher %d len %d\n",1896		   arg->key_idx, arg->key_cipher, arg->key_len);1897 1898	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_INSTALL_KEY_CMDID);1899	if (ret) {1900		ath12k_warn(ar->ab,1901			    "failed to send WMI_VDEV_INSTALL_KEY cmd\n");1902		dev_kfree_skb(skb);1903	}1904 1905	return ret;1906}1907 1908static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,1909				       struct ath12k_wmi_peer_assoc_arg *arg,1910				       bool hw_crypto_disabled)1911{1912	cmd->peer_flags = 0;1913	cmd->peer_flags_ext = 0;1914 1915	if (arg->is_wme_set) {1916		if (arg->qos_flag)1917			cmd->peer_flags |= cpu_to_le32(WMI_PEER_QOS);1918		if (arg->apsd_flag)1919			cmd->peer_flags |= cpu_to_le32(WMI_PEER_APSD);1920		if (arg->ht_flag)1921			cmd->peer_flags |= cpu_to_le32(WMI_PEER_HT);1922		if (arg->bw_40)1923			cmd->peer_flags |= cpu_to_le32(WMI_PEER_40MHZ);1924		if (arg->bw_80)1925			cmd->peer_flags |= cpu_to_le32(WMI_PEER_80MHZ);1926		if (arg->bw_160)1927			cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ);1928		if (arg->bw_320)1929			cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_320MHZ);1930 1931		/* Typically if STBC is enabled for VHT it should be enabled1932		 * for HT as well1933		 **/1934		if (arg->stbc_flag)1935			cmd->peer_flags |= cpu_to_le32(WMI_PEER_STBC);1936 1937		/* Typically if LDPC is enabled for VHT it should be enabled1938		 * for HT as well1939		 **/1940		if (arg->ldpc_flag)1941			cmd->peer_flags |= cpu_to_le32(WMI_PEER_LDPC);1942 1943		if (arg->static_mimops_flag)1944			cmd->peer_flags |= cpu_to_le32(WMI_PEER_STATIC_MIMOPS);1945		if (arg->dynamic_mimops_flag)1946			cmd->peer_flags |= cpu_to_le32(WMI_PEER_DYN_MIMOPS);1947		if (arg->spatial_mux_flag)1948			cmd->peer_flags |= cpu_to_le32(WMI_PEER_SPATIAL_MUX);1949		if (arg->vht_flag)1950			cmd->peer_flags |= cpu_to_le32(WMI_PEER_VHT);1951		if (arg->he_flag)1952			cmd->peer_flags |= cpu_to_le32(WMI_PEER_HE);1953		if (arg->twt_requester)1954			cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_REQ);1955		if (arg->twt_responder)1956			cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_RESP);1957		if (arg->eht_flag)1958			cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_EHT);1959	}1960 1961	/* Suppress authorization for all AUTH modes that need 4-way handshake1962	 * (during re-association).1963	 * Authorization will be done for these modes on key installation.1964	 */1965	if (arg->auth_flag)1966		cmd->peer_flags |= cpu_to_le32(WMI_PEER_AUTH);1967	if (arg->need_ptk_4_way) {1968		cmd->peer_flags |= cpu_to_le32(WMI_PEER_NEED_PTK_4_WAY);1969		if (!hw_crypto_disabled)1970			cmd->peer_flags &= cpu_to_le32(~WMI_PEER_AUTH);1971	}1972	if (arg->need_gtk_2_way)1973		cmd->peer_flags |= cpu_to_le32(WMI_PEER_NEED_GTK_2_WAY);1974	/* safe mode bypass the 4-way handshake */1975	if (arg->safe_mode_enabled)1976		cmd->peer_flags &= cpu_to_le32(~(WMI_PEER_NEED_PTK_4_WAY |1977						 WMI_PEER_NEED_GTK_2_WAY));1978 1979	if (arg->is_pmf_enabled)1980		cmd->peer_flags |= cpu_to_le32(WMI_PEER_PMF);1981 1982	/* Disable AMSDU for station transmit, if user configures it */1983	/* Disable AMSDU for AP transmit to 11n Stations, if user configures1984	 * it1985	 * if (arg->amsdu_disable) Add after FW support1986	 **/1987 1988	/* Target asserts if node is marked HT and all MCS is set to 0.1989	 * Mark the node as non-HT if all the mcs rates are disabled through1990	 * iwpriv1991	 **/1992	if (arg->peer_ht_rates.num_rates == 0)1993		cmd->peer_flags &= cpu_to_le32(~WMI_PEER_HT);1994}1995 1996int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,1997				   struct ath12k_wmi_peer_assoc_arg *arg)1998{1999	struct ath12k_wmi_pdev *wmi = ar->wmi;2000	struct wmi_peer_assoc_complete_cmd *cmd;2001	struct ath12k_wmi_vht_rate_set_params *mcs;2002	struct ath12k_wmi_he_rate_set_params *he_mcs;2003	struct ath12k_wmi_eht_rate_set_params *eht_mcs;2004	struct sk_buff *skb;2005	struct wmi_tlv *tlv;2006	void *ptr;2007	u32 peer_legacy_rates_align;2008	u32 peer_ht_rates_align;2009	int i, ret, len;2010 2011	peer_legacy_rates_align = roundup(arg->peer_legacy_rates.num_rates,2012					  sizeof(u32));2013	peer_ht_rates_align = roundup(arg->peer_ht_rates.num_rates,2014				      sizeof(u32));2015 2016	len = sizeof(*cmd) +2017	      TLV_HDR_SIZE + (peer_legacy_rates_align * sizeof(u8)) +2018	      TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) +2019	      sizeof(*mcs) + TLV_HDR_SIZE +2020	      (sizeof(*he_mcs) * arg->peer_he_mcs_count) +2021	      TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count) +2022	      TLV_HDR_SIZE + TLV_HDR_SIZE;2023 2024	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);2025	if (!skb)2026		return -ENOMEM;2027 2028	ptr = skb->data;2029 2030	cmd = ptr;2031	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_ASSOC_COMPLETE_CMD,2032						 sizeof(*cmd));2033 2034	cmd->vdev_id = cpu_to_le32(arg->vdev_id);2035 2036	cmd->peer_new_assoc = cpu_to_le32(arg->peer_new_assoc);2037	cmd->peer_associd = cpu_to_le32(arg->peer_associd);2038	cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap);2039 2040	ath12k_wmi_copy_peer_flags(cmd, arg,2041				   test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED,2042					    &ar->ab->dev_flags));2043 2044	ether_addr_copy(cmd->peer_macaddr.addr, arg->peer_mac);2045 2046	cmd->peer_rate_caps = cpu_to_le32(arg->peer_rate_caps);2047	cmd->peer_caps = cpu_to_le32(arg->peer_caps);2048	cmd->peer_listen_intval = cpu_to_le32(arg->peer_listen_intval);2049	cmd->peer_ht_caps = cpu_to_le32(arg->peer_ht_caps);2050	cmd->peer_max_mpdu = cpu_to_le32(arg->peer_max_mpdu);2051	cmd->peer_mpdu_density = cpu_to_le32(arg->peer_mpdu_density);2052	cmd->peer_vht_caps = cpu_to_le32(arg->peer_vht_caps);2053	cmd->peer_phymode = cpu_to_le32(arg->peer_phymode);2054 2055	/* Update 11ax capabilities */2056	cmd->peer_he_cap_info = cpu_to_le32(arg->peer_he_cap_macinfo[0]);2057	cmd->peer_he_cap_info_ext = cpu_to_le32(arg->peer_he_cap_macinfo[1]);2058	cmd->peer_he_cap_info_internal = cpu_to_le32(arg->peer_he_cap_macinfo_internal);2059	cmd->peer_he_caps_6ghz = cpu_to_le32(arg->peer_he_caps_6ghz);2060	cmd->peer_he_ops = cpu_to_le32(arg->peer_he_ops);2061	for (i = 0; i < WMI_MAX_HECAP_PHY_SIZE; i++)2062		cmd->peer_he_cap_phy[i] =2063			cpu_to_le32(arg->peer_he_cap_phyinfo[i]);2064	cmd->peer_ppet.numss_m1 = cpu_to_le32(arg->peer_ppet.numss_m1);2065	cmd->peer_ppet.ru_info = cpu_to_le32(arg->peer_ppet.ru_bit_mask);2066	for (i = 0; i < WMI_MAX_NUM_SS; i++)2067		cmd->peer_ppet.ppet16_ppet8_ru3_ru0[i] =2068			cpu_to_le32(arg->peer_ppet.ppet16_ppet8_ru3_ru0[i]);2069 2070	/* Update 11be capabilities */2071	memcpy_and_pad(cmd->peer_eht_cap_mac, sizeof(cmd->peer_eht_cap_mac),2072		       arg->peer_eht_cap_mac, sizeof(arg->peer_eht_cap_mac),2073		       0);2074	memcpy_and_pad(cmd->peer_eht_cap_phy, sizeof(cmd->peer_eht_cap_phy),2075		       arg->peer_eht_cap_phy, sizeof(arg->peer_eht_cap_phy),2076		       0);2077	memcpy_and_pad(&cmd->peer_eht_ppet, sizeof(cmd->peer_eht_ppet),2078		       &arg->peer_eht_ppet, sizeof(arg->peer_eht_ppet), 0);2079 2080	/* Update peer legacy rate information */2081	ptr += sizeof(*cmd);2082 2083	tlv = ptr;2084	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, peer_legacy_rates_align);2085 2086	ptr += TLV_HDR_SIZE;2087 2088	cmd->num_peer_legacy_rates = cpu_to_le32(arg->peer_legacy_rates.num_rates);2089	memcpy(ptr, arg->peer_legacy_rates.rates,2090	       arg->peer_legacy_rates.num_rates);2091 2092	/* Update peer HT rate information */2093	ptr += peer_legacy_rates_align;2094 2095	tlv = ptr;2096	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, peer_ht_rates_align);2097	ptr += TLV_HDR_SIZE;2098	cmd->num_peer_ht_rates = cpu_to_le32(arg->peer_ht_rates.num_rates);2099	memcpy(ptr, arg->peer_ht_rates.rates,2100	       arg->peer_ht_rates.num_rates);2101 2102	/* VHT Rates */2103	ptr += peer_ht_rates_align;2104 2105	mcs = ptr;2106 2107	mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VHT_RATE_SET,2108						 sizeof(*mcs));2109 2110	cmd->peer_nss = cpu_to_le32(arg->peer_nss);2111 2112	/* Update bandwidth-NSS mapping */2113	cmd->peer_bw_rxnss_override = 0;2114	cmd->peer_bw_rxnss_override |= cpu_to_le32(arg->peer_bw_rxnss_override);2115 2116	if (arg->vht_capable) {2117		mcs->rx_max_rate = cpu_to_le32(arg->rx_max_rate);2118		mcs->rx_mcs_set = cpu_to_le32(arg->rx_mcs_set);2119		mcs->tx_max_rate = cpu_to_le32(arg->tx_max_rate);2120		mcs->tx_mcs_set = cpu_to_le32(arg->tx_mcs_set);2121	}2122 2123	/* HE Rates */2124	cmd->peer_he_mcs = cpu_to_le32(arg->peer_he_mcs_count);2125	cmd->min_data_rate = cpu_to_le32(arg->min_data_rate);2126 2127	ptr += sizeof(*mcs);2128 2129	len = arg->peer_he_mcs_count * sizeof(*he_mcs);2130 2131	tlv = ptr;2132	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);2133	ptr += TLV_HDR_SIZE;2134 2135	/* Loop through the HE rate set */2136	for (i = 0; i < arg->peer_he_mcs_count; i++) {2137		he_mcs = ptr;2138		he_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET,2139							    sizeof(*he_mcs));2140 2141		he_mcs->rx_mcs_set = cpu_to_le32(arg->peer_he_rx_mcs_set[i]);2142		he_mcs->tx_mcs_set = cpu_to_le32(arg->peer_he_tx_mcs_set[i]);2143		ptr += sizeof(*he_mcs);2144	}2145 2146	/* MLO header tag with 0 length */2147	len = 0;2148	tlv = ptr;2149	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);2150	ptr += TLV_HDR_SIZE;2151 2152	/* Loop through the EHT rate set */2153	len = arg->peer_eht_mcs_count * sizeof(*eht_mcs);2154	tlv = ptr;2155	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);2156	ptr += TLV_HDR_SIZE;2157 2158	for (i = 0; i < arg->peer_eht_mcs_count; i++) {2159		eht_mcs = ptr;2160		eht_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET,2161							     sizeof(*eht_mcs));2162 2163		eht_mcs->rx_mcs_set = cpu_to_le32(arg->peer_eht_rx_mcs_set[i]);2164		eht_mcs->tx_mcs_set = cpu_to_le32(arg->peer_eht_tx_mcs_set[i]);2165		ptr += sizeof(*eht_mcs);2166	}2167 2168	/* ML partner links tag with 0 length */2169	len = 0;2170	tlv = ptr;2171	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);2172	ptr += TLV_HDR_SIZE;2173 2174	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2175		   "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x\n",2176		   cmd->vdev_id, cmd->peer_associd, arg->peer_mac,2177		   cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps,2178		   cmd->peer_listen_intval, cmd->peer_ht_caps,2179		   cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,2180		   cmd->peer_mpdu_density,2181		   cmd->peer_vht_caps, cmd->peer_he_cap_info,2182		   cmd->peer_he_ops, cmd->peer_he_cap_info_ext,2183		   cmd->peer_he_cap_phy[0], cmd->peer_he_cap_phy[1],2184		   cmd->peer_he_cap_phy[2],2185		   cmd->peer_bw_rxnss_override, cmd->peer_flags_ext,2186		   cmd->peer_eht_cap_mac[0], cmd->peer_eht_cap_mac[1],2187		   cmd->peer_eht_cap_phy[0], cmd->peer_eht_cap_phy[1],2188		   cmd->peer_eht_cap_phy[2]);2189 2190	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_ASSOC_CMDID);2191	if (ret) {2192		ath12k_warn(ar->ab,2193			    "failed to send WMI_PEER_ASSOC_CMDID\n");2194		dev_kfree_skb(skb);2195	}2196 2197	return ret;2198}2199 2200void ath12k_wmi_start_scan_init(struct ath12k *ar,2201				struct ath12k_wmi_scan_req_arg *arg)2202{2203	/* setup commonly used values */2204	arg->scan_req_id = 1;2205	arg->scan_priority = WMI_SCAN_PRIORITY_LOW;2206	arg->dwell_time_active = 50;2207	arg->dwell_time_active_2g = 0;2208	arg->dwell_time_passive = 150;2209	arg->dwell_time_active_6g = 40;2210	arg->dwell_time_passive_6g = 30;2211	arg->min_rest_time = 50;2212	arg->max_rest_time = 500;2213	arg->repeat_probe_time = 0;2214	arg->probe_spacing_time = 0;2215	arg->idle_time = 0;2216	arg->max_scan_time = 20000;2217	arg->probe_delay = 5;2218	arg->notify_scan_events = WMI_SCAN_EVENT_STARTED |2219				  WMI_SCAN_EVENT_COMPLETED |2220				  WMI_SCAN_EVENT_BSS_CHANNEL |2221				  WMI_SCAN_EVENT_FOREIGN_CHAN |2222				  WMI_SCAN_EVENT_DEQUEUED;2223	arg->scan_f_chan_stat_evnt = 1;2224	arg->num_bssid = 1;2225 2226	/* fill bssid_list[0] with 0xff, otherwise bssid and RA will be2227	 * ZEROs in probe request2228	 */2229	eth_broadcast_addr(arg->bssid_list[0].addr);2230}2231 2232static void ath12k_wmi_copy_scan_event_cntrl_flags(struct wmi_start_scan_cmd *cmd,2233						   struct ath12k_wmi_scan_req_arg *arg)2234{2235	/* Scan events subscription */2236	if (arg->scan_ev_started)2237		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_STARTED);2238	if (arg->scan_ev_completed)2239		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_COMPLETED);2240	if (arg->scan_ev_bss_chan)2241		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_BSS_CHANNEL);2242	if (arg->scan_ev_foreign_chan)2243		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_FOREIGN_CHAN);2244	if (arg->scan_ev_dequeued)2245		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_DEQUEUED);2246	if (arg->scan_ev_preempted)2247		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_PREEMPTED);2248	if (arg->scan_ev_start_failed)2249		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_START_FAILED);2250	if (arg->scan_ev_restarted)2251		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_RESTARTED);2252	if (arg->scan_ev_foreign_chn_exit)2253		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT);2254	if (arg->scan_ev_suspended)2255		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_SUSPENDED);2256	if (arg->scan_ev_resumed)2257		cmd->notify_scan_events |= cpu_to_le32(WMI_SCAN_EVENT_RESUMED);2258 2259	/** Set scan control flags */2260	cmd->scan_ctrl_flags = 0;2261	if (arg->scan_f_passive)2262		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_FLAG_PASSIVE);2263	if (arg->scan_f_strict_passive_pch)2264		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_FLAG_STRICT_PASSIVE_ON_PCHN);2265	if (arg->scan_f_promisc_mode)2266		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_FILTER_PROMISCUOS);2267	if (arg->scan_f_capture_phy_err)2268		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_CAPTURE_PHY_ERROR);2269	if (arg->scan_f_half_rate)2270		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_FLAG_HALF_RATE_SUPPORT);2271	if (arg->scan_f_quarter_rate)2272		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_FLAG_QUARTER_RATE_SUPPORT);2273	if (arg->scan_f_cck_rates)2274		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_ADD_CCK_RATES);2275	if (arg->scan_f_ofdm_rates)2276		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_ADD_OFDM_RATES);2277	if (arg->scan_f_chan_stat_evnt)2278		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_CHAN_STAT_EVENT);2279	if (arg->scan_f_filter_prb_req)2280		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);2281	if (arg->scan_f_bcast_probe)2282		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_ADD_BCAST_PROBE_REQ);2283	if (arg->scan_f_offchan_mgmt_tx)2284		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_OFFCHAN_MGMT_TX);2285	if (arg->scan_f_offchan_data_tx)2286		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_OFFCHAN_DATA_TX);2287	if (arg->scan_f_force_active_dfs_chn)2288		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_FLAG_FORCE_ACTIVE_ON_DFS);2289	if (arg->scan_f_add_tpc_ie_in_probe)2290		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_ADD_TPC_IE_IN_PROBE_REQ);2291	if (arg->scan_f_add_ds_ie_in_probe)2292		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ);2293	if (arg->scan_f_add_spoofed_mac_in_probe)2294		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_ADD_SPOOF_MAC_IN_PROBE_REQ);2295	if (arg->scan_f_add_rand_seq_in_probe)2296		cmd->scan_ctrl_flags |= cpu_to_le32(WMI_SCAN_RANDOM_SEQ_NO_IN_PROBE_REQ);2297	if (arg->scan_f_en_ie_whitelist_in_probe)2298		cmd->scan_ctrl_flags |=2299			cpu_to_le32(WMI_SCAN_ENABLE_IE_WHTELIST_IN_PROBE_REQ);2300 2301	cmd->scan_ctrl_flags |= le32_encode_bits(arg->adaptive_dwell_time_mode,2302						 WMI_SCAN_DWELL_MODE_MASK);2303}2304 2305int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,2306				   struct ath12k_wmi_scan_req_arg *arg)2307{2308	struct ath12k_wmi_pdev *wmi = ar->wmi;2309	struct wmi_start_scan_cmd *cmd;2310	struct ath12k_wmi_ssid_params *ssid = NULL;2311	struct ath12k_wmi_mac_addr_params *bssid;2312	struct sk_buff *skb;2313	struct wmi_tlv *tlv;2314	void *ptr;2315	int i, ret, len;2316	u32 *tmp_ptr, extraie_len_with_pad = 0;2317	struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL;2318	struct ath12k_wmi_hint_bssid_arg *hint_bssid = NULL;2319 2320	len = sizeof(*cmd);2321 2322	len += TLV_HDR_SIZE;2323	if (arg->num_chan)2324		len += arg->num_chan * sizeof(u32);2325 2326	len += TLV_HDR_SIZE;2327	if (arg->num_ssids)2328		len += arg->num_ssids * sizeof(*ssid);2329 2330	len += TLV_HDR_SIZE;2331	if (arg->num_bssid)2332		len += sizeof(*bssid) * arg->num_bssid;2333 2334	if (arg->num_hint_bssid)2335		len += TLV_HDR_SIZE +2336		       arg->num_hint_bssid * sizeof(*hint_bssid);2337 2338	if (arg->num_hint_s_ssid)2339		len += TLV_HDR_SIZE +2340		       arg->num_hint_s_ssid * sizeof(*s_ssid);2341 2342	len += TLV_HDR_SIZE;2343	if (arg->extraie.len)2344		extraie_len_with_pad =2345			roundup(arg->extraie.len, sizeof(u32));2346	if (extraie_len_with_pad <= (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len)) {2347		len += extraie_len_with_pad;2348	} else {2349		ath12k_warn(ar->ab, "discard large size %d bytes extraie for scan start\n",2350			    arg->extraie.len);2351		extraie_len_with_pad = 0;2352	}2353 2354	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);2355	if (!skb)2356		return -ENOMEM;2357 2358	ptr = skb->data;2359 2360	cmd = ptr;2361	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_START_SCAN_CMD,2362						 sizeof(*cmd));2363 2364	cmd->scan_id = cpu_to_le32(arg->scan_id);2365	cmd->scan_req_id = cpu_to_le32(arg->scan_req_id);2366	cmd->vdev_id = cpu_to_le32(arg->vdev_id);2367	cmd->scan_priority = cpu_to_le32(arg->scan_priority);2368	cmd->notify_scan_events = cpu_to_le32(arg->notify_scan_events);2369 2370	ath12k_wmi_copy_scan_event_cntrl_flags(cmd, arg);2371 2372	cmd->dwell_time_active = cpu_to_le32(arg->dwell_time_active);2373	cmd->dwell_time_active_2g = cpu_to_le32(arg->dwell_time_active_2g);2374	cmd->dwell_time_passive = cpu_to_le32(arg->dwell_time_passive);2375	cmd->dwell_time_active_6g = cpu_to_le32(arg->dwell_time_active_6g);2376	cmd->dwell_time_passive_6g = cpu_to_le32(arg->dwell_time_passive_6g);2377	cmd->min_rest_time = cpu_to_le32(arg->min_rest_time);2378	cmd->max_rest_time = cpu_to_le32(arg->max_rest_time);2379	cmd->repeat_probe_time = cpu_to_le32(arg->repeat_probe_time);2380	cmd->probe_spacing_time = cpu_to_le32(arg->probe_spacing_time);2381	cmd->idle_time = cpu_to_le32(arg->idle_time);2382	cmd->max_scan_time = cpu_to_le32(arg->max_scan_time);2383	cmd->probe_delay = cpu_to_le32(arg->probe_delay);2384	cmd->burst_duration = cpu_to_le32(arg->burst_duration);2385	cmd->num_chan = cpu_to_le32(arg->num_chan);2386	cmd->num_bssid = cpu_to_le32(arg->num_bssid);2387	cmd->num_ssids = cpu_to_le32(arg->num_ssids);2388	cmd->ie_len = cpu_to_le32(arg->extraie.len);2389	cmd->n_probes = cpu_to_le32(arg->n_probes);2390 2391	ptr += sizeof(*cmd);2392 2393	len = arg->num_chan * sizeof(u32);2394 2395	tlv = ptr;2396	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, len);2397	ptr += TLV_HDR_SIZE;2398	tmp_ptr = (u32 *)ptr;2399 2400	memcpy(tmp_ptr, arg->chan_list, arg->num_chan * 4);2401 2402	ptr += len;2403 2404	len = arg->num_ssids * sizeof(*ssid);2405	tlv = ptr;2406	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_FIXED_STRUCT, len);2407 2408	ptr += TLV_HDR_SIZE;2409 2410	if (arg->num_ssids) {2411		ssid = ptr;2412		for (i = 0; i < arg->num_ssids; ++i) {2413			ssid->ssid_len = cpu_to_le32(arg->ssid[i].ssid_len);2414			memcpy(ssid->ssid, arg->ssid[i].ssid,2415			       arg->ssid[i].ssid_len);2416			ssid++;2417		}2418	}2419 2420	ptr += (arg->num_ssids * sizeof(*ssid));2421	len = arg->num_bssid * sizeof(*bssid);2422	tlv = ptr;2423	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_FIXED_STRUCT, len);2424 2425	ptr += TLV_HDR_SIZE;2426	bssid = ptr;2427 2428	if (arg->num_bssid) {2429		for (i = 0; i < arg->num_bssid; ++i) {2430			ether_addr_copy(bssid->addr,2431					arg->bssid_list[i].addr);2432			bssid++;2433		}2434	}2435 2436	ptr += arg->num_bssid * sizeof(*bssid);2437 2438	len = extraie_len_with_pad;2439	tlv = ptr;2440	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len);2441	ptr += TLV_HDR_SIZE;2442 2443	if (extraie_len_with_pad)2444		memcpy(ptr, arg->extraie.ptr,2445		       arg->extraie.len);2446 2447	ptr += extraie_len_with_pad;2448 2449	if (arg->num_hint_s_ssid) {2450		len = arg->num_hint_s_ssid * sizeof(*s_ssid);2451		tlv = ptr;2452		tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_FIXED_STRUCT, len);2453		ptr += TLV_HDR_SIZE;2454		s_ssid = ptr;2455		for (i = 0; i < arg->num_hint_s_ssid; ++i) {2456			s_ssid->freq_flags = arg->hint_s_ssid[i].freq_flags;2457			s_ssid->short_ssid = arg->hint_s_ssid[i].short_ssid;2458			s_ssid++;2459		}2460		ptr += len;2461	}2462 2463	if (arg->num_hint_bssid) {2464		len = arg->num_hint_bssid * sizeof(struct ath12k_wmi_hint_bssid_arg);2465		tlv = ptr;2466		tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_FIXED_STRUCT, len);2467		ptr += TLV_HDR_SIZE;2468		hint_bssid = ptr;2469		for (i = 0; i < arg->num_hint_bssid; ++i) {2470			hint_bssid->freq_flags =2471				arg->hint_bssid[i].freq_flags;2472			ether_addr_copy(&arg->hint_bssid[i].bssid.addr[0],2473					&hint_bssid->bssid.addr[0]);2474			hint_bssid++;2475		}2476	}2477 2478	ret = ath12k_wmi_cmd_send(wmi, skb,2479				  WMI_START_SCAN_CMDID);2480	if (ret) {2481		ath12k_warn(ar->ab, "failed to send WMI_START_SCAN_CMDID\n");2482		dev_kfree_skb(skb);2483	}2484 2485	return ret;2486}2487 2488int ath12k_wmi_send_scan_stop_cmd(struct ath12k *ar,2489				  struct ath12k_wmi_scan_cancel_arg *arg)2490{2491	struct ath12k_wmi_pdev *wmi = ar->wmi;2492	struct wmi_stop_scan_cmd *cmd;2493	struct sk_buff *skb;2494	int ret;2495 2496	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));2497	if (!skb)2498		return -ENOMEM;2499 2500	cmd = (struct wmi_stop_scan_cmd *)skb->data;2501 2502	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_STOP_SCAN_CMD,2503						 sizeof(*cmd));2504 2505	cmd->vdev_id = cpu_to_le32(arg->vdev_id);2506	cmd->requestor = cpu_to_le32(arg->requester);2507	cmd->scan_id = cpu_to_le32(arg->scan_id);2508	cmd->pdev_id = cpu_to_le32(arg->pdev_id);2509	/* stop the scan with the corresponding scan_id */2510	if (arg->req_type == WLAN_SCAN_CANCEL_PDEV_ALL) {2511		/* Cancelling all scans */2512		cmd->req_type = cpu_to_le32(WMI_SCAN_STOP_ALL);2513	} else if (arg->req_type == WLAN_SCAN_CANCEL_VDEV_ALL) {2514		/* Cancelling VAP scans */2515		cmd->req_type = cpu_to_le32(WMI_SCAN_STOP_VAP_ALL);2516	} else if (arg->req_type == WLAN_SCAN_CANCEL_SINGLE) {2517		/* Cancelling specific scan */2518		cmd->req_type = WMI_SCAN_STOP_ONE;2519	} else {2520		ath12k_warn(ar->ab, "invalid scan cancel req_type %d",2521			    arg->req_type);2522		dev_kfree_skb(skb);2523		return -EINVAL;2524	}2525 2526	ret = ath12k_wmi_cmd_send(wmi, skb,2527				  WMI_STOP_SCAN_CMDID);2528	if (ret) {2529		ath12k_warn(ar->ab, "failed to send WMI_STOP_SCAN_CMDID\n");2530		dev_kfree_skb(skb);2531	}2532 2533	return ret;2534}2535 2536int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar,2537				       struct ath12k_wmi_scan_chan_list_arg *arg)2538{2539	struct ath12k_wmi_pdev *wmi = ar->wmi;2540	struct wmi_scan_chan_list_cmd *cmd;2541	struct sk_buff *skb;2542	struct ath12k_wmi_channel_params *chan_info;2543	struct ath12k_wmi_channel_arg *channel_arg;2544	struct wmi_tlv *tlv;2545	void *ptr;2546	int i, ret, len;2547	u16 num_send_chans, num_sends = 0, max_chan_limit = 0;2548	__le32 *reg1, *reg2;2549 2550	channel_arg = &arg->channel[0];2551	while (arg->nallchans) {2552		len = sizeof(*cmd) + TLV_HDR_SIZE;2553		max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) /2554			sizeof(*chan_info);2555 2556		num_send_chans = min(arg->nallchans, max_chan_limit);2557 2558		arg->nallchans -= num_send_chans;2559		len += sizeof(*chan_info) * num_send_chans;2560 2561		skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);2562		if (!skb)2563			return -ENOMEM;2564 2565		cmd = (struct wmi_scan_chan_list_cmd *)skb->data;2566		cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SCAN_CHAN_LIST_CMD,2567							 sizeof(*cmd));2568		cmd->pdev_id = cpu_to_le32(arg->pdev_id);2569		cmd->num_scan_chans = cpu_to_le32(num_send_chans);2570		if (num_sends)2571			cmd->flags |= cpu_to_le32(WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG);2572 2573		ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2574			   "WMI no.of chan = %d len = %d pdev_id = %d num_sends = %d\n",2575			   num_send_chans, len, cmd->pdev_id, num_sends);2576 2577		ptr = skb->data + sizeof(*cmd);2578 2579		len = sizeof(*chan_info) * num_send_chans;2580		tlv = ptr;2581		tlv->header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ARRAY_STRUCT,2582						     len);2583		ptr += TLV_HDR_SIZE;2584 2585		for (i = 0; i < num_send_chans; ++i) {2586			chan_info = ptr;2587			memset(chan_info, 0, sizeof(*chan_info));2588			len = sizeof(*chan_info);2589			chan_info->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_CHANNEL,2590								       len);2591 2592			reg1 = &chan_info->reg_info_1;2593			reg2 = &chan_info->reg_info_2;2594			chan_info->mhz = cpu_to_le32(channel_arg->mhz);2595			chan_info->band_center_freq1 = cpu_to_le32(channel_arg->cfreq1);2596			chan_info->band_center_freq2 = cpu_to_le32(channel_arg->cfreq2);2597 2598			if (channel_arg->is_chan_passive)2599				chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_PASSIVE);2600			if (channel_arg->allow_he)2601				chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_HE);2602			else if (channel_arg->allow_vht)2603				chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_VHT);2604			else if (channel_arg->allow_ht)2605				chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_HT);2606			if (channel_arg->half_rate)2607				chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_HALF_RATE);2608			if (channel_arg->quarter_rate)2609				chan_info->info |=2610					cpu_to_le32(WMI_CHAN_INFO_QUARTER_RATE);2611 2612			if (channel_arg->psc_channel)2613				chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_PSC);2614 2615			if (channel_arg->dfs_set)2616				chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_DFS);2617 2618			chan_info->info |= le32_encode_bits(channel_arg->phy_mode,2619							    WMI_CHAN_INFO_MODE);2620			*reg1 |= le32_encode_bits(channel_arg->minpower,2621						  WMI_CHAN_REG_INFO1_MIN_PWR);2622			*reg1 |= le32_encode_bits(channel_arg->maxpower,2623						  WMI_CHAN_REG_INFO1_MAX_PWR);2624			*reg1 |= le32_encode_bits(channel_arg->maxregpower,2625						  WMI_CHAN_REG_INFO1_MAX_REG_PWR);2626			*reg1 |= le32_encode_bits(channel_arg->reg_class_id,2627						  WMI_CHAN_REG_INFO1_REG_CLS);2628			*reg2 |= le32_encode_bits(channel_arg->antennamax,2629						  WMI_CHAN_REG_INFO2_ANT_MAX);2630 2631			ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2632				   "WMI chan scan list chan[%d] = %u, chan_info->info %8x\n",2633				   i, chan_info->mhz, chan_info->info);2634 2635			ptr += sizeof(*chan_info);2636 2637			channel_arg++;2638		}2639 2640		ret = ath12k_wmi_cmd_send(wmi, skb, WMI_SCAN_CHAN_LIST_CMDID);2641		if (ret) {2642			ath12k_warn(ar->ab, "failed to send WMI_SCAN_CHAN_LIST cmd\n");2643			dev_kfree_skb(skb);2644			return ret;2645		}2646 2647		num_sends++;2648	}2649 2650	return 0;2651}2652 2653int ath12k_wmi_send_wmm_update_cmd(struct ath12k *ar, u32 vdev_id,2654				   struct wmi_wmm_params_all_arg *param)2655{2656	struct ath12k_wmi_pdev *wmi = ar->wmi;2657	struct wmi_vdev_set_wmm_params_cmd *cmd;2658	struct wmi_wmm_params *wmm_param;2659	struct wmi_wmm_params_arg *wmi_wmm_arg;2660	struct sk_buff *skb;2661	int ret, ac;2662 2663	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));2664	if (!skb)2665		return -ENOMEM;2666 2667	cmd = (struct wmi_vdev_set_wmm_params_cmd *)skb->data;2668	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SET_WMM_PARAMS_CMD,2669						 sizeof(*cmd));2670 2671	cmd->vdev_id = cpu_to_le32(vdev_id);2672	cmd->wmm_param_type = 0;2673 2674	for (ac = 0; ac < WME_NUM_AC; ac++) {2675		switch (ac) {2676		case WME_AC_BE:2677			wmi_wmm_arg = &param->ac_be;2678			break;2679		case WME_AC_BK:2680			wmi_wmm_arg = &param->ac_bk;2681			break;2682		case WME_AC_VI:2683			wmi_wmm_arg = &param->ac_vi;2684			break;2685		case WME_AC_VO:2686			wmi_wmm_arg = &param->ac_vo;2687			break;2688		}2689 2690		wmm_param = (struct wmi_wmm_params *)&cmd->wmm_params[ac];2691		wmm_param->tlv_header =2692			ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SET_WMM_PARAMS_CMD,2693					       sizeof(*wmm_param));2694 2695		wmm_param->aifs = cpu_to_le32(wmi_wmm_arg->aifs);2696		wmm_param->cwmin = cpu_to_le32(wmi_wmm_arg->cwmin);2697		wmm_param->cwmax = cpu_to_le32(wmi_wmm_arg->cwmax);2698		wmm_param->txoplimit = cpu_to_le32(wmi_wmm_arg->txop);2699		wmm_param->acm = cpu_to_le32(wmi_wmm_arg->acm);2700		wmm_param->no_ack = cpu_to_le32(wmi_wmm_arg->no_ack);2701 2702		ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2703			   "wmi wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n",2704			   ac, wmm_param->aifs, wmm_param->cwmin,2705			   wmm_param->cwmax, wmm_param->txoplimit,2706			   wmm_param->acm, wmm_param->no_ack);2707	}2708	ret = ath12k_wmi_cmd_send(wmi, skb,2709				  WMI_VDEV_SET_WMM_PARAMS_CMDID);2710	if (ret) {2711		ath12k_warn(ar->ab,2712			    "failed to send WMI_VDEV_SET_WMM_PARAMS_CMDID");2713		dev_kfree_skb(skb);2714	}2715 2716	return ret;2717}2718 2719int ath12k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath12k *ar,2720						  u32 pdev_id)2721{2722	struct ath12k_wmi_pdev *wmi = ar->wmi;2723	struct wmi_dfs_phyerr_offload_cmd *cmd;2724	struct sk_buff *skb;2725	int ret;2726 2727	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));2728	if (!skb)2729		return -ENOMEM;2730 2731	cmd = (struct wmi_dfs_phyerr_offload_cmd *)skb->data;2732	cmd->tlv_header =2733		ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_DFS_PHYERR_OFFLOAD_ENABLE_CMD,2734				       sizeof(*cmd));2735 2736	cmd->pdev_id = cpu_to_le32(pdev_id);2737 2738	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2739		   "WMI dfs phy err offload enable pdev id %d\n", pdev_id);2740 2741	ret = ath12k_wmi_cmd_send(wmi, skb,2742				  WMI_PDEV_DFS_PHYERR_OFFLOAD_ENABLE_CMDID);2743	if (ret) {2744		ath12k_warn(ar->ab,2745			    "failed to send WMI_PDEV_DFS_PHYERR_OFFLOAD_ENABLE cmd\n");2746		dev_kfree_skb(skb);2747	}2748 2749	return ret;2750}2751 2752int ath12k_wmi_set_bios_cmd(struct ath12k_base *ab, u32 param_id,2753			    const u8 *buf, size_t buf_len)2754{2755	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;2756	struct wmi_pdev_set_bios_interface_cmd *cmd;2757	struct wmi_tlv *tlv;2758	struct sk_buff *skb;2759	u8 *ptr;2760	u32 len, len_aligned;2761	int ret;2762 2763	len_aligned = roundup(buf_len, sizeof(u32));2764	len = sizeof(*cmd) + TLV_HDR_SIZE + len_aligned;2765 2766	skb = ath12k_wmi_alloc_skb(wmi_ab, len);2767	if (!skb)2768		return -ENOMEM;2769 2770	cmd = (struct wmi_pdev_set_bios_interface_cmd *)skb->data;2771	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD,2772						 sizeof(*cmd));2773	cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC);2774	cmd->param_type_id = cpu_to_le32(param_id);2775	cmd->length = cpu_to_le32(buf_len);2776 2777	ptr = skb->data + sizeof(*cmd);2778	tlv = (struct wmi_tlv *)ptr;2779	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len_aligned);2780	ptr += TLV_HDR_SIZE;2781	memcpy(ptr, buf, buf_len);2782 2783	ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0],2784				  skb,2785				  WMI_PDEV_SET_BIOS_INTERFACE_CMDID);2786	if (ret) {2787		ath12k_warn(ab,2788			    "failed to send WMI_PDEV_SET_BIOS_INTERFACE_CMDID parameter id %d: %d\n",2789			    param_id, ret);2790		dev_kfree_skb(skb);2791	}2792 2793	return 0;2794}2795 2796int ath12k_wmi_set_bios_sar_cmd(struct ath12k_base *ab, const u8 *psar_table)2797{2798	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;2799	struct wmi_pdev_set_bios_sar_table_cmd *cmd;2800	struct wmi_tlv *tlv;2801	struct sk_buff *skb;2802	int ret;2803	u8 *buf_ptr;2804	u32 len, sar_table_len_aligned, sar_dbs_backoff_len_aligned;2805	const u8 *psar_value = psar_table + ATH12K_ACPI_POWER_LIMIT_DATA_OFFSET;2806	const u8 *pdbs_value = psar_table + ATH12K_ACPI_DBS_BACKOFF_DATA_OFFSET;2807 2808	sar_table_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_TABLE_LEN, sizeof(u32));2809	sar_dbs_backoff_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN,2810					      sizeof(u32));2811	len = sizeof(*cmd) + TLV_HDR_SIZE + sar_table_len_aligned +2812		TLV_HDR_SIZE + sar_dbs_backoff_len_aligned;2813 2814	skb = ath12k_wmi_alloc_skb(wmi_ab, len);2815	if (!skb)2816		return -ENOMEM;2817 2818	cmd = (struct wmi_pdev_set_bios_sar_table_cmd *)skb->data;2819	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD,2820						 sizeof(*cmd));2821	cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC);2822	cmd->sar_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_TABLE_LEN);2823	cmd->dbs_backoff_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN);2824 2825	buf_ptr = skb->data + sizeof(*cmd);2826	tlv = (struct wmi_tlv *)buf_ptr;2827	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE,2828					 sar_table_len_aligned);2829	buf_ptr += TLV_HDR_SIZE;2830	memcpy(buf_ptr, psar_value, ATH12K_ACPI_BIOS_SAR_TABLE_LEN);2831 2832	buf_ptr += sar_table_len_aligned;2833	tlv = (struct wmi_tlv *)buf_ptr;2834	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE,2835					 sar_dbs_backoff_len_aligned);2836	buf_ptr += TLV_HDR_SIZE;2837	memcpy(buf_ptr, pdbs_value, ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN);2838 2839	ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0],2840				  skb,2841				  WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID);2842	if (ret) {2843		ath12k_warn(ab,2844			    "failed to send WMI_PDEV_SET_BIOS_INTERFACE_CMDID %d\n",2845			    ret);2846		dev_kfree_skb(skb);2847	}2848 2849	return ret;2850}2851 2852int ath12k_wmi_set_bios_geo_cmd(struct ath12k_base *ab, const u8 *pgeo_table)2853{2854	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;2855	struct wmi_pdev_set_bios_geo_table_cmd *cmd;2856	struct wmi_tlv *tlv;2857	struct sk_buff *skb;2858	int ret;2859	u8 *buf_ptr;2860	u32 len, sar_geo_len_aligned;2861	const u8 *pgeo_value = pgeo_table + ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET;2862 2863	sar_geo_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN, sizeof(u32));2864	len = sizeof(*cmd) + TLV_HDR_SIZE + sar_geo_len_aligned;2865 2866	skb = ath12k_wmi_alloc_skb(wmi_ab, len);2867	if (!skb)2868		return -ENOMEM;2869 2870	cmd = (struct wmi_pdev_set_bios_geo_table_cmd *)skb->data;2871	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD,2872						 sizeof(*cmd));2873	cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC);2874	cmd->geo_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN);2875 2876	buf_ptr = skb->data + sizeof(*cmd);2877	tlv = (struct wmi_tlv *)buf_ptr;2878	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, sar_geo_len_aligned);2879	buf_ptr += TLV_HDR_SIZE;2880	memcpy(buf_ptr, pgeo_value, ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN);2881 2882	ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0],2883				  skb,2884				  WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);2885	if (ret) {2886		ath12k_warn(ab,2887			    "failed to send WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID %d\n",2888			    ret);2889		dev_kfree_skb(skb);2890	}2891 2892	return ret;2893}2894 2895int ath12k_wmi_delba_send(struct ath12k *ar, u32 vdev_id, const u8 *mac,2896			  u32 tid, u32 initiator, u32 reason)2897{2898	struct ath12k_wmi_pdev *wmi = ar->wmi;2899	struct wmi_delba_send_cmd *cmd;2900	struct sk_buff *skb;2901	int ret;2902 2903	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));2904	if (!skb)2905		return -ENOMEM;2906 2907	cmd = (struct wmi_delba_send_cmd *)skb->data;2908	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_DELBA_SEND_CMD,2909						 sizeof(*cmd));2910	cmd->vdev_id = cpu_to_le32(vdev_id);2911	ether_addr_copy(cmd->peer_macaddr.addr, mac);2912	cmd->tid = cpu_to_le32(tid);2913	cmd->initiator = cpu_to_le32(initiator);2914	cmd->reasoncode = cpu_to_le32(reason);2915 2916	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2917		   "wmi delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n",2918		   vdev_id, mac, tid, initiator, reason);2919 2920	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_DELBA_SEND_CMDID);2921 2922	if (ret) {2923		ath12k_warn(ar->ab,2924			    "failed to send WMI_DELBA_SEND_CMDID cmd\n");2925		dev_kfree_skb(skb);2926	}2927 2928	return ret;2929}2930 2931int ath12k_wmi_addba_set_resp(struct ath12k *ar, u32 vdev_id, const u8 *mac,2932			      u32 tid, u32 status)2933{2934	struct ath12k_wmi_pdev *wmi = ar->wmi;2935	struct wmi_addba_setresponse_cmd *cmd;2936	struct sk_buff *skb;2937	int ret;2938 2939	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));2940	if (!skb)2941		return -ENOMEM;2942 2943	cmd = (struct wmi_addba_setresponse_cmd *)skb->data;2944	cmd->tlv_header =2945		ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ADDBA_SETRESPONSE_CMD,2946				       sizeof(*cmd));2947	cmd->vdev_id = cpu_to_le32(vdev_id);2948	ether_addr_copy(cmd->peer_macaddr.addr, mac);2949	cmd->tid = cpu_to_le32(tid);2950	cmd->statuscode = cpu_to_le32(status);2951 2952	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2953		   "wmi addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n",2954		   vdev_id, mac, tid, status);2955 2956	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SET_RESP_CMDID);2957 2958	if (ret) {2959		ath12k_warn(ar->ab,2960			    "failed to send WMI_ADDBA_SET_RESP_CMDID cmd\n");2961		dev_kfree_skb(skb);2962	}2963 2964	return ret;2965}2966 2967int ath12k_wmi_addba_send(struct ath12k *ar, u32 vdev_id, const u8 *mac,2968			  u32 tid, u32 buf_size)2969{2970	struct ath12k_wmi_pdev *wmi = ar->wmi;2971	struct wmi_addba_send_cmd *cmd;2972	struct sk_buff *skb;2973	int ret;2974 2975	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));2976	if (!skb)2977		return -ENOMEM;2978 2979	cmd = (struct wmi_addba_send_cmd *)skb->data;2980	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ADDBA_SEND_CMD,2981						 sizeof(*cmd));2982	cmd->vdev_id = cpu_to_le32(vdev_id);2983	ether_addr_copy(cmd->peer_macaddr.addr, mac);2984	cmd->tid = cpu_to_le32(tid);2985	cmd->buffersize = cpu_to_le32(buf_size);2986 2987	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,2988		   "wmi addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n",2989		   vdev_id, mac, tid, buf_size);2990 2991	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SEND_CMDID);2992 2993	if (ret) {2994		ath12k_warn(ar->ab,2995			    "failed to send WMI_ADDBA_SEND_CMDID cmd\n");2996		dev_kfree_skb(skb);2997	}2998 2999	return ret;3000}3001 3002int ath12k_wmi_addba_clear_resp(struct ath12k *ar, u32 vdev_id, const u8 *mac)3003{3004	struct ath12k_wmi_pdev *wmi = ar->wmi;3005	struct wmi_addba_clear_resp_cmd *cmd;3006	struct sk_buff *skb;3007	int ret;3008 3009	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));3010	if (!skb)3011		return -ENOMEM;3012 3013	cmd = (struct wmi_addba_clear_resp_cmd *)skb->data;3014	cmd->tlv_header =3015		ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ADDBA_CLEAR_RESP_CMD,3016				       sizeof(*cmd));3017	cmd->vdev_id = cpu_to_le32(vdev_id);3018	ether_addr_copy(cmd->peer_macaddr.addr, mac);3019 3020	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3021		   "wmi addba clear resp vdev_id 0x%X mac_addr %pM\n",3022		   vdev_id, mac);3023 3024	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_ADDBA_CLEAR_RESP_CMDID);3025 3026	if (ret) {3027		ath12k_warn(ar->ab,3028			    "failed to send WMI_ADDBA_CLEAR_RESP_CMDID cmd\n");3029		dev_kfree_skb(skb);3030	}3031 3032	return ret;3033}3034 3035int ath12k_wmi_send_init_country_cmd(struct ath12k *ar,3036				     struct ath12k_wmi_init_country_arg *arg)3037{3038	struct ath12k_wmi_pdev *wmi = ar->wmi;3039	struct wmi_init_country_cmd *cmd;3040	struct sk_buff *skb;3041	int ret;3042 3043	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));3044	if (!skb)3045		return -ENOMEM;3046 3047	cmd = (struct wmi_init_country_cmd *)skb->data;3048	cmd->tlv_header =3049		ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SET_INIT_COUNTRY_CMD,3050				       sizeof(*cmd));3051 3052	cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id);3053 3054	switch (arg->flags) {3055	case ALPHA_IS_SET:3056		cmd->init_cc_type = WMI_COUNTRY_INFO_TYPE_ALPHA;3057		memcpy(&cmd->cc_info.alpha2, arg->cc_info.alpha2, 3);3058		break;3059	case CC_IS_SET:3060		cmd->init_cc_type = cpu_to_le32(WMI_COUNTRY_INFO_TYPE_COUNTRY_CODE);3061		cmd->cc_info.country_code =3062			cpu_to_le32(arg->cc_info.country_code);3063		break;3064	case REGDMN_IS_SET:3065		cmd->init_cc_type = cpu_to_le32(WMI_COUNTRY_INFO_TYPE_REGDOMAIN);3066		cmd->cc_info.regdom_id = cpu_to_le32(arg->cc_info.regdom_id);3067		break;3068	default:3069		ret = -EINVAL;3070		goto out;3071	}3072 3073	ret = ath12k_wmi_cmd_send(wmi, skb,3074				  WMI_SET_INIT_COUNTRY_CMDID);3075 3076out:3077	if (ret) {3078		ath12k_warn(ar->ab,3079			    "failed to send WMI_SET_INIT_COUNTRY CMD :%d\n",3080			    ret);3081		dev_kfree_skb(skb);3082	}3083 3084	return ret;3085}3086 3087int3088ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id)3089{3090	struct ath12k_wmi_pdev *wmi = ar->wmi;3091	struct ath12k_base *ab = wmi->wmi_ab->ab;3092	struct wmi_twt_enable_params_cmd *cmd;3093	struct sk_buff *skb;3094	int ret, len;3095 3096	len = sizeof(*cmd);3097 3098	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);3099	if (!skb)3100		return -ENOMEM;3101 3102	cmd = (struct wmi_twt_enable_params_cmd *)skb->data;3103	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_TWT_ENABLE_CMD,3104						 len);3105	cmd->pdev_id = cpu_to_le32(pdev_id);3106	cmd->sta_cong_timer_ms = cpu_to_le32(ATH12K_TWT_DEF_STA_CONG_TIMER_MS);3107	cmd->default_slot_size = cpu_to_le32(ATH12K_TWT_DEF_DEFAULT_SLOT_SIZE);3108	cmd->congestion_thresh_setup =3109		cpu_to_le32(ATH12K_TWT_DEF_CONGESTION_THRESH_SETUP);3110	cmd->congestion_thresh_teardown =3111		cpu_to_le32(ATH12K_TWT_DEF_CONGESTION_THRESH_TEARDOWN);3112	cmd->congestion_thresh_critical =3113		cpu_to_le32(ATH12K_TWT_DEF_CONGESTION_THRESH_CRITICAL);3114	cmd->interference_thresh_teardown =3115		cpu_to_le32(ATH12K_TWT_DEF_INTERFERENCE_THRESH_TEARDOWN);3116	cmd->interference_thresh_setup =3117		cpu_to_le32(ATH12K_TWT_DEF_INTERFERENCE_THRESH_SETUP);3118	cmd->min_no_sta_setup = cpu_to_le32(ATH12K_TWT_DEF_MIN_NO_STA_SETUP);3119	cmd->min_no_sta_teardown = cpu_to_le32(ATH12K_TWT_DEF_MIN_NO_STA_TEARDOWN);3120	cmd->no_of_bcast_mcast_slots =3121		cpu_to_le32(ATH12K_TWT_DEF_NO_OF_BCAST_MCAST_SLOTS);3122	cmd->min_no_twt_slots = cpu_to_le32(ATH12K_TWT_DEF_MIN_NO_TWT_SLOTS);3123	cmd->max_no_sta_twt = cpu_to_le32(ATH12K_TWT_DEF_MAX_NO_STA_TWT);3124	cmd->mode_check_interval = cpu_to_le32(ATH12K_TWT_DEF_MODE_CHECK_INTERVAL);3125	cmd->add_sta_slot_interval = cpu_to_le32(ATH12K_TWT_DEF_ADD_STA_SLOT_INTERVAL);3126	cmd->remove_sta_slot_interval =3127		cpu_to_le32(ATH12K_TWT_DEF_REMOVE_STA_SLOT_INTERVAL);3128	/* TODO add MBSSID support */3129	cmd->mbss_support = 0;3130 3131	ret = ath12k_wmi_cmd_send(wmi, skb,3132				  WMI_TWT_ENABLE_CMDID);3133	if (ret) {3134		ath12k_warn(ab, "Failed to send WMI_TWT_ENABLE_CMDID");3135		dev_kfree_skb(skb);3136	}3137	return ret;3138}3139 3140int3141ath12k_wmi_send_twt_disable_cmd(struct ath12k *ar, u32 pdev_id)3142{3143	struct ath12k_wmi_pdev *wmi = ar->wmi;3144	struct ath12k_base *ab = wmi->wmi_ab->ab;3145	struct wmi_twt_disable_params_cmd *cmd;3146	struct sk_buff *skb;3147	int ret, len;3148 3149	len = sizeof(*cmd);3150 3151	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);3152	if (!skb)3153		return -ENOMEM;3154 3155	cmd = (struct wmi_twt_disable_params_cmd *)skb->data;3156	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_TWT_DISABLE_CMD,3157						 len);3158	cmd->pdev_id = cpu_to_le32(pdev_id);3159 3160	ret = ath12k_wmi_cmd_send(wmi, skb,3161				  WMI_TWT_DISABLE_CMDID);3162	if (ret) {3163		ath12k_warn(ab, "Failed to send WMI_TWT_DISABLE_CMDID");3164		dev_kfree_skb(skb);3165	}3166	return ret;3167}3168 3169int3170ath12k_wmi_send_obss_spr_cmd(struct ath12k *ar, u32 vdev_id,3171			     struct ieee80211_he_obss_pd *he_obss_pd)3172{3173	struct ath12k_wmi_pdev *wmi = ar->wmi;3174	struct ath12k_base *ab = wmi->wmi_ab->ab;3175	struct wmi_obss_spatial_reuse_params_cmd *cmd;3176	struct sk_buff *skb;3177	int ret, len;3178 3179	len = sizeof(*cmd);3180 3181	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);3182	if (!skb)3183		return -ENOMEM;3184 3185	cmd = (struct wmi_obss_spatial_reuse_params_cmd *)skb->data;3186	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_OBSS_SPATIAL_REUSE_SET_CMD,3187						 len);3188	cmd->vdev_id = cpu_to_le32(vdev_id);3189	cmd->enable = cpu_to_le32(he_obss_pd->enable);3190	cmd->obss_min = a_cpu_to_sle32(he_obss_pd->min_offset);3191	cmd->obss_max = a_cpu_to_sle32(he_obss_pd->max_offset);3192 3193	ret = ath12k_wmi_cmd_send(wmi, skb,3194				  WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID);3195	if (ret) {3196		ath12k_warn(ab,3197			    "Failed to send WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID");3198		dev_kfree_skb(skb);3199	}3200	return ret;3201}3202 3203int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id,3204				  u8 bss_color, u32 period,3205				  bool enable)3206{3207	struct ath12k_wmi_pdev *wmi = ar->wmi;3208	struct ath12k_base *ab = wmi->wmi_ab->ab;3209	struct wmi_obss_color_collision_cfg_params_cmd *cmd;3210	struct sk_buff *skb;3211	int ret, len;3212 3213	len = sizeof(*cmd);3214 3215	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);3216	if (!skb)3217		return -ENOMEM;3218 3219	cmd = (struct wmi_obss_color_collision_cfg_params_cmd *)skb->data;3220	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_OBSS_COLOR_COLLISION_DET_CONFIG,3221						 len);3222	cmd->vdev_id = cpu_to_le32(vdev_id);3223	cmd->evt_type = enable ? cpu_to_le32(ATH12K_OBSS_COLOR_COLLISION_DETECTION) :3224		cpu_to_le32(ATH12K_OBSS_COLOR_COLLISION_DETECTION_DISABLE);3225	cmd->current_bss_color = cpu_to_le32(bss_color);3226	cmd->detection_period_ms = cpu_to_le32(period);3227	cmd->scan_period_ms = cpu_to_le32(ATH12K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS);3228	cmd->free_slot_expiry_time_ms = 0;3229	cmd->flags = 0;3230 3231	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3232		   "wmi_send_obss_color_collision_cfg id %d type %d bss_color %d detect_period %d scan_period %d\n",3233		   cmd->vdev_id, cmd->evt_type, cmd->current_bss_color,3234		   cmd->detection_period_ms, cmd->scan_period_ms);3235 3236	ret = ath12k_wmi_cmd_send(wmi, skb,3237				  WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID);3238	if (ret) {3239		ath12k_warn(ab, "Failed to send WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID");3240		dev_kfree_skb(skb);3241	}3242	return ret;3243}3244 3245int ath12k_wmi_send_bss_color_change_enable_cmd(struct ath12k *ar, u32 vdev_id,3246						bool enable)3247{3248	struct ath12k_wmi_pdev *wmi = ar->wmi;3249	struct ath12k_base *ab = wmi->wmi_ab->ab;3250	struct wmi_bss_color_change_enable_params_cmd *cmd;3251	struct sk_buff *skb;3252	int ret, len;3253 3254	len = sizeof(*cmd);3255 3256	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);3257	if (!skb)3258		return -ENOMEM;3259 3260	cmd = (struct wmi_bss_color_change_enable_params_cmd *)skb->data;3261	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_BSS_COLOR_CHANGE_ENABLE,3262						 len);3263	cmd->vdev_id = cpu_to_le32(vdev_id);3264	cmd->enable = enable ? cpu_to_le32(1) : 0;3265 3266	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3267		   "wmi_send_bss_color_change_enable id %d enable %d\n",3268		   cmd->vdev_id, cmd->enable);3269 3270	ret = ath12k_wmi_cmd_send(wmi, skb,3271				  WMI_BSS_COLOR_CHANGE_ENABLE_CMDID);3272	if (ret) {3273		ath12k_warn(ab, "Failed to send WMI_BSS_COLOR_CHANGE_ENABLE_CMDID");3274		dev_kfree_skb(skb);3275	}3276	return ret;3277}3278 3279int ath12k_wmi_fils_discovery_tmpl(struct ath12k *ar, u32 vdev_id,3280				   struct sk_buff *tmpl)3281{3282	struct wmi_tlv *tlv;3283	struct sk_buff *skb;3284	void *ptr;3285	int ret, len;3286	size_t aligned_len;3287	struct wmi_fils_discovery_tmpl_cmd *cmd;3288 3289	aligned_len = roundup(tmpl->len, 4);3290	len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;3291 3292	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3293		   "WMI vdev %i set FILS discovery template\n", vdev_id);3294 3295	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);3296	if (!skb)3297		return -ENOMEM;3298 3299	cmd = (struct wmi_fils_discovery_tmpl_cmd *)skb->data;3300	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_FILS_DISCOVERY_TMPL_CMD,3301						 sizeof(*cmd));3302	cmd->vdev_id = cpu_to_le32(vdev_id);3303	cmd->buf_len = cpu_to_le32(tmpl->len);3304	ptr = skb->data + sizeof(*cmd);3305 3306	tlv = ptr;3307	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, aligned_len);3308	memcpy(tlv->value, tmpl->data, tmpl->len);3309 3310	ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_FILS_DISCOVERY_TMPL_CMDID);3311	if (ret) {3312		ath12k_warn(ar->ab,3313			    "WMI vdev %i failed to send FILS discovery template command\n",3314			    vdev_id);3315		dev_kfree_skb(skb);3316	}3317	return ret;3318}3319 3320int ath12k_wmi_probe_resp_tmpl(struct ath12k *ar, u32 vdev_id,3321			       struct sk_buff *tmpl)3322{3323	struct wmi_probe_tmpl_cmd *cmd;3324	struct ath12k_wmi_bcn_prb_info_params *probe_info;3325	struct wmi_tlv *tlv;3326	struct sk_buff *skb;3327	void *ptr;3328	int ret, len;3329	size_t aligned_len = roundup(tmpl->len, 4);3330 3331	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3332		   "WMI vdev %i set probe response template\n", vdev_id);3333 3334	len = sizeof(*cmd) + sizeof(*probe_info) + TLV_HDR_SIZE + aligned_len;3335 3336	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);3337	if (!skb)3338		return -ENOMEM;3339 3340	cmd = (struct wmi_probe_tmpl_cmd *)skb->data;3341	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PRB_TMPL_CMD,3342						 sizeof(*cmd));3343	cmd->vdev_id = cpu_to_le32(vdev_id);3344	cmd->buf_len = cpu_to_le32(tmpl->len);3345 3346	ptr = skb->data + sizeof(*cmd);3347 3348	probe_info = ptr;3349	len = sizeof(*probe_info);3350	probe_info->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_BCN_PRB_INFO,3351							len);3352	probe_info->caps = 0;3353	probe_info->erp = 0;3354 3355	ptr += sizeof(*probe_info);3356 3357	tlv = ptr;3358	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, aligned_len);3359	memcpy(tlv->value, tmpl->data, tmpl->len);3360 3361	ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_PRB_TMPL_CMDID);3362	if (ret) {3363		ath12k_warn(ar->ab,3364			    "WMI vdev %i failed to send probe response template command\n",3365			    vdev_id);3366		dev_kfree_skb(skb);3367	}3368	return ret;3369}3370 3371int ath12k_wmi_fils_discovery(struct ath12k *ar, u32 vdev_id, u32 interval,3372			      bool unsol_bcast_probe_resp_enabled)3373{3374	struct sk_buff *skb;3375	int ret, len;3376	struct wmi_fils_discovery_cmd *cmd;3377 3378	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3379		   "WMI vdev %i set %s interval to %u TU\n",3380		   vdev_id, unsol_bcast_probe_resp_enabled ?3381		   "unsolicited broadcast probe response" : "FILS discovery",3382		   interval);3383 3384	len = sizeof(*cmd);3385	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);3386	if (!skb)3387		return -ENOMEM;3388 3389	cmd = (struct wmi_fils_discovery_cmd *)skb->data;3390	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ENABLE_FILS_CMD,3391						 len);3392	cmd->vdev_id = cpu_to_le32(vdev_id);3393	cmd->interval = cpu_to_le32(interval);3394	cmd->config = cpu_to_le32(unsol_bcast_probe_resp_enabled);3395 3396	ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_ENABLE_FILS_CMDID);3397	if (ret) {3398		ath12k_warn(ar->ab,3399			    "WMI vdev %i failed to send FILS discovery enable/disable command\n",3400			    vdev_id);3401		dev_kfree_skb(skb);3402	}3403	return ret;3404}3405 3406static void3407ath12k_fill_band_to_mac_param(struct ath12k_base  *soc,3408			      struct ath12k_wmi_pdev_band_arg *arg)3409{3410	u8 i;3411	struct ath12k_wmi_hal_reg_capabilities_ext_arg *hal_reg_cap;3412	struct ath12k_pdev *pdev;3413 3414	for (i = 0; i < soc->num_radios; i++) {3415		pdev = &soc->pdevs[i];3416		hal_reg_cap = &soc->hal_reg_cap[i];3417		arg[i].pdev_id = pdev->pdev_id;3418 3419		switch (pdev->cap.supported_bands) {3420		case WMI_HOST_WLAN_2G_5G_CAP:3421			arg[i].start_freq = hal_reg_cap->low_2ghz_chan;3422			arg[i].end_freq = hal_reg_cap->high_5ghz_chan;3423			break;3424		case WMI_HOST_WLAN_2G_CAP:3425			arg[i].start_freq = hal_reg_cap->low_2ghz_chan;3426			arg[i].end_freq = hal_reg_cap->high_2ghz_chan;3427			break;3428		case WMI_HOST_WLAN_5G_CAP:3429			arg[i].start_freq = hal_reg_cap->low_5ghz_chan;3430			arg[i].end_freq = hal_reg_cap->high_5ghz_chan;3431			break;3432		default:3433			break;3434		}3435	}3436}3437 3438static void3439ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cfg,3440				struct ath12k_wmi_resource_config_arg *tg_cfg)3441{3442	wmi_cfg->num_vdevs = cpu_to_le32(tg_cfg->num_vdevs);3443	wmi_cfg->num_peers = cpu_to_le32(tg_cfg->num_peers);3444	wmi_cfg->num_offload_peers = cpu_to_le32(tg_cfg->num_offload_peers);3445	wmi_cfg->num_offload_reorder_buffs =3446		cpu_to_le32(tg_cfg->num_offload_reorder_buffs);3447	wmi_cfg->num_peer_keys = cpu_to_le32(tg_cfg->num_peer_keys);3448	wmi_cfg->num_tids = cpu_to_le32(tg_cfg->num_tids);3449	wmi_cfg->ast_skid_limit = cpu_to_le32(tg_cfg->ast_skid_limit);3450	wmi_cfg->tx_chain_mask = cpu_to_le32(tg_cfg->tx_chain_mask);3451	wmi_cfg->rx_chain_mask = cpu_to_le32(tg_cfg->rx_chain_mask);3452	wmi_cfg->rx_timeout_pri[0] = cpu_to_le32(tg_cfg->rx_timeout_pri[0]);3453	wmi_cfg->rx_timeout_pri[1] = cpu_to_le32(tg_cfg->rx_timeout_pri[1]);3454	wmi_cfg->rx_timeout_pri[2] = cpu_to_le32(tg_cfg->rx_timeout_pri[2]);3455	wmi_cfg->rx_timeout_pri[3] = cpu_to_le32(tg_cfg->rx_timeout_pri[3]);3456	wmi_cfg->rx_decap_mode = cpu_to_le32(tg_cfg->rx_decap_mode);3457	wmi_cfg->scan_max_pending_req = cpu_to_le32(tg_cfg->scan_max_pending_req);3458	wmi_cfg->bmiss_offload_max_vdev = cpu_to_le32(tg_cfg->bmiss_offload_max_vdev);3459	wmi_cfg->roam_offload_max_vdev = cpu_to_le32(tg_cfg->roam_offload_max_vdev);3460	wmi_cfg->roam_offload_max_ap_profiles =3461		cpu_to_le32(tg_cfg->roam_offload_max_ap_profiles);3462	wmi_cfg->num_mcast_groups = cpu_to_le32(tg_cfg->num_mcast_groups);3463	wmi_cfg->num_mcast_table_elems = cpu_to_le32(tg_cfg->num_mcast_table_elems);3464	wmi_cfg->mcast2ucast_mode = cpu_to_le32(tg_cfg->mcast2ucast_mode);3465	wmi_cfg->tx_dbg_log_size = cpu_to_le32(tg_cfg->tx_dbg_log_size);3466	wmi_cfg->num_wds_entries = cpu_to_le32(tg_cfg->num_wds_entries);3467	wmi_cfg->dma_burst_size = cpu_to_le32(tg_cfg->dma_burst_size);3468	wmi_cfg->mac_aggr_delim = cpu_to_le32(tg_cfg->mac_aggr_delim);3469	wmi_cfg->rx_skip_defrag_timeout_dup_detection_check =3470		cpu_to_le32(tg_cfg->rx_skip_defrag_timeout_dup_detection_check);3471	wmi_cfg->vow_config = cpu_to_le32(tg_cfg->vow_config);3472	wmi_cfg->gtk_offload_max_vdev = cpu_to_le32(tg_cfg->gtk_offload_max_vdev);3473	wmi_cfg->num_msdu_desc = cpu_to_le32(tg_cfg->num_msdu_desc);3474	wmi_cfg->max_frag_entries = cpu_to_le32(tg_cfg->max_frag_entries);3475	wmi_cfg->num_tdls_vdevs = cpu_to_le32(tg_cfg->num_tdls_vdevs);3476	wmi_cfg->num_tdls_conn_table_entries =3477		cpu_to_le32(tg_cfg->num_tdls_conn_table_entries);3478	wmi_cfg->beacon_tx_offload_max_vdev =3479		cpu_to_le32(tg_cfg->beacon_tx_offload_max_vdev);3480	wmi_cfg->num_multicast_filter_entries =3481		cpu_to_le32(tg_cfg->num_multicast_filter_entries);3482	wmi_cfg->num_wow_filters = cpu_to_le32(tg_cfg->num_wow_filters);3483	wmi_cfg->num_keep_alive_pattern = cpu_to_le32(tg_cfg->num_keep_alive_pattern);3484	wmi_cfg->keep_alive_pattern_size = cpu_to_le32(tg_cfg->keep_alive_pattern_size);3485	wmi_cfg->max_tdls_concurrent_sleep_sta =3486		cpu_to_le32(tg_cfg->max_tdls_concurrent_sleep_sta);3487	wmi_cfg->max_tdls_concurrent_buffer_sta =3488		cpu_to_le32(tg_cfg->max_tdls_concurrent_buffer_sta);3489	wmi_cfg->wmi_send_separate = cpu_to_le32(tg_cfg->wmi_send_separate);3490	wmi_cfg->num_ocb_vdevs = cpu_to_le32(tg_cfg->num_ocb_vdevs);3491	wmi_cfg->num_ocb_channels = cpu_to_le32(tg_cfg->num_ocb_channels);3492	wmi_cfg->num_ocb_schedules = cpu_to_le32(tg_cfg->num_ocb_schedules);3493	wmi_cfg->bpf_instruction_size = cpu_to_le32(tg_cfg->bpf_instruction_size);3494	wmi_cfg->max_bssid_rx_filters = cpu_to_le32(tg_cfg->max_bssid_rx_filters);3495	wmi_cfg->use_pdev_id = cpu_to_le32(tg_cfg->use_pdev_id);3496	wmi_cfg->flag1 = cpu_to_le32(tg_cfg->atf_config |3497				     WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64);3498	wmi_cfg->peer_map_unmap_version = cpu_to_le32(tg_cfg->peer_map_unmap_version);3499	wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params);3500	wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count);3501	wmi_cfg->twt_ap_sta_count = cpu_to_le32(tg_cfg->twt_ap_sta_count);3502	wmi_cfg->flags2 = le32_encode_bits(tg_cfg->peer_metadata_ver,3503					   WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION);3504	wmi_cfg->host_service_flags = cpu_to_le32(tg_cfg->is_reg_cc_ext_event_supported <<3505				WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);3506	wmi_cfg->ema_max_vap_cnt = cpu_to_le32(tg_cfg->ema_max_vap_cnt);3507	wmi_cfg->ema_max_profile_period = cpu_to_le32(tg_cfg->ema_max_profile_period);3508	wmi_cfg->flags2 |= cpu_to_le32(WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET);3509}3510 3511static int ath12k_init_cmd_send(struct ath12k_wmi_pdev *wmi,3512				struct ath12k_wmi_init_cmd_arg *arg)3513{3514	struct ath12k_base *ab = wmi->wmi_ab->ab;3515	struct sk_buff *skb;3516	struct wmi_init_cmd *cmd;3517	struct ath12k_wmi_resource_config_params *cfg;3518	struct ath12k_wmi_pdev_set_hw_mode_cmd *hw_mode;3519	struct ath12k_wmi_pdev_band_to_mac_params *band_to_mac;3520	struct ath12k_wmi_host_mem_chunk_params *host_mem_chunks;3521	struct wmi_tlv *tlv;3522	size_t ret, len;3523	void *ptr;3524	u32 hw_mode_len = 0;3525	u16 idx;3526 3527	if (arg->hw_mode_id != WMI_HOST_HW_MODE_MAX)3528		hw_mode_len = sizeof(*hw_mode) + TLV_HDR_SIZE +3529			      (arg->num_band_to_mac * sizeof(*band_to_mac));3530 3531	len = sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*cfg) + hw_mode_len +3532	      (arg->num_mem_chunks ? (sizeof(*host_mem_chunks) * WMI_MAX_MEM_REQS) : 0);3533 3534	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);3535	if (!skb)3536		return -ENOMEM;3537 3538	cmd = (struct wmi_init_cmd *)skb->data;3539 3540	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_INIT_CMD,3541						 sizeof(*cmd));3542 3543	ptr = skb->data + sizeof(*cmd);3544	cfg = ptr;3545 3546	ath12k_wmi_copy_resource_config(cfg, &arg->res_cfg);3547 3548	cfg->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_RESOURCE_CONFIG,3549						 sizeof(*cfg));3550 3551	ptr += sizeof(*cfg);3552	host_mem_chunks = ptr + TLV_HDR_SIZE;3553	len = sizeof(struct ath12k_wmi_host_mem_chunk_params);3554 3555	for (idx = 0; idx < arg->num_mem_chunks; ++idx) {3556		host_mem_chunks[idx].tlv_header =3557			ath12k_wmi_tlv_hdr(WMI_TAG_WLAN_HOST_MEMORY_CHUNK,3558					   len);3559 3560		host_mem_chunks[idx].ptr = cpu_to_le32(arg->mem_chunks[idx].paddr);3561		host_mem_chunks[idx].size = cpu_to_le32(arg->mem_chunks[idx].len);3562		host_mem_chunks[idx].req_id = cpu_to_le32(arg->mem_chunks[idx].req_id);3563 3564		ath12k_dbg(ab, ATH12K_DBG_WMI,3565			   "WMI host mem chunk req_id %d paddr 0x%llx len %d\n",3566			   arg->mem_chunks[idx].req_id,3567			   (u64)arg->mem_chunks[idx].paddr,3568			   arg->mem_chunks[idx].len);3569	}3570	cmd->num_host_mem_chunks = cpu_to_le32(arg->num_mem_chunks);3571	len = sizeof(struct ath12k_wmi_host_mem_chunk_params) * arg->num_mem_chunks;3572 3573	/* num_mem_chunks is zero */3574	tlv = ptr;3575	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);3576	ptr += TLV_HDR_SIZE + len;3577 3578	if (arg->hw_mode_id != WMI_HOST_HW_MODE_MAX) {3579		hw_mode = (struct ath12k_wmi_pdev_set_hw_mode_cmd *)ptr;3580		hw_mode->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_HW_MODE_CMD,3581							     sizeof(*hw_mode));3582 3583		hw_mode->hw_mode_index = cpu_to_le32(arg->hw_mode_id);3584		hw_mode->num_band_to_mac = cpu_to_le32(arg->num_band_to_mac);3585 3586		ptr += sizeof(*hw_mode);3587 3588		len = arg->num_band_to_mac * sizeof(*band_to_mac);3589		tlv = ptr;3590		tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);3591 3592		ptr += TLV_HDR_SIZE;3593		len = sizeof(*band_to_mac);3594 3595		for (idx = 0; idx < arg->num_band_to_mac; idx++) {3596			band_to_mac = (void *)ptr;3597 3598			band_to_mac->tlv_header =3599				ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_BAND_TO_MAC,3600						       len);3601			band_to_mac->pdev_id = cpu_to_le32(arg->band_to_mac[idx].pdev_id);3602			band_to_mac->start_freq =3603				cpu_to_le32(arg->band_to_mac[idx].start_freq);3604			band_to_mac->end_freq =3605				cpu_to_le32(arg->band_to_mac[idx].end_freq);3606			ptr += sizeof(*band_to_mac);3607		}3608	}3609 3610	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_INIT_CMDID);3611	if (ret) {3612		ath12k_warn(ab, "failed to send WMI_INIT_CMDID\n");3613		dev_kfree_skb(skb);3614	}3615 3616	return ret;3617}3618 3619int ath12k_wmi_pdev_lro_cfg(struct ath12k *ar,3620			    int pdev_id)3621{3622	struct ath12k_wmi_pdev_lro_config_cmd *cmd;3623	struct sk_buff *skb;3624	int ret;3625 3626	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));3627	if (!skb)3628		return -ENOMEM;3629 3630	cmd = (struct ath12k_wmi_pdev_lro_config_cmd *)skb->data;3631	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_LRO_INFO_CMD,3632						 sizeof(*cmd));3633 3634	get_random_bytes(cmd->th_4, sizeof(cmd->th_4));3635	get_random_bytes(cmd->th_6, sizeof(cmd->th_6));3636 3637	cmd->pdev_id = cpu_to_le32(pdev_id);3638 3639	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3640		   "WMI lro cfg cmd pdev_id 0x%x\n", pdev_id);3641 3642	ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_LRO_CONFIG_CMDID);3643	if (ret) {3644		ath12k_warn(ar->ab,3645			    "failed to send lro cfg req wmi cmd\n");3646		goto err;3647	}3648 3649	return 0;3650err:3651	dev_kfree_skb(skb);3652	return ret;3653}3654 3655int ath12k_wmi_wait_for_service_ready(struct ath12k_base *ab)3656{3657	unsigned long time_left;3658 3659	time_left = wait_for_completion_timeout(&ab->wmi_ab.service_ready,3660						WMI_SERVICE_READY_TIMEOUT_HZ);3661	if (!time_left)3662		return -ETIMEDOUT;3663 3664	return 0;3665}3666 3667int ath12k_wmi_wait_for_unified_ready(struct ath12k_base *ab)3668{3669	unsigned long time_left;3670 3671	time_left = wait_for_completion_timeout(&ab->wmi_ab.unified_ready,3672						WMI_SERVICE_READY_TIMEOUT_HZ);3673	if (!time_left)3674		return -ETIMEDOUT;3675 3676	return 0;3677}3678 3679int ath12k_wmi_set_hw_mode(struct ath12k_base *ab,3680			   enum wmi_host_hw_mode_config_type mode)3681{3682	struct ath12k_wmi_pdev_set_hw_mode_cmd *cmd;3683	struct sk_buff *skb;3684	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;3685	int len;3686	int ret;3687 3688	len = sizeof(*cmd);3689 3690	skb = ath12k_wmi_alloc_skb(wmi_ab, len);3691	if (!skb)3692		return -ENOMEM;3693 3694	cmd = (struct ath12k_wmi_pdev_set_hw_mode_cmd *)skb->data;3695 3696	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_HW_MODE_CMD,3697						 sizeof(*cmd));3698 3699	cmd->pdev_id = WMI_PDEV_ID_SOC;3700	cmd->hw_mode_index = cpu_to_le32(mode);3701 3702	ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0], skb, WMI_PDEV_SET_HW_MODE_CMDID);3703	if (ret) {3704		ath12k_warn(ab, "failed to send WMI_PDEV_SET_HW_MODE_CMDID\n");3705		dev_kfree_skb(skb);3706	}3707 3708	return ret;3709}3710 3711int ath12k_wmi_cmd_init(struct ath12k_base *ab)3712{3713	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;3714	struct ath12k_wmi_init_cmd_arg arg = {};3715 3716	if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,3717		     ab->wmi_ab.svc_map))3718		arg.res_cfg.is_reg_cc_ext_event_supported = true;3719 3720	ab->hw_params->wmi_init(ab, &arg.res_cfg);3721	ab->wow.wmi_conf_rx_decap_mode = arg.res_cfg.rx_decap_mode;3722 3723	arg.num_mem_chunks = wmi_ab->num_mem_chunks;3724	arg.hw_mode_id = wmi_ab->preferred_hw_mode;3725	arg.mem_chunks = wmi_ab->mem_chunks;3726 3727	if (ab->hw_params->single_pdev_only)3728		arg.hw_mode_id = WMI_HOST_HW_MODE_MAX;3729 3730	arg.num_band_to_mac = ab->num_radios;3731	ath12k_fill_band_to_mac_param(ab, arg.band_to_mac);3732 3733	ab->dp.peer_metadata_ver = arg.res_cfg.peer_metadata_ver;3734 3735	return ath12k_init_cmd_send(&wmi_ab->wmi[0], &arg);3736}3737 3738int ath12k_wmi_vdev_spectral_conf(struct ath12k *ar,3739				  struct ath12k_wmi_vdev_spectral_conf_arg *arg)3740{3741	struct ath12k_wmi_vdev_spectral_conf_cmd *cmd;3742	struct sk_buff *skb;3743	int ret;3744 3745	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));3746	if (!skb)3747		return -ENOMEM;3748 3749	cmd = (struct ath12k_wmi_vdev_spectral_conf_cmd *)skb->data;3750	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SPECTRAL_CONFIGURE_CMD,3751						 sizeof(*cmd));3752	cmd->vdev_id = cpu_to_le32(arg->vdev_id);3753	cmd->scan_count = cpu_to_le32(arg->scan_count);3754	cmd->scan_period = cpu_to_le32(arg->scan_period);3755	cmd->scan_priority = cpu_to_le32(arg->scan_priority);3756	cmd->scan_fft_size = cpu_to_le32(arg->scan_fft_size);3757	cmd->scan_gc_ena = cpu_to_le32(arg->scan_gc_ena);3758	cmd->scan_restart_ena = cpu_to_le32(arg->scan_restart_ena);3759	cmd->scan_noise_floor_ref = cpu_to_le32(arg->scan_noise_floor_ref);3760	cmd->scan_init_delay = cpu_to_le32(arg->scan_init_delay);3761	cmd->scan_nb_tone_thr = cpu_to_le32(arg->scan_nb_tone_thr);3762	cmd->scan_str_bin_thr = cpu_to_le32(arg->scan_str_bin_thr);3763	cmd->scan_wb_rpt_mode = cpu_to_le32(arg->scan_wb_rpt_mode);3764	cmd->scan_rssi_rpt_mode = cpu_to_le32(arg->scan_rssi_rpt_mode);3765	cmd->scan_rssi_thr = cpu_to_le32(arg->scan_rssi_thr);3766	cmd->scan_pwr_format = cpu_to_le32(arg->scan_pwr_format);3767	cmd->scan_rpt_mode = cpu_to_le32(arg->scan_rpt_mode);3768	cmd->scan_bin_scale = cpu_to_le32(arg->scan_bin_scale);3769	cmd->scan_dbm_adj = cpu_to_le32(arg->scan_dbm_adj);3770	cmd->scan_chn_mask = cpu_to_le32(arg->scan_chn_mask);3771 3772	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3773		   "WMI spectral scan config cmd vdev_id 0x%x\n",3774		   arg->vdev_id);3775 3776	ret = ath12k_wmi_cmd_send(ar->wmi, skb,3777				  WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID);3778	if (ret) {3779		ath12k_warn(ar->ab,3780			    "failed to send spectral scan config wmi cmd\n");3781		goto err;3782	}3783 3784	return 0;3785err:3786	dev_kfree_skb(skb);3787	return ret;3788}3789 3790int ath12k_wmi_vdev_spectral_enable(struct ath12k *ar, u32 vdev_id,3791				    u32 trigger, u32 enable)3792{3793	struct ath12k_wmi_vdev_spectral_enable_cmd *cmd;3794	struct sk_buff *skb;3795	int ret;3796 3797	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));3798	if (!skb)3799		return -ENOMEM;3800 3801	cmd = (struct ath12k_wmi_vdev_spectral_enable_cmd *)skb->data;3802	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SPECTRAL_ENABLE_CMD,3803						 sizeof(*cmd));3804 3805	cmd->vdev_id = cpu_to_le32(vdev_id);3806	cmd->trigger_cmd = cpu_to_le32(trigger);3807	cmd->enable_cmd = cpu_to_le32(enable);3808 3809	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3810		   "WMI spectral enable cmd vdev id 0x%x\n",3811		   vdev_id);3812 3813	ret = ath12k_wmi_cmd_send(ar->wmi, skb,3814				  WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID);3815	if (ret) {3816		ath12k_warn(ar->ab,3817			    "failed to send spectral enable wmi cmd\n");3818		goto err;3819	}3820 3821	return 0;3822err:3823	dev_kfree_skb(skb);3824	return ret;3825}3826 3827int ath12k_wmi_pdev_dma_ring_cfg(struct ath12k *ar,3828				 struct ath12k_wmi_pdev_dma_ring_cfg_arg *arg)3829{3830	struct ath12k_wmi_pdev_dma_ring_cfg_req_cmd *cmd;3831	struct sk_buff *skb;3832	int ret;3833 3834	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));3835	if (!skb)3836		return -ENOMEM;3837 3838	cmd = (struct ath12k_wmi_pdev_dma_ring_cfg_req_cmd *)skb->data;3839	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_DMA_RING_CFG_REQ,3840						 sizeof(*cmd));3841 3842	cmd->pdev_id = cpu_to_le32(arg->pdev_id);3843	cmd->module_id = cpu_to_le32(arg->module_id);3844	cmd->base_paddr_lo = cpu_to_le32(arg->base_paddr_lo);3845	cmd->base_paddr_hi = cpu_to_le32(arg->base_paddr_hi);3846	cmd->head_idx_paddr_lo = cpu_to_le32(arg->head_idx_paddr_lo);3847	cmd->head_idx_paddr_hi = cpu_to_le32(arg->head_idx_paddr_hi);3848	cmd->tail_idx_paddr_lo = cpu_to_le32(arg->tail_idx_paddr_lo);3849	cmd->tail_idx_paddr_hi = cpu_to_le32(arg->tail_idx_paddr_hi);3850	cmd->num_elems = cpu_to_le32(arg->num_elems);3851	cmd->buf_size = cpu_to_le32(arg->buf_size);3852	cmd->num_resp_per_event = cpu_to_le32(arg->num_resp_per_event);3853	cmd->event_timeout_ms = cpu_to_le32(arg->event_timeout_ms);3854 3855	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,3856		   "WMI DMA ring cfg req cmd pdev_id 0x%x\n",3857		   arg->pdev_id);3858 3859	ret = ath12k_wmi_cmd_send(ar->wmi, skb,3860				  WMI_PDEV_DMA_RING_CFG_REQ_CMDID);3861	if (ret) {3862		ath12k_warn(ar->ab,3863			    "failed to send dma ring cfg req wmi cmd\n");3864		goto err;3865	}3866 3867	return 0;3868err:3869	dev_kfree_skb(skb);3870	return ret;3871}3872 3873static int ath12k_wmi_dma_buf_entry_parse(struct ath12k_base *soc,3874					  u16 tag, u16 len,3875					  const void *ptr, void *data)3876{3877	struct ath12k_wmi_dma_buf_release_arg *arg = data;3878 3879	if (tag != WMI_TAG_DMA_BUF_RELEASE_ENTRY)3880		return -EPROTO;3881 3882	if (arg->num_buf_entry >= le32_to_cpu(arg->fixed.num_buf_release_entry))3883		return -ENOBUFS;3884 3885	arg->num_buf_entry++;3886	return 0;3887}3888 3889static int ath12k_wmi_dma_buf_meta_parse(struct ath12k_base *soc,3890					 u16 tag, u16 len,3891					 const void *ptr, void *data)3892{3893	struct ath12k_wmi_dma_buf_release_arg *arg = data;3894 3895	if (tag != WMI_TAG_DMA_BUF_RELEASE_SPECTRAL_META_DATA)3896		return -EPROTO;3897 3898	if (arg->num_meta >= le32_to_cpu(arg->fixed.num_meta_data_entry))3899		return -ENOBUFS;3900 3901	arg->num_meta++;3902 3903	return 0;3904}3905 3906static int ath12k_wmi_dma_buf_parse(struct ath12k_base *ab,3907				    u16 tag, u16 len,3908				    const void *ptr, void *data)3909{3910	struct ath12k_wmi_dma_buf_release_arg *arg = data;3911	const struct ath12k_wmi_dma_buf_release_fixed_params *fixed;3912	u32 pdev_id;3913	int ret;3914 3915	switch (tag) {3916	case WMI_TAG_DMA_BUF_RELEASE:3917		fixed = ptr;3918		arg->fixed = *fixed;3919		pdev_id = DP_HW2SW_MACID(le32_to_cpu(fixed->pdev_id));3920		arg->fixed.pdev_id = cpu_to_le32(pdev_id);3921		break;3922	case WMI_TAG_ARRAY_STRUCT:3923		if (!arg->buf_entry_done) {3924			arg->num_buf_entry = 0;3925			arg->buf_entry = ptr;3926 3927			ret = ath12k_wmi_tlv_iter(ab, ptr, len,3928						  ath12k_wmi_dma_buf_entry_parse,3929						  arg);3930			if (ret) {3931				ath12k_warn(ab, "failed to parse dma buf entry tlv %d\n",3932					    ret);3933				return ret;3934			}3935 3936			arg->buf_entry_done = true;3937		} else if (!arg->meta_data_done) {3938			arg->num_meta = 0;3939			arg->meta_data = ptr;3940 3941			ret = ath12k_wmi_tlv_iter(ab, ptr, len,3942						  ath12k_wmi_dma_buf_meta_parse,3943						  arg);3944			if (ret) {3945				ath12k_warn(ab, "failed to parse dma buf meta tlv %d\n",3946					    ret);3947				return ret;3948			}3949 3950			arg->meta_data_done = true;3951		}3952		break;3953	default:3954		break;3955	}3956	return 0;3957}3958 3959static void ath12k_wmi_pdev_dma_ring_buf_release_event(struct ath12k_base *ab,3960						       struct sk_buff *skb)3961{3962	struct ath12k_wmi_dma_buf_release_arg arg = {};3963	struct ath12k_dbring_buf_release_event param;3964	int ret;3965 3966	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,3967				  ath12k_wmi_dma_buf_parse,3968				  &arg);3969	if (ret) {3970		ath12k_warn(ab, "failed to parse dma buf release tlv %d\n", ret);3971		return;3972	}3973 3974	param.fixed = arg.fixed;3975	param.buf_entry = arg.buf_entry;3976	param.num_buf_entry = arg.num_buf_entry;3977	param.meta_data = arg.meta_data;3978	param.num_meta = arg.num_meta;3979 3980	ret = ath12k_dbring_buffer_release_event(ab, &param);3981	if (ret) {3982		ath12k_warn(ab, "failed to handle dma buf release event %d\n", ret);3983		return;3984	}3985}3986 3987static int ath12k_wmi_hw_mode_caps_parse(struct ath12k_base *soc,3988					 u16 tag, u16 len,3989					 const void *ptr, void *data)3990{3991	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;3992	struct ath12k_wmi_hw_mode_cap_params *hw_mode_cap;3993	u32 phy_map = 0;3994 3995	if (tag != WMI_TAG_HW_MODE_CAPABILITIES)3996		return -EPROTO;3997 3998	if (svc_rdy_ext->n_hw_mode_caps >= svc_rdy_ext->arg.num_hw_modes)3999		return -ENOBUFS;4000 4001	hw_mode_cap = container_of(ptr, struct ath12k_wmi_hw_mode_cap_params,4002				   hw_mode_id);4003	svc_rdy_ext->n_hw_mode_caps++;4004 4005	phy_map = le32_to_cpu(hw_mode_cap->phy_id_map);4006	svc_rdy_ext->tot_phy_id += fls(phy_map);4007 4008	return 0;4009}4010 4011static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,4012				   u16 len, const void *ptr, void *data)4013{4014	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;4015	const struct ath12k_wmi_hw_mode_cap_params *hw_mode_caps;4016	enum wmi_host_hw_mode_config_type mode, pref;4017	u32 i;4018	int ret;4019 4020	svc_rdy_ext->n_hw_mode_caps = 0;4021	svc_rdy_ext->hw_mode_caps = ptr;4022 4023	ret = ath12k_wmi_tlv_iter(soc, ptr, len,4024				  ath12k_wmi_hw_mode_caps_parse,4025				  svc_rdy_ext);4026	if (ret) {4027		ath12k_warn(soc, "failed to parse tlv %d\n", ret);4028		return ret;4029	}4030 4031	for (i = 0 ; i < svc_rdy_ext->n_hw_mode_caps; i++) {4032		hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i];4033		mode = le32_to_cpu(hw_mode_caps->hw_mode_id);4034 4035		if (mode >= WMI_HOST_HW_MODE_MAX)4036			continue;4037 4038		pref = soc->wmi_ab.preferred_hw_mode;4039 4040		if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {4041			svc_rdy_ext->pref_hw_mode_caps = *hw_mode_caps;4042			soc->wmi_ab.preferred_hw_mode = mode;4043		}4044	}4045 4046	ath12k_dbg(soc, ATH12K_DBG_WMI, "preferred_hw_mode:%d\n",4047		   soc->wmi_ab.preferred_hw_mode);4048	if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)4049		return -EINVAL;4050 4051	return 0;4052}4053 4054static int ath12k_wmi_mac_phy_caps_parse(struct ath12k_base *soc,4055					 u16 tag, u16 len,4056					 const void *ptr, void *data)4057{4058	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;4059 4060	if (tag != WMI_TAG_MAC_PHY_CAPABILITIES)4061		return -EPROTO;4062 4063	if (svc_rdy_ext->n_mac_phy_caps >= svc_rdy_ext->tot_phy_id)4064		return -ENOBUFS;4065 4066	len = min_t(u16, len, sizeof(struct ath12k_wmi_mac_phy_caps_params));4067	if (!svc_rdy_ext->n_mac_phy_caps) {4068		svc_rdy_ext->mac_phy_caps = kzalloc((svc_rdy_ext->tot_phy_id) * len,4069						    GFP_ATOMIC);4070		if (!svc_rdy_ext->mac_phy_caps)4071			return -ENOMEM;4072	}4073 4074	memcpy(svc_rdy_ext->mac_phy_caps + svc_rdy_ext->n_mac_phy_caps, ptr, len);4075	svc_rdy_ext->n_mac_phy_caps++;4076	return 0;4077}4078 4079static int ath12k_wmi_ext_hal_reg_caps_parse(struct ath12k_base *soc,4080					     u16 tag, u16 len,4081					     const void *ptr, void *data)4082{4083	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;4084 4085	if (tag != WMI_TAG_HAL_REG_CAPABILITIES_EXT)4086		return -EPROTO;4087 4088	if (svc_rdy_ext->n_ext_hal_reg_caps >= svc_rdy_ext->arg.num_phy)4089		return -ENOBUFS;4090 4091	svc_rdy_ext->n_ext_hal_reg_caps++;4092	return 0;4093}4094 4095static int ath12k_wmi_ext_hal_reg_caps(struct ath12k_base *soc,4096				       u16 len, const void *ptr, void *data)4097{4098	struct ath12k_wmi_pdev *wmi_handle = &soc->wmi_ab.wmi[0];4099	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;4100	struct ath12k_wmi_hal_reg_capabilities_ext_arg reg_cap;4101	int ret;4102	u32 i;4103 4104	svc_rdy_ext->n_ext_hal_reg_caps = 0;4105	svc_rdy_ext->ext_hal_reg_caps = ptr;4106	ret = ath12k_wmi_tlv_iter(soc, ptr, len,4107				  ath12k_wmi_ext_hal_reg_caps_parse,4108				  svc_rdy_ext);4109	if (ret) {4110		ath12k_warn(soc, "failed to parse tlv %d\n", ret);4111		return ret;4112	}4113 4114	for (i = 0; i < svc_rdy_ext->arg.num_phy; i++) {4115		ret = ath12k_pull_reg_cap_svc_rdy_ext(wmi_handle,4116						      svc_rdy_ext->soc_hal_reg_caps,4117						      svc_rdy_ext->ext_hal_reg_caps, i,4118						      &reg_cap);4119		if (ret) {4120			ath12k_warn(soc, "failed to extract reg cap %d\n", i);4121			return ret;4122		}4123 4124		if (reg_cap.phy_id >= MAX_RADIOS) {4125			ath12k_warn(soc, "unexpected phy id %u\n", reg_cap.phy_id);4126			return -EINVAL;4127		}4128 4129		soc->hal_reg_cap[reg_cap.phy_id] = reg_cap;4130	}4131	return 0;4132}4133 4134static int ath12k_wmi_ext_soc_hal_reg_caps_parse(struct ath12k_base *soc,4135						 u16 len, const void *ptr,4136						 void *data)4137{4138	struct ath12k_wmi_pdev *wmi_handle = &soc->wmi_ab.wmi[0];4139	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;4140	u8 hw_mode_id = le32_to_cpu(svc_rdy_ext->pref_hw_mode_caps.hw_mode_id);4141	u32 phy_id_map;4142	int pdev_index = 0;4143	int ret;4144 4145	svc_rdy_ext->soc_hal_reg_caps = ptr;4146	svc_rdy_ext->arg.num_phy = le32_to_cpu(svc_rdy_ext->soc_hal_reg_caps->num_phy);4147 4148	soc->num_radios = 0;4149	phy_id_map = le32_to_cpu(svc_rdy_ext->pref_hw_mode_caps.phy_id_map);4150	soc->fw_pdev_count = 0;4151 4152	while (phy_id_map && soc->num_radios < MAX_RADIOS) {4153		ret = ath12k_pull_mac_phy_cap_svc_ready_ext(wmi_handle,4154							    svc_rdy_ext,4155							    hw_mode_id, soc->num_radios,4156							    &soc->pdevs[pdev_index]);4157		if (ret) {4158			ath12k_warn(soc, "failed to extract mac caps, idx :%d\n",4159				    soc->num_radios);4160			return ret;4161		}4162 4163		soc->num_radios++;4164 4165		/* For single_pdev_only targets,4166		 * save mac_phy capability in the same pdev4167		 */4168		if (soc->hw_params->single_pdev_only)4169			pdev_index = 0;4170		else4171			pdev_index = soc->num_radios;4172 4173		/* TODO: mac_phy_cap prints */4174		phy_id_map >>= 1;4175	}4176 4177	if (soc->hw_params->single_pdev_only) {4178		soc->num_radios = 1;4179		soc->pdevs[0].pdev_id = 0;4180	}4181 4182	return 0;4183}4184 4185static int ath12k_wmi_dma_ring_caps_parse(struct ath12k_base *soc,4186					  u16 tag, u16 len,4187					  const void *ptr, void *data)4188{4189	struct ath12k_wmi_dma_ring_caps_parse *parse = data;4190 4191	if (tag != WMI_TAG_DMA_RING_CAPABILITIES)4192		return -EPROTO;4193 4194	parse->n_dma_ring_caps++;4195	return 0;4196}4197 4198static int ath12k_wmi_alloc_dbring_caps(struct ath12k_base *ab,4199					u32 num_cap)4200{4201	size_t sz;4202	void *ptr;4203 4204	sz = num_cap * sizeof(struct ath12k_dbring_cap);4205	ptr = kzalloc(sz, GFP_ATOMIC);4206	if (!ptr)4207		return -ENOMEM;4208 4209	ab->db_caps = ptr;4210	ab->num_db_cap = num_cap;4211 4212	return 0;4213}4214 4215static void ath12k_wmi_free_dbring_caps(struct ath12k_base *ab)4216{4217	kfree(ab->db_caps);4218	ab->db_caps = NULL;4219	ab->num_db_cap = 0;4220}4221 4222static int ath12k_wmi_dma_ring_caps(struct ath12k_base *ab,4223				    u16 len, const void *ptr, void *data)4224{4225	struct ath12k_wmi_dma_ring_caps_parse *dma_caps_parse = data;4226	struct ath12k_wmi_dma_ring_caps_params *dma_caps;4227	struct ath12k_dbring_cap *dir_buff_caps;4228	int ret;4229	u32 i;4230 4231	dma_caps_parse->n_dma_ring_caps = 0;4232	dma_caps = (struct ath12k_wmi_dma_ring_caps_params *)ptr;4233	ret = ath12k_wmi_tlv_iter(ab, ptr, len,4234				  ath12k_wmi_dma_ring_caps_parse,4235				  dma_caps_parse);4236	if (ret) {4237		ath12k_warn(ab, "failed to parse dma ring caps tlv %d\n", ret);4238		return ret;4239	}4240 4241	if (!dma_caps_parse->n_dma_ring_caps)4242		return 0;4243 4244	if (ab->num_db_cap) {4245		ath12k_warn(ab, "Already processed, so ignoring dma ring caps\n");4246		return 0;4247	}4248 4249	ret = ath12k_wmi_alloc_dbring_caps(ab, dma_caps_parse->n_dma_ring_caps);4250	if (ret)4251		return ret;4252 4253	dir_buff_caps = ab->db_caps;4254	for (i = 0; i < dma_caps_parse->n_dma_ring_caps; i++) {4255		if (le32_to_cpu(dma_caps[i].module_id) >= WMI_DIRECT_BUF_MAX) {4256			ath12k_warn(ab, "Invalid module id %d\n",4257				    le32_to_cpu(dma_caps[i].module_id));4258			ret = -EINVAL;4259			goto free_dir_buff;4260		}4261 4262		dir_buff_caps[i].id = le32_to_cpu(dma_caps[i].module_id);4263		dir_buff_caps[i].pdev_id =4264			DP_HW2SW_MACID(le32_to_cpu(dma_caps[i].pdev_id));4265		dir_buff_caps[i].min_elem = le32_to_cpu(dma_caps[i].min_elem);4266		dir_buff_caps[i].min_buf_sz = le32_to_cpu(dma_caps[i].min_buf_sz);4267		dir_buff_caps[i].min_buf_align = le32_to_cpu(dma_caps[i].min_buf_align);4268	}4269 4270	return 0;4271 4272free_dir_buff:4273	ath12k_wmi_free_dbring_caps(ab);4274	return ret;4275}4276 4277static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab,4278					u16 tag, u16 len,4279					const void *ptr, void *data)4280{4281	struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];4282	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;4283	int ret;4284 4285	switch (tag) {4286	case WMI_TAG_SERVICE_READY_EXT_EVENT:4287		ret = ath12k_pull_svc_ready_ext(wmi_handle, ptr,4288						&svc_rdy_ext->arg);4289		if (ret) {4290			ath12k_warn(ab, "unable to extract ext params\n");4291			return ret;4292		}4293		break;4294 4295	case WMI_TAG_SOC_MAC_PHY_HW_MODE_CAPS:4296		svc_rdy_ext->hw_caps = ptr;4297		svc_rdy_ext->arg.num_hw_modes =4298			le32_to_cpu(svc_rdy_ext->hw_caps->num_hw_modes);4299		break;4300 4301	case WMI_TAG_SOC_HAL_REG_CAPABILITIES:4302		ret = ath12k_wmi_ext_soc_hal_reg_caps_parse(ab, len, ptr,4303							    svc_rdy_ext);4304		if (ret)4305			return ret;4306		break;4307 4308	case WMI_TAG_ARRAY_STRUCT:4309		if (!svc_rdy_ext->hw_mode_done) {4310			ret = ath12k_wmi_hw_mode_caps(ab, len, ptr, svc_rdy_ext);4311			if (ret)4312				return ret;4313 4314			svc_rdy_ext->hw_mode_done = true;4315		} else if (!svc_rdy_ext->mac_phy_done) {4316			svc_rdy_ext->n_mac_phy_caps = 0;4317			ret = ath12k_wmi_tlv_iter(ab, ptr, len,4318						  ath12k_wmi_mac_phy_caps_parse,4319						  svc_rdy_ext);4320			if (ret) {4321				ath12k_warn(ab, "failed to parse tlv %d\n", ret);4322				return ret;4323			}4324 4325			svc_rdy_ext->mac_phy_done = true;4326		} else if (!svc_rdy_ext->ext_hal_reg_done) {4327			ret = ath12k_wmi_ext_hal_reg_caps(ab, len, ptr, svc_rdy_ext);4328			if (ret)4329				return ret;4330 4331			svc_rdy_ext->ext_hal_reg_done = true;4332		} else if (!svc_rdy_ext->mac_phy_chainmask_combo_done) {4333			svc_rdy_ext->mac_phy_chainmask_combo_done = true;4334		} else if (!svc_rdy_ext->mac_phy_chainmask_cap_done) {4335			svc_rdy_ext->mac_phy_chainmask_cap_done = true;4336		} else if (!svc_rdy_ext->oem_dma_ring_cap_done) {4337			svc_rdy_ext->oem_dma_ring_cap_done = true;4338		} else if (!svc_rdy_ext->dma_ring_cap_done) {4339			ret = ath12k_wmi_dma_ring_caps(ab, len, ptr,4340						       &svc_rdy_ext->dma_caps_parse);4341			if (ret)4342				return ret;4343 4344			svc_rdy_ext->dma_ring_cap_done = true;4345		}4346		break;4347 4348	default:4349		break;4350	}4351	return 0;4352}4353 4354static int ath12k_service_ready_ext_event(struct ath12k_base *ab,4355					  struct sk_buff *skb)4356{4357	struct ath12k_wmi_svc_rdy_ext_parse svc_rdy_ext = { };4358	int ret;4359 4360	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,4361				  ath12k_wmi_svc_rdy_ext_parse,4362				  &svc_rdy_ext);4363	if (ret) {4364		ath12k_warn(ab, "failed to parse tlv %d\n", ret);4365		goto err;4366	}4367 4368	if (!test_bit(WMI_TLV_SERVICE_EXT2_MSG, ab->wmi_ab.svc_map))4369		complete(&ab->wmi_ab.service_ready);4370 4371	kfree(svc_rdy_ext.mac_phy_caps);4372	return 0;4373 4374err:4375	ath12k_wmi_free_dbring_caps(ab);4376	return ret;4377}4378 4379static int ath12k_pull_svc_ready_ext2(struct ath12k_wmi_pdev *wmi_handle,4380				      const void *ptr,4381				      struct ath12k_wmi_svc_rdy_ext2_arg *arg)4382{4383	const struct wmi_service_ready_ext2_event *ev = ptr;4384 4385	if (!ev)4386		return -EINVAL;4387 4388	arg->reg_db_version = le32_to_cpu(ev->reg_db_version);4389	arg->hw_min_max_tx_power_2ghz = le32_to_cpu(ev->hw_min_max_tx_power_2ghz);4390	arg->hw_min_max_tx_power_5ghz = le32_to_cpu(ev->hw_min_max_tx_power_5ghz);4391	arg->chwidth_num_peer_caps = le32_to_cpu(ev->chwidth_num_peer_caps);4392	arg->preamble_puncture_bw = le32_to_cpu(ev->preamble_puncture_bw);4393	arg->max_user_per_ppdu_ofdma = le32_to_cpu(ev->max_user_per_ppdu_ofdma);4394	arg->max_user_per_ppdu_mumimo = le32_to_cpu(ev->max_user_per_ppdu_mumimo);4395	arg->target_cap_flags = le32_to_cpu(ev->target_cap_flags);4396	return 0;4397}4398 4399static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band,4400				      const __le32 cap_mac_info[],4401				      const __le32 cap_phy_info[],4402				      const __le32 supp_mcs[],4403				      const struct ath12k_wmi_ppe_threshold_params *ppet,4404				       __le32 cap_info_internal)4405{4406	struct ath12k_band_cap *cap_band = &pdev->cap.band[band];4407	u32 support_320mhz;4408	u8 i;4409 4410	if (band == NL80211_BAND_6GHZ)4411		support_320mhz = cap_band->eht_cap_phy_info[0] &4412					IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;4413 4414	for (i = 0; i < WMI_MAX_EHTCAP_MAC_SIZE; i++)4415		cap_band->eht_cap_mac_info[i] = le32_to_cpu(cap_mac_info[i]);4416 4417	for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++)4418		cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]);4419 4420	if (band == NL80211_BAND_6GHZ)4421		cap_band->eht_cap_phy_info[0] |= support_320mhz;4422 4423	cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]);4424	cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]);4425	if (band != NL80211_BAND_2GHZ) {4426		cap_band->eht_mcs_160 = le32_to_cpu(supp_mcs[2]);4427		cap_band->eht_mcs_320 = le32_to_cpu(supp_mcs[3]);4428	}4429 4430	cap_band->eht_ppet.numss_m1 = le32_to_cpu(ppet->numss_m1);4431	cap_band->eht_ppet.ru_bit_mask = le32_to_cpu(ppet->ru_info);4432	for (i = 0; i < WMI_MAX_NUM_SS; i++)4433		cap_band->eht_ppet.ppet16_ppet8_ru3_ru0[i] =4434			le32_to_cpu(ppet->ppet16_ppet8_ru3_ru0[i]);4435 4436	cap_band->eht_cap_info_internal = le32_to_cpu(cap_info_internal);4437}4438 4439static int4440ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,4441				      const struct ath12k_wmi_caps_ext_params *caps,4442				      struct ath12k_pdev *pdev)4443{4444	struct ath12k_band_cap *cap_band;4445	u32 bands, support_320mhz;4446	int i;4447 4448	if (ab->hw_params->single_pdev_only) {4449		if (caps->hw_mode_id == WMI_HOST_HW_MODE_SINGLE) {4450			support_320mhz = le32_to_cpu(caps->eht_cap_phy_info_5ghz[0]) &4451				IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;4452			cap_band = &pdev->cap.band[NL80211_BAND_6GHZ];4453			cap_band->eht_cap_phy_info[0] |= support_320mhz;4454			return 0;4455		}4456 4457		for (i = 0; i < ab->fw_pdev_count; i++) {4458			struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i];4459 4460			if (fw_pdev->pdev_id == ath12k_wmi_caps_ext_get_pdev_id(caps) &&4461			    fw_pdev->phy_id == le32_to_cpu(caps->phy_id)) {4462				bands = fw_pdev->supported_bands;4463				break;4464			}4465		}4466 4467		if (i == ab->fw_pdev_count)4468			return -EINVAL;4469	} else {4470		bands = pdev->cap.supported_bands;4471	}4472 4473	if (bands & WMI_HOST_WLAN_2G_CAP) {4474		ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_2GHZ,4475					  caps->eht_cap_mac_info_2ghz,4476					  caps->eht_cap_phy_info_2ghz,4477					  caps->eht_supp_mcs_ext_2ghz,4478					  &caps->eht_ppet_2ghz,4479					  caps->eht_cap_info_internal);4480	}4481 4482	if (bands & WMI_HOST_WLAN_5G_CAP) {4483		ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_5GHZ,4484					  caps->eht_cap_mac_info_5ghz,4485					  caps->eht_cap_phy_info_5ghz,4486					  caps->eht_supp_mcs_ext_5ghz,4487					  &caps->eht_ppet_5ghz,4488					  caps->eht_cap_info_internal);4489 4490		ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_6GHZ,4491					  caps->eht_cap_mac_info_5ghz,4492					  caps->eht_cap_phy_info_5ghz,4493					  caps->eht_supp_mcs_ext_5ghz,4494					  &caps->eht_ppet_5ghz,4495					  caps->eht_cap_info_internal);4496	}4497 4498	return 0;4499}4500 4501static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag,4502					   u16 len, const void *ptr,4503					   void *data)4504{4505	const struct ath12k_wmi_caps_ext_params *caps = ptr;4506	int i = 0, ret;4507 4508	if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT)4509		return -EPROTO;4510 4511	if (ab->hw_params->single_pdev_only) {4512		if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id) &&4513		    caps->hw_mode_id != WMI_HOST_HW_MODE_SINGLE)4514			return 0;4515	} else {4516		for (i = 0; i < ab->num_radios; i++) {4517			if (ab->pdevs[i].pdev_id ==4518			    ath12k_wmi_caps_ext_get_pdev_id(caps))4519				break;4520		}4521 4522		if (i == ab->num_radios)4523			return -EINVAL;4524	}4525 4526	ret = ath12k_wmi_tlv_mac_phy_caps_ext_parse(ab, caps, &ab->pdevs[i]);4527	if (ret) {4528		ath12k_warn(ab,4529			    "failed to parse extended MAC PHY capabilities for pdev %d: %d\n",4530			    ret, ab->pdevs[i].pdev_id);4531		return ret;4532	}4533 4534	return 0;4535}4536 4537static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,4538					 u16 tag, u16 len,4539					 const void *ptr, void *data)4540{4541	struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];4542	struct ath12k_wmi_svc_rdy_ext2_parse *parse = data;4543	int ret;4544 4545	switch (tag) {4546	case WMI_TAG_SERVICE_READY_EXT2_EVENT:4547		ret = ath12k_pull_svc_ready_ext2(wmi_handle, ptr,4548						 &parse->arg);4549		if (ret) {4550			ath12k_warn(ab,4551				    "failed to extract wmi service ready ext2 parameters: %d\n",4552				    ret);4553			return ret;4554		}4555		break;4556 4557	case WMI_TAG_ARRAY_STRUCT:4558		if (!parse->dma_ring_cap_done) {4559			ret = ath12k_wmi_dma_ring_caps(ab, len, ptr,4560						       &parse->dma_caps_parse);4561			if (ret)4562				return ret;4563 4564			parse->dma_ring_cap_done = true;4565		} else if (!parse->spectral_bin_scaling_done) {4566			/* TODO: This is a place-holder as WMI tag for4567			 * spectral scaling is before4568			 * WMI_TAG_MAC_PHY_CAPABILITIES_EXT4569			 */4570			parse->spectral_bin_scaling_done = true;4571		} else if (!parse->mac_phy_caps_ext_done) {4572			ret = ath12k_wmi_tlv_iter(ab, ptr, len,4573						  ath12k_wmi_tlv_mac_phy_caps_ext,4574						  parse);4575			if (ret) {4576				ath12k_warn(ab, "failed to parse extended MAC PHY capabilities WMI TLV: %d\n",4577					    ret);4578				return ret;4579			}4580 4581			parse->mac_phy_caps_ext_done = true;4582		}4583		break;4584	default:4585		break;4586	}4587 4588	return 0;4589}4590 4591static int ath12k_service_ready_ext2_event(struct ath12k_base *ab,4592					   struct sk_buff *skb)4593{4594	struct ath12k_wmi_svc_rdy_ext2_parse svc_rdy_ext2 = { };4595	int ret;4596 4597	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,4598				  ath12k_wmi_svc_rdy_ext2_parse,4599				  &svc_rdy_ext2);4600	if (ret) {4601		ath12k_warn(ab, "failed to parse ext2 event tlv %d\n", ret);4602		goto err;4603	}4604 4605	complete(&ab->wmi_ab.service_ready);4606 4607	return 0;4608 4609err:4610	ath12k_wmi_free_dbring_caps(ab);4611	return ret;4612}4613 4614static int ath12k_pull_vdev_start_resp_tlv(struct ath12k_base *ab, struct sk_buff *skb,4615					   struct wmi_vdev_start_resp_event *vdev_rsp)4616{4617	const void **tb;4618	const struct wmi_vdev_start_resp_event *ev;4619	int ret;4620 4621	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);4622	if (IS_ERR(tb)) {4623		ret = PTR_ERR(tb);4624		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);4625		return ret;4626	}4627 4628	ev = tb[WMI_TAG_VDEV_START_RESPONSE_EVENT];4629	if (!ev) {4630		ath12k_warn(ab, "failed to fetch vdev start resp ev");4631		kfree(tb);4632		return -EPROTO;4633	}4634 4635	*vdev_rsp = *ev;4636 4637	kfree(tb);4638	return 0;4639}4640 4641static struct ath12k_reg_rule4642*create_ext_reg_rules_from_wmi(u32 num_reg_rules,4643			       struct ath12k_wmi_reg_rule_ext_params *wmi_reg_rule)4644{4645	struct ath12k_reg_rule *reg_rule_ptr;4646	u32 count;4647 4648	reg_rule_ptr = kzalloc((num_reg_rules * sizeof(*reg_rule_ptr)),4649			       GFP_ATOMIC);4650 4651	if (!reg_rule_ptr)4652		return NULL;4653 4654	for (count = 0; count < num_reg_rules; count++) {4655		reg_rule_ptr[count].start_freq =4656			le32_get_bits(wmi_reg_rule[count].freq_info,4657				      REG_RULE_START_FREQ);4658		reg_rule_ptr[count].end_freq =4659			le32_get_bits(wmi_reg_rule[count].freq_info,4660				      REG_RULE_END_FREQ);4661		reg_rule_ptr[count].max_bw =4662			le32_get_bits(wmi_reg_rule[count].bw_pwr_info,4663				      REG_RULE_MAX_BW);4664		reg_rule_ptr[count].reg_power =4665			le32_get_bits(wmi_reg_rule[count].bw_pwr_info,4666				      REG_RULE_REG_PWR);4667		reg_rule_ptr[count].ant_gain =4668			le32_get_bits(wmi_reg_rule[count].bw_pwr_info,4669				      REG_RULE_ANT_GAIN);4670		reg_rule_ptr[count].flags =4671			le32_get_bits(wmi_reg_rule[count].flag_info,4672				      REG_RULE_FLAGS);4673		reg_rule_ptr[count].psd_flag =4674			le32_get_bits(wmi_reg_rule[count].psd_power_info,4675				      REG_RULE_PSD_INFO);4676		reg_rule_ptr[count].psd_eirp =4677			le32_get_bits(wmi_reg_rule[count].psd_power_info,4678				      REG_RULE_PSD_EIRP);4679	}4680 4681	return reg_rule_ptr;4682}4683 4684static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,4685						   struct sk_buff *skb,4686						   struct ath12k_reg_info *reg_info)4687{4688	const void **tb;4689	const struct wmi_reg_chan_list_cc_ext_event *ev;4690	struct ath12k_wmi_reg_rule_ext_params *ext_wmi_reg_rule;4691	u32 num_2g_reg_rules, num_5g_reg_rules;4692	u32 num_6g_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE];4693	u32 num_6g_reg_rules_cl[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];4694	u32 total_reg_rules = 0;4695	int ret, i, j;4696 4697	ath12k_dbg(ab, ATH12K_DBG_WMI, "processing regulatory ext channel list\n");4698 4699	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);4700	if (IS_ERR(tb)) {4701		ret = PTR_ERR(tb);4702		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);4703		return ret;4704	}4705 4706	ev = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT];4707	if (!ev) {4708		ath12k_warn(ab, "failed to fetch reg chan list ext update ev\n");4709		kfree(tb);4710		return -EPROTO;4711	}4712 4713	reg_info->num_2g_reg_rules = le32_to_cpu(ev->num_2g_reg_rules);4714	reg_info->num_5g_reg_rules = le32_to_cpu(ev->num_5g_reg_rules);4715	reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP] =4716		le32_to_cpu(ev->num_6g_reg_rules_ap_lpi);4717	reg_info->num_6g_reg_rules_ap[WMI_REG_STD_POWER_AP] =4718		le32_to_cpu(ev->num_6g_reg_rules_ap_sp);4719	reg_info->num_6g_reg_rules_ap[WMI_REG_VLP_AP] =4720		le32_to_cpu(ev->num_6g_reg_rules_ap_vlp);4721 4722	for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {4723		reg_info->num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][i] =4724			le32_to_cpu(ev->num_6g_reg_rules_cl_lpi[i]);4725		reg_info->num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][i] =4726			le32_to_cpu(ev->num_6g_reg_rules_cl_sp[i]);4727		reg_info->num_6g_reg_rules_cl[WMI_REG_VLP_AP][i] =4728			le32_to_cpu(ev->num_6g_reg_rules_cl_vlp[i]);4729	}4730 4731	num_2g_reg_rules = reg_info->num_2g_reg_rules;4732	total_reg_rules += num_2g_reg_rules;4733	num_5g_reg_rules = reg_info->num_5g_reg_rules;4734	total_reg_rules += num_5g_reg_rules;4735 4736	if (num_2g_reg_rules > MAX_REG_RULES || num_5g_reg_rules > MAX_REG_RULES) {4737		ath12k_warn(ab, "Num reg rules for 2G/5G exceeds max limit (num_2g_reg_rules: %d num_5g_reg_rules: %d max_rules: %d)\n",4738			    num_2g_reg_rules, num_5g_reg_rules, MAX_REG_RULES);4739		kfree(tb);4740		return -EINVAL;4741	}4742 4743	for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {4744		num_6g_reg_rules_ap[i] = reg_info->num_6g_reg_rules_ap[i];4745 4746		if (num_6g_reg_rules_ap[i] > MAX_6G_REG_RULES) {4747			ath12k_warn(ab, "Num 6G reg rules for AP mode(%d) exceeds max limit (num_6g_reg_rules_ap: %d, max_rules: %d)\n",4748				    i, num_6g_reg_rules_ap[i], MAX_6G_REG_RULES);4749			kfree(tb);4750			return -EINVAL;4751		}4752 4753		total_reg_rules += num_6g_reg_rules_ap[i];4754	}4755 4756	for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {4757		num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][i] =4758				reg_info->num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][i];4759		total_reg_rules += num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][i];4760 4761		num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][i] =4762				reg_info->num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][i];4763		total_reg_rules += num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][i];4764 4765		num_6g_reg_rules_cl[WMI_REG_VLP_AP][i] =4766				reg_info->num_6g_reg_rules_cl[WMI_REG_VLP_AP][i];4767		total_reg_rules += num_6g_reg_rules_cl[WMI_REG_VLP_AP][i];4768 4769		if (num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][i] > MAX_6G_REG_RULES ||4770		    num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][i] > MAX_6G_REG_RULES ||4771		    num_6g_reg_rules_cl[WMI_REG_VLP_AP][i] >  MAX_6G_REG_RULES) {4772			ath12k_warn(ab, "Num 6g client reg rules exceeds max limit, for client(type: %d)\n",4773				    i);4774			kfree(tb);4775			return -EINVAL;4776		}4777	}4778 4779	if (!total_reg_rules) {4780		ath12k_warn(ab, "No reg rules available\n");4781		kfree(tb);4782		return -EINVAL;4783	}4784 4785	memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN);4786 4787	/* FIXME: Currently FW includes 6G reg rule also in 5G rule4788	 * list for country US.4789	 * Having same 6G reg rule in 5G and 6G rules list causes4790	 * intersect check to be true, and same rules will be shown4791	 * multiple times in iw cmd. So added hack below to avoid4792	 * parsing 6G rule from 5G reg rule list, and this can be4793	 * removed later, after FW updates to remove 6G reg rule4794	 * from 5G rules list.4795	 */4796	if (memcmp(reg_info->alpha2, "US", 2) == 0) {4797		reg_info->num_5g_reg_rules = REG_US_5G_NUM_REG_RULES;4798		num_5g_reg_rules = reg_info->num_5g_reg_rules;4799	}4800 4801	reg_info->dfs_region = le32_to_cpu(ev->dfs_region);4802	reg_info->phybitmap = le32_to_cpu(ev->phybitmap);4803	reg_info->num_phy = le32_to_cpu(ev->num_phy);4804	reg_info->phy_id = le32_to_cpu(ev->phy_id);4805	reg_info->ctry_code = le32_to_cpu(ev->country_id);4806	reg_info->reg_dmn_pair = le32_to_cpu(ev->domain_code);4807 4808	switch (le32_to_cpu(ev->status_code)) {4809	case WMI_REG_SET_CC_STATUS_PASS:4810		reg_info->status_code = REG_SET_CC_STATUS_PASS;4811		break;4812	case WMI_REG_CURRENT_ALPHA2_NOT_FOUND:4813		reg_info->status_code = REG_CURRENT_ALPHA2_NOT_FOUND;4814		break;4815	case WMI_REG_INIT_ALPHA2_NOT_FOUND:4816		reg_info->status_code = REG_INIT_ALPHA2_NOT_FOUND;4817		break;4818	case WMI_REG_SET_CC_CHANGE_NOT_ALLOWED:4819		reg_info->status_code = REG_SET_CC_CHANGE_NOT_ALLOWED;4820		break;4821	case WMI_REG_SET_CC_STATUS_NO_MEMORY:4822		reg_info->status_code = REG_SET_CC_STATUS_NO_MEMORY;4823		break;4824	case WMI_REG_SET_CC_STATUS_FAIL:4825		reg_info->status_code = REG_SET_CC_STATUS_FAIL;4826		break;4827	}4828 4829	reg_info->is_ext_reg_event = true;4830 4831	reg_info->min_bw_2g = le32_to_cpu(ev->min_bw_2g);4832	reg_info->max_bw_2g = le32_to_cpu(ev->max_bw_2g);4833	reg_info->min_bw_5g = le32_to_cpu(ev->min_bw_5g);4834	reg_info->max_bw_5g = le32_to_cpu(ev->max_bw_5g);4835	reg_info->min_bw_6g_ap[WMI_REG_INDOOR_AP] = le32_to_cpu(ev->min_bw_6g_ap_lpi);4836	reg_info->max_bw_6g_ap[WMI_REG_INDOOR_AP] = le32_to_cpu(ev->max_bw_6g_ap_lpi);4837	reg_info->min_bw_6g_ap[WMI_REG_STD_POWER_AP] = le32_to_cpu(ev->min_bw_6g_ap_sp);4838	reg_info->max_bw_6g_ap[WMI_REG_STD_POWER_AP] = le32_to_cpu(ev->max_bw_6g_ap_sp);4839	reg_info->min_bw_6g_ap[WMI_REG_VLP_AP] = le32_to_cpu(ev->min_bw_6g_ap_vlp);4840	reg_info->max_bw_6g_ap[WMI_REG_VLP_AP] = le32_to_cpu(ev->max_bw_6g_ap_vlp);4841 4842	for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {4843		reg_info->min_bw_6g_client[WMI_REG_INDOOR_AP][i] =4844			le32_to_cpu(ev->min_bw_6g_client_lpi[i]);4845		reg_info->max_bw_6g_client[WMI_REG_INDOOR_AP][i] =4846			le32_to_cpu(ev->max_bw_6g_client_lpi[i]);4847		reg_info->min_bw_6g_client[WMI_REG_STD_POWER_AP][i] =4848			le32_to_cpu(ev->min_bw_6g_client_sp[i]);4849		reg_info->max_bw_6g_client[WMI_REG_STD_POWER_AP][i] =4850			le32_to_cpu(ev->max_bw_6g_client_sp[i]);4851		reg_info->min_bw_6g_client[WMI_REG_VLP_AP][i] =4852			le32_to_cpu(ev->min_bw_6g_client_vlp[i]);4853		reg_info->max_bw_6g_client[WMI_REG_VLP_AP][i] =4854			le32_to_cpu(ev->max_bw_6g_client_vlp[i]);4855	}4856 4857	ath12k_dbg(ab, ATH12K_DBG_WMI,4858		   "%s:cc_ext %s dfs %d BW: min_2g %d max_2g %d min_5g %d max_5g %d phy_bitmap 0x%x",4859		   __func__, reg_info->alpha2, reg_info->dfs_region,4860		   reg_info->min_bw_2g, reg_info->max_bw_2g,4861		   reg_info->min_bw_5g, reg_info->max_bw_5g,4862		   reg_info->phybitmap);4863 4864	ath12k_dbg(ab, ATH12K_DBG_WMI,4865		   "num_2g_reg_rules %d num_5g_reg_rules %d",4866		   num_2g_reg_rules, num_5g_reg_rules);4867 4868	ath12k_dbg(ab, ATH12K_DBG_WMI,4869		   "num_6g_reg_rules_ap_lpi: %d num_6g_reg_rules_ap_sp: %d num_6g_reg_rules_ap_vlp: %d",4870		   num_6g_reg_rules_ap[WMI_REG_INDOOR_AP],4871		   num_6g_reg_rules_ap[WMI_REG_STD_POWER_AP],4872		   num_6g_reg_rules_ap[WMI_REG_VLP_AP]);4873 4874	ath12k_dbg(ab, ATH12K_DBG_WMI,4875		   "6g Regular client: num_6g_reg_rules_lpi: %d num_6g_reg_rules_sp: %d num_6g_reg_rules_vlp: %d",4876		   num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][WMI_REG_DEFAULT_CLIENT],4877		   num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][WMI_REG_DEFAULT_CLIENT],4878		   num_6g_reg_rules_cl[WMI_REG_VLP_AP][WMI_REG_DEFAULT_CLIENT]);4879 4880	ath12k_dbg(ab, ATH12K_DBG_WMI,4881		   "6g Subordinate client: num_6g_reg_rules_lpi: %d num_6g_reg_rules_sp: %d num_6g_reg_rules_vlp: %d",4882		   num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][WMI_REG_SUBORDINATE_CLIENT],4883		   num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][WMI_REG_SUBORDINATE_CLIENT],4884		   num_6g_reg_rules_cl[WMI_REG_VLP_AP][WMI_REG_SUBORDINATE_CLIENT]);4885 4886	ext_wmi_reg_rule =4887		(struct ath12k_wmi_reg_rule_ext_params *)((u8 *)ev4888			+ sizeof(*ev)4889			+ sizeof(struct wmi_tlv));4890 4891	if (num_2g_reg_rules) {4892		reg_info->reg_rules_2g_ptr =4893			create_ext_reg_rules_from_wmi(num_2g_reg_rules,4894						      ext_wmi_reg_rule);4895 4896		if (!reg_info->reg_rules_2g_ptr) {4897			kfree(tb);4898			ath12k_warn(ab, "Unable to Allocate memory for 2g rules\n");4899			return -ENOMEM;4900		}4901	}4902 4903	if (num_5g_reg_rules) {4904		ext_wmi_reg_rule += num_2g_reg_rules;4905		reg_info->reg_rules_5g_ptr =4906			create_ext_reg_rules_from_wmi(num_5g_reg_rules,4907						      ext_wmi_reg_rule);4908 4909		if (!reg_info->reg_rules_5g_ptr) {4910			kfree(tb);4911			ath12k_warn(ab, "Unable to Allocate memory for 5g rules\n");4912			return -ENOMEM;4913		}4914	}4915 4916	ext_wmi_reg_rule += num_5g_reg_rules;4917 4918	for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {4919		reg_info->reg_rules_6g_ap_ptr[i] =4920			create_ext_reg_rules_from_wmi(num_6g_reg_rules_ap[i],4921						      ext_wmi_reg_rule);4922 4923		if (!reg_info->reg_rules_6g_ap_ptr[i]) {4924			kfree(tb);4925			ath12k_warn(ab, "Unable to Allocate memory for 6g ap rules\n");4926			return -ENOMEM;4927		}4928 4929		ext_wmi_reg_rule += num_6g_reg_rules_ap[i];4930	}4931 4932	for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) {4933		for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {4934			reg_info->reg_rules_6g_client_ptr[j][i] =4935				create_ext_reg_rules_from_wmi(num_6g_reg_rules_cl[j][i],4936							      ext_wmi_reg_rule);4937 4938			if (!reg_info->reg_rules_6g_client_ptr[j][i]) {4939				kfree(tb);4940				ath12k_warn(ab, "Unable to Allocate memory for 6g client rules\n");4941				return -ENOMEM;4942			}4943 4944			ext_wmi_reg_rule += num_6g_reg_rules_cl[j][i];4945		}4946	}4947 4948	reg_info->client_type = le32_to_cpu(ev->client_type);4949	reg_info->rnr_tpe_usable = ev->rnr_tpe_usable;4950	reg_info->unspecified_ap_usable = ev->unspecified_ap_usable;4951	reg_info->domain_code_6g_ap[WMI_REG_INDOOR_AP] =4952		le32_to_cpu(ev->domain_code_6g_ap_lpi);4953	reg_info->domain_code_6g_ap[WMI_REG_STD_POWER_AP] =4954		le32_to_cpu(ev->domain_code_6g_ap_sp);4955	reg_info->domain_code_6g_ap[WMI_REG_VLP_AP] =4956		le32_to_cpu(ev->domain_code_6g_ap_vlp);4957 4958	for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {4959		reg_info->domain_code_6g_client[WMI_REG_INDOOR_AP][i] =4960			le32_to_cpu(ev->domain_code_6g_client_lpi[i]);4961		reg_info->domain_code_6g_client[WMI_REG_STD_POWER_AP][i] =4962			le32_to_cpu(ev->domain_code_6g_client_sp[i]);4963		reg_info->domain_code_6g_client[WMI_REG_VLP_AP][i] =4964			le32_to_cpu(ev->domain_code_6g_client_vlp[i]);4965	}4966 4967	reg_info->domain_code_6g_super_id = le32_to_cpu(ev->domain_code_6g_super_id);4968 4969	ath12k_dbg(ab, ATH12K_DBG_WMI, "6g client_type: %d domain_code_6g_super_id: %d",4970		   reg_info->client_type, reg_info->domain_code_6g_super_id);4971 4972	ath12k_dbg(ab, ATH12K_DBG_WMI, "processed regulatory ext channel list\n");4973 4974	kfree(tb);4975	return 0;4976}4977 4978static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *skb,4979					struct wmi_peer_delete_resp_event *peer_del_resp)4980{4981	const void **tb;4982	const struct wmi_peer_delete_resp_event *ev;4983	int ret;4984 4985	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);4986	if (IS_ERR(tb)) {4987		ret = PTR_ERR(tb);4988		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);4989		return ret;4990	}4991 4992	ev = tb[WMI_TAG_PEER_DELETE_RESP_EVENT];4993	if (!ev) {4994		ath12k_warn(ab, "failed to fetch peer delete resp ev");4995		kfree(tb);4996		return -EPROTO;4997	}4998 4999	memset(peer_del_resp, 0, sizeof(*peer_del_resp));5000 5001	peer_del_resp->vdev_id = ev->vdev_id;5002	ether_addr_copy(peer_del_resp->peer_macaddr.addr,5003			ev->peer_macaddr.addr);5004 5005	kfree(tb);5006	return 0;5007}5008 5009static int ath12k_pull_vdev_del_resp_ev(struct ath12k_base *ab,5010					struct sk_buff *skb,5011					u32 *vdev_id)5012{5013	const void **tb;5014	const struct wmi_vdev_delete_resp_event *ev;5015	int ret;5016 5017	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5018	if (IS_ERR(tb)) {5019		ret = PTR_ERR(tb);5020		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5021		return ret;5022	}5023 5024	ev = tb[WMI_TAG_VDEV_DELETE_RESP_EVENT];5025	if (!ev) {5026		ath12k_warn(ab, "failed to fetch vdev delete resp ev");5027		kfree(tb);5028		return -EPROTO;5029	}5030 5031	*vdev_id = le32_to_cpu(ev->vdev_id);5032 5033	kfree(tb);5034	return 0;5035}5036 5037static int ath12k_pull_bcn_tx_status_ev(struct ath12k_base *ab,5038					struct sk_buff *skb,5039					u32 *vdev_id, u32 *tx_status)5040{5041	const void **tb;5042	const struct wmi_bcn_tx_status_event *ev;5043	int ret;5044 5045	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5046	if (IS_ERR(tb)) {5047		ret = PTR_ERR(tb);5048		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5049		return ret;5050	}5051 5052	ev = tb[WMI_TAG_OFFLOAD_BCN_TX_STATUS_EVENT];5053	if (!ev) {5054		ath12k_warn(ab, "failed to fetch bcn tx status ev");5055		kfree(tb);5056		return -EPROTO;5057	}5058 5059	*vdev_id = le32_to_cpu(ev->vdev_id);5060	*tx_status = le32_to_cpu(ev->tx_status);5061 5062	kfree(tb);5063	return 0;5064}5065 5066static int ath12k_pull_vdev_stopped_param_tlv(struct ath12k_base *ab, struct sk_buff *skb,5067					      u32 *vdev_id)5068{5069	const void **tb;5070	const struct wmi_vdev_stopped_event *ev;5071	int ret;5072 5073	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5074	if (IS_ERR(tb)) {5075		ret = PTR_ERR(tb);5076		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5077		return ret;5078	}5079 5080	ev = tb[WMI_TAG_VDEV_STOPPED_EVENT];5081	if (!ev) {5082		ath12k_warn(ab, "failed to fetch vdev stop ev");5083		kfree(tb);5084		return -EPROTO;5085	}5086 5087	*vdev_id = le32_to_cpu(ev->vdev_id);5088 5089	kfree(tb);5090	return 0;5091}5092 5093static int ath12k_wmi_tlv_mgmt_rx_parse(struct ath12k_base *ab,5094					u16 tag, u16 len,5095					const void *ptr, void *data)5096{5097	struct wmi_tlv_mgmt_rx_parse *parse = data;5098 5099	switch (tag) {5100	case WMI_TAG_MGMT_RX_HDR:5101		parse->fixed = ptr;5102		break;5103	case WMI_TAG_ARRAY_BYTE:5104		if (!parse->frame_buf_done) {5105			parse->frame_buf = ptr;5106			parse->frame_buf_done = true;5107		}5108		break;5109	}5110	return 0;5111}5112 5113static int ath12k_pull_mgmt_rx_params_tlv(struct ath12k_base *ab,5114					  struct sk_buff *skb,5115					  struct ath12k_wmi_mgmt_rx_arg *hdr)5116{5117	struct wmi_tlv_mgmt_rx_parse parse = { };5118	const struct ath12k_wmi_mgmt_rx_params *ev;5119	const u8 *frame;5120	int i, ret;5121 5122	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,5123				  ath12k_wmi_tlv_mgmt_rx_parse,5124				  &parse);5125	if (ret) {5126		ath12k_warn(ab, "failed to parse mgmt rx tlv %d\n", ret);5127		return ret;5128	}5129 5130	ev = parse.fixed;5131	frame = parse.frame_buf;5132 5133	if (!ev || !frame) {5134		ath12k_warn(ab, "failed to fetch mgmt rx hdr");5135		return -EPROTO;5136	}5137 5138	hdr->pdev_id = le32_to_cpu(ev->pdev_id);5139	hdr->chan_freq = le32_to_cpu(ev->chan_freq);5140	hdr->channel = le32_to_cpu(ev->channel);5141	hdr->snr = le32_to_cpu(ev->snr);5142	hdr->rate = le32_to_cpu(ev->rate);5143	hdr->phy_mode = le32_to_cpu(ev->phy_mode);5144	hdr->buf_len = le32_to_cpu(ev->buf_len);5145	hdr->status = le32_to_cpu(ev->status);5146	hdr->flags = le32_to_cpu(ev->flags);5147	hdr->rssi = a_sle32_to_cpu(ev->rssi);5148	hdr->tsf_delta = le32_to_cpu(ev->tsf_delta);5149 5150	for (i = 0; i < ATH_MAX_ANTENNA; i++)5151		hdr->rssi_ctl[i] = le32_to_cpu(ev->rssi_ctl[i]);5152 5153	if (skb->len < (frame - skb->data) + hdr->buf_len) {5154		ath12k_warn(ab, "invalid length in mgmt rx hdr ev");5155		return -EPROTO;5156	}5157 5158	/* shift the sk_buff to point to `frame` */5159	skb_trim(skb, 0);5160	skb_put(skb, frame - skb->data);5161	skb_pull(skb, frame - skb->data);5162	skb_put(skb, hdr->buf_len);5163 5164	return 0;5165}5166 5167static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,5168				    u32 status)5169{5170	struct sk_buff *msdu;5171	struct ieee80211_tx_info *info;5172	struct ath12k_skb_cb *skb_cb;5173	int num_mgmt;5174 5175	spin_lock_bh(&ar->txmgmt_idr_lock);5176	msdu = idr_find(&ar->txmgmt_idr, desc_id);5177 5178	if (!msdu) {5179		ath12k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n",5180			    desc_id);5181		spin_unlock_bh(&ar->txmgmt_idr_lock);5182		return -ENOENT;5183	}5184 5185	idr_remove(&ar->txmgmt_idr, desc_id);5186	spin_unlock_bh(&ar->txmgmt_idr_lock);5187 5188	skb_cb = ATH12K_SKB_CB(msdu);5189	dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);5190 5191	info = IEEE80211_SKB_CB(msdu);5192	if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status)5193		info->flags |= IEEE80211_TX_STAT_ACK;5194 5195	ieee80211_tx_status_irqsafe(ath12k_ar_to_hw(ar), msdu);5196 5197	num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);5198 5199	/* WARN when we received this event without doing any mgmt tx */5200	if (num_mgmt < 0)5201		WARN_ON_ONCE(1);5202 5203	if (!num_mgmt)5204		wake_up(&ar->txmgmt_empty_waitq);5205 5206	return 0;5207}5208 5209static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,5210					       struct sk_buff *skb,5211					       struct wmi_mgmt_tx_compl_event *param)5212{5213	const void **tb;5214	const struct wmi_mgmt_tx_compl_event *ev;5215	int ret;5216 5217	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5218	if (IS_ERR(tb)) {5219		ret = PTR_ERR(tb);5220		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5221		return ret;5222	}5223 5224	ev = tb[WMI_TAG_MGMT_TX_COMPL_EVENT];5225	if (!ev) {5226		ath12k_warn(ab, "failed to fetch mgmt tx compl ev");5227		kfree(tb);5228		return -EPROTO;5229	}5230 5231	param->pdev_id = ev->pdev_id;5232	param->desc_id = ev->desc_id;5233	param->status = ev->status;5234 5235	kfree(tb);5236	return 0;5237}5238 5239static void ath12k_wmi_event_scan_started(struct ath12k *ar)5240{5241	lockdep_assert_held(&ar->data_lock);5242 5243	switch (ar->scan.state) {5244	case ATH12K_SCAN_IDLE:5245	case ATH12K_SCAN_RUNNING:5246	case ATH12K_SCAN_ABORTING:5247		ath12k_warn(ar->ab, "received scan started event in an invalid scan state: %s (%d)\n",5248			    ath12k_scan_state_str(ar->scan.state),5249			    ar->scan.state);5250		break;5251	case ATH12K_SCAN_STARTING:5252		ar->scan.state = ATH12K_SCAN_RUNNING;5253 5254		if (ar->scan.is_roc)5255			ieee80211_ready_on_channel(ath12k_ar_to_hw(ar));5256 5257		complete(&ar->scan.started);5258		break;5259	}5260}5261 5262static void ath12k_wmi_event_scan_start_failed(struct ath12k *ar)5263{5264	lockdep_assert_held(&ar->data_lock);5265 5266	switch (ar->scan.state) {5267	case ATH12K_SCAN_IDLE:5268	case ATH12K_SCAN_RUNNING:5269	case ATH12K_SCAN_ABORTING:5270		ath12k_warn(ar->ab, "received scan start failed event in an invalid scan state: %s (%d)\n",5271			    ath12k_scan_state_str(ar->scan.state),5272			    ar->scan.state);5273		break;5274	case ATH12K_SCAN_STARTING:5275		complete(&ar->scan.started);5276		__ath12k_mac_scan_finish(ar);5277		break;5278	}5279}5280 5281static void ath12k_wmi_event_scan_completed(struct ath12k *ar)5282{5283	lockdep_assert_held(&ar->data_lock);5284 5285	switch (ar->scan.state) {5286	case ATH12K_SCAN_IDLE:5287	case ATH12K_SCAN_STARTING:5288		/* One suspected reason scan can be completed while starting is5289		 * if firmware fails to deliver all scan events to the host,5290		 * e.g. when transport pipe is full. This has been observed5291		 * with spectral scan phyerr events starving wmi transport5292		 * pipe. In such case the "scan completed" event should be (and5293		 * is) ignored by the host as it may be just firmware's scan5294		 * state machine recovering.5295		 */5296		ath12k_warn(ar->ab, "received scan completed event in an invalid scan state: %s (%d)\n",5297			    ath12k_scan_state_str(ar->scan.state),5298			    ar->scan.state);5299		break;5300	case ATH12K_SCAN_RUNNING:5301	case ATH12K_SCAN_ABORTING:5302		__ath12k_mac_scan_finish(ar);5303		break;5304	}5305}5306 5307static void ath12k_wmi_event_scan_bss_chan(struct ath12k *ar)5308{5309	lockdep_assert_held(&ar->data_lock);5310 5311	switch (ar->scan.state) {5312	case ATH12K_SCAN_IDLE:5313	case ATH12K_SCAN_STARTING:5314		ath12k_warn(ar->ab, "received scan bss chan event in an invalid scan state: %s (%d)\n",5315			    ath12k_scan_state_str(ar->scan.state),5316			    ar->scan.state);5317		break;5318	case ATH12K_SCAN_RUNNING:5319	case ATH12K_SCAN_ABORTING:5320		ar->scan_channel = NULL;5321		break;5322	}5323}5324 5325static void ath12k_wmi_event_scan_foreign_chan(struct ath12k *ar, u32 freq)5326{5327	struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);5328 5329	lockdep_assert_held(&ar->data_lock);5330 5331	switch (ar->scan.state) {5332	case ATH12K_SCAN_IDLE:5333	case ATH12K_SCAN_STARTING:5334		ath12k_warn(ar->ab, "received scan foreign chan event in an invalid scan state: %s (%d)\n",5335			    ath12k_scan_state_str(ar->scan.state),5336			    ar->scan.state);5337		break;5338	case ATH12K_SCAN_RUNNING:5339	case ATH12K_SCAN_ABORTING:5340		ar->scan_channel = ieee80211_get_channel(hw->wiphy, freq);5341 5342		if (ar->scan.is_roc && ar->scan.roc_freq == freq)5343			complete(&ar->scan.on_channel);5344 5345		break;5346	}5347}5348 5349static const char *5350ath12k_wmi_event_scan_type_str(enum wmi_scan_event_type type,5351			       enum wmi_scan_completion_reason reason)5352{5353	switch (type) {5354	case WMI_SCAN_EVENT_STARTED:5355		return "started";5356	case WMI_SCAN_EVENT_COMPLETED:5357		switch (reason) {5358		case WMI_SCAN_REASON_COMPLETED:5359			return "completed";5360		case WMI_SCAN_REASON_CANCELLED:5361			return "completed [cancelled]";5362		case WMI_SCAN_REASON_PREEMPTED:5363			return "completed [preempted]";5364		case WMI_SCAN_REASON_TIMEDOUT:5365			return "completed [timedout]";5366		case WMI_SCAN_REASON_INTERNAL_FAILURE:5367			return "completed [internal err]";5368		case WMI_SCAN_REASON_MAX:5369			break;5370		}5371		return "completed [unknown]";5372	case WMI_SCAN_EVENT_BSS_CHANNEL:5373		return "bss channel";5374	case WMI_SCAN_EVENT_FOREIGN_CHAN:5375		return "foreign channel";5376	case WMI_SCAN_EVENT_DEQUEUED:5377		return "dequeued";5378	case WMI_SCAN_EVENT_PREEMPTED:5379		return "preempted";5380	case WMI_SCAN_EVENT_START_FAILED:5381		return "start failed";5382	case WMI_SCAN_EVENT_RESTARTED:5383		return "restarted";5384	case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT:5385		return "foreign channel exit";5386	default:5387		return "unknown";5388	}5389}5390 5391static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,5392			       struct wmi_scan_event *scan_evt_param)5393{5394	const void **tb;5395	const struct wmi_scan_event *ev;5396	int ret;5397 5398	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5399	if (IS_ERR(tb)) {5400		ret = PTR_ERR(tb);5401		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5402		return ret;5403	}5404 5405	ev = tb[WMI_TAG_SCAN_EVENT];5406	if (!ev) {5407		ath12k_warn(ab, "failed to fetch scan ev");5408		kfree(tb);5409		return -EPROTO;5410	}5411 5412	scan_evt_param->event_type = ev->event_type;5413	scan_evt_param->reason = ev->reason;5414	scan_evt_param->channel_freq = ev->channel_freq;5415	scan_evt_param->scan_req_id = ev->scan_req_id;5416	scan_evt_param->scan_id = ev->scan_id;5417	scan_evt_param->vdev_id = ev->vdev_id;5418	scan_evt_param->tsf_timestamp = ev->tsf_timestamp;5419 5420	kfree(tb);5421	return 0;5422}5423 5424static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buff *skb,5425					   struct wmi_peer_sta_kickout_arg *arg)5426{5427	const void **tb;5428	const struct wmi_peer_sta_kickout_event *ev;5429	int ret;5430 5431	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5432	if (IS_ERR(tb)) {5433		ret = PTR_ERR(tb);5434		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5435		return ret;5436	}5437 5438	ev = tb[WMI_TAG_PEER_STA_KICKOUT_EVENT];5439	if (!ev) {5440		ath12k_warn(ab, "failed to fetch peer sta kickout ev");5441		kfree(tb);5442		return -EPROTO;5443	}5444 5445	arg->mac_addr = ev->peer_macaddr.addr;5446 5447	kfree(tb);5448	return 0;5449}5450 5451static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,5452			       struct wmi_roam_event *roam_ev)5453{5454	const void **tb;5455	const struct wmi_roam_event *ev;5456	int ret;5457 5458	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5459	if (IS_ERR(tb)) {5460		ret = PTR_ERR(tb);5461		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5462		return ret;5463	}5464 5465	ev = tb[WMI_TAG_ROAM_EVENT];5466	if (!ev) {5467		ath12k_warn(ab, "failed to fetch roam ev");5468		kfree(tb);5469		return -EPROTO;5470	}5471 5472	roam_ev->vdev_id = ev->vdev_id;5473	roam_ev->reason = ev->reason;5474	roam_ev->rssi = ev->rssi;5475 5476	kfree(tb);5477	return 0;5478}5479 5480static int freq_to_idx(struct ath12k *ar, int freq)5481{5482	struct ieee80211_supported_band *sband;5483	struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);5484	int band, ch, idx = 0;5485 5486	for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {5487		if (!ar->mac.sbands[band].channels)5488			continue;5489 5490		sband = hw->wiphy->bands[band];5491		if (!sband)5492			continue;5493 5494		for (ch = 0; ch < sband->n_channels; ch++, idx++)5495			if (sband->channels[ch].center_freq == freq)5496				goto exit;5497	}5498 5499exit:5500	return idx;5501}5502 5503static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,5504				    struct wmi_chan_info_event *ch_info_ev)5505{5506	const void **tb;5507	const struct wmi_chan_info_event *ev;5508	int ret;5509 5510	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5511	if (IS_ERR(tb)) {5512		ret = PTR_ERR(tb);5513		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5514		return ret;5515	}5516 5517	ev = tb[WMI_TAG_CHAN_INFO_EVENT];5518	if (!ev) {5519		ath12k_warn(ab, "failed to fetch chan info ev");5520		kfree(tb);5521		return -EPROTO;5522	}5523 5524	ch_info_ev->err_code = ev->err_code;5525	ch_info_ev->freq = ev->freq;5526	ch_info_ev->cmd_flags = ev->cmd_flags;5527	ch_info_ev->noise_floor = ev->noise_floor;5528	ch_info_ev->rx_clear_count = ev->rx_clear_count;5529	ch_info_ev->cycle_count = ev->cycle_count;5530	ch_info_ev->chan_tx_pwr_range = ev->chan_tx_pwr_range;5531	ch_info_ev->chan_tx_pwr_tp = ev->chan_tx_pwr_tp;5532	ch_info_ev->rx_frame_count = ev->rx_frame_count;5533	ch_info_ev->tx_frame_cnt = ev->tx_frame_cnt;5534	ch_info_ev->mac_clk_mhz = ev->mac_clk_mhz;5535	ch_info_ev->vdev_id = ev->vdev_id;5536 5537	kfree(tb);5538	return 0;5539}5540 5541static int5542ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,5543				  struct wmi_pdev_bss_chan_info_event *bss_ch_info_ev)5544{5545	const void **tb;5546	const struct wmi_pdev_bss_chan_info_event *ev;5547	int ret;5548 5549	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5550	if (IS_ERR(tb)) {5551		ret = PTR_ERR(tb);5552		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5553		return ret;5554	}5555 5556	ev = tb[WMI_TAG_PDEV_BSS_CHAN_INFO_EVENT];5557	if (!ev) {5558		ath12k_warn(ab, "failed to fetch pdev bss chan info ev");5559		kfree(tb);5560		return -EPROTO;5561	}5562 5563	bss_ch_info_ev->pdev_id = ev->pdev_id;5564	bss_ch_info_ev->freq = ev->freq;5565	bss_ch_info_ev->noise_floor = ev->noise_floor;5566	bss_ch_info_ev->rx_clear_count_low = ev->rx_clear_count_low;5567	bss_ch_info_ev->rx_clear_count_high = ev->rx_clear_count_high;5568	bss_ch_info_ev->cycle_count_low = ev->cycle_count_low;5569	bss_ch_info_ev->cycle_count_high = ev->cycle_count_high;5570	bss_ch_info_ev->tx_cycle_count_low = ev->tx_cycle_count_low;5571	bss_ch_info_ev->tx_cycle_count_high = ev->tx_cycle_count_high;5572	bss_ch_info_ev->rx_cycle_count_low = ev->rx_cycle_count_low;5573	bss_ch_info_ev->rx_cycle_count_high = ev->rx_cycle_count_high;5574	bss_ch_info_ev->rx_bss_cycle_count_low = ev->rx_bss_cycle_count_low;5575	bss_ch_info_ev->rx_bss_cycle_count_high = ev->rx_bss_cycle_count_high;5576 5577	kfree(tb);5578	return 0;5579}5580 5581static int5582ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *skb,5583				      struct wmi_vdev_install_key_complete_arg *arg)5584{5585	const void **tb;5586	const struct wmi_vdev_install_key_compl_event *ev;5587	int ret;5588 5589	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5590	if (IS_ERR(tb)) {5591		ret = PTR_ERR(tb);5592		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5593		return ret;5594	}5595 5596	ev = tb[WMI_TAG_VDEV_INSTALL_KEY_COMPLETE_EVENT];5597	if (!ev) {5598		ath12k_warn(ab, "failed to fetch vdev install key compl ev");5599		kfree(tb);5600		return -EPROTO;5601	}5602 5603	arg->vdev_id = le32_to_cpu(ev->vdev_id);5604	arg->macaddr = ev->peer_macaddr.addr;5605	arg->key_idx = le32_to_cpu(ev->key_idx);5606	arg->key_flags = le32_to_cpu(ev->key_flags);5607	arg->status = le32_to_cpu(ev->status);5608 5609	kfree(tb);5610	return 0;5611}5612 5613static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff *skb,5614					  struct wmi_peer_assoc_conf_arg *peer_assoc_conf)5615{5616	const void **tb;5617	const struct wmi_peer_assoc_conf_event *ev;5618	int ret;5619 5620	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5621	if (IS_ERR(tb)) {5622		ret = PTR_ERR(tb);5623		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5624		return ret;5625	}5626 5627	ev = tb[WMI_TAG_PEER_ASSOC_CONF_EVENT];5628	if (!ev) {5629		ath12k_warn(ab, "failed to fetch peer assoc conf ev");5630		kfree(tb);5631		return -EPROTO;5632	}5633 5634	peer_assoc_conf->vdev_id = le32_to_cpu(ev->vdev_id);5635	peer_assoc_conf->macaddr = ev->peer_macaddr.addr;5636 5637	kfree(tb);5638	return 0;5639}5640 5641static int5642ath12k_pull_pdev_temp_ev(struct ath12k_base *ab, struct sk_buff *skb,5643			 const struct wmi_pdev_temperature_event *ev)5644{5645	const void **tb;5646	int ret;5647 5648	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);5649	if (IS_ERR(tb)) {5650		ret = PTR_ERR(tb);5651		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);5652		return ret;5653	}5654 5655	ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT];5656	if (!ev) {5657		ath12k_warn(ab, "failed to fetch pdev temp ev");5658		kfree(tb);5659		return -EPROTO;5660	}5661 5662	kfree(tb);5663	return 0;5664}5665 5666static void ath12k_wmi_op_ep_tx_credits(struct ath12k_base *ab)5667{5668	/* try to send pending beacons first. they take priority */5669	wake_up(&ab->wmi_ab.tx_credits_wq);5670}5671 5672static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab,5673				       struct sk_buff *skb)5674{5675	dev_kfree_skb(skb);5676}5677 5678static bool ath12k_reg_is_world_alpha(char *alpha)5679{5680	if (alpha[0] == '0' && alpha[1] == '0')5681		return true;5682 5683	if (alpha[0] == 'n' && alpha[1] == 'a')5684		return true;5685 5686	return false;5687}5688 5689static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)5690{5691	struct ath12k_reg_info *reg_info = NULL;5692	struct ieee80211_regdomain *regd = NULL;5693	bool intersect = false;5694	int ret = 0, pdev_idx, i, j;5695	struct ath12k *ar;5696 5697	reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);5698	if (!reg_info) {5699		ret = -ENOMEM;5700		goto fallback;5701	}5702 5703	ret = ath12k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);5704 5705	if (ret) {5706		ath12k_warn(ab, "failed to extract regulatory info from received event\n");5707		goto fallback;5708	}5709 5710	if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {5711		/* In case of failure to set the requested ctry,5712		 * fw retains the current regd. We print a failure info5713		 * and return from here.5714		 */5715		ath12k_warn(ab, "Failed to set the requested Country regulatory setting\n");5716		goto mem_free;5717	}5718 5719	pdev_idx = reg_info->phy_id;5720 5721	if (pdev_idx >= ab->num_radios) {5722		/* Process the event for phy0 only if single_pdev_only5723		 * is true. If pdev_idx is valid but not 0, discard the5724		 * event. Otherwise, it goes to fallback.5725		 */5726		if (ab->hw_params->single_pdev_only &&5727		    pdev_idx < ab->hw_params->num_rxdma_per_pdev)5728			goto mem_free;5729		else5730			goto fallback;5731	}5732 5733	/* Avoid multiple overwrites to default regd, during core5734	 * stop-start after mac registration.5735	 */5736	if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&5737	    !memcmp(ab->default_regd[pdev_idx]->alpha2,5738		    reg_info->alpha2, 2))5739		goto mem_free;5740 5741	/* Intersect new rules with default regd if a new country setting was5742	 * requested, i.e a default regd was already set during initialization5743	 * and the regd coming from this event has a valid country info.5744	 */5745	if (ab->default_regd[pdev_idx] &&5746	    !ath12k_reg_is_world_alpha((char *)5747		ab->default_regd[pdev_idx]->alpha2) &&5748	    !ath12k_reg_is_world_alpha((char *)reg_info->alpha2))5749		intersect = true;5750 5751	regd = ath12k_reg_build_regd(ab, reg_info, intersect);5752	if (!regd) {5753		ath12k_warn(ab, "failed to build regd from reg_info\n");5754		goto fallback;5755	}5756 5757	spin_lock(&ab->base_lock);5758	if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {5759		/* Once mac is registered, ar is valid and all CC events from5760		 * fw is considered to be received due to user requests5761		 * currently.5762		 * Free previously built regd before assigning the newly5763		 * generated regd to ar. NULL pointer handling will be5764		 * taken care by kfree itself.5765		 */5766		ar = ab->pdevs[pdev_idx].ar;5767		kfree(ab->new_regd[pdev_idx]);5768		ab->new_regd[pdev_idx] = regd;5769		queue_work(ab->workqueue, &ar->regd_update_work);5770	} else {5771		/* Multiple events for the same *ar is not expected. But we5772		 * can still clear any previously stored default_regd if we5773		 * are receiving this event for the same radio by mistake.5774		 * NULL pointer handling will be taken care by kfree itself.5775		 */5776		kfree(ab->default_regd[pdev_idx]);5777		/* This regd would be applied during mac registration */5778		ab->default_regd[pdev_idx] = regd;5779	}5780	ab->dfs_region = reg_info->dfs_region;5781	spin_unlock(&ab->base_lock);5782 5783	goto mem_free;5784 5785fallback:5786	/* Fallback to older reg (by sending previous country setting5787	 * again if fw has succeeded and we failed to process here.5788	 * The Regdomain should be uniform across driver and fw. Since the5789	 * FW has processed the command and sent a success status, we expect5790	 * this function to succeed as well. If it doesn't, CTRY needs to be5791	 * reverted at the fw and the old SCAN_CHAN_LIST cmd needs to be sent.5792	 */5793	/* TODO: This is rare, but still should also be handled */5794	WARN_ON(1);5795mem_free:5796	if (reg_info) {5797		kfree(reg_info->reg_rules_2g_ptr);5798		kfree(reg_info->reg_rules_5g_ptr);5799		if (reg_info->is_ext_reg_event) {5800			for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++)5801				kfree(reg_info->reg_rules_6g_ap_ptr[i]);5802 5803			for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++)5804				for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++)5805					kfree(reg_info->reg_rules_6g_client_ptr[j][i]);5806		}5807		kfree(reg_info);5808	}5809	return ret;5810}5811 5812static int ath12k_wmi_rdy_parse(struct ath12k_base *ab, u16 tag, u16 len,5813				const void *ptr, void *data)5814{5815	struct ath12k_wmi_rdy_parse *rdy_parse = data;5816	struct wmi_ready_event fixed_param;5817	struct ath12k_wmi_mac_addr_params *addr_list;5818	struct ath12k_pdev *pdev;5819	u32 num_mac_addr;5820	int i;5821 5822	switch (tag) {5823	case WMI_TAG_READY_EVENT:5824		memset(&fixed_param, 0, sizeof(fixed_param));5825		memcpy(&fixed_param, (struct wmi_ready_event *)ptr,5826		       min_t(u16, sizeof(fixed_param), len));5827		ab->wlan_init_status = le32_to_cpu(fixed_param.ready_event_min.status);5828		rdy_parse->num_extra_mac_addr =5829			le32_to_cpu(fixed_param.ready_event_min.num_extra_mac_addr);5830 5831		ether_addr_copy(ab->mac_addr,5832				fixed_param.ready_event_min.mac_addr.addr);5833		ab->pktlog_defs_checksum = le32_to_cpu(fixed_param.pktlog_defs_checksum);5834		ab->wmi_ready = true;5835		break;5836	case WMI_TAG_ARRAY_FIXED_STRUCT:5837		addr_list = (struct ath12k_wmi_mac_addr_params *)ptr;5838		num_mac_addr = rdy_parse->num_extra_mac_addr;5839 5840		if (!(ab->num_radios > 1 && num_mac_addr >= ab->num_radios))5841			break;5842 5843		for (i = 0; i < ab->num_radios; i++) {5844			pdev = &ab->pdevs[i];5845			ether_addr_copy(pdev->mac_addr, addr_list[i].addr);5846		}5847		ab->pdevs_macaddr_valid = true;5848		break;5849	default:5850		break;5851	}5852 5853	return 0;5854}5855 5856static int ath12k_ready_event(struct ath12k_base *ab, struct sk_buff *skb)5857{5858	struct ath12k_wmi_rdy_parse rdy_parse = { };5859	int ret;5860 5861	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,5862				  ath12k_wmi_rdy_parse, &rdy_parse);5863	if (ret) {5864		ath12k_warn(ab, "failed to parse tlv %d\n", ret);5865		return ret;5866	}5867 5868	complete(&ab->wmi_ab.unified_ready);5869	return 0;5870}5871 5872static void ath12k_peer_delete_resp_event(struct ath12k_base *ab, struct sk_buff *skb)5873{5874	struct wmi_peer_delete_resp_event peer_del_resp;5875	struct ath12k *ar;5876 5877	if (ath12k_pull_peer_del_resp_ev(ab, skb, &peer_del_resp) != 0) {5878		ath12k_warn(ab, "failed to extract peer delete resp");5879		return;5880	}5881 5882	rcu_read_lock();5883	ar = ath12k_mac_get_ar_by_vdev_id(ab, le32_to_cpu(peer_del_resp.vdev_id));5884	if (!ar) {5885		ath12k_warn(ab, "invalid vdev id in peer delete resp ev %d",5886			    peer_del_resp.vdev_id);5887		rcu_read_unlock();5888		return;5889	}5890 5891	complete(&ar->peer_delete_done);5892	rcu_read_unlock();5893	ath12k_dbg(ab, ATH12K_DBG_WMI, "peer delete resp for vdev id %d addr %pM\n",5894		   peer_del_resp.vdev_id, peer_del_resp.peer_macaddr.addr);5895}5896 5897static void ath12k_vdev_delete_resp_event(struct ath12k_base *ab,5898					  struct sk_buff *skb)5899{5900	struct ath12k *ar;5901	u32 vdev_id = 0;5902 5903	if (ath12k_pull_vdev_del_resp_ev(ab, skb, &vdev_id) != 0) {5904		ath12k_warn(ab, "failed to extract vdev delete resp");5905		return;5906	}5907 5908	rcu_read_lock();5909	ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);5910	if (!ar) {5911		ath12k_warn(ab, "invalid vdev id in vdev delete resp ev %d",5912			    vdev_id);5913		rcu_read_unlock();5914		return;5915	}5916 5917	complete(&ar->vdev_delete_done);5918 5919	rcu_read_unlock();5920 5921	ath12k_dbg(ab, ATH12K_DBG_WMI, "vdev delete resp for vdev id %d\n",5922		   vdev_id);5923}5924 5925static const char *ath12k_wmi_vdev_resp_print(u32 vdev_resp_status)5926{5927	switch (vdev_resp_status) {5928	case WMI_VDEV_START_RESPONSE_INVALID_VDEVID:5929		return "invalid vdev id";5930	case WMI_VDEV_START_RESPONSE_NOT_SUPPORTED:5931		return "not supported";5932	case WMI_VDEV_START_RESPONSE_DFS_VIOLATION:5933		return "dfs violation";5934	case WMI_VDEV_START_RESPONSE_INVALID_REGDOMAIN:5935		return "invalid regdomain";5936	default:5937		return "unknown";5938	}5939}5940 5941static void ath12k_vdev_start_resp_event(struct ath12k_base *ab, struct sk_buff *skb)5942{5943	struct wmi_vdev_start_resp_event vdev_start_resp;5944	struct ath12k *ar;5945	u32 status;5946 5947	if (ath12k_pull_vdev_start_resp_tlv(ab, skb, &vdev_start_resp) != 0) {5948		ath12k_warn(ab, "failed to extract vdev start resp");5949		return;5950	}5951 5952	rcu_read_lock();5953	ar = ath12k_mac_get_ar_by_vdev_id(ab, le32_to_cpu(vdev_start_resp.vdev_id));5954	if (!ar) {5955		ath12k_warn(ab, "invalid vdev id in vdev start resp ev %d",5956			    vdev_start_resp.vdev_id);5957		rcu_read_unlock();5958		return;5959	}5960 5961	ar->last_wmi_vdev_start_status = 0;5962 5963	status = le32_to_cpu(vdev_start_resp.status);5964 5965	if (WARN_ON_ONCE(status)) {5966		ath12k_warn(ab, "vdev start resp error status %d (%s)\n",5967			    status, ath12k_wmi_vdev_resp_print(status));5968		ar->last_wmi_vdev_start_status = status;5969	}5970 5971	complete(&ar->vdev_setup_done);5972 5973	rcu_read_unlock();5974 5975	ath12k_dbg(ab, ATH12K_DBG_WMI, "vdev start resp for vdev id %d",5976		   vdev_start_resp.vdev_id);5977}5978 5979static void ath12k_bcn_tx_status_event(struct ath12k_base *ab, struct sk_buff *skb)5980{5981	u32 vdev_id, tx_status;5982 5983	if (ath12k_pull_bcn_tx_status_ev(ab, skb, &vdev_id, &tx_status) != 0) {5984		ath12k_warn(ab, "failed to extract bcn tx status");5985		return;5986	}5987}5988 5989static void ath12k_vdev_stopped_event(struct ath12k_base *ab, struct sk_buff *skb)5990{5991	struct ath12k *ar;5992	u32 vdev_id = 0;5993 5994	if (ath12k_pull_vdev_stopped_param_tlv(ab, skb, &vdev_id) != 0) {5995		ath12k_warn(ab, "failed to extract vdev stopped event");5996		return;5997	}5998 5999	rcu_read_lock();6000	ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);6001	if (!ar) {6002		ath12k_warn(ab, "invalid vdev id in vdev stopped ev %d",6003			    vdev_id);6004		rcu_read_unlock();6005		return;6006	}6007 6008	complete(&ar->vdev_setup_done);6009 6010	rcu_read_unlock();6011 6012	ath12k_dbg(ab, ATH12K_DBG_WMI, "vdev stopped for vdev id %d", vdev_id);6013}6014 6015static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)6016{6017	struct ath12k_wmi_mgmt_rx_arg rx_ev = {0};6018	struct ath12k *ar;6019	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);6020	struct ieee80211_hdr *hdr;6021	u16 fc;6022	struct ieee80211_supported_band *sband;6023 6024	if (ath12k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) {6025		ath12k_warn(ab, "failed to extract mgmt rx event");6026		dev_kfree_skb(skb);6027		return;6028	}6029 6030	memset(status, 0, sizeof(*status));6031 6032	ath12k_dbg(ab, ATH12K_DBG_MGMT, "mgmt rx event status %08x\n",6033		   rx_ev.status);6034 6035	rcu_read_lock();6036	ar = ath12k_mac_get_ar_by_pdev_id(ab, rx_ev.pdev_id);6037 6038	if (!ar) {6039		ath12k_warn(ab, "invalid pdev_id %d in mgmt_rx_event\n",6040			    rx_ev.pdev_id);6041		dev_kfree_skb(skb);6042		goto exit;6043	}6044 6045	if ((test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) ||6046	    (rx_ev.status & (WMI_RX_STATUS_ERR_DECRYPT |6047			     WMI_RX_STATUS_ERR_KEY_CACHE_MISS |6048			     WMI_RX_STATUS_ERR_CRC))) {6049		dev_kfree_skb(skb);6050		goto exit;6051	}6052 6053	if (rx_ev.status & WMI_RX_STATUS_ERR_MIC)6054		status->flag |= RX_FLAG_MMIC_ERROR;6055 6056	if (rx_ev.chan_freq >= ATH12K_MIN_6G_FREQ &&6057	    rx_ev.chan_freq <= ATH12K_MAX_6G_FREQ) {6058		status->band = NL80211_BAND_6GHZ;6059		status->freq = rx_ev.chan_freq;6060	} else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) {6061		status->band = NL80211_BAND_2GHZ;6062	} else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH12K_MAX_5G_CHAN) {6063		status->band = NL80211_BAND_5GHZ;6064	} else {6065		/* Shouldn't happen unless list of advertised channels to6066		 * mac80211 has been changed.6067		 */6068		WARN_ON_ONCE(1);6069		dev_kfree_skb(skb);6070		goto exit;6071	}6072 6073	if (rx_ev.phy_mode == MODE_11B &&6074	    (status->band == NL80211_BAND_5GHZ || status->band == NL80211_BAND_6GHZ))6075		ath12k_dbg(ab, ATH12K_DBG_WMI,6076			   "wmi mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band);6077 6078	sband = &ar->mac.sbands[status->band];6079 6080	if (status->band != NL80211_BAND_6GHZ)6081		status->freq = ieee80211_channel_to_frequency(rx_ev.channel,6082							      status->band);6083 6084	status->signal = rx_ev.snr + ATH12K_DEFAULT_NOISE_FLOOR;6085	status->rate_idx = ath12k_mac_bitrate_to_idx(sband, rx_ev.rate / 100);6086 6087	hdr = (struct ieee80211_hdr *)skb->data;6088	fc = le16_to_cpu(hdr->frame_control);6089 6090	/* Firmware is guaranteed to report all essential management frames via6091	 * WMI while it can deliver some extra via HTT. Since there can be6092	 * duplicates split the reporting wrt monitor/sniffing.6093	 */6094	status->flag |= RX_FLAG_SKIP_MONITOR;6095 6096	/* In case of PMF, FW delivers decrypted frames with Protected Bit set6097	 * including group privacy action frames.6098	 */6099	if (ieee80211_has_protected(hdr->frame_control)) {6100		status->flag |= RX_FLAG_DECRYPTED;6101 6102		if (!ieee80211_is_robust_mgmt_frame(skb)) {6103			status->flag |= RX_FLAG_IV_STRIPPED |6104					RX_FLAG_MMIC_STRIPPED;6105			hdr->frame_control = __cpu_to_le16(fc &6106					     ~IEEE80211_FCTL_PROTECTED);6107		}6108	}6109 6110	if (ieee80211_is_beacon(hdr->frame_control))6111		ath12k_mac_handle_beacon(ar, skb);6112 6113	ath12k_dbg(ab, ATH12K_DBG_MGMT,6114		   "event mgmt rx skb %p len %d ftype %02x stype %02x\n",6115		   skb, skb->len,6116		   fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);6117 6118	ath12k_dbg(ab, ATH12K_DBG_MGMT,6119		   "event mgmt rx freq %d band %d snr %d, rate_idx %d\n",6120		   status->freq, status->band, status->signal,6121		   status->rate_idx);6122 6123	ieee80211_rx_ni(ath12k_ar_to_hw(ar), skb);6124 6125exit:6126	rcu_read_unlock();6127}6128 6129static void ath12k_mgmt_tx_compl_event(struct ath12k_base *ab, struct sk_buff *skb)6130{6131	struct wmi_mgmt_tx_compl_event tx_compl_param = {0};6132	struct ath12k *ar;6133 6134	if (ath12k_pull_mgmt_tx_compl_param_tlv(ab, skb, &tx_compl_param) != 0) {6135		ath12k_warn(ab, "failed to extract mgmt tx compl event");6136		return;6137	}6138 6139	rcu_read_lock();6140	ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(tx_compl_param.pdev_id));6141	if (!ar) {6142		ath12k_warn(ab, "invalid pdev id %d in mgmt_tx_compl_event\n",6143			    tx_compl_param.pdev_id);6144		goto exit;6145	}6146 6147	wmi_process_mgmt_tx_comp(ar, le32_to_cpu(tx_compl_param.desc_id),6148				 le32_to_cpu(tx_compl_param.status));6149 6150	ath12k_dbg(ab, ATH12K_DBG_MGMT,6151		   "mgmt tx compl ev pdev_id %d, desc_id %d, status %d",6152		   tx_compl_param.pdev_id, tx_compl_param.desc_id,6153		   tx_compl_param.status);6154 6155exit:6156	rcu_read_unlock();6157}6158 6159static struct ath12k *ath12k_get_ar_on_scan_state(struct ath12k_base *ab,6160						  u32 vdev_id,6161						  enum ath12k_scan_state state)6162{6163	int i;6164	struct ath12k_pdev *pdev;6165	struct ath12k *ar;6166 6167	for (i = 0; i < ab->num_radios; i++) {6168		pdev = rcu_dereference(ab->pdevs_active[i]);6169		if (pdev && pdev->ar) {6170			ar = pdev->ar;6171 6172			spin_lock_bh(&ar->data_lock);6173			if (ar->scan.state == state &&6174			    ar->scan.vdev_id == vdev_id) {6175				spin_unlock_bh(&ar->data_lock);6176				return ar;6177			}6178			spin_unlock_bh(&ar->data_lock);6179		}6180	}6181	return NULL;6182}6183 6184static void ath12k_scan_event(struct ath12k_base *ab, struct sk_buff *skb)6185{6186	struct ath12k *ar;6187	struct wmi_scan_event scan_ev = {0};6188 6189	if (ath12k_pull_scan_ev(ab, skb, &scan_ev) != 0) {6190		ath12k_warn(ab, "failed to extract scan event");6191		return;6192	}6193 6194	rcu_read_lock();6195 6196	/* In case the scan was cancelled, ex. during interface teardown,6197	 * the interface will not be found in active interfaces.6198	 * Rather, in such scenarios, iterate over the active pdev's to6199	 * search 'ar' if the corresponding 'ar' scan is ABORTING and the6200	 * aborting scan's vdev id matches this event info.6201	 */6202	if (le32_to_cpu(scan_ev.event_type) == WMI_SCAN_EVENT_COMPLETED &&6203	    le32_to_cpu(scan_ev.reason) == WMI_SCAN_REASON_CANCELLED) {6204		ar = ath12k_get_ar_on_scan_state(ab, le32_to_cpu(scan_ev.vdev_id),6205						 ATH12K_SCAN_ABORTING);6206		if (!ar)6207			ar = ath12k_get_ar_on_scan_state(ab, le32_to_cpu(scan_ev.vdev_id),6208							 ATH12K_SCAN_RUNNING);6209	} else {6210		ar = ath12k_mac_get_ar_by_vdev_id(ab, le32_to_cpu(scan_ev.vdev_id));6211	}6212 6213	if (!ar) {6214		ath12k_warn(ab, "Received scan event for unknown vdev");6215		rcu_read_unlock();6216		return;6217	}6218 6219	spin_lock_bh(&ar->data_lock);6220 6221	ath12k_dbg(ab, ATH12K_DBG_WMI,6222		   "scan event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",6223		   ath12k_wmi_event_scan_type_str(le32_to_cpu(scan_ev.event_type),6224						  le32_to_cpu(scan_ev.reason)),6225		   le32_to_cpu(scan_ev.event_type),6226		   le32_to_cpu(scan_ev.reason),6227		   le32_to_cpu(scan_ev.channel_freq),6228		   le32_to_cpu(scan_ev.scan_req_id),6229		   le32_to_cpu(scan_ev.scan_id),6230		   le32_to_cpu(scan_ev.vdev_id),6231		   ath12k_scan_state_str(ar->scan.state), ar->scan.state);6232 6233	switch (le32_to_cpu(scan_ev.event_type)) {6234	case WMI_SCAN_EVENT_STARTED:6235		ath12k_wmi_event_scan_started(ar);6236		break;6237	case WMI_SCAN_EVENT_COMPLETED:6238		ath12k_wmi_event_scan_completed(ar);6239		break;6240	case WMI_SCAN_EVENT_BSS_CHANNEL:6241		ath12k_wmi_event_scan_bss_chan(ar);6242		break;6243	case WMI_SCAN_EVENT_FOREIGN_CHAN:6244		ath12k_wmi_event_scan_foreign_chan(ar, le32_to_cpu(scan_ev.channel_freq));6245		break;6246	case WMI_SCAN_EVENT_START_FAILED:6247		ath12k_warn(ab, "received scan start failure event\n");6248		ath12k_wmi_event_scan_start_failed(ar);6249		break;6250	case WMI_SCAN_EVENT_DEQUEUED:6251		__ath12k_mac_scan_finish(ar);6252		break;6253	case WMI_SCAN_EVENT_PREEMPTED:6254	case WMI_SCAN_EVENT_RESTARTED:6255	case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT:6256	default:6257		break;6258	}6259 6260	spin_unlock_bh(&ar->data_lock);6261 6262	rcu_read_unlock();6263}6264 6265static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff *skb)6266{6267	struct wmi_peer_sta_kickout_arg arg = {};6268	struct ieee80211_sta *sta;6269	struct ath12k_peer *peer;6270	struct ath12k *ar;6271 6272	if (ath12k_pull_peer_sta_kickout_ev(ab, skb, &arg) != 0) {6273		ath12k_warn(ab, "failed to extract peer sta kickout event");6274		return;6275	}6276 6277	rcu_read_lock();6278 6279	spin_lock_bh(&ab->base_lock);6280 6281	peer = ath12k_peer_find_by_addr(ab, arg.mac_addr);6282 6283	if (!peer) {6284		ath12k_warn(ab, "peer not found %pM\n",6285			    arg.mac_addr);6286		goto exit;6287	}6288 6289	ar = ath12k_mac_get_ar_by_vdev_id(ab, peer->vdev_id);6290	if (!ar) {6291		ath12k_warn(ab, "invalid vdev id in peer sta kickout ev %d",6292			    peer->vdev_id);6293		goto exit;6294	}6295 6296	sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),6297					   arg.mac_addr, NULL);6298	if (!sta) {6299		ath12k_warn(ab, "Spurious quick kickout for STA %pM\n",6300			    arg.mac_addr);6301		goto exit;6302	}6303 6304	ath12k_dbg(ab, ATH12K_DBG_WMI, "peer sta kickout event %pM",6305		   arg.mac_addr);6306 6307	ieee80211_report_low_ack(sta, 10);6308 6309exit:6310	spin_unlock_bh(&ab->base_lock);6311	rcu_read_unlock();6312}6313 6314static void ath12k_roam_event(struct ath12k_base *ab, struct sk_buff *skb)6315{6316	struct wmi_roam_event roam_ev = {};6317	struct ath12k *ar;6318	u32 vdev_id;6319	u8 roam_reason;6320 6321	if (ath12k_pull_roam_ev(ab, skb, &roam_ev) != 0) {6322		ath12k_warn(ab, "failed to extract roam event");6323		return;6324	}6325 6326	vdev_id = le32_to_cpu(roam_ev.vdev_id);6327	roam_reason = u32_get_bits(le32_to_cpu(roam_ev.reason),6328				   WMI_ROAM_REASON_MASK);6329 6330	ath12k_dbg(ab, ATH12K_DBG_WMI,6331		   "wmi roam event vdev %u reason %d rssi %d\n",6332		   vdev_id, roam_reason, roam_ev.rssi);6333 6334	rcu_read_lock();6335	ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);6336	if (!ar) {6337		ath12k_warn(ab, "invalid vdev id in roam ev %d", vdev_id);6338		rcu_read_unlock();6339		return;6340	}6341 6342	if (roam_reason >= WMI_ROAM_REASON_MAX)6343		ath12k_warn(ab, "ignoring unknown roam event reason %d on vdev %i\n",6344			    roam_reason, vdev_id);6345 6346	switch (roam_reason) {6347	case WMI_ROAM_REASON_BEACON_MISS:6348		ath12k_mac_handle_beacon_miss(ar, vdev_id);6349		break;6350	case WMI_ROAM_REASON_BETTER_AP:6351	case WMI_ROAM_REASON_LOW_RSSI:6352	case WMI_ROAM_REASON_SUITABLE_AP_FOUND:6353	case WMI_ROAM_REASON_HO_FAILED:6354		ath12k_warn(ab, "ignoring not implemented roam event reason %d on vdev %i\n",6355			    roam_reason, vdev_id);6356		break;6357	}6358 6359	rcu_read_unlock();6360}6361 6362static void ath12k_chan_info_event(struct ath12k_base *ab, struct sk_buff *skb)6363{6364	struct wmi_chan_info_event ch_info_ev = {0};6365	struct ath12k *ar;6366	struct survey_info *survey;6367	int idx;6368	/* HW channel counters frequency value in hertz */6369	u32 cc_freq_hz = ab->cc_freq_hz;6370 6371	if (ath12k_pull_chan_info_ev(ab, skb, &ch_info_ev) != 0) {6372		ath12k_warn(ab, "failed to extract chan info event");6373		return;6374	}6375 6376	ath12k_dbg(ab, ATH12K_DBG_WMI,6377		   "chan info vdev_id %d err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d mac_clk_mhz %d\n",6378		   ch_info_ev.vdev_id, ch_info_ev.err_code, ch_info_ev.freq,6379		   ch_info_ev.cmd_flags, ch_info_ev.noise_floor,6380		   ch_info_ev.rx_clear_count, ch_info_ev.cycle_count,6381		   ch_info_ev.mac_clk_mhz);6382 6383	if (le32_to_cpu(ch_info_ev.cmd_flags) == WMI_CHAN_INFO_END_RESP) {6384		ath12k_dbg(ab, ATH12K_DBG_WMI, "chan info report completed\n");6385		return;6386	}6387 6388	rcu_read_lock();6389	ar = ath12k_mac_get_ar_by_vdev_id(ab, le32_to_cpu(ch_info_ev.vdev_id));6390	if (!ar) {6391		ath12k_warn(ab, "invalid vdev id in chan info ev %d",6392			    ch_info_ev.vdev_id);6393		rcu_read_unlock();6394		return;6395	}6396	spin_lock_bh(&ar->data_lock);6397 6398	switch (ar->scan.state) {6399	case ATH12K_SCAN_IDLE:6400	case ATH12K_SCAN_STARTING:6401		ath12k_warn(ab, "received chan info event without a scan request, ignoring\n");6402		goto exit;6403	case ATH12K_SCAN_RUNNING:6404	case ATH12K_SCAN_ABORTING:6405		break;6406	}6407 6408	idx = freq_to_idx(ar, le32_to_cpu(ch_info_ev.freq));6409	if (idx >= ARRAY_SIZE(ar->survey)) {6410		ath12k_warn(ab, "chan info: invalid frequency %d (idx %d out of bounds)\n",6411			    ch_info_ev.freq, idx);6412		goto exit;6413	}6414 6415	/* If FW provides MAC clock frequency in Mhz, overriding the initialized6416	 * HW channel counters frequency value6417	 */6418	if (ch_info_ev.mac_clk_mhz)6419		cc_freq_hz = (le32_to_cpu(ch_info_ev.mac_clk_mhz) * 1000);6420 6421	if (ch_info_ev.cmd_flags == WMI_CHAN_INFO_START_RESP) {6422		survey = &ar->survey[idx];6423		memset(survey, 0, sizeof(*survey));6424		survey->noise = le32_to_cpu(ch_info_ev.noise_floor);6425		survey->filled = SURVEY_INFO_NOISE_DBM | SURVEY_INFO_TIME |6426				 SURVEY_INFO_TIME_BUSY;6427		survey->time = div_u64(le32_to_cpu(ch_info_ev.cycle_count), cc_freq_hz);6428		survey->time_busy = div_u64(le32_to_cpu(ch_info_ev.rx_clear_count),6429					    cc_freq_hz);6430	}6431exit:6432	spin_unlock_bh(&ar->data_lock);6433	rcu_read_unlock();6434}6435 6436static void6437ath12k_pdev_bss_chan_info_event(struct ath12k_base *ab, struct sk_buff *skb)6438{6439	struct wmi_pdev_bss_chan_info_event bss_ch_info_ev = {};6440	struct survey_info *survey;6441	struct ath12k *ar;6442	u32 cc_freq_hz = ab->cc_freq_hz;6443	u64 busy, total, tx, rx, rx_bss;6444	int idx;6445 6446	if (ath12k_pull_pdev_bss_chan_info_ev(ab, skb, &bss_ch_info_ev) != 0) {6447		ath12k_warn(ab, "failed to extract pdev bss chan info event");6448		return;6449	}6450 6451	busy = (u64)(le32_to_cpu(bss_ch_info_ev.rx_clear_count_high)) << 32 |6452		le32_to_cpu(bss_ch_info_ev.rx_clear_count_low);6453 6454	total = (u64)(le32_to_cpu(bss_ch_info_ev.cycle_count_high)) << 32 |6455		le32_to_cpu(bss_ch_info_ev.cycle_count_low);6456 6457	tx = (u64)(le32_to_cpu(bss_ch_info_ev.tx_cycle_count_high)) << 32 |6458		le32_to_cpu(bss_ch_info_ev.tx_cycle_count_low);6459 6460	rx = (u64)(le32_to_cpu(bss_ch_info_ev.rx_cycle_count_high)) << 32 |6461		le32_to_cpu(bss_ch_info_ev.rx_cycle_count_low);6462 6463	rx_bss = (u64)(le32_to_cpu(bss_ch_info_ev.rx_bss_cycle_count_high)) << 32 |6464		le32_to_cpu(bss_ch_info_ev.rx_bss_cycle_count_low);6465 6466	ath12k_dbg(ab, ATH12K_DBG_WMI,6467		   "pdev bss chan info:\n pdev_id: %d freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n",6468		   bss_ch_info_ev.pdev_id, bss_ch_info_ev.freq,6469		   bss_ch_info_ev.noise_floor, busy, total,6470		   tx, rx, rx_bss);6471 6472	rcu_read_lock();6473	ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(bss_ch_info_ev.pdev_id));6474 6475	if (!ar) {6476		ath12k_warn(ab, "invalid pdev id %d in bss_chan_info event\n",6477			    bss_ch_info_ev.pdev_id);6478		rcu_read_unlock();6479		return;6480	}6481 6482	spin_lock_bh(&ar->data_lock);6483	idx = freq_to_idx(ar, le32_to_cpu(bss_ch_info_ev.freq));6484	if (idx >= ARRAY_SIZE(ar->survey)) {6485		ath12k_warn(ab, "bss chan info: invalid frequency %d (idx %d out of bounds)\n",6486			    bss_ch_info_ev.freq, idx);6487		goto exit;6488	}6489 6490	survey = &ar->survey[idx];6491 6492	survey->noise     = le32_to_cpu(bss_ch_info_ev.noise_floor);6493	survey->time      = div_u64(total, cc_freq_hz);6494	survey->time_busy = div_u64(busy, cc_freq_hz);6495	survey->time_rx   = div_u64(rx_bss, cc_freq_hz);6496	survey->time_tx   = div_u64(tx, cc_freq_hz);6497	survey->filled   |= (SURVEY_INFO_NOISE_DBM |6498			     SURVEY_INFO_TIME |6499			     SURVEY_INFO_TIME_BUSY |6500			     SURVEY_INFO_TIME_RX |6501			     SURVEY_INFO_TIME_TX);6502exit:6503	spin_unlock_bh(&ar->data_lock);6504	complete(&ar->bss_survey_done);6505 6506	rcu_read_unlock();6507}6508 6509static void ath12k_vdev_install_key_compl_event(struct ath12k_base *ab,6510						struct sk_buff *skb)6511{6512	struct wmi_vdev_install_key_complete_arg install_key_compl = {0};6513	struct ath12k *ar;6514 6515	if (ath12k_pull_vdev_install_key_compl_ev(ab, skb, &install_key_compl) != 0) {6516		ath12k_warn(ab, "failed to extract install key compl event");6517		return;6518	}6519 6520	ath12k_dbg(ab, ATH12K_DBG_WMI,6521		   "vdev install key ev idx %d flags %08x macaddr %pM status %d\n",6522		   install_key_compl.key_idx, install_key_compl.key_flags,6523		   install_key_compl.macaddr, install_key_compl.status);6524 6525	rcu_read_lock();6526	ar = ath12k_mac_get_ar_by_vdev_id(ab, install_key_compl.vdev_id);6527	if (!ar) {6528		ath12k_warn(ab, "invalid vdev id in install key compl ev %d",6529			    install_key_compl.vdev_id);6530		rcu_read_unlock();6531		return;6532	}6533 6534	ar->install_key_status = 0;6535 6536	if (install_key_compl.status != WMI_VDEV_INSTALL_KEY_COMPL_STATUS_SUCCESS) {6537		ath12k_warn(ab, "install key failed for %pM status %d\n",6538			    install_key_compl.macaddr, install_key_compl.status);6539		ar->install_key_status = install_key_compl.status;6540	}6541 6542	complete(&ar->install_key_done);6543	rcu_read_unlock();6544}6545 6546static int ath12k_wmi_tlv_services_parser(struct ath12k_base *ab,6547					  u16 tag, u16 len,6548					  const void *ptr,6549					  void *data)6550{6551	const struct wmi_service_available_event *ev;6552	u32 *wmi_ext2_service_bitmap;6553	int i, j;6554	u16 expected_len;6555 6556	expected_len = WMI_SERVICE_SEGMENT_BM_SIZE32 * sizeof(u32);6557	if (len < expected_len) {6558		ath12k_warn(ab, "invalid length %d for the WMI services available tag 0x%x\n",6559			    len, tag);6560		return -EINVAL;6561	}6562 6563	switch (tag) {6564	case WMI_TAG_SERVICE_AVAILABLE_EVENT:6565		ev = (struct wmi_service_available_event *)ptr;6566		for (i = 0, j = WMI_MAX_SERVICE;6567		     i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE;6568		     i++) {6569			do {6570				if (le32_to_cpu(ev->wmi_service_segment_bitmap[i]) &6571				    BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))6572					set_bit(j, ab->wmi_ab.svc_map);6573			} while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);6574		}6575 6576		ath12k_dbg(ab, ATH12K_DBG_WMI,6577			   "wmi_ext_service_bitmap 0x%x 0x%x 0x%x 0x%x",6578			   ev->wmi_service_segment_bitmap[0],6579			   ev->wmi_service_segment_bitmap[1],6580			   ev->wmi_service_segment_bitmap[2],6581			   ev->wmi_service_segment_bitmap[3]);6582		break;6583	case WMI_TAG_ARRAY_UINT32:6584		wmi_ext2_service_bitmap = (u32 *)ptr;6585		for (i = 0, j = WMI_MAX_EXT_SERVICE;6586		     i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT2_SERVICE;6587		     i++) {6588			do {6589				if (wmi_ext2_service_bitmap[i] &6590				    BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))6591					set_bit(j, ab->wmi_ab.svc_map);6592			} while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);6593		}6594 6595		ath12k_dbg(ab, ATH12K_DBG_WMI,6596			   "wmi_ext2_service_bitmap 0x%04x 0x%04x 0x%04x 0x%04x",6597			   wmi_ext2_service_bitmap[0], wmi_ext2_service_bitmap[1],6598			   wmi_ext2_service_bitmap[2], wmi_ext2_service_bitmap[3]);6599		break;6600	}6601	return 0;6602}6603 6604static int ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb)6605{6606	int ret;6607 6608	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,6609				  ath12k_wmi_tlv_services_parser,6610				  NULL);6611	return ret;6612}6613 6614static void ath12k_peer_assoc_conf_event(struct ath12k_base *ab, struct sk_buff *skb)6615{6616	struct wmi_peer_assoc_conf_arg peer_assoc_conf = {0};6617	struct ath12k *ar;6618 6619	if (ath12k_pull_peer_assoc_conf_ev(ab, skb, &peer_assoc_conf) != 0) {6620		ath12k_warn(ab, "failed to extract peer assoc conf event");6621		return;6622	}6623 6624	ath12k_dbg(ab, ATH12K_DBG_WMI,6625		   "peer assoc conf ev vdev id %d macaddr %pM\n",6626		   peer_assoc_conf.vdev_id, peer_assoc_conf.macaddr);6627 6628	rcu_read_lock();6629	ar = ath12k_mac_get_ar_by_vdev_id(ab, peer_assoc_conf.vdev_id);6630 6631	if (!ar) {6632		ath12k_warn(ab, "invalid vdev id in peer assoc conf ev %d",6633			    peer_assoc_conf.vdev_id);6634		rcu_read_unlock();6635		return;6636	}6637 6638	complete(&ar->peer_assoc_done);6639	rcu_read_unlock();6640}6641 6642static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb)6643{6644}6645 6646/* PDEV_CTL_FAILSAFE_CHECK_EVENT is received from FW when the frequency scanned6647 * is not part of BDF CTL(Conformance test limits) table entries.6648 */6649static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,6650						 struct sk_buff *skb)6651{6652	const void **tb;6653	const struct wmi_pdev_ctl_failsafe_chk_event *ev;6654	int ret;6655 6656	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6657	if (IS_ERR(tb)) {6658		ret = PTR_ERR(tb);6659		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);6660		return;6661	}6662 6663	ev = tb[WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT];6664	if (!ev) {6665		ath12k_warn(ab, "failed to fetch pdev ctl failsafe check ev");6666		kfree(tb);6667		return;6668	}6669 6670	ath12k_dbg(ab, ATH12K_DBG_WMI,6671		   "pdev ctl failsafe check ev status %d\n",6672		   ev->ctl_failsafe_status);6673 6674	/* If ctl_failsafe_status is set to 1 FW will max out the Transmit power6675	 * to 10 dBm else the CTL power entry in the BDF would be picked up.6676	 */6677	if (ev->ctl_failsafe_status != 0)6678		ath12k_warn(ab, "pdev ctl failsafe failure status %d",6679			    ev->ctl_failsafe_status);6680 6681	kfree(tb);6682}6683 6684static void6685ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,6686					  const struct ath12k_wmi_pdev_csa_event *ev,6687					  const u32 *vdev_ids)6688{6689	int i;6690	struct ath12k_vif *arvif;6691 6692	/* Finish CSA once the switch count becomes NULL */6693	if (ev->current_switch_count)6694		return;6695 6696	rcu_read_lock();6697	for (i = 0; i < le32_to_cpu(ev->num_vdevs); i++) {6698		arvif = ath12k_mac_get_arvif_by_vdev_id(ab, vdev_ids[i]);6699 6700		if (!arvif) {6701			ath12k_warn(ab, "Recvd csa status for unknown vdev %d",6702				    vdev_ids[i]);6703			continue;6704		}6705 6706		if (arvif->is_up && arvif->vif->bss_conf.csa_active)6707			ieee80211_csa_finish(arvif->vif, 0);6708	}6709	rcu_read_unlock();6710}6711 6712static void6713ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,6714					      struct sk_buff *skb)6715{6716	const void **tb;6717	const struct ath12k_wmi_pdev_csa_event *ev;6718	const u32 *vdev_ids;6719	int ret;6720 6721	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6722	if (IS_ERR(tb)) {6723		ret = PTR_ERR(tb);6724		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);6725		return;6726	}6727 6728	ev = tb[WMI_TAG_PDEV_CSA_SWITCH_COUNT_STATUS_EVENT];6729	vdev_ids = tb[WMI_TAG_ARRAY_UINT32];6730 6731	if (!ev || !vdev_ids) {6732		ath12k_warn(ab, "failed to fetch pdev csa switch count ev");6733		kfree(tb);6734		return;6735	}6736 6737	ath12k_dbg(ab, ATH12K_DBG_WMI,6738		   "pdev csa switch count %d for pdev %d, num_vdevs %d",6739		   ev->current_switch_count, ev->pdev_id,6740		   ev->num_vdevs);6741 6742	ath12k_wmi_process_csa_switch_count_event(ab, ev, vdev_ids);6743 6744	kfree(tb);6745}6746 6747static void6748ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff *skb)6749{6750	const void **tb;6751	const struct ath12k_wmi_pdev_radar_event *ev;6752	struct ath12k *ar;6753	int ret;6754 6755	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6756	if (IS_ERR(tb)) {6757		ret = PTR_ERR(tb);6758		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);6759		return;6760	}6761 6762	ev = tb[WMI_TAG_PDEV_DFS_RADAR_DETECTION_EVENT];6763 6764	if (!ev) {6765		ath12k_warn(ab, "failed to fetch pdev dfs radar detected ev");6766		kfree(tb);6767		return;6768	}6769 6770	ath12k_dbg(ab, ATH12K_DBG_WMI,6771		   "pdev dfs radar detected on pdev %d, detection mode %d, chan freq %d, chan_width %d, detector id %d, seg id %d, timestamp %d, chirp %d, freq offset %d, sidx %d",6772		   ev->pdev_id, ev->detection_mode, ev->chan_freq, ev->chan_width,6773		   ev->detector_id, ev->segment_id, ev->timestamp, ev->is_chirp,6774		   ev->freq_offset, ev->sidx);6775 6776	rcu_read_lock();6777 6778	ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(ev->pdev_id));6779 6780	if (!ar) {6781		ath12k_warn(ab, "radar detected in invalid pdev %d\n",6782			    ev->pdev_id);6783		goto exit;6784	}6785 6786	ath12k_dbg(ar->ab, ATH12K_DBG_REG, "DFS Radar Detected in pdev %d\n",6787		   ev->pdev_id);6788 6789	if (ar->dfs_block_radar_events)6790		ath12k_info(ab, "DFS Radar detected, but ignored as requested\n");6791	else6792		ieee80211_radar_detected(ath12k_ar_to_hw(ar), NULL);6793 6794exit:6795	rcu_read_unlock();6796 6797	kfree(tb);6798}6799 6800static void6801ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,6802				  struct sk_buff *skb)6803{6804	struct ath12k *ar;6805	struct wmi_pdev_temperature_event ev = {0};6806 6807	if (ath12k_pull_pdev_temp_ev(ab, skb, &ev) != 0) {6808		ath12k_warn(ab, "failed to extract pdev temperature event");6809		return;6810	}6811 6812	ath12k_dbg(ab, ATH12K_DBG_WMI,6813		   "pdev temperature ev temp %d pdev_id %d\n", ev.temp, ev.pdev_id);6814 6815	rcu_read_lock();6816 6817	ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(ev.pdev_id));6818	if (!ar) {6819		ath12k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id);6820		goto exit;6821	}6822 6823exit:6824	rcu_read_unlock();6825}6826 6827static void ath12k_fils_discovery_event(struct ath12k_base *ab,6828					struct sk_buff *skb)6829{6830	const void **tb;6831	const struct wmi_fils_discovery_event *ev;6832	int ret;6833 6834	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6835	if (IS_ERR(tb)) {6836		ret = PTR_ERR(tb);6837		ath12k_warn(ab,6838			    "failed to parse FILS discovery event tlv %d\n",6839			    ret);6840		return;6841	}6842 6843	ev = tb[WMI_TAG_HOST_SWFDA_EVENT];6844	if (!ev) {6845		ath12k_warn(ab, "failed to fetch FILS discovery event\n");6846		kfree(tb);6847		return;6848	}6849 6850	ath12k_warn(ab,6851		    "FILS discovery frame expected from host for vdev_id: %u, transmission scheduled at %u, next TBTT: %u\n",6852		    ev->vdev_id, ev->fils_tt, ev->tbtt);6853 6854	kfree(tb);6855}6856 6857static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,6858					      struct sk_buff *skb)6859{6860	const void **tb;6861	const struct wmi_probe_resp_tx_status_event *ev;6862	int ret;6863 6864	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6865	if (IS_ERR(tb)) {6866		ret = PTR_ERR(tb);6867		ath12k_warn(ab,6868			    "failed to parse probe response transmission status event tlv: %d\n",6869			    ret);6870		return;6871	}6872 6873	ev = tb[WMI_TAG_OFFLOAD_PRB_RSP_TX_STATUS_EVENT];6874	if (!ev) {6875		ath12k_warn(ab,6876			    "failed to fetch probe response transmission status event");6877		kfree(tb);6878		return;6879	}6880 6881	if (ev->tx_status)6882		ath12k_warn(ab,6883			    "Probe response transmission failed for vdev_id %u, status %u\n",6884			    ev->vdev_id, ev->tx_status);6885 6886	kfree(tb);6887}6888 6889static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,6890				    struct sk_buff *skb)6891{6892	const void **tb;6893	const struct wmi_p2p_noa_event *ev;6894	const struct ath12k_wmi_p2p_noa_info *noa;6895	struct ath12k *ar;6896	int ret, vdev_id;6897 6898	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6899	if (IS_ERR(tb)) {6900		ret = PTR_ERR(tb);6901		ath12k_warn(ab, "failed to parse P2P NoA TLV: %d\n", ret);6902		return ret;6903	}6904 6905	ev = tb[WMI_TAG_P2P_NOA_EVENT];6906	noa = tb[WMI_TAG_P2P_NOA_INFO];6907 6908	if (!ev || !noa) {6909		ret = -EPROTO;6910		goto out;6911	}6912 6913	vdev_id = __le32_to_cpu(ev->vdev_id);6914 6915	ath12k_dbg(ab, ATH12K_DBG_WMI,6916		   "wmi tlv p2p noa vdev_id %i descriptors %u\n",6917		   vdev_id, le32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_DESC_NUM));6918 6919	rcu_read_lock();6920	ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);6921	if (!ar) {6922		ath12k_warn(ab, "invalid vdev id %d in P2P NoA event\n",6923			    vdev_id);6924		ret = -EINVAL;6925		goto unlock;6926	}6927 6928	ath12k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);6929 6930	ret = 0;6931 6932unlock:6933	rcu_read_unlock();6934out:6935	kfree(tb);6936	return ret;6937}6938 6939static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,6940					     struct sk_buff *skb)6941{6942	const struct wmi_rfkill_state_change_event *ev;6943	const void **tb;6944	int ret;6945 6946	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6947	if (IS_ERR(tb)) {6948		ret = PTR_ERR(tb);6949		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);6950		return;6951	}6952 6953	ev = tb[WMI_TAG_RFKILL_EVENT];6954	if (!ev) {6955		kfree(tb);6956		return;6957	}6958 6959	ath12k_dbg(ab, ATH12K_DBG_MAC,6960		   "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",6961		   le32_to_cpu(ev->gpio_pin_num),6962		   le32_to_cpu(ev->int_type),6963		   le32_to_cpu(ev->radio_state));6964 6965	spin_lock_bh(&ab->base_lock);6966	ab->rfkill_radio_on = (ev->radio_state == cpu_to_le32(WMI_RFKILL_RADIO_STATE_ON));6967	spin_unlock_bh(&ab->base_lock);6968 6969	queue_work(ab->workqueue, &ab->rfkill_work);6970	kfree(tb);6971}6972 6973static void6974ath12k_wmi_diag_event(struct ath12k_base *ab, struct sk_buff *skb)6975{6976	trace_ath12k_wmi_diag(ab, skb->data, skb->len);6977}6978 6979static void ath12k_wmi_twt_enable_event(struct ath12k_base *ab,6980					struct sk_buff *skb)6981{6982	const void **tb;6983	const struct wmi_twt_enable_event *ev;6984	int ret;6985 6986	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);6987	if (IS_ERR(tb)) {6988		ret = PTR_ERR(tb);6989		ath12k_warn(ab, "failed to parse wmi twt enable status event tlv: %d\n",6990			    ret);6991		return;6992	}6993 6994	ev = tb[WMI_TAG_TWT_ENABLE_COMPLETE_EVENT];6995	if (!ev) {6996		ath12k_warn(ab, "failed to fetch twt enable wmi event\n");6997		goto exit;6998	}6999 7000	ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt enable event pdev id %u status %u\n",7001		   le32_to_cpu(ev->pdev_id),7002		   le32_to_cpu(ev->status));7003 7004exit:7005	kfree(tb);7006}7007 7008static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,7009					 struct sk_buff *skb)7010{7011	const void **tb;7012	const struct wmi_twt_disable_event *ev;7013	int ret;7014 7015	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);7016	if (IS_ERR(tb)) {7017		ret = PTR_ERR(tb);7018		ath12k_warn(ab, "failed to parse wmi twt disable status event tlv: %d\n",7019			    ret);7020		return;7021	}7022 7023	ev = tb[WMI_TAG_TWT_DISABLE_COMPLETE_EVENT];7024	if (!ev) {7025		ath12k_warn(ab, "failed to fetch twt disable wmi event\n");7026		goto exit;7027	}7028 7029	ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt disable event pdev id %d status %u\n",7030		   le32_to_cpu(ev->pdev_id),7031		   le32_to_cpu(ev->status));7032 7033exit:7034	kfree(tb);7035}7036 7037static int ath12k_wmi_wow_wakeup_host_parse(struct ath12k_base *ab,7038					    u16 tag, u16 len,7039					    const void *ptr, void *data)7040{7041	const struct wmi_wow_ev_pg_fault_param *pf_param;7042	const struct wmi_wow_ev_param *param;7043	struct wmi_wow_ev_arg *arg = data;7044	int pf_len;7045 7046	switch (tag) {7047	case WMI_TAG_WOW_EVENT_INFO:7048		param = ptr;7049		arg->wake_reason = le32_to_cpu(param->wake_reason);7050		ath12k_dbg(ab, ATH12K_DBG_WMI, "wow wakeup host reason %d %s\n",7051			   arg->wake_reason, wow_reason(arg->wake_reason));7052		break;7053 7054	case WMI_TAG_ARRAY_BYTE:7055		if (arg && arg->wake_reason == WOW_REASON_PAGE_FAULT) {7056			pf_param = ptr;7057			pf_len = le32_to_cpu(pf_param->len);7058			if (pf_len > len - sizeof(pf_len) ||7059			    pf_len < 0) {7060				ath12k_warn(ab, "invalid wo reason page fault buffer len %d\n",7061					    pf_len);7062				return -EINVAL;7063			}7064			ath12k_dbg(ab, ATH12K_DBG_WMI, "wow_reason_page_fault len %d\n",7065				   pf_len);7066			ath12k_dbg_dump(ab, ATH12K_DBG_WMI,7067					"wow_reason_page_fault packet present",7068					"wow_pg_fault ",7069					pf_param->data,7070					pf_len);7071		}7072		break;7073	default:7074		break;7075	}7076 7077	return 0;7078}7079 7080static void ath12k_wmi_event_wow_wakeup_host(struct ath12k_base *ab, struct sk_buff *skb)7081{7082	struct wmi_wow_ev_arg arg = { };7083	int ret;7084 7085	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,7086				  ath12k_wmi_wow_wakeup_host_parse,7087				  &arg);7088	if (ret) {7089		ath12k_warn(ab, "failed to parse wmi wow wakeup host event tlv: %d\n",7090			    ret);7091		return;7092	}7093 7094	complete(&ab->wow.wakeup_completed);7095}7096 7097static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,7098						struct sk_buff *skb)7099{7100	const struct wmi_gtk_offload_status_event *ev;7101	struct ath12k_vif *arvif;7102	__be64 replay_ctr_be;7103	u64 replay_ctr;7104	const void **tb;7105	int ret;7106 7107	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);7108	if (IS_ERR(tb)) {7109		ret = PTR_ERR(tb);7110		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);7111		return;7112	}7113 7114	ev = tb[WMI_TAG_GTK_OFFLOAD_STATUS_EVENT];7115	if (!ev) {7116		ath12k_warn(ab, "failed to fetch gtk offload status ev");7117		kfree(tb);7118		return;7119	}7120 7121	rcu_read_lock();7122	arvif = ath12k_mac_get_arvif_by_vdev_id(ab, le32_to_cpu(ev->vdev_id));7123	if (!arvif) {7124		rcu_read_unlock();7125		ath12k_warn(ab, "failed to get arvif for vdev_id:%d\n",7126			    le32_to_cpu(ev->vdev_id));7127		kfree(tb);7128		return;7129	}7130 7131	replay_ctr = le64_to_cpu(ev->replay_ctr);7132	arvif->rekey_data.replay_ctr = replay_ctr;7133	ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi gtk offload event refresh_cnt %d replay_ctr %llu\n",7134		   le32_to_cpu(ev->refresh_cnt), replay_ctr);7135 7136	/* supplicant expects big-endian replay counter */7137	replay_ctr_be = cpu_to_be64(replay_ctr);7138 7139	ieee80211_gtk_rekey_notify(arvif->vif, arvif->bssid,7140				   (void *)&replay_ctr_be, GFP_ATOMIC);7141 7142	rcu_read_unlock();7143 7144	kfree(tb);7145}7146 7147static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)7148{7149	struct wmi_cmd_hdr *cmd_hdr;7150	enum wmi_tlv_event_id id;7151 7152	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;7153	id = le32_get_bits(cmd_hdr->cmd_id, WMI_CMD_HDR_CMD_ID);7154 7155	if (!skb_pull(skb, sizeof(struct wmi_cmd_hdr)))7156		goto out;7157 7158	switch (id) {7159		/* Process all the WMI events here */7160	case WMI_SERVICE_READY_EVENTID:7161		ath12k_service_ready_event(ab, skb);7162		break;7163	case WMI_SERVICE_READY_EXT_EVENTID:7164		ath12k_service_ready_ext_event(ab, skb);7165		break;7166	case WMI_SERVICE_READY_EXT2_EVENTID:7167		ath12k_service_ready_ext2_event(ab, skb);7168		break;7169	case WMI_REG_CHAN_LIST_CC_EXT_EVENTID:7170		ath12k_reg_chan_list_event(ab, skb);7171		break;7172	case WMI_READY_EVENTID:7173		ath12k_ready_event(ab, skb);7174		break;7175	case WMI_PEER_DELETE_RESP_EVENTID:7176		ath12k_peer_delete_resp_event(ab, skb);7177		break;7178	case WMI_VDEV_START_RESP_EVENTID:7179		ath12k_vdev_start_resp_event(ab, skb);7180		break;7181	case WMI_OFFLOAD_BCN_TX_STATUS_EVENTID:7182		ath12k_bcn_tx_status_event(ab, skb);7183		break;7184	case WMI_VDEV_STOPPED_EVENTID:7185		ath12k_vdev_stopped_event(ab, skb);7186		break;7187	case WMI_MGMT_RX_EVENTID:7188		ath12k_mgmt_rx_event(ab, skb);7189		/* mgmt_rx_event() owns the skb now! */7190		return;7191	case WMI_MGMT_TX_COMPLETION_EVENTID:7192		ath12k_mgmt_tx_compl_event(ab, skb);7193		break;7194	case WMI_SCAN_EVENTID:7195		ath12k_scan_event(ab, skb);7196		break;7197	case WMI_PEER_STA_KICKOUT_EVENTID:7198		ath12k_peer_sta_kickout_event(ab, skb);7199		break;7200	case WMI_ROAM_EVENTID:7201		ath12k_roam_event(ab, skb);7202		break;7203	case WMI_CHAN_INFO_EVENTID:7204		ath12k_chan_info_event(ab, skb);7205		break;7206	case WMI_PDEV_BSS_CHAN_INFO_EVENTID:7207		ath12k_pdev_bss_chan_info_event(ab, skb);7208		break;7209	case WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID:7210		ath12k_vdev_install_key_compl_event(ab, skb);7211		break;7212	case WMI_SERVICE_AVAILABLE_EVENTID:7213		ath12k_service_available_event(ab, skb);7214		break;7215	case WMI_PEER_ASSOC_CONF_EVENTID:7216		ath12k_peer_assoc_conf_event(ab, skb);7217		break;7218	case WMI_UPDATE_STATS_EVENTID:7219		ath12k_update_stats_event(ab, skb);7220		break;7221	case WMI_PDEV_CTL_FAILSAFE_CHECK_EVENTID:7222		ath12k_pdev_ctl_failsafe_check_event(ab, skb);7223		break;7224	case WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID:7225		ath12k_wmi_pdev_csa_switch_count_status_event(ab, skb);7226		break;7227	case WMI_PDEV_TEMPERATURE_EVENTID:7228		ath12k_wmi_pdev_temperature_event(ab, skb);7229		break;7230	case WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID:7231		ath12k_wmi_pdev_dma_ring_buf_release_event(ab, skb);7232		break;7233	case WMI_HOST_FILS_DISCOVERY_EVENTID:7234		ath12k_fils_discovery_event(ab, skb);7235		break;7236	case WMI_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID:7237		ath12k_probe_resp_tx_status_event(ab, skb);7238		break;7239	case WMI_RFKILL_STATE_CHANGE_EVENTID:7240		ath12k_rfkill_state_change_event(ab, skb);7241		break;7242	case WMI_TWT_ENABLE_EVENTID:7243		ath12k_wmi_twt_enable_event(ab, skb);7244		break;7245	case WMI_TWT_DISABLE_EVENTID:7246		ath12k_wmi_twt_disable_event(ab, skb);7247		break;7248	case WMI_P2P_NOA_EVENTID:7249		ath12k_wmi_p2p_noa_event(ab, skb);7250		break;7251	/* add Unsupported events here */7252	case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:7253	case WMI_PEER_OPER_MODE_CHANGE_EVENTID:7254	case WMI_PDEV_DMA_RING_CFG_RSP_EVENTID:7255		ath12k_dbg(ab, ATH12K_DBG_WMI,7256			   "ignoring unsupported event 0x%x\n", id);7257		break;7258	case WMI_PDEV_DFS_RADAR_DETECTION_EVENTID:7259		ath12k_wmi_pdev_dfs_radar_detected_event(ab, skb);7260		break;7261	case WMI_VDEV_DELETE_RESP_EVENTID:7262		ath12k_vdev_delete_resp_event(ab, skb);7263		break;7264	case WMI_DIAG_EVENTID:7265		ath12k_wmi_diag_event(ab, skb);7266		break;7267	case WMI_WOW_WAKEUP_HOST_EVENTID:7268		ath12k_wmi_event_wow_wakeup_host(ab, skb);7269		break;7270	case WMI_GTK_OFFLOAD_STATUS_EVENTID:7271		ath12k_wmi_gtk_offload_status_event(ab, skb);7272		break;7273	/* TODO: Add remaining events */7274	default:7275		ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id);7276		break;7277	}7278 7279out:7280	dev_kfree_skb(skb);7281}7282 7283static int ath12k_connect_pdev_htc_service(struct ath12k_base *ab,7284					   u32 pdev_idx)7285{7286	int status;7287	u32 svc_id[] = { ATH12K_HTC_SVC_ID_WMI_CONTROL,7288			 ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1,7289			 ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2 };7290	struct ath12k_htc_svc_conn_req conn_req = {};7291	struct ath12k_htc_svc_conn_resp conn_resp = {};7292 7293	/* these fields are the same for all service endpoints */7294	conn_req.ep_ops.ep_tx_complete = ath12k_wmi_htc_tx_complete;7295	conn_req.ep_ops.ep_rx_complete = ath12k_wmi_op_rx;7296	conn_req.ep_ops.ep_tx_credits = ath12k_wmi_op_ep_tx_credits;7297 7298	/* connect to control service */7299	conn_req.service_id = svc_id[pdev_idx];7300 7301	status = ath12k_htc_connect_service(&ab->htc, &conn_req, &conn_resp);7302	if (status) {7303		ath12k_warn(ab, "failed to connect to WMI CONTROL service status: %d\n",7304			    status);7305		return status;7306	}7307 7308	ab->wmi_ab.wmi_endpoint_id[pdev_idx] = conn_resp.eid;7309	ab->wmi_ab.wmi[pdev_idx].eid = conn_resp.eid;7310	ab->wmi_ab.max_msg_len[pdev_idx] = conn_resp.max_msg_len;7311 7312	return 0;7313}7314 7315static int7316ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,7317			      struct wmi_unit_test_cmd ut_cmd,7318			      u32 *test_args)7319{7320	struct ath12k_wmi_pdev *wmi = ar->wmi;7321	struct wmi_unit_test_cmd *cmd;7322	struct sk_buff *skb;7323	struct wmi_tlv *tlv;7324	void *ptr;7325	u32 *ut_cmd_args;7326	int buf_len, arg_len;7327	int ret;7328	int i;7329 7330	arg_len = sizeof(u32) * le32_to_cpu(ut_cmd.num_args);7331	buf_len = sizeof(ut_cmd) + arg_len + TLV_HDR_SIZE;7332 7333	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, buf_len);7334	if (!skb)7335		return -ENOMEM;7336 7337	cmd = (struct wmi_unit_test_cmd *)skb->data;7338	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_UNIT_TEST_CMD,7339						 sizeof(ut_cmd));7340 7341	cmd->vdev_id = ut_cmd.vdev_id;7342	cmd->module_id = ut_cmd.module_id;7343	cmd->num_args = ut_cmd.num_args;7344	cmd->diag_token = ut_cmd.diag_token;7345 7346	ptr = skb->data + sizeof(ut_cmd);7347 7348	tlv = ptr;7349	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, arg_len);7350 7351	ptr += TLV_HDR_SIZE;7352 7353	ut_cmd_args = ptr;7354	for (i = 0; i < le32_to_cpu(ut_cmd.num_args); i++)7355		ut_cmd_args[i] = test_args[i];7356 7357	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,7358		   "WMI unit test : module %d vdev %d n_args %d token %d\n",7359		   cmd->module_id, cmd->vdev_id, cmd->num_args,7360		   cmd->diag_token);7361 7362	ret = ath12k_wmi_cmd_send(wmi, skb, WMI_UNIT_TEST_CMDID);7363 7364	if (ret) {7365		ath12k_warn(ar->ab, "failed to send WMI_UNIT_TEST CMD :%d\n",7366			    ret);7367		dev_kfree_skb(skb);7368	}7369 7370	return ret;7371}7372 7373int ath12k_wmi_simulate_radar(struct ath12k *ar)7374{7375	struct ath12k_vif *arvif;7376	u32 dfs_args[DFS_MAX_TEST_ARGS];7377	struct wmi_unit_test_cmd wmi_ut;7378	bool arvif_found = false;7379 7380	list_for_each_entry(arvif, &ar->arvifs, list) {7381		if (arvif->is_started && arvif->vdev_type == WMI_VDEV_TYPE_AP) {7382			arvif_found = true;7383			break;7384		}7385	}7386 7387	if (!arvif_found)7388		return -EINVAL;7389 7390	dfs_args[DFS_TEST_CMDID] = 0;7391	dfs_args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id;7392	/* Currently we could pass segment_id(b0 - b1), chirp(b2)7393	 * freq offset (b3 - b10) to unit test. For simulation7394	 * purpose this can be set to 0 which is valid.7395	 */7396	dfs_args[DFS_TEST_RADAR_PARAM] = 0;7397 7398	wmi_ut.vdev_id = cpu_to_le32(arvif->vdev_id);7399	wmi_ut.module_id = cpu_to_le32(DFS_UNIT_TEST_MODULE);7400	wmi_ut.num_args = cpu_to_le32(DFS_MAX_TEST_ARGS);7401	wmi_ut.diag_token = cpu_to_le32(DFS_UNIT_TEST_TOKEN);7402 7403	ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Triggering Radar Simulation\n");7404 7405	return ath12k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args);7406}7407 7408int ath12k_wmi_connect(struct ath12k_base *ab)7409{7410	u32 i;7411	u8 wmi_ep_count;7412 7413	wmi_ep_count = ab->htc.wmi_ep_count;7414	if (wmi_ep_count > ab->hw_params->max_radios)7415		return -1;7416 7417	for (i = 0; i < wmi_ep_count; i++)7418		ath12k_connect_pdev_htc_service(ab, i);7419 7420	return 0;7421}7422 7423static void ath12k_wmi_pdev_detach(struct ath12k_base *ab, u8 pdev_id)7424{7425	if (WARN_ON(pdev_id >= MAX_RADIOS))7426		return;7427 7428	/* TODO: Deinit any pdev specific wmi resource */7429}7430 7431int ath12k_wmi_pdev_attach(struct ath12k_base *ab,7432			   u8 pdev_id)7433{7434	struct ath12k_wmi_pdev *wmi_handle;7435 7436	if (pdev_id >= ab->hw_params->max_radios)7437		return -EINVAL;7438 7439	wmi_handle = &ab->wmi_ab.wmi[pdev_id];7440 7441	wmi_handle->wmi_ab = &ab->wmi_ab;7442 7443	ab->wmi_ab.ab = ab;7444	/* TODO: Init remaining resource specific to pdev */7445 7446	return 0;7447}7448 7449int ath12k_wmi_attach(struct ath12k_base *ab)7450{7451	int ret;7452 7453	ret = ath12k_wmi_pdev_attach(ab, 0);7454	if (ret)7455		return ret;7456 7457	ab->wmi_ab.ab = ab;7458	ab->wmi_ab.preferred_hw_mode = WMI_HOST_HW_MODE_MAX;7459 7460	/* It's overwritten when service_ext_ready is handled */7461	if (ab->hw_params->single_pdev_only)7462		ab->wmi_ab.preferred_hw_mode = WMI_HOST_HW_MODE_SINGLE;7463 7464	/* TODO: Init remaining wmi soc resources required */7465	init_completion(&ab->wmi_ab.service_ready);7466	init_completion(&ab->wmi_ab.unified_ready);7467 7468	return 0;7469}7470 7471void ath12k_wmi_detach(struct ath12k_base *ab)7472{7473	int i;7474 7475	/* TODO: Deinit wmi resource specific to SOC as required */7476 7477	for (i = 0; i < ab->htc.wmi_ep_count; i++)7478		ath12k_wmi_pdev_detach(ab, i);7479 7480	ath12k_wmi_free_dbring_caps(ab);7481}7482 7483int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_arg *arg)7484{7485	struct wmi_hw_data_filter_cmd *cmd;7486	struct sk_buff *skb;7487	int len;7488 7489	len = sizeof(*cmd);7490	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7491 7492	if (!skb)7493		return -ENOMEM;7494 7495	cmd = (struct wmi_hw_data_filter_cmd *)skb->data;7496	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HW_DATA_FILTER_CMD,7497						 sizeof(*cmd));7498	cmd->vdev_id = cpu_to_le32(arg->vdev_id);7499	cmd->enable = cpu_to_le32(arg->enable ? 1 : 0);7500 7501	/* Set all modes in case of disable */7502	if (arg->enable)7503		cmd->hw_filter_bitmap = cpu_to_le32(arg->hw_filter_bitmap);7504	else7505		cmd->hw_filter_bitmap = cpu_to_le32((u32)~0U);7506 7507	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,7508		   "wmi hw data filter enable %d filter_bitmap 0x%x\n",7509		   arg->enable, arg->hw_filter_bitmap);7510 7511	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);7512}7513 7514int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)7515{7516	struct wmi_wow_host_wakeup_cmd *cmd;7517	struct sk_buff *skb;7518	size_t len;7519 7520	len = sizeof(*cmd);7521	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7522	if (!skb)7523		return -ENOMEM;7524 7525	cmd = (struct wmi_wow_host_wakeup_cmd *)skb->data;7526	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_HOSTWAKEUP_FROM_SLEEP_CMD,7527						 sizeof(*cmd));7528 7529	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow host wakeup ind\n");7530 7531	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);7532}7533 7534int ath12k_wmi_wow_enable(struct ath12k *ar)7535{7536	struct wmi_wow_enable_cmd *cmd;7537	struct sk_buff *skb;7538	int len;7539 7540	len = sizeof(*cmd);7541	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7542	if (!skb)7543		return -ENOMEM;7544 7545	cmd = (struct wmi_wow_enable_cmd *)skb->data;7546	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_ENABLE_CMD,7547						 sizeof(*cmd));7548 7549	cmd->enable = cpu_to_le32(1);7550	cmd->pause_iface_config = cpu_to_le32(WOW_IFACE_PAUSE_ENABLED);7551	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow enable\n");7552 7553	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);7554}7555 7556int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,7557				    enum wmi_wow_wakeup_event event,7558				    u32 enable)7559{7560	struct wmi_wow_add_del_event_cmd *cmd;7561	struct sk_buff *skb;7562	size_t len;7563 7564	len = sizeof(*cmd);7565	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7566	if (!skb)7567		return -ENOMEM;7568 7569	cmd = (struct wmi_wow_add_del_event_cmd *)skb->data;7570	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_ADD_DEL_EVT_CMD,7571						 sizeof(*cmd));7572	cmd->vdev_id = cpu_to_le32(vdev_id);7573	cmd->is_add = cpu_to_le32(enable);7574	cmd->event_bitmap = cpu_to_le32((1 << event));7575 7576	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",7577		   wow_wakeup_event(event), enable, vdev_id);7578 7579	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);7580}7581 7582int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,7583			       const u8 *pattern, const u8 *mask,7584			       int pattern_len, int pattern_offset)7585{7586	struct wmi_wow_add_pattern_cmd *cmd;7587	struct wmi_wow_bitmap_pattern_params *bitmap;7588	struct wmi_tlv *tlv;7589	struct sk_buff *skb;7590	void *ptr;7591	size_t len;7592 7593	len = sizeof(*cmd) +7594	      sizeof(*tlv) +			/* array struct */7595	      sizeof(*bitmap) +			/* bitmap */7596	      sizeof(*tlv) +			/* empty ipv4 sync */7597	      sizeof(*tlv) +			/* empty ipv6 sync */7598	      sizeof(*tlv) +			/* empty magic */7599	      sizeof(*tlv) +			/* empty info timeout */7600	      sizeof(*tlv) + sizeof(u32);	/* ratelimit interval */7601 7602	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7603	if (!skb)7604		return -ENOMEM;7605 7606	/* cmd */7607	ptr = skb->data;7608	cmd = ptr;7609	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_ADD_PATTERN_CMD,7610						 sizeof(*cmd));7611	cmd->vdev_id = cpu_to_le32(vdev_id);7612	cmd->pattern_id = cpu_to_le32(pattern_id);7613	cmd->pattern_type = cpu_to_le32(WOW_BITMAP_PATTERN);7614 7615	ptr += sizeof(*cmd);7616 7617	/* bitmap */7618	tlv = ptr;7619	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, sizeof(*bitmap));7620 7621	ptr += sizeof(*tlv);7622 7623	bitmap = ptr;7624	bitmap->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_BITMAP_PATTERN_T,7625						    sizeof(*bitmap));7626	memcpy(bitmap->patternbuf, pattern, pattern_len);7627	memcpy(bitmap->bitmaskbuf, mask, pattern_len);7628	bitmap->pattern_offset = cpu_to_le32(pattern_offset);7629	bitmap->pattern_len = cpu_to_le32(pattern_len);7630	bitmap->bitmask_len = cpu_to_le32(pattern_len);7631	bitmap->pattern_id = cpu_to_le32(pattern_id);7632 7633	ptr += sizeof(*bitmap);7634 7635	/* ipv4 sync */7636	tlv = ptr;7637	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);7638 7639	ptr += sizeof(*tlv);7640 7641	/* ipv6 sync */7642	tlv = ptr;7643	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);7644 7645	ptr += sizeof(*tlv);7646 7647	/* magic */7648	tlv = ptr;7649	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);7650 7651	ptr += sizeof(*tlv);7652 7653	/* pattern info timeout */7654	tlv = ptr;7655	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0);7656 7657	ptr += sizeof(*tlv);7658 7659	/* ratelimit interval */7660	tlv = ptr;7661	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, sizeof(u32));7662 7663	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d pattern_len %d\n",7664		   vdev_id, pattern_id, pattern_offset, pattern_len);7665 7666	ath12k_dbg_dump(ar->ab, ATH12K_DBG_WMI, NULL, "wow pattern: ",7667			bitmap->patternbuf, pattern_len);7668	ath12k_dbg_dump(ar->ab, ATH12K_DBG_WMI, NULL, "wow bitmask: ",7669			bitmap->bitmaskbuf, pattern_len);7670 7671	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);7672}7673 7674int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)7675{7676	struct wmi_wow_del_pattern_cmd *cmd;7677	struct sk_buff *skb;7678	size_t len;7679 7680	len = sizeof(*cmd);7681	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7682	if (!skb)7683		return -ENOMEM;7684 7685	cmd = (struct wmi_wow_del_pattern_cmd *)skb->data;7686	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_DEL_PATTERN_CMD,7687						 sizeof(*cmd));7688	cmd->vdev_id = cpu_to_le32(vdev_id);7689	cmd->pattern_id = cpu_to_le32(pattern_id);7690	cmd->pattern_type = cpu_to_le32(WOW_BITMAP_PATTERN);7691 7692	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",7693		   vdev_id, pattern_id);7694 7695	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);7696}7697 7698static struct sk_buff *7699ath12k_wmi_op_gen_config_pno_start(struct ath12k *ar, u32 vdev_id,7700				   struct wmi_pno_scan_req_arg *pno)7701{7702	struct nlo_configured_params *nlo_list;7703	size_t len, nlo_list_len, channel_list_len;7704	struct wmi_wow_nlo_config_cmd *cmd;7705	__le32 *channel_list;7706	struct wmi_tlv *tlv;7707	struct sk_buff *skb;7708	void *ptr;7709	u32 i;7710 7711	len = sizeof(*cmd) +7712	      sizeof(*tlv) +7713	      /* TLV place holder for array of structures7714	       * nlo_configured_params(nlo_list)7715	       */7716	      sizeof(*tlv);7717	      /* TLV place holder for array of uint32 channel_list */7718 7719	channel_list_len = sizeof(u32) * pno->a_networks[0].channel_count;7720	len += channel_list_len;7721 7722	nlo_list_len = sizeof(*nlo_list) * pno->uc_networks_count;7723	len += nlo_list_len;7724 7725	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7726	if (!skb)7727		return ERR_PTR(-ENOMEM);7728 7729	ptr = skb->data;7730	cmd = ptr;7731	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_NLO_CONFIG_CMD, sizeof(*cmd));7732 7733	cmd->vdev_id = cpu_to_le32(pno->vdev_id);7734	cmd->flags = cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);7735 7736	/* current FW does not support min-max range for dwell time */7737	cmd->active_dwell_time = cpu_to_le32(pno->active_max_time);7738	cmd->passive_dwell_time = cpu_to_le32(pno->passive_max_time);7739 7740	if (pno->do_passive_scan)7741		cmd->flags |= cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);7742 7743	cmd->fast_scan_period = cpu_to_le32(pno->fast_scan_period);7744	cmd->slow_scan_period = cpu_to_le32(pno->slow_scan_period);7745	cmd->fast_scan_max_cycles = cpu_to_le32(pno->fast_scan_max_cycles);7746	cmd->delay_start_time = cpu_to_le32(pno->delay_start_time);7747 7748	if (pno->enable_pno_scan_randomization) {7749		cmd->flags |= cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |7750					  WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);7751		ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);7752		ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);7753	}7754 7755	ptr += sizeof(*cmd);7756 7757	/* nlo_configured_params(nlo_list) */7758	cmd->no_of_ssids = cpu_to_le32(pno->uc_networks_count);7759	tlv = ptr;7760	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, nlo_list_len);7761 7762	ptr += sizeof(*tlv);7763	nlo_list = ptr;7764	for (i = 0; i < pno->uc_networks_count; i++) {7765		tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);7766		tlv->header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ARRAY_BYTE,7767						     sizeof(*nlo_list));7768 7769		nlo_list[i].ssid.valid = cpu_to_le32(1);7770		nlo_list[i].ssid.ssid.ssid_len =7771			cpu_to_le32(pno->a_networks[i].ssid.ssid_len);7772		memcpy(nlo_list[i].ssid.ssid.ssid,7773		       pno->a_networks[i].ssid.ssid,7774		       le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));7775 7776		if (pno->a_networks[i].rssi_threshold &&7777		    pno->a_networks[i].rssi_threshold > -300) {7778			nlo_list[i].rssi_cond.valid = cpu_to_le32(1);7779			nlo_list[i].rssi_cond.rssi =7780					cpu_to_le32(pno->a_networks[i].rssi_threshold);7781		}7782 7783		nlo_list[i].bcast_nw_type.valid = cpu_to_le32(1);7784		nlo_list[i].bcast_nw_type.bcast_nw_type =7785					cpu_to_le32(pno->a_networks[i].bcast_nw_type);7786	}7787 7788	ptr += nlo_list_len;7789	cmd->num_of_channels = cpu_to_le32(pno->a_networks[0].channel_count);7790	tlv = ptr;7791	tlv->header =  ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, channel_list_len);7792	ptr += sizeof(*tlv);7793	channel_list = ptr;7794 7795	for (i = 0; i < pno->a_networks[0].channel_count; i++)7796		channel_list[i] = cpu_to_le32(pno->a_networks[0].channels[i]);7797 7798	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",7799		   vdev_id);7800 7801	return skb;7802}7803 7804static struct sk_buff *ath12k_wmi_op_gen_config_pno_stop(struct ath12k *ar,7805							 u32 vdev_id)7806{7807	struct wmi_wow_nlo_config_cmd *cmd;7808	struct sk_buff *skb;7809	size_t len;7810 7811	len = sizeof(*cmd);7812	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7813	if (!skb)7814		return ERR_PTR(-ENOMEM);7815 7816	cmd = (struct wmi_wow_nlo_config_cmd *)skb->data;7817	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_NLO_CONFIG_CMD, len);7818 7819	cmd->vdev_id = cpu_to_le32(vdev_id);7820	cmd->flags = cpu_to_le32(WMI_NLO_CONFIG_STOP);7821 7822	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,7823		   "wmi tlv stop pno config vdev_id %d\n", vdev_id);7824	return skb;7825}7826 7827int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,7828			      struct wmi_pno_scan_req_arg  *pno_scan)7829{7830	struct sk_buff *skb;7831 7832	if (pno_scan->enable)7833		skb = ath12k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan);7834	else7835		skb = ath12k_wmi_op_gen_config_pno_stop(ar, vdev_id);7836 7837	if (IS_ERR_OR_NULL(skb))7838		return -ENOMEM;7839 7840	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);7841}7842 7843static void ath12k_wmi_fill_ns_offload(struct ath12k *ar,7844				       struct wmi_arp_ns_offload_arg *offload,7845				       void **ptr,7846				       bool enable,7847				       bool ext)7848{7849	struct wmi_ns_offload_params *ns;7850	struct wmi_tlv *tlv;7851	void *buf_ptr = *ptr;7852	u32 ns_cnt, ns_ext_tuples;7853	int i, max_offloads;7854 7855	ns_cnt = offload->ipv6_count;7856 7857	tlv  = buf_ptr;7858 7859	if (ext) {7860		ns_ext_tuples = offload->ipv6_count - WMI_MAX_NS_OFFLOADS;7861		tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,7862						 ns_ext_tuples * sizeof(*ns));7863		i = WMI_MAX_NS_OFFLOADS;7864		max_offloads = offload->ipv6_count;7865	} else {7866		tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,7867						 WMI_MAX_NS_OFFLOADS * sizeof(*ns));7868		i = 0;7869		max_offloads = WMI_MAX_NS_OFFLOADS;7870	}7871 7872	buf_ptr += sizeof(*tlv);7873 7874	for (; i < max_offloads; i++) {7875		ns = buf_ptr;7876		ns->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_NS_OFFLOAD_TUPLE,7877							sizeof(*ns));7878 7879		if (enable) {7880			if (i < ns_cnt)7881				ns->flags |= cpu_to_le32(WMI_NSOL_FLAGS_VALID);7882 7883			memcpy(ns->target_ipaddr[0], offload->ipv6_addr[i], 16);7884			memcpy(ns->solicitation_ipaddr, offload->self_ipv6_addr[i], 16);7885 7886			if (offload->ipv6_type[i])7887				ns->flags |= cpu_to_le32(WMI_NSOL_FLAGS_IS_IPV6_ANYCAST);7888 7889			memcpy(ns->target_mac.addr, offload->mac_addr, ETH_ALEN);7890 7891			if (!is_zero_ether_addr(ns->target_mac.addr))7892				ns->flags |= cpu_to_le32(WMI_NSOL_FLAGS_MAC_VALID);7893 7894			ath12k_dbg(ar->ab, ATH12K_DBG_WMI,7895				   "wmi index %d ns_solicited %pI6 target %pI6",7896				   i, ns->solicitation_ipaddr,7897				   ns->target_ipaddr[0]);7898		}7899 7900		buf_ptr += sizeof(*ns);7901	}7902 7903	*ptr = buf_ptr;7904}7905 7906static void ath12k_wmi_fill_arp_offload(struct ath12k *ar,7907					struct wmi_arp_ns_offload_arg *offload,7908					void **ptr,7909					bool enable)7910{7911	struct wmi_arp_offload_params *arp;7912	struct wmi_tlv *tlv;7913	void *buf_ptr = *ptr;7914	int i;7915 7916	/* fill arp tuple */7917	tlv = buf_ptr;7918	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,7919					 WMI_MAX_ARP_OFFLOADS * sizeof(*arp));7920	buf_ptr += sizeof(*tlv);7921 7922	for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {7923		arp = buf_ptr;7924		arp->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ARP_OFFLOAD_TUPLE,7925							 sizeof(*arp));7926 7927		if (enable && i < offload->ipv4_count) {7928			/* Copy the target ip addr and flags */7929			arp->flags = cpu_to_le32(WMI_ARPOL_FLAGS_VALID);7930			memcpy(arp->target_ipaddr, offload->ipv4_addr[i], 4);7931 7932			ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi arp offload address %pI4",7933				   arp->target_ipaddr);7934		}7935 7936		buf_ptr += sizeof(*arp);7937	}7938 7939	*ptr = buf_ptr;7940}7941 7942int ath12k_wmi_arp_ns_offload(struct ath12k *ar,7943			      struct ath12k_vif *arvif,7944			      struct wmi_arp_ns_offload_arg *offload,7945			      bool enable)7946{7947	struct wmi_set_arp_ns_offload_cmd *cmd;7948	struct wmi_tlv *tlv;7949	struct sk_buff *skb;7950	void *buf_ptr;7951	size_t len;7952	u8 ns_cnt, ns_ext_tuples = 0;7953 7954	ns_cnt = offload->ipv6_count;7955 7956	len = sizeof(*cmd) +7957	      sizeof(*tlv) +7958	      WMI_MAX_NS_OFFLOADS * sizeof(struct wmi_ns_offload_params) +7959	      sizeof(*tlv) +7960	      WMI_MAX_ARP_OFFLOADS * sizeof(struct wmi_arp_offload_params);7961 7962	if (ns_cnt > WMI_MAX_NS_OFFLOADS) {7963		ns_ext_tuples = ns_cnt - WMI_MAX_NS_OFFLOADS;7964		len += sizeof(*tlv) +7965		       ns_ext_tuples * sizeof(struct wmi_ns_offload_params);7966	}7967 7968	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);7969	if (!skb)7970		return -ENOMEM;7971 7972	buf_ptr = skb->data;7973	cmd = buf_ptr;7974	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SET_ARP_NS_OFFLOAD_CMD,7975						 sizeof(*cmd));7976	cmd->flags = cpu_to_le32(0);7977	cmd->vdev_id = cpu_to_le32(arvif->vdev_id);7978	cmd->num_ns_ext_tuples = cpu_to_le32(ns_ext_tuples);7979 7980	buf_ptr += sizeof(*cmd);7981 7982	ath12k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 0);7983	ath12k_wmi_fill_arp_offload(ar, offload, &buf_ptr, enable);7984 7985	if (ns_ext_tuples)7986		ath12k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1);7987 7988	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);7989}7990 7991int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,7992				 struct ath12k_vif *arvif, bool enable)7993{7994	struct ath12k_rekey_data *rekey_data = &arvif->rekey_data;7995	struct wmi_gtk_rekey_offload_cmd *cmd;7996	struct sk_buff *skb;7997	__le64 replay_ctr;7998	int len;7999 8000	len = sizeof(*cmd);8001	skb =  ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);8002	if (!skb)8003		return -ENOMEM;8004 8005	cmd = (struct wmi_gtk_rekey_offload_cmd *)skb->data;8006	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_GTK_OFFLOAD_CMD, sizeof(*cmd));8007	cmd->vdev_id = cpu_to_le32(arvif->vdev_id);8008 8009	if (enable) {8010		cmd->flags = cpu_to_le32(GTK_OFFLOAD_ENABLE_OPCODE);8011 8012		/* the length in rekey_data and cmd is equal */8013		memcpy(cmd->kck, rekey_data->kck, sizeof(cmd->kck));8014		memcpy(cmd->kek, rekey_data->kek, sizeof(cmd->kek));8015 8016		replay_ctr = cpu_to_le64(rekey_data->replay_ctr);8017		memcpy(cmd->replay_ctr, &replay_ctr,8018		       sizeof(replay_ctr));8019	} else {8020		cmd->flags = cpu_to_le32(GTK_OFFLOAD_DISABLE_OPCODE);8021	}8022 8023	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "offload gtk rekey vdev: %d %d\n",8024		   arvif->vdev_id, enable);8025	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);8026}8027 8028int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,8029				 struct ath12k_vif *arvif)8030{8031	struct wmi_gtk_rekey_offload_cmd *cmd;8032	struct sk_buff *skb;8033	int len;8034 8035	len = sizeof(*cmd);8036	skb =  ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);8037	if (!skb)8038		return -ENOMEM;8039 8040	cmd = (struct wmi_gtk_rekey_offload_cmd *)skb->data;8041	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_GTK_OFFLOAD_CMD, sizeof(*cmd));8042	cmd->vdev_id = cpu_to_le32(arvif->vdev_id);8043	cmd->flags = cpu_to_le32(GTK_OFFLOAD_REQUEST_STATUS_OPCODE);8044 8045	ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "get gtk rekey vdev_id: %d\n",8046		   arvif->vdev_id);8047	return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);8048}8049 8050int ath12k_wmi_sta_keepalive(struct ath12k *ar,8051			     const struct wmi_sta_keepalive_arg *arg)8052{8053	struct wmi_sta_keepalive_arp_resp_params *arp;8054	struct ath12k_wmi_pdev *wmi = ar->wmi;8055	struct wmi_sta_keepalive_cmd *cmd;8056	struct sk_buff *skb;8057	size_t len;8058 8059	len = sizeof(*cmd) + sizeof(*arp);8060	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);8061	if (!skb)8062		return -ENOMEM;8063 8064	cmd = (struct wmi_sta_keepalive_cmd *)skb->data;8065	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_STA_KEEPALIVE_CMD, sizeof(*cmd));8066	cmd->vdev_id = cpu_to_le32(arg->vdev_id);8067	cmd->enabled = cpu_to_le32(arg->enabled);8068	cmd->interval = cpu_to_le32(arg->interval);8069	cmd->method = cpu_to_le32(arg->method);8070 8071	arp = (struct wmi_sta_keepalive_arp_resp_params *)(cmd + 1);8072	arp->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_STA_KEEPALVE_ARP_RESPONSE,8073						 sizeof(*arp));8074	if (arg->method == WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE ||8075	    arg->method == WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST) {8076		arp->src_ip4_addr = cpu_to_le32(arg->src_ip4_addr);8077		arp->dest_ip4_addr = cpu_to_le32(arg->dest_ip4_addr);8078		ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);8079	}8080 8081	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,8082		   "wmi sta keepalive vdev %d enabled %d method %d interval %d\n",8083		   arg->vdev_id, arg->enabled, arg->method, arg->interval);8084 8085	return ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);8086}8087