File Index
Files and directories
Sign in
FILE

smd.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/ath/wcn36xx/smd.c C
   1/*
   2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  18
  19#include <linux/bitfield.h>
  20#include <linux/etherdevice.h>
  21#include <linux/firmware.h>
  22#include <linux/bitops.h>
  23#include <linux/rpmsg.h>
  24#include "smd.h"
  25#include "firmware.h"
  26
  27struct wcn36xx_cfg_val {
  28	u32 cfg_id;
  29	u32 value;
  30};
  31
  32#define WCN36XX_CFG_VAL(id, val) \
  33{ \
  34	.cfg_id = WCN36XX_HAL_CFG_ ## id, \
  35	.value = val \
  36}
  37
  38static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
  39	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
  40	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
  41	WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
  42	WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
  43	WCN36XX_CFG_VAL(CAL_PERIOD, 5),
  44	WCN36XX_CFG_VAL(CAL_CONTROL, 1),
  45	WCN36XX_CFG_VAL(PROXIMITY, 0),
  46	WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
  47	WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
  48	WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
  49	WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
  50	WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
  51	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
  52	WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
  53	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
  54	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
  55	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
  56	WCN36XX_CFG_VAL(FIXED_RATE, 0),
  57	WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
  58	WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
  59	WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
  60	WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
  61	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
  62	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
  63	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
  64	WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
  65	WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
  66	WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
  67	WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
  68	WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
  69	WCN36XX_CFG_VAL(STATS_PERIOD, 10),
  70	WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
  71	WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
  72	WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
  73	WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
  74	WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
  75	WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
  76	WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
  77	WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
  78	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
  79	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
  80	WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
  81	WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
  82	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */
  83	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
  84};
  85
  86static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
  87	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
  88	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
  89	WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
  90	WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
  91	WCN36XX_CFG_VAL(CAL_PERIOD, 5),
  92	WCN36XX_CFG_VAL(CAL_CONTROL, 1),
  93	WCN36XX_CFG_VAL(PROXIMITY, 0),
  94	WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
  95	WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 4096),
  96	WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
  97	WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
  98	WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
  99	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
 100	WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
 101	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
 102	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
 103	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
 104	WCN36XX_CFG_VAL(FIXED_RATE, 0),
 105	WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
 106	WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
 107	WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
 108	WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
 109	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
 110	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
 111	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 1),
 112	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
 113	WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
 114	WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
 115	WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
 116	WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
 117	WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
 118	WCN36XX_CFG_VAL(STATS_PERIOD, 10),
 119	WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
 120	WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
 121	WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
 122	WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
 123	WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
 124	WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
 125	WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
 126	WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
 127	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
 128	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
 129	WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
 130	WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
 131	WCN36XX_CFG_VAL(TDLS_PUAPSD_MASK, 0),
 132	WCN36XX_CFG_VAL(TDLS_PUAPSD_BUFFER_STA_CAPABLE, 1),
 133	WCN36XX_CFG_VAL(TDLS_PUAPSD_INACTIVITY_TIME, 0),
 134	WCN36XX_CFG_VAL(TDLS_PUAPSD_RX_FRAME_THRESHOLD, 10),
 135	WCN36XX_CFG_VAL(TDLS_OFF_CHANNEL_CAPABLE, 1),
 136	WCN36XX_CFG_VAL(ENABLE_ADAPTIVE_RX_DRAIN, 1),
 137	WCN36XX_CFG_VAL(FLEXCONNECT_POWER_FACTOR, 0),
 138	WCN36XX_CFG_VAL(ANTENNA_DIVERSITY, 3),
 139	WCN36XX_CFG_VAL(ATH_DISABLE, 0),
 140	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 60000),
 141	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 90000),
 142	WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN, 30000),
 143	WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN, 30000),
 144	WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL, 50),
 145	WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD, -60),
 146	WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD, 3),
 147	WCN36XX_CFG_VAL(BTC_CTS2S_ON_STA_DURING_SCO, 0),
 148	WCN36XX_CFG_VAL(RA_FILTER_ENABLE, 0),
 149	WCN36XX_CFG_VAL(RA_RATE_LIMIT_INTERVAL, 60),
 150	WCN36XX_CFG_VAL(BTC_FATAL_HID_NSNIFF_BLK, 2),
 151	WCN36XX_CFG_VAL(BTC_CRITICAL_HID_NSNIFF_BLK, 1),
 152	WCN36XX_CFG_VAL(BTC_DYN_A2DP_TX_QUEUE_THOLD, 0),
 153	WCN36XX_CFG_VAL(BTC_DYN_OPP_TX_QUEUE_THOLD, 1),
 154	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_SP, 10),
 155	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT, 50),
 156	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT, 50),
 157	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW, 500),
 158	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW, 500),
 159	WCN36XX_CFG_VAL(MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE, 0),
 160	WCN36XX_CFG_VAL(MAX_UAPSD_INACTIVITY_INTERVALS, 10),
 161	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_WMMPS, 1),
 162	WCN36XX_CFG_VAL(BURST_MODE_BE_TXOP_VALUE, 0),
 163	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 136),
 164	WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1),
 165	WCN36XX_CFG_VAL(ENABLE_RTSCTS_HTVHT, 0),
 166	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000),
 167	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000),
 168	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
 169	WCN36XX_CFG_VAL(TOGGLE_ARP_BDRATES, 0),
 170	WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT, 0),
 171	WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE, 0),
 172	WCN36XX_CFG_VAL(BAR_WAKEUP_HOST_DISABLE, 0),
 173	WCN36XX_CFG_VAL(SAR_BOFFSET_CORRECTION_ENABLE, 0),
 174	WCN36XX_CFG_VAL(BTC_DISABLE_WLAN_LINK_CRITICAL, 5),
 175	WCN36XX_CFG_VAL(DISABLE_SCAN_DURING_SCO, 2),
 176	WCN36XX_CFG_VAL(CONS_BCNMISS_COUNT, 0),
 177	WCN36XX_CFG_VAL(UNITS_OF_BCN_WAIT_TIME, 0),
 178	WCN36XX_CFG_VAL(TRIGGER_NULLFRAME_BEFORE_HB, 0),
 179	WCN36XX_CFG_VAL(ENABLE_POWERSAVE_OFFLOAD, 0),
 180};
 181
 182static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
 183{
 184	struct wcn36xx_hal_cfg *entry;
 185	u32 *val;
 186
 187	if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
 188		wcn36xx_err("Not enough room for TLV entry\n");
 189		return -ENOMEM;
 190	}
 191
 192	entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
 193	entry->id = id;
 194	entry->len = sizeof(u32);
 195	entry->pad_bytes = 0;
 196	entry->reserve = 0;
 197
 198	val = (u32 *) (entry + 1);
 199	*val = value;
 200
 201	*len += sizeof(*entry) + sizeof(u32);
 202
 203	return 0;
 204}
 205
 206static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
 207		struct ieee80211_sta *sta,
 208		struct wcn36xx_hal_config_bss_params *bss_params)
 209{
 210	if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn))
 211		bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
 212	else if (sta && sta->deflink.ht_cap.ht_supported)
 213		bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
 214	else if (sta && (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0x7f))
 215		bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
 216	else
 217		bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
 218}
 219
 220static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
 221{
 222	return caps & flag ? 1 : 0;
 223}
 224
 225static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
 226		struct ieee80211_sta *sta,
 227		struct wcn36xx_hal_config_bss_params *bss_params)
 228{
 229	if (sta && sta->deflink.ht_cap.ht_supported) {
 230		unsigned long caps = sta->deflink.ht_cap.cap;
 231
 232		bss_params->ht = sta->deflink.ht_cap.ht_supported;
 233		bss_params->tx_channel_width_set = is_cap_supported(caps,
 234			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
 235		bss_params->lsig_tx_op_protection_full_support =
 236			is_cap_supported(caps,
 237					 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
 238
 239		bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
 240		bss_params->lln_non_gf_coexist =
 241			!!(vif->bss_conf.ht_operation_mode &
 242			   IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
 243		/* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
 244		bss_params->dual_cts_protection = 0;
 245		/* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
 246		bss_params->ht20_coexist = 0;
 247	}
 248}
 249
 250static void
 251wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif *vif,
 252			       struct ieee80211_sta *sta,
 253			       struct wcn36xx_hal_config_bss_params_v1 *bss)
 254{
 255	if (sta && sta->deflink.vht_cap.vht_supported)
 256		bss->vht_capable = 1;
 257}
 258
 259static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
 260		struct wcn36xx_hal_config_sta_params *sta_params)
 261{
 262	if (sta->deflink.ht_cap.ht_supported) {
 263		unsigned long caps = sta->deflink.ht_cap.cap;
 264
 265		sta_params->ht_capable = sta->deflink.ht_cap.ht_supported;
 266		sta_params->tx_channel_width_set = is_cap_supported(caps,
 267			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
 268		sta_params->lsig_txop_protection = is_cap_supported(caps,
 269			IEEE80211_HT_CAP_LSIG_TXOP_PROT);
 270
 271		sta_params->max_ampdu_size = sta->deflink.ht_cap.ampdu_factor;
 272		sta_params->max_ampdu_density = sta->deflink.ht_cap.ampdu_density;
 273		/* max_amsdu_size: 1 : 3839 bytes, 0 : 7935 bytes (max) */
 274		sta_params->max_amsdu_size = !is_cap_supported(caps,
 275			IEEE80211_HT_CAP_MAX_AMSDU);
 276		sta_params->sgi_20Mhz = is_cap_supported(caps,
 277			IEEE80211_HT_CAP_SGI_20);
 278		sta_params->sgi_40mhz =	is_cap_supported(caps,
 279			IEEE80211_HT_CAP_SGI_40);
 280		sta_params->green_field_capable = is_cap_supported(caps,
 281			IEEE80211_HT_CAP_GRN_FLD);
 282		sta_params->delayed_ba_support = is_cap_supported(caps,
 283			IEEE80211_HT_CAP_DELAY_BA);
 284		sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
 285			IEEE80211_HT_CAP_DSSSCCK40);
 286	}
 287}
 288
 289static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn,
 290		struct ieee80211_sta *sta,
 291		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
 292{
 293	if (sta->deflink.vht_cap.vht_supported) {
 294		unsigned long caps = sta->deflink.vht_cap.cap;
 295
 296		sta_params->vht_capable = sta->deflink.vht_cap.vht_supported;
 297		sta_params->vht_ldpc_enabled =
 298			is_cap_supported(caps, IEEE80211_VHT_CAP_RXLDPC);
 299		if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, MU_MIMO)) {
 300			sta_params->vht_tx_mu_beamformee_capable =
 301				is_cap_supported(caps, IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
 302			if (sta_params->vht_tx_mu_beamformee_capable)
 303			       sta_params->vht_tx_bf_enabled = 1;
 304		} else {
 305			sta_params->vht_tx_mu_beamformee_capable = 0;
 306		}
 307		sta_params->vht_tx_channel_width_set = 0;
 308	}
 309}
 310
 311static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta *sta,
 312		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
 313{
 314	if (sta->deflink.ht_cap.ht_supported) {
 315		sta_params->ht_ldpc_enabled =
 316			is_cap_supported(sta->deflink.ht_cap.cap,
 317					 IEEE80211_HT_CAP_LDPC_CODING);
 318	}
 319}
 320
 321static void wcn36xx_smd_set_sta_default_ht_params(
 322		struct wcn36xx_hal_config_sta_params *sta_params)
 323{
 324	sta_params->ht_capable = 1;
 325	sta_params->tx_channel_width_set = 1;
 326	sta_params->lsig_txop_protection = 1;
 327	sta_params->max_ampdu_size = 3;
 328	sta_params->max_ampdu_density = 5;
 329	sta_params->max_amsdu_size = 0;
 330	sta_params->sgi_20Mhz = 1;
 331	sta_params->sgi_40mhz = 1;
 332	sta_params->green_field_capable = 1;
 333	sta_params->delayed_ba_support = 0;
 334	sta_params->dsss_cck_mode_40mhz = 1;
 335}
 336
 337static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx *wcn,
 338		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
 339{
 340	if (wcn->rf_id == RF_IRIS_WCN3680) {
 341		sta_params->vht_capable = 1;
 342		sta_params->vht_tx_mu_beamformee_capable = 1;
 343	} else {
 344		sta_params->vht_capable = 0;
 345		sta_params->vht_tx_mu_beamformee_capable = 0;
 346	}
 347
 348	sta_params->vht_ldpc_enabled = 0;
 349	sta_params->vht_tx_channel_width_set = 0;
 350	sta_params->vht_tx_bf_enabled = 0;
 351}
 352
 353static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx *wcn,
 354		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
 355{
 356	if (wcn->rf_id == RF_IRIS_WCN3680)
 357		sta_params->ht_ldpc_enabled = 1;
 358	else
 359		sta_params->ht_ldpc_enabled = 0;
 360}
 361
 362static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
 363		struct ieee80211_vif *vif,
 364		struct ieee80211_sta *sta,
 365		struct wcn36xx_hal_config_sta_params *sta_params)
 366{
 367	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 368	struct wcn36xx_sta *sta_priv = NULL;
 369	if (vif->type == NL80211_IFTYPE_ADHOC ||
 370	    vif->type == NL80211_IFTYPE_AP ||
 371	    vif->type == NL80211_IFTYPE_MESH_POINT) {
 372		sta_params->type = 1;
 373		sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
 374	} else {
 375		sta_params->type = 0;
 376		sta_params->sta_index = vif_priv->self_sta_index;
 377	}
 378
 379	sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
 380
 381	/*
 382	 * In STA mode ieee80211_sta contains bssid and ieee80211_vif
 383	 * contains our mac address. In  AP mode we are bssid so vif
 384	 * contains bssid and ieee80211_sta contains mac.
 385	 */
 386	if (NL80211_IFTYPE_STATION == vif->type)
 387		memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
 388	else
 389		memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
 390
 391	sta_params->encrypt_type = vif_priv->encrypt_type;
 392	sta_params->short_preamble_supported = true;
 393
 394	sta_params->rifs_mode = 0;
 395	sta_params->rmf = 0;
 396	sta_params->action = 0;
 397	sta_params->uapsd = 0;
 398	sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
 399	sta_params->max_ampdu_duration = 0;
 400	sta_params->bssid_index = vif_priv->bss_index;
 401	sta_params->p2p = 0;
 402
 403	if (sta) {
 404		sta_priv = wcn36xx_sta_to_priv(sta);
 405		if (NL80211_IFTYPE_STATION == vif->type)
 406			memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
 407		else
 408			memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
 409		sta_params->wmm_enabled = sta->wme;
 410		sta_params->max_sp_len = sta->max_sp;
 411		sta_params->aid = sta_priv->aid;
 412		wcn36xx_smd_set_sta_ht_params(sta, sta_params);
 413		memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
 414			sizeof(struct wcn36xx_hal_supported_rates));
 415	} else {
 416		wcn36xx_set_default_rates((struct wcn36xx_hal_supported_rates *)
 417					  &sta_params->supported_rates);
 418		wcn36xx_smd_set_sta_default_ht_params(sta_params);
 419	}
 420}
 421
 422static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 423{
 424	int ret;
 425	unsigned long start;
 426	struct wcn36xx_hal_msg_header *hdr =
 427		(struct wcn36xx_hal_msg_header *)wcn->hal_buf;
 428	u16 req_type = hdr->msg_type;
 429
 430	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
 431
 432	init_completion(&wcn->hal_rsp_compl);
 433	start = jiffies;
 434	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len);
 435	if (ret) {
 436		wcn36xx_err("HAL TX failed for req %d\n", req_type);
 437		goto out;
 438	}
 439	if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
 440		msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
 441		wcn36xx_err("Timeout! No SMD response to req %d in %dms\n",
 442			    req_type, HAL_MSG_TIMEOUT);
 443		ret = -ETIME;
 444		goto out;
 445	}
 446	wcn36xx_dbg(WCN36XX_DBG_SMD,
 447		    "SMD command (req %d, rsp %d) completed in %dms\n",
 448		    req_type, hdr->msg_type,
 449		    jiffies_to_msecs(jiffies - start));
 450out:
 451	return ret;
 452}
 453
 454#define __INIT_HAL_MSG(msg_body, type, version) \
 455	do {								\
 456		memset(&(msg_body), 0, sizeof(msg_body));		\
 457		(msg_body).header.msg_type = type;			\
 458		(msg_body).header.msg_version = version;		\
 459		(msg_body).header.len = sizeof(msg_body);		\
 460	} while (0)							\
 461
 462#define INIT_HAL_MSG(msg_body, type)	\
 463	__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0)
 464
 465#define INIT_HAL_MSG_V1(msg_body, type) \
 466	__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1)
 467
 468#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
 469	do { \
 470		memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
 471		p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \
 472		p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
 473		p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \
 474	} while (0)
 475
 476#define PREPARE_HAL_BUF(send_buf, msg_body) \
 477	do {							\
 478		memcpy_and_pad(send_buf, msg_body.header.len,	\
 479			       &msg_body, sizeof(msg_body), 0);	\
 480	} while (0)						\
 481
 482#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
 483	do {							\
 484		memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
 485	} while (0)
 486
 487static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
 488{
 489	struct wcn36xx_fw_msg_status_rsp *rsp;
 490
 491	if (len < sizeof(struct wcn36xx_hal_msg_header) +
 492	    sizeof(struct wcn36xx_fw_msg_status_rsp))
 493		return -EIO;
 494
 495	rsp = (struct wcn36xx_fw_msg_status_rsp *)
 496		(buf + sizeof(struct wcn36xx_hal_msg_header));
 497
 498	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
 499		return rsp->status;
 500
 501	return 0;
 502}
 503
 504int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 505{
 506	struct nv_data *nv_d;
 507	struct wcn36xx_hal_nv_img_download_req_msg msg_body;
 508	int fw_bytes_left;
 509	int ret;
 510	u16 fm_offset = 0;
 511
 512	if (!wcn->nv) {
 513		ret = request_firmware(&wcn->nv, wcn->nv_file, wcn->dev);
 514		if (ret) {
 515			wcn36xx_err("Failed to load nv file %s: %d\n",
 516				    wcn->nv_file, ret);
 517			goto out;
 518		}
 519	}
 520
 521	nv_d = (struct nv_data *)wcn->nv->data;
 522	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
 523
 524	msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
 525
 526	msg_body.frag_number = 0;
 527	/* hal_buf must be protected with  mutex */
 528	mutex_lock(&wcn->hal_mutex);
 529
 530	do {
 531		fw_bytes_left = wcn->nv->size - fm_offset - 4;
 532		if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
 533			msg_body.last_fragment = 0;
 534			msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
 535		} else {
 536			msg_body.last_fragment = 1;
 537			msg_body.nv_img_buffer_size = fw_bytes_left;
 538
 539			/* Do not forget update general message len */
 540			msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
 541
 542		}
 543
 544		/* Add load NV request message header */
 545		memcpy(wcn->hal_buf, &msg_body,	sizeof(msg_body));
 546
 547		/* Add NV body itself */
 548		memcpy(wcn->hal_buf + sizeof(msg_body),
 549		       &nv_d->table + fm_offset,
 550		       msg_body.nv_img_buffer_size);
 551
 552		ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 553		if (ret)
 554			goto out_unlock;
 555		ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
 556						   wcn->hal_rsp_len);
 557		if (ret) {
 558			wcn36xx_err("hal_load_nv response failed err=%d\n",
 559				    ret);
 560			goto out_unlock;
 561		}
 562		msg_body.frag_number++;
 563		fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
 564
 565	} while (msg_body.last_fragment != 1);
 566
 567out_unlock:
 568	mutex_unlock(&wcn->hal_mutex);
 569out:	return ret;
 570}
 571
 572static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
 573{
 574	struct wcn36xx_hal_mac_start_rsp_msg *rsp;
 575
 576	if (len < sizeof(*rsp))
 577		return -EIO;
 578
 579	rsp = buf;
 580
 581	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
 582		return -EIO;
 583
 584	memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
 585	       WCN36XX_HAL_VERSION_LENGTH);
 586	memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
 587	       WCN36XX_HAL_VERSION_LENGTH);
 588
 589	/* null terminate the strings, just in case */
 590	wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
 591	wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
 592
 593	wcn->fw_revision = rsp->start_rsp_params.version.revision;
 594	wcn->fw_version = rsp->start_rsp_params.version.version;
 595	wcn->fw_minor = rsp->start_rsp_params.version.minor;
 596	wcn->fw_major = rsp->start_rsp_params.version.major;
 597
 598	if (wcn->first_boot) {
 599		wcn->first_boot = false;
 600		wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
 601			     wcn->wlan_version, wcn->crm_version);
 602
 603		wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
 604			     wcn->fw_major, wcn->fw_minor,
 605			     wcn->fw_version, wcn->fw_revision,
 606			     rsp->start_rsp_params.stations,
 607			     rsp->start_rsp_params.bssids);
 608	}
 609	return 0;
 610}
 611
 612int wcn36xx_smd_start(struct wcn36xx *wcn)
 613{
 614	struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
 615	int ret;
 616	int i;
 617	size_t len;
 618	int cfg_elements;
 619	static struct wcn36xx_cfg_val *cfg_vals;
 620
 621	mutex_lock(&wcn->hal_mutex);
 622	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
 623
 624	msg_body.params.type = DRIVER_TYPE_PRODUCTION;
 625	msg_body.params.len = 0;
 626
 627	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 628
 629	body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
 630	len = body->header.len;
 631
 632	if (wcn->rf_id == RF_IRIS_WCN3680) {
 633		cfg_vals = wcn3680_cfg_vals;
 634		cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals);
 635	} else {
 636		cfg_vals = wcn36xx_cfg_vals;
 637		cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals);
 638	}
 639
 640	for (i = 0; i < cfg_elements; i++) {
 641		ret = put_cfg_tlv_u32(wcn, &len, cfg_vals[i].cfg_id,
 642				      cfg_vals[i].value);
 643		if (ret)
 644			goto out;
 645	}
 646	body->header.len = len;
 647	body->params.len = len - sizeof(*body);
 648
 649	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
 650		    msg_body.params.type);
 651
 652	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
 653	if (ret) {
 654		wcn36xx_err("Sending hal_start failed\n");
 655		goto out;
 656	}
 657
 658	ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
 659	if (ret) {
 660		wcn36xx_err("hal_start response failed err=%d\n", ret);
 661		goto out;
 662	}
 663
 664out:
 665	mutex_unlock(&wcn->hal_mutex);
 666	return ret;
 667}
 668
 669int wcn36xx_smd_stop(struct wcn36xx *wcn)
 670{
 671	struct wcn36xx_hal_mac_stop_req_msg msg_body;
 672	int ret;
 673
 674	mutex_lock(&wcn->hal_mutex);
 675	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
 676
 677	msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
 678
 679	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 680
 681	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 682	if (ret) {
 683		wcn36xx_err("Sending hal_stop failed\n");
 684		goto out;
 685	}
 686	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 687	if (ret) {
 688		wcn36xx_err("hal_stop response failed err=%d\n", ret);
 689		goto out;
 690	}
 691out:
 692	mutex_unlock(&wcn->hal_mutex);
 693	return ret;
 694}
 695
 696int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode,
 697			  struct ieee80211_vif *vif)
 698{
 699	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 700	struct wcn36xx_hal_init_scan_req_msg msg_body;
 701	int ret;
 702
 703	mutex_lock(&wcn->hal_mutex);
 704	INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
 705
 706	msg_body.mode = mode;
 707	if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
 708		/* Notify BSSID with null DATA packet */
 709		msg_body.frame_type = 2;
 710		msg_body.notify = 1;
 711		msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
 712		msg_body.scan_entry.active_bss_count = 1;
 713	}
 714
 715	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 716
 717	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
 718
 719	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 720	if (ret) {
 721		wcn36xx_err("Sending hal_init_scan failed\n");
 722		goto out;
 723	}
 724	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 725	if (ret) {
 726		wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
 727		goto out;
 728	}
 729	wcn->sw_scan_init = true;
 730out:
 731	mutex_unlock(&wcn->hal_mutex);
 732	return ret;
 733}
 734
 735int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
 736{
 737	struct wcn36xx_hal_start_scan_req_msg msg_body;
 738	int ret;
 739
 740	mutex_lock(&wcn->hal_mutex);
 741	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
 742
 743	msg_body.scan_channel = scan_channel;
 744
 745	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 746
 747	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
 748		    msg_body.scan_channel);
 749
 750	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 751	if (ret) {
 752		wcn36xx_err("Sending hal_start_scan failed\n");
 753		goto out;
 754	}
 755	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 756	if (ret) {
 757		wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
 758		goto out;
 759	}
 760	wcn->sw_scan_channel = scan_channel;
 761out:
 762	mutex_unlock(&wcn->hal_mutex);
 763	return ret;
 764}
 765
 766int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
 767{
 768	struct wcn36xx_hal_end_scan_req_msg msg_body;
 769	int ret;
 770
 771	mutex_lock(&wcn->hal_mutex);
 772	INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
 773
 774	msg_body.scan_channel = scan_channel;
 775
 776	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 777
 778	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
 779		    msg_body.scan_channel);
 780
 781	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 782	if (ret) {
 783		wcn36xx_err("Sending hal_end_scan failed\n");
 784		goto out;
 785	}
 786	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 787	if (ret) {
 788		wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
 789		goto out;
 790	}
 791	wcn->sw_scan_channel = 0;
 792out:
 793	mutex_unlock(&wcn->hal_mutex);
 794	return ret;
 795}
 796
 797int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
 798			    enum wcn36xx_hal_sys_mode mode,
 799			    struct ieee80211_vif *vif)
 800{
 801	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 802	struct wcn36xx_hal_finish_scan_req_msg msg_body;
 803	int ret;
 804
 805	mutex_lock(&wcn->hal_mutex);
 806	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
 807
 808	msg_body.mode = mode;
 809	msg_body.oper_channel = WCN36XX_HW_CHANNEL(wcn);
 810	if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
 811		/* Notify BSSID with null data packet */
 812		msg_body.notify = 1;
 813		msg_body.frame_type = 2;
 814		msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
 815		msg_body.scan_entry.active_bss_count = 1;
 816	}
 817
 818	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 819
 820	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
 821		    msg_body.mode);
 822
 823	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 824	if (ret) {
 825		wcn36xx_err("Sending hal_finish_scan failed\n");
 826		goto out;
 827	}
 828	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 829	if (ret) {
 830		wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
 831		goto out;
 832	}
 833	wcn->sw_scan_init = false;
 834out:
 835	mutex_unlock(&wcn->hal_mutex);
 836	return ret;
 837}
 838
 839int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
 840			      struct cfg80211_scan_request *req)
 841{
 842	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 843	struct wcn36xx_hal_start_scan_offload_req_msg *msg_body;
 844	int ret, i;
 845
 846	if (req->ie_len > WCN36XX_MAX_SCAN_IE_LEN)
 847		return -EINVAL;
 848
 849	mutex_lock(&wcn->hal_mutex);
 850	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
 851	if (!msg_body) {
 852		ret = -ENOMEM;
 853		goto out;
 854	}
 855
 856	INIT_HAL_MSG((*msg_body), WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
 857
 858	msg_body->scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
 859	msg_body->min_ch_time = 30;
 860	msg_body->max_ch_time = 100;
 861	msg_body->scan_hidden = 1;
 862	memcpy(msg_body->mac, vif->addr, ETH_ALEN);
 863	msg_body->bss_type = vif_priv->bss_type;
 864	msg_body->p2p_search = vif->p2p;
 865
 866	msg_body->num_ssid = min_t(u8, req->n_ssids, ARRAY_SIZE(msg_body->ssids));
 867	for (i = 0; i < msg_body->num_ssid; i++) {
 868		msg_body->ssids[i].length = min_t(u8, req->ssids[i].ssid_len,
 869						sizeof(msg_body->ssids[i].ssid));
 870		memcpy(msg_body->ssids[i].ssid, req->ssids[i].ssid,
 871		       msg_body->ssids[i].length);
 872	}
 873
 874	msg_body->num_channel = min_t(u8, req->n_channels,
 875				     sizeof(msg_body->channels));
 876	for (i = 0; i < msg_body->num_channel; i++) {
 877		msg_body->channels[i] =
 878			HW_VALUE_CHANNEL(req->channels[i]->hw_value);
 879	}
 880
 881	msg_body->header.len -= WCN36XX_MAX_SCAN_IE_LEN;
 882
 883	if (req->ie_len > 0) {
 884		msg_body->ie_len = req->ie_len;
 885		msg_body->header.len += req->ie_len;
 886		memcpy(msg_body->ie, req->ie, req->ie_len);
 887	}
 888
 889	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
 890
 891	wcn36xx_dbg(WCN36XX_DBG_HAL,
 892		    "hal start hw-scan (channels: %u; ssids: %u; p2p: %s)\n",
 893		    msg_body->num_channel, msg_body->num_ssid,
 894		    msg_body->p2p_search ? "yes" : "no");
 895
 896	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
 897	if (ret) {
 898		wcn36xx_err("Sending hal_start_scan_offload failed\n");
 899		goto out;
 900	}
 901	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 902	if (ret) {
 903		wcn36xx_err("hal_start_scan_offload response failed err=%d\n",
 904			    ret);
 905		goto out;
 906	}
 907out:
 908	kfree(msg_body);
 909	mutex_unlock(&wcn->hal_mutex);
 910	return ret;
 911}
 912
 913int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn)
 914{
 915	struct wcn36xx_hal_stop_scan_offload_req_msg msg_body;
 916	int ret;
 917
 918	mutex_lock(&wcn->hal_mutex);
 919	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ);
 920	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 921
 922	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal stop hw-scan\n");
 923
 924	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 925	if (ret) {
 926		wcn36xx_err("Sending hal_stop_scan_offload failed\n");
 927		goto out;
 928	}
 929	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 930	if (ret) {
 931		wcn36xx_err("hal_stop_scan_offload response failed err=%d\n",
 932			    ret);
 933		goto out;
 934	}
 935out:
 936	mutex_unlock(&wcn->hal_mutex);
 937	return ret;
 938}
 939
 940int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req)
 941{
 942	struct wcn36xx_hal_update_channel_list_req_msg *msg_body;
 943	int ret, i;
 944
 945	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
 946	if (!msg_body)
 947		return -ENOMEM;
 948
 949	INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ);
 950
 951	msg_body->num_channel = min_t(u8, req->n_channels, ARRAY_SIZE(msg_body->channels));
 952	for (i = 0; i < msg_body->num_channel; i++) {
 953		struct wcn36xx_hal_channel_param *param = &msg_body->channels[i];
 954		u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER;
 955		u32 ant_gain = WCN36XX_HAL_DEFAULT_ANT_GAIN;
 956
 957		param->mhz = req->channels[i]->center_freq;
 958		param->band_center_freq1 = req->channels[i]->center_freq;
 959		param->band_center_freq2 = 0;
 960
 961		if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR)
 962			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE;
 963
 964		if (req->channels[i]->flags & IEEE80211_CHAN_RADAR)
 965			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_DFS;
 966
 967		if (req->channels[i]->band == NL80211_BAND_5GHZ) {
 968			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_HT;
 969			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_VHT;
 970			param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11A;
 971		} else {
 972			param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11BG;
 973		}
 974
 975		if (min_power > req->channels[i]->max_power)
 976			min_power = req->channels[i]->max_power;
 977
 978		if (req->channels[i]->max_antenna_gain)
 979			ant_gain = req->channels[i]->max_antenna_gain;
 980
 981		u32p_replace_bits(&param->reg_info_1, min_power,
 982				  WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK);
 983		u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_power,
 984				  WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK);
 985		u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_reg_power,
 986				  WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK);
 987		u32p_replace_bits(&param->reg_info_1, 0,
 988				  WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK);
 989		u32p_replace_bits(&param->reg_info_2, ant_gain,
 990				  WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK);
 991
 992		wcn36xx_dbg(WCN36XX_DBG_HAL,
 993			    "%s: freq=%u, channel_info=%08x, reg_info1=%08x, reg_info2=%08x\n",
 994			    __func__, param->mhz, param->channel_info, param->reg_info_1,
 995			    param->reg_info_2);
 996	}
 997
 998	mutex_lock(&wcn->hal_mutex);
 999
