Linux Audio

Check our new training course

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