cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

smd.c (99799B)


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