1000	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1001
1002	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1003	if (ret) {
1004		wcn36xx_err("Sending hal_update_channel_list failed\n");
1005		goto out;
1006	}
1007
1008	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1009	if (ret) {
1010		wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret);
1011		goto out;
1012	}
1013
1014out:
1015	kfree(msg_body);
1016	mutex_unlock(&wcn->hal_mutex);
1017	return ret;
1018}
1019
1020static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
1021{
1022	struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
1023	int ret;
1024
1025	ret = wcn36xx_smd_rsp_status_check(buf, len);
1026	if (ret)
1027		return ret;
1028	rsp = buf;
1029	wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
1030		    rsp->channel_number, rsp->status);
1031	return ret;
1032}
1033
1034int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
1035			       struct ieee80211_vif *vif, int ch)
1036{
1037	struct wcn36xx_hal_switch_channel_req_msg msg_body;
1038	int ret;
1039
1040	mutex_lock(&wcn->hal_mutex);
1041	INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
1042
1043	msg_body.channel_number = (u8)ch;
1044	msg_body.tx_mgmt_power = 0xbf;
1045	msg_body.max_tx_power = 0xbf;
1046	memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
1047
1048	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1049
1050	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1051	if (ret) {
1052		wcn36xx_err("Sending hal_switch_channel failed\n");
1053		goto out;
1054	}
1055	ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1056	if (ret) {
1057		wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
1058		goto out;
1059	}
1060out:
1061	mutex_unlock(&wcn->hal_mutex);
1062	return ret;
1063}
1064
1065static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len,
1066					   void **p_ptt_rsp_msg)
1067{
1068	struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp;
1069	int ret;
1070
1071	ret = wcn36xx_smd_rsp_status_check(buf, len);
1072	if (ret)
1073		return ret;
1074
1075	rsp = buf;
1076
1077	wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length %d\n",
1078		    rsp->header.len);
1079	wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg,
1080			 rsp->header.len - sizeof(rsp->ptt_msg_resp_status));
1081
1082	if (rsp->header.len > 0) {
1083		*p_ptt_rsp_msg = kmemdup(rsp->ptt_msg, rsp->header.len,
1084					 GFP_ATOMIC);
1085		if (!*p_ptt_rsp_msg)
1086			return -ENOMEM;
1087	}
1088	return ret;
1089}
1090
1091int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn,
1092				struct ieee80211_vif *vif, void *ptt_msg, size_t len,
1093		void **ptt_rsp_msg)
1094{
1095	struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body;
1096	int ret;
1097
1098	mutex_lock(&wcn->hal_mutex);
1099	p_msg_body = kmalloc(
1100		sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len,
1101		GFP_ATOMIC);
1102	if (!p_msg_body) {
1103		ret = -ENOMEM;
1104		goto out_nomem;
1105	}
1106	INIT_HAL_PTT_MSG(p_msg_body, len);
1107
1108	memcpy(&p_msg_body->ptt_msg, ptt_msg, len);
1109
1110	PREPARE_HAL_PTT_MSG_BUF(wcn->hal_buf, p_msg_body);
1111
1112	ret = wcn36xx_smd_send_and_wait(wcn, p_msg_body->header.len);
1113	if (ret) {
1114		wcn36xx_err("Sending hal_process_ptt_msg failed\n");
1115		goto out;
1116	}
1117	ret = wcn36xx_smd_process_ptt_msg_rsp(wcn->hal_buf, wcn->hal_rsp_len,
1118					      ptt_rsp_msg);
1119	if (ret) {
1120		wcn36xx_err("process_ptt_msg response failed err=%d\n", ret);
1121		goto out;
1122	}
1123out:
1124	kfree(p_msg_body);
1125out_nomem:
1126	mutex_unlock(&wcn->hal_mutex);
1127	return ret;
1128}
1129
1130static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
1131					struct ieee80211_vif *vif,
1132					void *buf,
1133					size_t len)
1134{
1135	struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
1136	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1137
1138	if (len < sizeof(*rsp))
1139		return -EINVAL;
1140
1141	rsp = buf;
1142
1143	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1144		wcn36xx_warn("hal add sta self failure: %d\n",
1145			     rsp->status);
1146		return rsp->status;
1147	}
1148
1149	wcn36xx_dbg(WCN36XX_DBG_HAL,
1150		    "hal add sta self status %d self_sta_index %d dpu_index %d\n",
1151		    rsp->status, rsp->self_sta_index, rsp->dpu_index);
1152
1153	vif_priv->self_sta_index = rsp->self_sta_index;
1154	vif_priv->self_dpu_desc_index = rsp->dpu_index;
1155
1156	return 0;
1157}
1158
1159int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1160{
1161	struct wcn36xx_hal_add_sta_self_req msg_body;
1162	int ret;
1163
1164	mutex_lock(&wcn->hal_mutex);
1165	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
1166
1167	memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
1168
1169	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1170
1171	wcn36xx_dbg(WCN36XX_DBG_HAL,
1172		    "hal add sta self self_addr %pM status %d\n",
1173		    msg_body.self_addr, msg_body.status);
1174
1175	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1176	if (ret) {
1177		wcn36xx_err("Sending hal_add_sta_self failed\n");
1178		goto out;
1179	}
1180	ret = wcn36xx_smd_add_sta_self_rsp(wcn,
1181					   vif,
1182					   wcn->hal_buf,
1183					   wcn->hal_rsp_len);
1184	if (ret) {
1185		wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
1186		goto out;
1187	}
1188out:
1189	mutex_unlock(&wcn->hal_mutex);
1190	return ret;
1191}
1192
1193int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
1194{
1195	struct wcn36xx_hal_del_sta_self_req_msg msg_body;
1196	int ret;
1197
1198	mutex_lock(&wcn->hal_mutex);
1199	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
1200
1201	memcpy(&msg_body.self_addr, addr, ETH_ALEN);
1202
1203	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1204
1205	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1206	if (ret) {
1207		wcn36xx_err("Sending hal_delete_sta_self failed\n");
1208		goto out;
1209	}
1210	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1211	if (ret) {
1212		wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
1213			    ret);
1214		goto out;
1215	}
1216out:
1217	mutex_unlock(&wcn->hal_mutex);
1218	return ret;
1219}
1220
1221int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
1222{
1223	struct wcn36xx_hal_delete_sta_req_msg msg_body;
1224	int ret;
1225
1226	mutex_lock(&wcn->hal_mutex);
1227	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
1228
1229	msg_body.sta_index = sta_index;
1230
1231	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1232
1233	wcn36xx_dbg(WCN36XX_DBG_HAL,
1234		    "hal delete sta sta_index %d\n",
1235		    msg_body.sta_index);
1236
1237	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1238	if (ret) {
1239		wcn36xx_err("Sending hal_delete_sta failed\n");
1240		goto out;
1241	}
1242	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1243	if (ret) {
1244		wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
1245		goto out;
1246	}
1247out:
1248	mutex_unlock(&wcn->hal_mutex);
1249	return ret;
1250}
1251
1252static int wcn36xx_smd_join_rsp(void *buf, size_t len)
1253{
1254	struct wcn36xx_hal_join_rsp_msg *rsp;
1255
1256	if (wcn36xx_smd_rsp_status_check(buf, len))
1257		return -EIO;
1258
1259	rsp = buf;
1260
1261	wcn36xx_dbg(WCN36XX_DBG_HAL,
1262		    "hal rsp join status %d tx_mgmt_power %d\n",
1263		    rsp->status, rsp->tx_mgmt_power);
1264
1265	return 0;
1266}
1267
1268int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
1269{
1270	struct wcn36xx_hal_join_req_msg msg_body;
1271	int ret;
1272
1273	mutex_lock(&wcn->hal_mutex);
1274	INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
1275
1276	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1277	memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
1278	msg_body.channel = ch;
1279
1280	if (conf_is_ht40_minus(&wcn->hw->conf))
1281		msg_body.secondary_channel_offset =
1282			PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
1283	else if (conf_is_ht40_plus(&wcn->hw->conf))
1284		msg_body.secondary_channel_offset =
1285			PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
1286	else
1287		msg_body.secondary_channel_offset =
1288			PHY_SINGLE_CHANNEL_CENTERED;
1289
1290	msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
1291
1292	msg_body.max_tx_power = 0xbf;
1293	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1294
1295	wcn36xx_dbg(WCN36XX_DBG_HAL,
1296		    "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1297		    msg_body.bssid, msg_body.self_sta_mac_addr,
1298		    msg_body.channel, msg_body.link_state);
1299
1300	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1301	if (ret) {
1302		wcn36xx_err("Sending hal_join failed\n");
1303		goto out;
1304	}
1305	ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1306	if (ret) {
1307		wcn36xx_err("hal_join response failed err=%d\n", ret);
1308		goto out;
1309	}
1310out:
1311	mutex_unlock(&wcn->hal_mutex);
1312	return ret;
1313}
1314
1315int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
1316			    const u8 *sta_mac,
1317			    enum wcn36xx_hal_link_state state)
1318{
1319	struct wcn36xx_hal_set_link_state_req_msg msg_body;
1320	int ret;
1321
1322	mutex_lock(&wcn->hal_mutex);
1323	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
1324
1325	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1326	memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
1327	msg_body.state = state;
1328
1329	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1330
1331	wcn36xx_dbg(WCN36XX_DBG_HAL,
1332		    "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1333		    msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
1334
1335	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1336	if (ret) {
1337		wcn36xx_err("Sending hal_set_link_st failed\n");
1338		goto out;
1339	}
1340	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1341	if (ret) {
1342		wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
1343		goto out;
1344	}
1345out:
1346	mutex_unlock(&wcn->hal_mutex);
1347	return ret;
1348}
1349
1350static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
1351			const struct wcn36xx_hal_config_sta_params *orig,
1352			struct wcn36xx_hal_config_sta_params_v1 *v1)
1353{
1354	/* convert orig to v1 format */
1355	memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
1356	memcpy(&v1->mac, orig->mac, ETH_ALEN);
1357	v1->aid = orig->aid;
1358	v1->type = orig->type;
1359	v1->short_preamble_supported = orig->short_preamble_supported;
1360	v1->listen_interval = orig->listen_interval;
1361	v1->wmm_enabled = orig->wmm_enabled;
1362	v1->ht_capable = orig->ht_capable;
1363	v1->tx_channel_width_set = orig->tx_channel_width_set;
1364	v1->rifs_mode = orig->rifs_mode;
1365	v1->lsig_txop_protection = orig->lsig_txop_protection;
1366	v1->max_ampdu_size = orig->max_ampdu_size;
1367	v1->max_ampdu_density = orig->max_ampdu_density;
1368	v1->sgi_40mhz = orig->sgi_40mhz;
1369	v1->sgi_20Mhz = orig->sgi_20Mhz;
1370	v1->rmf = orig->rmf;
1371	v1->encrypt_type = orig->encrypt_type;
1372	v1->action = orig->action;
1373	v1->uapsd = orig->uapsd;
1374	v1->max_sp_len = orig->max_sp_len;
1375	v1->green_field_capable = orig->green_field_capable;
1376	v1->mimo_ps = orig->mimo_ps;
1377	v1->delayed_ba_support = orig->delayed_ba_support;
1378	v1->max_ampdu_duration = orig->max_ampdu_duration;
1379	v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
1380	memcpy(&v1->supported_rates, &orig->supported_rates,
1381	       sizeof(orig->supported_rates));
1382	v1->sta_index = orig->sta_index;
1383	v1->bssid_index = orig->bssid_index;
1384	v1->p2p = orig->p2p;
1385}
1386
1387static void
1388wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn,
1389			      struct ieee80211_vif *vif,
1390			      struct ieee80211_sta *sta,
1391			      struct wcn36xx_hal_config_sta_params_v1 *sta_par)
1392{
1393	struct wcn36xx_sta *sta_priv = NULL;
1394	struct wcn36xx_hal_config_sta_params sta_par_v0;
1395
1396	wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0);
1397	wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par);
1398
1399	if (sta) {
1400		sta_priv = wcn36xx_sta_to_priv(sta);
1401		wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par);
1402		wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par);
1403		memcpy(&sta_par->supported_rates, &sta_priv->supported_rates,
1404		       sizeof(sta_par->supported_rates));
1405	} else {
1406		wcn36xx_set_default_rates_v1(&sta_par->supported_rates);
1407		wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par);
1408		wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par);
1409	}
1410}
1411
1412static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
1413				      struct ieee80211_sta *sta,
1414				      void *buf,
1415				      size_t len)
1416{
1417	struct wcn36xx_hal_config_sta_rsp_msg *rsp;
1418	struct config_sta_rsp_params *params;
1419	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1420
1421	if (len < sizeof(*rsp))
1422		return -EINVAL;
1423
1424	rsp = buf;
1425	params = &rsp->params;
1426
1427	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1428		wcn36xx_warn("hal config sta response failure: %d\n",
1429			     params->status);
1430		return -EIO;
1431	}
1432
1433	sta_priv->sta_index = params->sta_index;
1434	sta_priv->dpu_desc_index = params->dpu_index;
1435	sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
1436
1437	wcn36xx_dbg(WCN36XX_DBG_HAL,
1438		    "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1439		    params->status, params->sta_index, params->bssid_index,
1440		    params->uc_ucast_sig, params->p2p);
1441
1442	return 0;
1443}
1444
1445static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
1446				     struct ieee80211_vif *vif,
1447				     struct ieee80211_sta *sta)
1448{
1449	struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1450	struct wcn36xx_hal_config_sta_params_v1 *sta_params;
1451
1452	if (wcn->rf_id == RF_IRIS_WCN3680) {
1453		INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1454	} else {
1455		INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1456		msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT;
1457	}
1458
1459	sta_params = &msg_body.sta_params;
1460
1461	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params);
1462
1463	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1464
1465	wcn36xx_dbg(WCN36XX_DBG_HAL,
1466		    "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1467		    sta_params->action, sta_params->sta_index, sta_params->bssid_index,
1468		    sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid);
1469
1470	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1471}
1472
1473static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn,
1474				     struct ieee80211_vif *vif,
1475				     struct ieee80211_sta *sta)
1476{
1477	struct wcn36xx_hal_config_sta_req_msg msg;
1478	struct wcn36xx_hal_config_sta_params *sta_params;
1479
1480	INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1481
1482	sta_params = &msg.sta_params;
1483
1484	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1485
1486	PREPARE_HAL_BUF(wcn->hal_buf, msg);
1487
1488	wcn36xx_dbg(WCN36XX_DBG_HAL,
1489		    "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1490		    sta_params->action, sta_params->sta_index,
1491		    sta_params->bssid_index, sta_params->bssid,
1492		    sta_params->type, sta_params->mac, sta_params->aid);
1493
1494	return wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1495}
1496
1497int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1498			   struct ieee80211_sta *sta)
1499{
1500	int ret;
1501
1502	mutex_lock(&wcn->hal_mutex);
1503
1504	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1505		ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta);
1506	else
1507		ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta);
1508
1509	if (ret) {
1510		wcn36xx_err("Sending hal_config_sta failed\n");
1511		goto out;
1512	}
1513	ret = wcn36xx_smd_config_sta_rsp(wcn,
1514					 sta,
1515					 wcn->hal_buf,
1516					 wcn->hal_rsp_len);
1517	if (ret) {
1518		wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1519		goto out;
1520	}
1521out:
1522	mutex_unlock(&wcn->hal_mutex);
1523	return ret;
1524}
1525
1526static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn,
1527				       struct ieee80211_vif *vif,
1528				       struct ieee80211_sta *sta,
1529				       const u8 *bssid,
1530				       bool update,
1531				       struct wcn36xx_hal_config_bss_params *bss)
1532{
1533	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1534
1535	WARN_ON(is_zero_ether_addr(bssid));
1536
1537	memcpy(&bss->bssid, bssid, ETH_ALEN);
1538
1539	memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1540
1541	if (vif->type == NL80211_IFTYPE_STATION) {
1542		bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1543
1544		/* STA */
1545		bss->oper_mode = 1;
1546		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1547	} else if (vif->type == NL80211_IFTYPE_AP ||
1548		   vif->type == NL80211_IFTYPE_MESH_POINT) {
1549		bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1550
1551		/* AP */
1552		bss->oper_mode = 0;
1553		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1554	} else if (vif->type == NL80211_IFTYPE_ADHOC) {
1555		bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1556
1557		/* STA */
1558		bss->oper_mode = 1;
1559	} else {
1560		wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1561	}
1562
1563	if (vif->type == NL80211_IFTYPE_STATION)
1564		wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1565	else
1566		bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1567
1568	bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1569	bss->lla_coexist = 0;
1570	bss->llb_coexist = 0;
1571	bss->llg_coexist = 0;
1572	bss->rifs_mode = 0;
1573	bss->beacon_interval = vif->bss_conf.beacon_int;
1574	bss->dtim_period = vif_priv->dtim_period;
1575
1576	wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1577
1578	bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1579
1580	if (conf_is_ht40_minus(&wcn->hw->conf))
1581		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1582	else if (conf_is_ht40_plus(&wcn->hw->conf))
1583		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1584	else
1585		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1586
1587	bss->reserved = 0;
1588
1589	/* wcn->ssid is only valid in AP and IBSS mode */
1590	bss->ssid.length = vif_priv->ssid.length;
1591	memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1592
1593	bss->obss_prot_enabled = 0;
1594	bss->rmf = 0;
1595	bss->max_probe_resp_retry_limit = 0;
1596	bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1597	bss->proxy_probe_resp = 0;
1598	bss->edca_params_valid = 0;
1599
1600	/* FIXME: set acbe, acbk, acvi and acvo */
1601
1602	bss->ext_set_sta_key_param_valid = 0;
1603
1604	/* FIXME: set ext_set_sta_key_param */
1605
1606	bss->spectrum_mgt_enable = 0;
1607	bss->tx_mgmt_power = 0;
1608	bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1609	bss->action = update;
1610
1611	vif_priv->bss_type = bss->bss_type;
1612}
1613
1614static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1615				     struct ieee80211_vif *vif,
1616				     struct ieee80211_sta *sta_80211,
1617				     const u8 *bssid,
1618				     bool update)
1619{
1620	struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body;
1621	struct wcn36xx_hal_config_bss_params_v1 *bss;
1622	struct wcn36xx_hal_config_bss_params bss_v0;
1623	struct wcn36xx_hal_config_sta_params_v1 *sta;
1624	struct cfg80211_chan_def *chandef;
1625	int ret;
1626
1627	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
1628	if (!msg_body)
1629		return -ENOMEM;
1630
1631	if (wcn->rf_id == RF_IRIS_WCN3680) {
1632		INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1633	} else {
1634		INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1635		msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT;
1636	}
1637
1638	bss = &msg_body->bss_params;
1639	sta = &bss->sta;
1640
1641	memset(&bss_v0, 0x00, sizeof(bss_v0));
1642	wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0);
1643	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta);
1644
1645	/* convert orig to v1 */
1646	memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN);
1647	memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN);
1648
1649	bss->bss_type = bss_v0.bss_type;
1650	bss->oper_mode = bss_v0.oper_mode;
1651	bss->nw_type = bss_v0.nw_type;
1652
1653	bss->short_slot_time_supported =
1654		bss_v0.short_slot_time_supported;
1655	bss->lla_coexist = bss_v0.lla_coexist;
1656	bss->llb_coexist = bss_v0.llb_coexist;
1657	bss->llg_coexist = bss_v0.llg_coexist;
1658	bss->ht20_coexist = bss_v0.ht20_coexist;
1659	bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist;
1660
1661	bss->lsig_tx_op_protection_full_support =
1662		bss_v0.lsig_tx_op_protection_full_support;
1663	bss->rifs_mode = bss_v0.rifs_mode;
1664	bss->beacon_interval = bss_v0.beacon_interval;
1665	bss->dtim_period = bss_v0.dtim_period;
1666	bss->tx_channel_width_set = bss_v0.tx_channel_width_set;
1667	bss->oper_channel = bss_v0.oper_channel;
1668
1669	if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) {
1670		chandef = &wcn->hw->conf.chandef;
1671		bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value);
1672	} else {
1673		bss->ext_channel = bss_v0.ext_channel;
1674	}
1675
1676	bss->reserved = bss_v0.reserved;
1677
1678	memcpy(&bss->ssid, &bss_v0.ssid,
1679	       sizeof(bss_v0.ssid));
1680
1681	bss->action = bss_v0.action;
1682	bss->rateset = bss_v0.rateset;
1683	bss->ht = bss_v0.ht;
1684	bss->obss_prot_enabled = bss_v0.obss_prot_enabled;
1685	bss->rmf = bss_v0.rmf;
1686	bss->ht_oper_mode = bss_v0.ht_oper_mode;
1687	bss->dual_cts_protection = bss_v0.dual_cts_protection;
1688
1689	bss->max_probe_resp_retry_limit =
1690		bss_v0.max_probe_resp_retry_limit;
1691	bss->hidden_ssid = bss_v0.hidden_ssid;
1692	bss->proxy_probe_resp =	bss_v0.proxy_probe_resp;
1693	bss->edca_params_valid = bss_v0.edca_params_valid;
1694
1695	memcpy(&bss->acbe, &bss_v0.acbe,
1696	       sizeof(bss_v0.acbe));
1697	memcpy(&bss->acbk, &bss_v0.acbk,
1698	       sizeof(bss_v0.acbk));
1699	memcpy(&bss->acvi, &bss_v0.acvi,
1700	       sizeof(bss_v0.acvi));
1701	memcpy(&bss->acvo, &bss_v0.acvo,
1702	       sizeof(bss_v0.acvo));
1703
1704	bss->ext_set_sta_key_param_valid =
1705		bss_v0.ext_set_sta_key_param_valid;
1706
1707	memcpy(&bss->ext_set_sta_key_param,
1708	       &bss_v0.ext_set_sta_key_param,
1709	       sizeof(bss_v0.acvo));
1710
1711	bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona;
1712	bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable;
1713	bss->tx_mgmt_power = bss_v0.tx_mgmt_power;
1714	bss->max_tx_power = bss_v0.max_tx_power;
1715
1716	wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss);
1717
1718	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1719
1720	wcn36xx_dbg(WCN36XX_DBG_HAL,
1721		    "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1722		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1723		    bss->oper_mode, bss->nw_type);
1724
1725	wcn36xx_dbg(WCN36XX_DBG_HAL,
1726		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1727		    sta->bssid, sta->action, sta->sta_index,
1728		    sta->bssid_index, sta->aid, sta->type, sta->mac);
1729
1730	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1731	kfree(msg_body);
1732
1733	return ret;
1734}
1735
1736static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn,
1737				     struct ieee80211_vif *vif,
1738				     struct ieee80211_sta *sta,
1739				     const u8 *bssid,
1740				     bool update)
1741{
1742	struct wcn36xx_hal_config_bss_req_msg *msg;
1743	struct wcn36xx_hal_config_bss_params *bss;
1744	struct wcn36xx_hal_config_sta_params *sta_params;
1745	int ret;
1746
1747	msg = kzalloc(sizeof(*msg), GFP_KERNEL);
1748	if (!msg)
1749		return -ENOMEM;
1750
1751	INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ);
1752
1753	bss = &msg->bss_params;
1754	sta_params = &bss->sta;
1755
1756	wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss);
1757	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1758
1759	PREPARE_HAL_BUF(wcn->hal_buf, (*msg));
1760
1761	wcn36xx_dbg(WCN36XX_DBG_HAL,
1762		    "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1763		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1764		    bss->oper_mode, bss->nw_type);
1765
1766	wcn36xx_dbg(WCN36XX_DBG_HAL,
1767		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1768		    sta_params->bssid, sta_params->action,
1769		    sta_params->sta_index, sta_params->bssid_index,
1770		    sta_params->aid, sta_params->type,
1771		    sta_params->mac);
1772
1773	ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len);
1774	kfree(msg);
1775
1776	return ret;
1777}
1778
1779static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1780				      struct ieee80211_vif *vif,
1781				      struct ieee80211_sta *sta,
1782				      void *buf,
1783				      size_t len)
1784{
1785	struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1786	struct wcn36xx_hal_config_bss_rsp_params *params;
1787	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1788
1789	if (len < sizeof(*rsp))
1790		return -EINVAL;
1791
1792	rsp = buf;
1793	params = &rsp->bss_rsp_params;
1794
1795	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1796		wcn36xx_warn("hal config bss response failure: %d\n",
1797			     params->status);
1798		return -EIO;
1799	}
1800
1801	wcn36xx_dbg(WCN36XX_DBG_HAL,
1802		    "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1803		    " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1804		    " power %d ucast_dpu_signature %d\n",
1805		    params->status, params->bss_index, params->dpu_desc_index,
1806		    params->bss_sta_index, params->bss_self_sta_index,
1807		    params->bss_bcast_sta_idx, params->mac,
1808		    params->tx_mgmt_power, params->ucast_dpu_signature);
1809
1810	vif_priv->bss_index = params->bss_index;
1811
1812	if (sta) {
1813		struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1814		sta_priv->bss_sta_index = params->bss_sta_index;
1815		sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
1816	}
1817
1818	vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
1819
1820	return 0;
1821}
1822
1823int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1824			   struct ieee80211_sta *sta, const u8 *bssid,
1825			   bool update)
1826{
1827	int ret;
1828
1829	mutex_lock(&wcn->hal_mutex);
1830
1831	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1832		ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update);
1833	else
1834		ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update);
1835
1836	if (ret) {
1837		wcn36xx_err("Sending hal_config_bss failed\n");
1838		goto out;
1839	}
1840	ret = wcn36xx_smd_config_bss_rsp(wcn,
1841					 vif,
1842					 sta,
1843					 wcn->hal_buf,
1844					 wcn->hal_rsp_len);
1845	if (ret)
1846		wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1847
1848out:
1849	mutex_unlock(&wcn->hal_mutex);
1850	return ret;
1851}
1852
1853int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1854{
1855	struct wcn36xx_hal_delete_bss_req_msg msg_body;
1856	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1857	int ret = 0;
1858
1859	mutex_lock(&wcn->hal_mutex);
1860
1861	if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX)
1862		goto out;
1863
1864	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1865
1866	msg_body.bss_index = vif_priv->bss_index;
1867
1868	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1869
1870	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1871
1872	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1873	if (ret) {
1874		wcn36xx_err("Sending hal_delete_bss failed\n");
1875		goto out;
1876	}
1877	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1878	if (ret) {
1879		wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1880		goto out;
1881	}
1882
1883	vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1884out:
1885	mutex_unlock(&wcn->hal_mutex);
1886	return ret;
1887}
1888
1889int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1890			    struct sk_buff *skb_beacon, u16 tim_off,
1891			    u16 p2p_off)
1892{
1893	struct wcn36xx_hal_send_beacon_req_msg msg_body;
1894	int ret, pad, pvm_len;
1895
1896	mutex_lock(&wcn->hal_mutex);
1897	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1898
1899	pvm_len = skb_beacon->data[tim_off + 1] - 3;
1900	pad = TIM_MIN_PVM_SIZE - pvm_len;
1901
1902	/* Padding is irrelevant to mesh mode since tim_off is always 0. */
1903	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1904		pad = 0;
1905
1906	msg_body.beacon_length = skb_beacon->len + pad;
1907	/* TODO need to find out why + 6 is needed */
1908	msg_body.beacon_length6 = msg_body.beacon_length + 6;
1909
1910	if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
1911		wcn36xx_err("Beacon is too big: beacon size=%d\n",
1912			      msg_body.beacon_length);
1913		ret = -ENOMEM;
1914		goto out;
1915	}
1916	memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
1917	memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1918
1919	if (pad > 0) {
1920		/*
1921		 * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1922		 * given the beacon template from mac80211 with a PVM shorter
1923		 * than the FW expectes it will overwrite the data after the
1924		 * TIM.
1925		 */
1926		wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
1927			    pad, pvm_len);
1928		memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
1929			&msg_body.beacon[tim_off + 5 + pvm_len],
1930			skb_beacon->len - (tim_off + 5 + pvm_len));
1931		memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
1932		msg_body.beacon[tim_off + 1] += pad;
1933	}
1934
1935	/* TODO need to find out why this is needed? */
1936	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1937		/* mesh beacon don't need this, so push further down */
1938		msg_body.tim_ie_offset = 256;
1939	else
1940		msg_body.tim_ie_offset = tim_off+4;
1941	msg_body.p2p_ie_offset = p2p_off;
1942	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1943
1944	wcn36xx_dbg(WCN36XX_DBG_HAL,
1945		    "hal send beacon beacon_length %d\n",
1946		    msg_body.beacon_length);
1947
1948	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1949	if (ret) {
1950		wcn36xx_err("Sending hal_send_beacon failed\n");
1951		goto out;
1952	}
1953	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1954	if (ret) {
1955		wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
1956		goto out;
1957	}
1958out:
1959	mutex_unlock(&wcn->hal_mutex);
1960	return ret;
1961}
1962
1963int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
1964				      struct ieee80211_vif *vif,
1965				      struct sk_buff *skb)
1966{
1967	struct wcn36xx_hal_send_probe_resp_req_msg msg;
1968	int ret;
1969
1970	mutex_lock(&wcn->hal_mutex);
1971	INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
1972
1973	if (skb->len > BEACON_TEMPLATE_SIZE) {
1974		wcn36xx_warn("probe response template is too big: %d\n",
1975			     skb->len);
1976		ret = -E2BIG;
1977		goto out;
1978	}
1979
1980	msg.probe_resp_template_len = skb->len;
1981	memcpy(&msg.probe_resp_template, skb->data, skb->len);
1982
1983	memcpy(msg.bssid, vif->addr, ETH_ALEN);
1984
1985	PREPARE_HAL_BUF(wcn->hal_buf, msg);
1986
1987	wcn36xx_dbg(WCN36XX_DBG_HAL,
1988		    "hal update probe rsp len %d bssid %pM\n",
1989		    msg.probe_resp_template_len, msg.bssid);
1990
1991	ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1992	if (ret) {
1993		wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1994		goto out;
1995	}
1996	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1997	if (ret) {
1998		wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1999			    ret);
2000		goto out;
2001	}
2002out:
2003	mutex_unlock(&wcn->hal_mutex);
2004	return ret;
2005}
2006
2007int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
2008			   enum ani_ed_type enc_type,
2009			   u8 keyidx,
2010			   u8 keylen,
2011			   u8 *key,
2012			   u8 sta_index)
2013{
2014	struct wcn36xx_hal_set_sta_key_req_msg msg_body;
2015	int ret;
2016
2017	mutex_lock(&wcn->hal_mutex);
2018	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
2019
2020	msg_body.set_sta_key_params.sta_index = sta_index;
2021	msg_body.set_sta_key_params.enc_type = enc_type;
2022
2023	if (enc_type == WCN36XX_HAL_ED_WEP104 ||
2024	    enc_type == WCN36XX_HAL_ED_WEP40) {
2025		/* Use bss key for wep (static) */
2026		msg_body.set_sta_key_params.def_wep_idx = keyidx;
2027		msg_body.set_sta_key_params.wep_type = 0;
2028	} else {
2029		msg_body.set_sta_key_params.key[0].id = keyidx;
2030		msg_body.set_sta_key_params.key[0].unicast = 1;
2031		msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
2032		msg_body.set_sta_key_params.key[0].pae_role = 0;
2033		msg_body.set_sta_key_params.key[0].length = keylen;
2034		memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
2035	}
2036
2037	msg_body.set_sta_key_params.single_tid_rc = 1;
2038
2039	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2040
2041	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2042	if (ret) {
2043		wcn36xx_err("Sending hal_set_stakey failed\n");
2044		goto out;
2045	}
2046	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2047	if (ret) {
2048		wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
2049		goto out;
2050	}
2051out:
2052	mutex_unlock(&wcn->hal_mutex);
2053	return ret;
2054}
2055
2056int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
2057			   enum ani_ed_type enc_type,
2058			   u8 bssidx,
2059			   u8 keyidx,
2060			   u8 keylen,
2061			   u8 *key)
2062{
2063	struct wcn36xx_hal_set_bss_key_req_msg msg_body;
2064	int ret;
2065
2066	mutex_lock(&wcn->hal_mutex);
2067	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
2068	msg_body.bss_idx = bssidx;
2069	msg_body.enc_type = enc_type;
2070	msg_body.num_keys = 1;
2071	msg_body.keys[0].id = keyidx;
2072	msg_body.keys[0].unicast = 0;
2073	msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
2074	msg_body.keys[0].pae_role = 0;
2075	msg_body.keys[0].length = keylen;
2076	memcpy(msg_body.keys[0].key, key, keylen);
2077
2078	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2079
2080	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2081	if (ret) {
2082		wcn36xx_err("Sending hal_set_bsskey failed\n");
2083		goto out;
2084	}
2085	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2086	if (ret) {
2087		wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
2088		goto out;
2089	}
2090out:
2091	mutex_unlock(&wcn->hal_mutex);
2092	return ret;
2093}
2094
2095int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
2096			      enum ani_ed_type enc_type,
2097			      u8 keyidx,
2098			      u8 sta_index)
2099{
2100	struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
2101	int ret;
2102
2103	mutex_lock(&wcn->hal_mutex);
2104	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
2105
2106	msg_body.sta_idx = sta_index;
2107	msg_body.enc_type = enc_type;
2108	msg_body.key_id = keyidx;
2109
2110	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2111
2112	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2113	if (ret) {
2114		wcn36xx_err("Sending hal_remove_stakey failed\n");
2115		goto out;
2116	}
2117	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2118	if (ret) {
2119		wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
2120		goto out;
2121	}
2122out:
2123	mutex_unlock(&wcn->hal_mutex);
2124	return ret;
2125}
2126
2127int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
2128			      enum ani_ed_type enc_type,
2129			      u8 bssidx,
2130			      u8 keyidx)
2131{
2132	struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
2133	int ret;
2134
2135	mutex_lock(&wcn->hal_mutex);
2136	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
2137	msg_body.bss_idx = bssidx;
2138	msg_body.enc_type = enc_type;
2139	msg_body.key_id = keyidx;
2140
2141	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2142
2143	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2144	if (ret) {
2145		wcn36xx_err("Sending hal_remove_bsskey failed\n");
2146		goto out;
2147	}
2148	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2149	if (ret) {
2150		wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
2151		goto out;
2152	}
2153out:
2154	mutex_unlock(&wcn->hal_mutex);
2155	return ret;
2156}
2157
2158int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2159{
2160	struct wcn36xx_hal_enter_bmps_req_msg msg_body;
2161	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2162	int ret;
2163
2164	mutex_lock(&wcn->hal_mutex);
2165	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
2166
2167	msg_body.bss_index = vif_priv->bss_index;
2168	msg_body.tbtt = vif->bss_conf.sync_tsf;
2169	msg_body.dtim_period = vif_priv->dtim_period;
2170
2171	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2172
2173	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2174	if (ret) {
2175		wcn36xx_err("Sending hal_enter_bmps failed\n");
2176		goto out;
2177	}
2178	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2179	if (ret) {
2180		wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
2181		goto out;
2182	}
2183out:
2184	mutex_unlock(&wcn->hal_mutex);
2185	return ret;
2186}
2187
2188int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2189{
2190	struct wcn36xx_hal_exit_bmps_req_msg msg_body;
2191	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2192	int ret;
2193
2194	mutex_lock(&wcn->hal_mutex);
2195	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
2196
2197	msg_body.bss_index = vif_priv->bss_index;
2198	msg_body.send_data_null = 1;
2199
2200	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2201
2202	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2203	if (ret) {
2204		wcn36xx_err("Sending hal_exit_bmps failed\n");
2205		goto out;
2206	}
2207	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2208	if (ret) {
2209		wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
2210		goto out;
2211	}
2212out:
2213	mutex_unlock(&wcn->hal_mutex);
2214	return ret;
2215}
2216
2217int wcn36xx_smd_enter_imps(struct wcn36xx *wcn)
2218{
2219	struct wcn36xx_hal_enter_imps_req_msg msg_body;
2220	int ret;
2221
2222	mutex_lock(&wcn->hal_mutex);
2223	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_IMPS_REQ);
2224
2225	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2226
2227	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2228	if (ret) {
2229		wcn36xx_err("Sending hal_enter_imps failed\n");
2230		goto out;
2231	}
2232	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2233	if (ret) {
2234		wcn36xx_err("hal_enter_imps response failed err=%d\n", ret);
2235		goto out;
2236	}
2237
2238	wcn36xx_dbg(WCN36XX_DBG_HAL, "Entered idle mode\n");
2239out:
2240	mutex_unlock(&wcn->hal_mutex);
2241	return ret;
2242}
2243
2244int wcn36xx_smd_exit_imps(struct wcn36xx *wcn)
2245{
2246	struct wcn36xx_hal_exit_imps_req_msg msg_body;
2247	int ret;
2248
2249	mutex_lock(&wcn->hal_mutex);
2250	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_IMPS_REQ);
2251
2252	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2253
2254	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2255	if (ret) {
2256		wcn36xx_err("Sending hal_exit_imps failed\n");
2257		goto out;
2258	}
2259	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2260	if (ret) {
2261		wcn36xx_err("hal_exit_imps response failed err=%d\n", ret);
2262		goto out;
2263	}
2264	wcn36xx_dbg(WCN36XX_DBG_HAL, "Exited idle mode\n");
2265out:
2266	mutex_unlock(&wcn->hal_mutex);
2267	return ret;
2268}
2269
2270int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
2271{
2272	struct wcn36xx_hal_set_power_params_req_msg msg_body;
2273	int ret;
2274
2275	mutex_lock(&wcn->hal_mutex);
2276	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
2277
2278	/*
2279	 * When host is down ignore every second dtim
2280	 */
2281	if (ignore_dtim) {
2282		msg_body.ignore_dtim = 1;
2283		msg_body.dtim_period = 2;
2284	}
2285	msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
2286
2287	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2288
2289	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2290	if (ret) {
2291		wcn36xx_err("Sending hal_set_power_params failed\n");
2292		goto out;
2293	}
2294
2295out:
2296	mutex_unlock(&wcn->hal_mutex);
2297	return ret;
2298}
2299
2300/* Notice: This function should be called after associated, or else it
2301 * will be invalid
2302 */
2303int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
2304			       struct ieee80211_vif *vif,
2305			       int packet_type)
2306{
2307	struct wcn36xx_hal_keep_alive_req_msg msg_body;
2308	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2309	int ret;
2310
2311	mutex_lock(&wcn->hal_mutex);
2312	INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
2313
2314	if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
2315		msg_body.bss_index = vif_priv->bss_index;
2316		msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
2317		msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
2318	} else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
2319		/* TODO: it also support ARP response type */
2320	} else {
2321		wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
2322		ret = -EINVAL;
2323		goto out;
2324	}
2325
2326	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2327
2328	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2329	if (ret) {
2330		wcn36xx_err("Sending hal_keep_alive failed\n");
2331		goto out;
2332	}
2333	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2334	if (ret) {
2335		wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
2336		goto out;
2337	}
2338out:
2339	mutex_unlock(&wcn->hal_mutex);
2340	return ret;
2341}
2342
2343int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
2344			     u32 arg3, u32 arg4, u32 arg5)
2345{
2346	struct wcn36xx_hal_dump_cmd_req_msg msg_body;
2347	int ret;
2348
2349	mutex_lock(&wcn->hal_mutex);
2350	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
2351
2352	msg_body.arg1 = arg1;
2353	msg_body.arg2 = arg2;
2354	msg_body.arg3 = arg3;
2355	msg_body.arg4 = arg4;
2356	msg_body.arg5 = arg5;
2357
2358	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2359
2360	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2361	if (ret) {
2362		wcn36xx_err("Sending hal_dump_cmd failed\n");
2363		goto out;
2364	}
2365	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2366	if (ret) {
2367		wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
2368		goto out;
2369	}
2370out:
2371	mutex_unlock(&wcn->hal_mutex);
2372	return ret;
2373}
2374
2375int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
2376{
2377	struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
2378	int ret, i;
2379
2380	mutex_lock(&wcn->hal_mutex);
2381	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
2382
2383	wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
2384	if (wcn->rf_id == RF_IRIS_WCN3680) {
2385		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC);
2386		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144);
2387		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps,
2388					       ANTENNA_DIVERSITY_SELECTION);
2389	}
2390
2391	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2392
2393	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2394	if (ret) {
2395		wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2396		goto out;
2397	}
2398	if (wcn->hal_rsp_len != sizeof(*rsp)) {
2399		wcn36xx_err("Invalid hal_feature_caps_exchange response");
2400		goto out;
2401	}
2402
2403	rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
2404
2405	for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
2406		wcn->fw_feat_caps[i] = rsp->feat_caps[i];
2407out:
2408	mutex_unlock(&wcn->hal_mutex);
2409	return ret;
2410}
2411
2412static int wcn36xx_smd_add_ba_session_rsp(void *buf, int len, u8 *session)
2413{
2414	struct wcn36xx_hal_add_ba_session_rsp_msg *rsp;
2415
2416	if (len < sizeof(*rsp))
2417		return -EINVAL;
2418
2419	rsp = buf;
2420	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS)
2421		return rsp->status;
2422
2423	*session = rsp->ba_session_id;
2424
2425	return 0;
2426}
2427
2428int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
2429		struct ieee80211_sta *sta,
2430		u16 tid,
2431		u16 *ssn,
2432		u8 direction,
2433		u8 sta_index)
2434{
2435	struct wcn36xx_hal_add_ba_session_req_msg msg_body;
2436	u8 session_id;
2437	int ret;
2438
2439	mutex_lock(&wcn->hal_mutex);
2440	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
2441
2442	msg_body.sta_index = sta_index;
2443	memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
2444	msg_body.dialog_token = 0x10;
2445	msg_body.tid = tid;
2446
2447	/* Immediate BA because Delayed BA is not supported */
2448	msg_body.policy = 1;
2449	msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
2450	msg_body.timeout = 0;
2451	if (ssn)
2452		msg_body.ssn = *ssn;
2453	msg_body.direction = direction;
2454
2455	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2456
2457	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2458	if (ret) {
2459		wcn36xx_err("Sending hal_add_ba_session failed\n");
2460		goto out;
2461	}
2462	ret = wcn36xx_smd_add_ba_session_rsp(wcn->hal_buf, wcn->hal_rsp_len,
2463					     &session_id);
2464	if (ret) {
2465		wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
2466		ret = -EINVAL;
2467		goto out;
2468	}
2469
2470	ret = session_id;
2471out:
2472	mutex_unlock(&wcn->hal_mutex);
2473	return ret;
2474}
2475
2476int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id)
2477{
2478	struct wcn36xx_hal_add_ba_req_msg msg_body;
2479	int ret;
2480
2481	mutex_lock(&wcn->hal_mutex);
2482	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
2483
2484	msg_body.session_id = session_id;
2485	msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
2486
2487	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2488
2489	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2490	if (ret) {
2491		wcn36xx_err("Sending hal_add_ba failed\n");
2492		goto out;
2493	}
2494	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2495	if (ret) {
2496		wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
2497		goto out;
2498	}
2499out:
2500	mutex_unlock(&wcn->hal_mutex);
2501	return ret;
2502}
2503
2504int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index)
2505{
2506	struct wcn36xx_hal_del_ba_req_msg msg_body;
2507	int ret;
2508
2509	mutex_lock(&wcn->hal_mutex);
2510	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
2511
2512	msg_body.sta_index = sta_index;
2513	msg_body.tid = tid;
2514	msg_body.direction = direction;
2515	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2516
2517	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2518	if (ret) {
2519		wcn36xx_err("Sending hal_del_ba failed\n");
2520		goto out;
2521	}
2522	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2523	if (ret) {
2524		wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
2525		goto out;
2526	}
2527out:
2528	mutex_unlock(&wcn->hal_mutex);
2529	return ret;
2530}
2531
2532int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask,
2533			  struct station_info *sinfo)
2534{
2535	struct wcn36xx_hal_stats_req_msg msg_body;
2536	struct wcn36xx_hal_stats_rsp_msg *rsp;
2537	void *rsp_body;
2538	int ret;
2539
2540	if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) {
2541		wcn36xx_err("stats_mask 0x%x contains unimplemented types\n",
2542			    stats_mask);
2543		return -EINVAL;
2544	}
2545
2546	mutex_lock(&wcn->hal_mutex);
2547	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ);
2548
2549	msg_body.sta_id = sta_index;
2550	msg_body.stats_mask = stats_mask;
2551
2552	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2553
2554	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2555	if (ret) {
2556		wcn36xx_err("sending hal_get_stats failed\n");
2557		goto out;
2558	}
2559
2560	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2561	if (ret) {
2562		wcn36xx_err("hal_get_stats response failed err=%d\n", ret);
2563		goto out;
2564	}
2565
2566	rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf;
2567	rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg));
2568
2569	if (rsp->stats_mask != stats_mask) {
2570		wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n",
2571			    rsp->stats_mask, stats_mask);
2572		goto out;
2573	}
2574
2575	if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) {
2576		struct ani_global_class_a_stats_info *stats_info = rsp_body;
2577
2578		wcn36xx_process_tx_rate(stats_info, &sinfo->txrate);
2579		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
2580		rsp_body += sizeof(struct ani_global_class_a_stats_info);
2581	}
2582out:
2583	mutex_unlock(&wcn->hal_mutex);
2584
2585	return ret;
2586}
2587
2588static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
2589{
2590	struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
2591	struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
2592	int i;
2593
2594	if (len < sizeof(*rsp))
2595		return -EINVAL;
2596
2597	rsp = buf;
2598
2599	if (rsp->candidate_cnt < 1)
2600		return rsp->status ? rsp->status : -EINVAL;
2601
2602	candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp));
2603
2604	for (i = 0; i < STACFG_MAX_TC; i++) {
2605		ba_info[i] = candidate->ba_info[i];
2606	}
2607
2608	return rsp->status;
2609}
2610
2611int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn)
2612{
2613	struct wcn36xx_hal_trigger_ba_req_msg msg_body;
2614	struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
2615	struct add_ba_info ba_info[STACFG_MAX_TC];
2616	int ret;
2617
2618	if (tid >= STACFG_MAX_TC)
2619		return -EINVAL;
2620
2621	mutex_lock(&wcn->hal_mutex);
2622	INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
2623
2624	msg_body.session_id = 0; /* not really used */
2625	msg_body.candidate_cnt = 1;
2626	msg_body.header.len += sizeof(*candidate);
2627	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2628
2629	candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
2630		(wcn->hal_buf + sizeof(msg_body));
2631	candidate->sta_index = sta_index;
2632	candidate->tid_bitmap = 1 << tid;
2633
2634	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2635	if (ret) {
2636		wcn36xx_err("Sending hal_trigger_ba failed\n");
2637		goto out;
2638	}
2639	ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info);
2640	if (ret) {
2641		wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
2642		goto out;
2643	}
2644out:
2645	mutex_unlock(&wcn->hal_mutex);
2646
2647	if (ssn)
2648		*ssn = ba_info[tid].starting_seq_num;
2649
2650	return ret;
2651}
2652
2653static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
2654{
2655	struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
2656
2657	if (len != sizeof(*rsp)) {
2658		wcn36xx_warn("Bad TX complete indication\n");
2659		return -EIO;
2660	}
2661
2662	wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
2663
2664	return 0;
2665}
2666
2667static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len)
2668{
2669	struct wcn36xx_hal_scan_offload_ind *rsp = buf;
2670	struct cfg80211_scan_info scan_info = {};
2671
2672	if (len != sizeof(*rsp)) {
2673		wcn36xx_warn("Corrupted delete scan indication\n");
2674		return -EIO;
2675	}
2676
2677	wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type);
2678
2679	switch (rsp->type) {
2680	case WCN36XX_HAL_SCAN_IND_FAILED:
2681	case WCN36XX_HAL_SCAN_IND_DEQUEUED:
2682		scan_info.aborted = true;
2683		fallthrough;
2684	case WCN36XX_HAL_SCAN_IND_COMPLETED:
2685		mutex_lock(&wcn->scan_lock);
2686		wcn->scan_req = NULL;
2687		if (wcn->scan_aborted)
2688			scan_info.aborted = true;
2689		mutex_unlock(&wcn->scan_lock);
2690		ieee80211_scan_completed(wcn->hw, &scan_info);
2691		break;
2692	case WCN36XX_HAL_SCAN_IND_STARTED:
2693	case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL:
2694	case WCN36XX_HAL_SCAN_IND_PREEMPTED:
2695	case WCN36XX_HAL_SCAN_IND_RESTARTED:
2696		break;
2697	default:
2698		wcn36xx_warn("Unknown scan indication type %x\n", rsp->type);
2699	}
2700
2701	return 0;
2702}
2703
2704static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2705					 void *buf,
2706					 size_t len)
2707{
2708	struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2709	struct ieee80211_vif *vif = NULL;
2710	struct wcn36xx_vif *tmp;
2711
2712	/* Old FW does not have bss index */
2713	if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2714		list_for_each_entry(tmp, &wcn->vif_list, list) {
2715			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2716				    tmp->bss_index);
2717			vif = wcn36xx_priv_to_vif(tmp);
2718			ieee80211_beacon_loss(vif);
2719		}
2720		return 0;
2721	}
2722
2723	if (len != sizeof(*rsp)) {
2724		wcn36xx_warn("Corrupted missed beacon indication\n");
2725		return -EIO;
2726	}
2727
2728	list_for_each_entry(tmp, &wcn->vif_list, list) {
2729		if (tmp->bss_index == rsp->bss_index) {
2730			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2731				    rsp->bss_index);
2732			vif = wcn36xx_priv_to_vif(tmp);
2733			ieee80211_beacon_loss(vif);
2734			return 0;
2735		}
2736	}
2737
2738	wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2739	return -ENOENT;
2740}
2741
2742static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2743					      void *buf,
2744					      size_t len)
2745{
2746	struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2747	struct wcn36xx_vif *vif_priv;
2748	struct ieee80211_vif *vif;
2749	struct ieee80211_bss_conf *bss_conf;
2750	struct ieee80211_sta *sta;
2751	bool found = false;
2752
2753	if (len != sizeof(*rsp)) {
2754		wcn36xx_warn("Corrupted delete sta indication\n");
2755		return -EIO;
2756	}
2757
2758	wcn36xx_dbg(WCN36XX_DBG_HAL,
2759		    "delete station indication %pM index %d reason %d\n",
2760		    rsp->addr2, rsp->sta_id, rsp->reason_code);
2761
2762	list_for_each_entry(vif_priv, &wcn->vif_list, list) {
2763		rcu_read_lock();
2764		vif = wcn36xx_priv_to_vif(vif_priv);
2765
2766		if (vif->type == NL80211_IFTYPE_STATION) {
2767			/* We could call ieee80211_find_sta too, but checking
2768			 * bss_conf is clearer.
2769			 */
2770			bss_conf = &vif->bss_conf;
2771			if (vif_priv->sta_assoc &&
2772			    !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
2773				found = true;
2774				wcn36xx_dbg(WCN36XX_DBG_HAL,
2775					    "connection loss bss_index %d\n",
2776					    vif_priv->bss_index);
2777				ieee80211_connection_loss(vif);
2778			}
2779		} else {
2780			sta = ieee80211_find_sta(vif, rsp->addr2);
2781			if (sta) {
2782				found = true;
2783				ieee80211_report_low_ack(sta, 0);
2784			}
2785		}
2786
2787		rcu_read_unlock();
2788		if (found)
2789			return 0;
2790	}
2791
2792	wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
2793	return -ENOENT;
2794}
2795
2796static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
2797					  void *buf,
2798					  size_t len)
2799{
2800	struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
2801	int i;
2802
2803	if (len < sizeof(*rsp)) {
2804		wcn36xx_warn("Corrupted print reg info indication\n");
2805		return -EIO;
2806	}
2807
2808	wcn36xx_dbg(WCN36XX_DBG_HAL,
2809		    "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2810		    rsp->scenario, rsp->reason);
2811
2812	for (i = 0; i < rsp->count; i++) {
2813		wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
2814			    rsp->regs[i].addr, rsp->regs[i].value);
2815	}
2816
2817	return 0;
2818}
2819
2820int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2821{
2822	struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2823	size_t len;
2824	int ret;
2825
2826	mutex_lock(&wcn->hal_mutex);
2827	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2828
2829	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2830
2831	body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2832	len = msg_body.header.len;
2833
2834	put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2835	body->header.len = len;
2836	body->len = len - sizeof(*body);
2837
2838	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2839	if (ret) {
2840		wcn36xx_err("Sending hal_update_cfg failed\n");
2841		goto out;
2842	}
2843	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2844	if (ret) {
2845		wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2846		goto out;
2847	}
2848out:
2849	mutex_unlock(&wcn->hal_mutex);
2850	return ret;
2851}
2852
2853int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
2854			    struct ieee80211_vif *vif,
2855			    struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
2856{
2857	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2858	struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
2859	int ret;
2860
2861	mutex_lock(&wcn->hal_mutex);
2862
2863	msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
2864		   wcn->hal_buf;
2865	INIT_HAL_MSG(*msg_body, WCN36XX_HAL_8023_MULTICAST_LIST_REQ);
2866
2867	/* An empty list means all mc traffic will be received */
2868	if (fp)
2869		memcpy(&msg_body->mc_addr_list, fp,
2870		       sizeof(msg_body->mc_addr_list));
2871	else
2872		msg_body->mc_addr_list.mc_addr_count = 0;
2873
2874	msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
2875
2876	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
2877	if (ret) {
2878		wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2879		goto out;
2880	}
2881	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2882	if (ret) {
2883		wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
2884		goto out;
2885	}
2886out:
2887	mutex_unlock(&wcn->hal_mutex);
2888	return ret;
2889}
2890
2891int wcn36xx_smd_arp_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2892			    bool enable)
2893{
2894	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2895	struct wcn36xx_hal_host_offload_req_msg msg_body;
2896	int ret;
2897
2898	mutex_lock(&wcn->hal_mutex);
2899
2900	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
2901	msg_body.host_offload_params.offload_type =
2902		WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD;
2903	if (enable) {
2904		msg_body.host_offload_params.enable =
2905			WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
2906		memcpy(&msg_body.host_offload_params.u,
2907		       &vif->cfg.arp_addr_list[0], sizeof(__be32));
2908	}
2909	msg_body.ns_offload_params.bss_index = vif_priv->bss_index;
2910
2911	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2912
2913	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2914	if (ret) {
2915		wcn36xx_err("Sending host_offload_arp failed\n");
2916		goto out;
2917	}
2918	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2919	if (ret) {
2920		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
2921		goto out;
2922	}
2923out:
2924	mutex_unlock(&wcn->hal_mutex);
2925	return ret;
2926}
2927
2928#if IS_ENABLED(CONFIG_IPV6)
2929int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2930				bool enable)
2931{
2932	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2933	struct wcn36xx_hal_host_offload_req_msg msg_body;
2934	struct wcn36xx_hal_ns_offload_params *ns_params;
2935	struct wcn36xx_hal_host_offload_req *ho_params;
2936	int ret;
2937
2938	mutex_lock(&wcn->hal_mutex);
2939
2940	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
2941	ho_params = &msg_body.host_offload_params;
2942	ns_params = &msg_body.ns_offload_params;
2943
2944	ho_params->offload_type = WCN36XX_HAL_IPV6_NS_OFFLOAD;
2945	if (enable) {
2946		ho_params->enable =
2947			WCN36XX_HAL_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
2948		if (vif_priv->num_target_ipv6_addrs) {
2949			memcpy(&ho_params->u,
2950			       &vif_priv->target_ipv6_addrs[0].in6_u,
2951			       sizeof(struct in6_addr));
2952			memcpy(&ns_params->target_ipv6_addr1,
2953			       &vif_priv->target_ipv6_addrs[0].in6_u,
2954			       sizeof(struct in6_addr));
2955			ns_params->target_ipv6_addr1_valid = 1;
2956		}
2957		if (vif_priv->num_target_ipv6_addrs > 1) {
2958			memcpy(&ns_params->target_ipv6_addr2,
2959			       &vif_priv->target_ipv6_addrs[1].in6_u,
2960			       sizeof(struct in6_addr));
2961			ns_params->target_ipv6_addr2_valid = 1;
2962		}
2963	}
2964	memcpy(&ns_params->self_addr, vif->addr, ETH_ALEN);
2965	ns_params->bss_index = vif_priv->bss_index;
2966
2967	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2968
2969	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2970	if (ret) {
2971		wcn36xx_err("Sending host_offload_arp failed\n");
2972		goto out;
2973	}
2974	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2975	if (ret) {
2976		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
2977		goto out;
2978	}
2979out:
2980	mutex_unlock(&wcn->hal_mutex);
2981	return ret;
2982}
2983#else
2984int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2985				bool enable)
2986{
2987	return 0;
2988}
2989#endif
2990
2991int wcn36xx_smd_gtk_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2992			    bool enable)
2993{
2994	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2995	struct wcn36xx_hal_gtk_offload_req_msg msg_body;
2996	int ret;
2997
2998	mutex_lock(&wcn->hal_mutex);
2999
3000	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_REQ);
3001
3002	if (enable) {
3003		memcpy(&msg_body.kek, vif_priv->rekey_data.kek, NL80211_KEK_LEN);
3004		memcpy(&msg_body.kck, vif_priv->rekey_data.kck, NL80211_KCK_LEN);
3005		msg_body.key_replay_counter =
3006			le64_to_cpu(vif_priv->rekey_data.replay_ctr);
3007		msg_body.bss_index = vif_priv->bss_index;
3008	} else {
3009		msg_body.flags = WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE;
3010	}
3011
3012	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3013
3014	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3015	if (ret) {
3016		wcn36xx_err("Sending host_offload_arp failed\n");
3017		goto out;
3018	}
3019	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3020	if (ret) {
3021		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3022		goto out;
3023	}
3024out:
3025	mutex_unlock(&wcn->hal_mutex);
3026	return ret;
3027}
3028
3029static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx *wcn,
3030						struct ieee80211_vif *vif)
3031{
3032	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3033	struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *rsp;
3034	__be64 replay_ctr;
3035
3036	if (wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len))
3037		return -EIO;
3038
3039	rsp = (struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *)wcn->hal_buf;
3040
3041	if (rsp->bss_index != vif_priv->bss_index) {
3042		wcn36xx_err("gtk_offload_info invalid response bss index %d\n",
3043			    rsp->bss_index);
3044		return -ENOENT;
3045	}
3046
3047	if (vif_priv->rekey_data.replay_ctr != cpu_to_le64(rsp->key_replay_counter)) {
3048		replay_ctr = cpu_to_be64(rsp->key_replay_counter);
3049		vif_priv->rekey_data.replay_ctr =
3050			cpu_to_le64(rsp->key_replay_counter);
3051		ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
3052					   (void *)&replay_ctr, GFP_KERNEL);
3053		wcn36xx_dbg(WCN36XX_DBG_HAL,
3054			    "GTK replay counter increment %llu\n",
3055			    rsp->key_replay_counter);
3056	}
3057
3058	wcn36xx_dbg(WCN36XX_DBG_HAL,
3059		    "gtk offload info status %d last_rekey_status %d "
3060		    "replay_counter %llu total_rekey_count %d gtk_rekey_count %d "
3061		    "igtk_rekey_count %d bss_index %d\n",
3062		    rsp->status, rsp->last_rekey_status,
3063		    rsp->key_replay_counter, rsp->total_rekey_count,
3064		    rsp->gtk_rekey_count, rsp->igtk_rekey_count,
3065		    rsp->bss_index);
3066
3067	return 0;
3068}
3069
3070int wcn36xx_smd_gtk_offload_get_info(struct wcn36xx *wcn,
3071				     struct ieee80211_vif *vif)
3072{
3073	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3074	struct wcn36xx_hal_gtk_offload_get_info_req_msg msg_body;
3075	int ret;
3076
3077	mutex_lock(&wcn->hal_mutex);
3078
3079	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ);
3080
3081	msg_body.bss_index = vif_priv->bss_index;
3082
3083	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3084
3085	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3086	if (ret) {
3087		wcn36xx_err("Sending gtk_offload_get_info failed\n");
3088		goto out;
3089	}
3090	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3091	if (ret) {
3092		wcn36xx_err("gtk_offload_get_info failed err=%d\n", ret);
3093		goto out;
3094	}
3095	ret = wcn36xx_smd_gtk_offload_get_info_rsp(wcn, vif);
3096out:
3097	mutex_unlock(&wcn->hal_mutex);
3098	return ret;
3099}
3100
3101int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx *wcn)
3102{
3103	struct wcn36xx_hal_wlan_host_suspend_ind_msg msg_body;
3104	int ret;
3105
3106	mutex_lock(&wcn->hal_mutex);
3107
3108	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_SUSPEND_IND);
3109	msg_body.configured_mcst_bcst_filter_setting = 0;
3110	msg_body.active_session_count = 1;
3111	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3112
3113	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, msg_body.header.len);
3114
3115	mutex_unlock(&wcn->hal_mutex);
3116
3117	return ret;
3118}
3119
3120int wcn36xx_smd_host_resume(struct wcn36xx *wcn)
3121{
3122	struct wcn36xx_hal_wlan_host_resume_req_msg msg_body;
3123	struct wcn36xx_hal_host_resume_rsp_msg *rsp;
3124	int ret;
3125
3126	mutex_lock(&wcn->hal_mutex);
3127
3128	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_RESUME_REQ);
3129	msg_body.configured_mcst_bcst_filter_setting = 0;
3130
3131	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3132
3133	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3134	if (ret) {
3135		wcn36xx_err("Sending wlan_host_resume failed\n");
3136		goto out;
3137	}
3138	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3139	if (ret) {
3140		wcn36xx_err("wlan_host_resume err=%d\n", ret);
3141		goto out;
3142	}
3143
3144	rsp = (struct wcn36xx_hal_host_resume_rsp_msg *)wcn->hal_buf;
3145	if (rsp->status)
3146		wcn36xx_warn("wlan_host_resume status=%d\n", rsp->status);
3147
3148out:
3149	mutex_unlock(&wcn->hal_mutex);
3150
3151	return ret;
3152}
3153
3154#define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \
3155	{					\
3156		.element_id = eid,		\
3157		.check_ie_presence = presence,	\
3158		.offset = offs,			\
3159		.value = val,			\
3160		.bitmask = mask,		\
3161		.ref = ref_val,			\
3162	}
3163
3164static const struct beacon_filter_ie bcn_filter_ies[] = {
3165	BEACON_FILTER(WLAN_EID_DS_PARAMS, 0, 0, 0,
3166		      WCN36XX_FILTER_IE_DS_CHANNEL_MASK, 0),
3167	BEACON_FILTER(WLAN_EID_ERP_INFO, 0, 0, 0,
3168		      WCN36XX_FILTER_IE_ERP_FILTER_MASK, 0),
3169	BEACON_FILTER(WLAN_EID_EDCA_PARAM_SET, 0, 0, 0,
3170		      WCN36XX_FILTER_IE_EDCA_FILTER_MASK, 0),
3171	BEACON_FILTER(WLAN_EID_QOS_CAPA, 0, 0, 0,
3172		      WCN36XX_FILTER_IE_QOS_FILTER_MASK, 0),
3173	BEACON_FILTER(WLAN_EID_CHANNEL_SWITCH, 1, 0, 0,
3174		      WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK, 0),
3175	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 0, 0,
3176		      WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK, 0),
3177	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 2, 0,
3178		      WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK, 0),
3179	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 5, 0,
3180		      WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK, 0),
3181	BEACON_FILTER(WLAN_EID_PWR_CONSTRAINT, 0, 0, 0,
3182		      WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK, 0),
3183	BEACON_FILTER(WLAN_EID_OPMODE_NOTIF, 0, 0, 0,
3184		      WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK, 0),
3185	BEACON_FILTER(WLAN_EID_VHT_OPERATION, 0, 0, 0,
3186		      WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK, 0),
3187	BEACON_FILTER(WLAN_EID_RSN, 1, 0, 0,
3188		      WCN36XX_FILTER_IE_RSN_MASK, 0),
3189	BEACON_FILTER(WLAN_EID_VENDOR_SPECIFIC, 1, 0, 0,
3190		      WCN36XX_FILTER_IE_VENDOR_MASK, 0),
3191};
3192
3193int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn,
3194				  struct ieee80211_vif *vif)
3195{
3196	struct wcn36xx_hal_add_bcn_filter_req_msg msg_body, *body;
3197	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3198	u8 *payload;
3199	size_t payload_size;
3200	int ret;
3201
3202	if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, BCN_FILTER))
3203		return -EOPNOTSUPP;
3204
3205	mutex_lock(&wcn->hal_mutex);
3206	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BCN_FILTER_REQ);
3207
3208	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3209
3210	body = (struct wcn36xx_hal_add_bcn_filter_req_msg *)wcn->hal_buf;
3211	body->capability_info = vif->bss_conf.assoc_capability;
3212	body->capability_mask = WCN36XX_FILTER_CAPABILITY_MASK;
3213	body->beacon_interval = vif->bss_conf.beacon_int;
3214	body->ie_num = ARRAY_SIZE(bcn_filter_ies);
3215	body->bss_index = vif_priv->bss_index;
3216
3217	payload = ((u8 *)body) + body->header.len;
3218	payload_size = sizeof(bcn_filter_ies);
3219	memcpy(payload, &bcn_filter_ies, payload_size);
3220
3221	body->header.len += payload_size;
3222
3223	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
3224	if (ret) {
3225		wcn36xx_err("Sending add bcn_filter failed\n");
3226		goto out;
3227	}
3228
3229	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3230	if (ret) {
3231		wcn36xx_err("add bcn filter response failed err=%d\n", ret);
3232		goto out;
3233	}
3234out:
3235	mutex_unlock(&wcn->hal_mutex);
3236	return ret;
3237}
3238
3239int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
3240			    void *buf, int len, void *priv, u32 addr)
3241{
3242	const struct wcn36xx_hal_msg_header *msg_header = buf;
3243	struct ieee80211_hw *hw = priv;
3244	struct wcn36xx *wcn = hw->priv;
3245	struct wcn36xx_hal_ind_msg *msg_ind;
3246	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
3247
3248	switch (msg_header->msg_type) {
3249	case WCN36XX_HAL_START_RSP:
3250	case WCN36XX_HAL_CONFIG_STA_RSP:
3251	case WCN36XX_HAL_CONFIG_BSS_RSP:
3252	case WCN36XX_HAL_ADD_STA_SELF_RSP:
3253	case WCN36XX_HAL_STOP_RSP:
3254	case WCN36XX_HAL_DEL_STA_SELF_RSP:
3255	case WCN36XX_HAL_DELETE_STA_RSP:
3256	case WCN36XX_HAL_INIT_SCAN_RSP:
3257	case WCN36XX_HAL_START_SCAN_RSP:
3258	case WCN36XX_HAL_END_SCAN_RSP:
3259	case WCN36XX_HAL_FINISH_SCAN_RSP:
3260	case WCN36XX_HAL_DOWNLOAD_NV_RSP:
3261	case WCN36XX_HAL_DELETE_BSS_RSP:
3262	case WCN36XX_HAL_SEND_BEACON_RSP:
3263	case WCN36XX_HAL_SET_LINK_ST_RSP:
3264	case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
3265	case WCN36XX_HAL_SET_BSSKEY_RSP:
3266	case WCN36XX_HAL_SET_STAKEY_RSP:
3267	case WCN36XX_HAL_RMV_STAKEY_RSP:
3268	case WCN36XX_HAL_RMV_BSSKEY_RSP:
3269	case WCN36XX_HAL_ENTER_BMPS_RSP:
3270	case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
3271	case WCN36XX_HAL_EXIT_BMPS_RSP:
3272	case WCN36XX_HAL_KEEP_ALIVE_RSP:
3273	case WCN36XX_HAL_DUMP_COMMAND_RSP:
3274	case WCN36XX_HAL_ADD_BA_SESSION_RSP:
3275	case WCN36XX_HAL_ADD_BA_RSP:
3276	case WCN36XX_HAL_DEL_BA_RSP:
3277	case WCN36XX_HAL_GET_STATS_RSP:
3278	case WCN36XX_HAL_TRIGGER_BA_RSP:
3279	case WCN36XX_HAL_UPDATE_CFG_RSP:
3280	case WCN36XX_HAL_JOIN_RSP:
3281	case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
3282	case WCN36XX_HAL_CH_SWITCH_RSP:
3283	case WCN36XX_HAL_PROCESS_PTT_RSP:
3284	case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
3285	case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
3286	case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP:
3287	case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP:
3288	case WCN36XX_HAL_HOST_OFFLOAD_RSP:
3289	case WCN36XX_HAL_GTK_OFFLOAD_RSP:
3290	case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP:
3291	case WCN36XX_HAL_HOST_RESUME_RSP:
3292	case WCN36XX_HAL_ENTER_IMPS_RSP:
3293	case WCN36XX_HAL_EXIT_IMPS_RSP:
3294	case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP:
3295	case WCN36XX_HAL_ADD_BCN_FILTER_RSP:
3296		memcpy(wcn->hal_buf, buf, len);
3297		wcn->hal_rsp_len = len;
3298		complete(&wcn->hal_rsp_compl);
3299		break;
3300
3301	case WCN36XX_HAL_COEX_IND:
3302	case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3303	case WCN36XX_HAL_DEL_BA_IND:
3304	case WCN36XX_HAL_OTA_TX_COMPL_IND:
3305	case WCN36XX_HAL_MISSED_BEACON_IND:
3306	case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3307	case WCN36XX_HAL_PRINT_REG_INFO_IND:
3308	case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3309		msg_ind = kmalloc(struct_size(msg_ind, msg, len), GFP_ATOMIC);
3310		if (!msg_ind) {
3311			wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
3312				    msg_header->msg_type);
3313			return -ENOMEM;
3314		}
3315
3316		msg_ind->msg_len = len;
3317		memcpy(msg_ind->msg, buf, len);
3318
3319		spin_lock(&wcn->hal_ind_lock);
3320		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
3321		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
3322		spin_unlock(&wcn->hal_ind_lock);
3323		wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
3324		break;
3325	default:
3326		wcn36xx_err("SMD_EVENT (%d) not supported\n",
3327			      msg_header->msg_type);
3328	}
3329
3330	return 0;
3331}
3332
3333static void wcn36xx_ind_smd_work(struct work_struct *work)
3334{
3335	struct wcn36xx *wcn =
3336		container_of(work, struct wcn36xx, hal_ind_work);
3337
3338	for (;;) {
3339		struct wcn36xx_hal_msg_header *msg_header;
3340		struct wcn36xx_hal_ind_msg *hal_ind_msg;
3341		unsigned long flags;
3342
3343		spin_lock_irqsave(&wcn->hal_ind_lock, flags);
3344
3345		if (list_empty(&wcn->hal_ind_queue)) {
3346			spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3347			return;
3348		}
3349
3350		hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
3351					       struct wcn36xx_hal_ind_msg,
3352					       list);
3353		list_del(&hal_ind_msg->list);
3354		spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3355
3356		msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
3357
3358		switch (msg_header->msg_type) {
3359		case WCN36XX_HAL_COEX_IND:
3360		case WCN36XX_HAL_DEL_BA_IND:
3361		case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3362			break;
3363		case WCN36XX_HAL_OTA_TX_COMPL_IND:
3364			wcn36xx_smd_tx_compl_ind(wcn,
3365						 hal_ind_msg->msg,
3366						 hal_ind_msg->msg_len);
3367			break;
3368		case WCN36XX_HAL_MISSED_BEACON_IND:
3369			wcn36xx_smd_missed_beacon_ind(wcn,
3370						      hal_ind_msg->msg,
3371						      hal_ind_msg->msg_len);
3372			break;
3373		case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3374			wcn36xx_smd_delete_sta_context_ind(wcn,
3375							   hal_ind_msg->msg,
3376							   hal_ind_msg->msg_len);
3377			break;
3378		case WCN36XX_HAL_PRINT_REG_INFO_IND:
3379			wcn36xx_smd_print_reg_info_ind(wcn,
3380						       hal_ind_msg->msg,
3381						       hal_ind_msg->msg_len);
3382			break;
3383		case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3384			wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
3385						hal_ind_msg->msg_len);
3386			break;
3387		default:
3388			wcn36xx_err("SMD_EVENT (%d) not supported\n",
3389				    msg_header->msg_type);
3390		}
3391
3392		kfree(hal_ind_msg);
3393	}
3394}
3395
3396int wcn36xx_smd_open(struct wcn36xx *wcn)
3397{
3398	wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
3399	if (!wcn->hal_ind_wq)
3400		return -ENOMEM;
3401
3402	INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
3403	INIT_LIST_HEAD(&wcn->hal_ind_queue);
3404	spin_lock_init(&wcn->hal_ind_lock);
3405
3406	return 0;
3407}
3408
3409void wcn36xx_smd_close(struct wcn36xx *wcn)
3410{
3411	struct wcn36xx_hal_ind_msg *msg, *tmp;
3412
3413	cancel_work_sync(&wcn->hal_ind_work);
3414	destroy_workqueue(wcn->hal_ind_wq);
3415
3416	list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list)
3417		kfree(msg);
3418}
~/ Read-only file preview.