Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
0011  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
0013  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0014  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018 
0019 #include <linux/bitfield.h>
0020 #include <linux/etherdevice.h>
0021 #include <linux/firmware.h>
0022 #include <linux/bitops.h>
0023 #include <linux/rpmsg.h>
0024 #include "smd.h"
0025 #include "firmware.h"
0026 
0027 struct wcn36xx_cfg_val {
0028     u32 cfg_id;
0029     u32 value;
0030 };
0031 
0032 #define WCN36XX_CFG_VAL(id, val) \
0033 { \
0034     .cfg_id = WCN36XX_HAL_CFG_ ## id, \
0035     .value = val \
0036 }
0037 
0038 static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
0039     WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
0040     WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
0041     WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
0042     WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
0043     WCN36XX_CFG_VAL(CAL_PERIOD, 5),
0044     WCN36XX_CFG_VAL(CAL_CONTROL, 1),
0045     WCN36XX_CFG_VAL(PROXIMITY, 0),
0046     WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
0047     WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
0048     WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
0049     WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
0050     WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
0051     WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
0052     WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
0053     WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
0054     WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
0055     WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
0056     WCN36XX_CFG_VAL(FIXED_RATE, 0),
0057     WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
0058     WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
0059     WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
0060     WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
0061     WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
0062     WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
0063     WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
0064     WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
0065     WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
0066     WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
0067     WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
0068     WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
0069     WCN36XX_CFG_VAL(STATS_PERIOD, 10),
0070     WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
0071     WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
0072     WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
0073     WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
0074     WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
0075     WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
0076     WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
0077     WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
0078     WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
0079     WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
0080     WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
0081     WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
0082     WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */
0083     WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
0084 };
0085 
0086 static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
0087     WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
0088     WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
0089     WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
0090     WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
0091     WCN36XX_CFG_VAL(CAL_PERIOD, 5),
0092     WCN36XX_CFG_VAL(CAL_CONTROL, 1),
0093     WCN36XX_CFG_VAL(PROXIMITY, 0),
0094     WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
0095     WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 4096),
0096     WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
0097     WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
0098     WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
0099     WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
0100     WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
0101     WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
0102     WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
0103     WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
0104     WCN36XX_CFG_VAL(FIXED_RATE, 0),
0105     WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
0106     WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
0107     WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
0108     WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
0109     WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
0110     WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
0111     WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 1),
0112     WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
0113     WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
0114     WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
0115     WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
0116     WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
0117     WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
0118     WCN36XX_CFG_VAL(STATS_PERIOD, 10),
0119     WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
0120     WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
0121     WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
0122     WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
0123     WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
0124     WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
0125     WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
0126     WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
0127     WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
0128     WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
0129     WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
0130     WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
0131     WCN36XX_CFG_VAL(TDLS_PUAPSD_MASK, 0),
0132     WCN36XX_CFG_VAL(TDLS_PUAPSD_BUFFER_STA_CAPABLE, 1),
0133     WCN36XX_CFG_VAL(TDLS_PUAPSD_INACTIVITY_TIME, 0),
0134     WCN36XX_CFG_VAL(TDLS_PUAPSD_RX_FRAME_THRESHOLD, 10),
0135     WCN36XX_CFG_VAL(TDLS_OFF_CHANNEL_CAPABLE, 1),
0136     WCN36XX_CFG_VAL(ENABLE_ADAPTIVE_RX_DRAIN, 1),
0137     WCN36XX_CFG_VAL(FLEXCONNECT_POWER_FACTOR, 0),
0138     WCN36XX_CFG_VAL(ANTENNA_DIVERSITY, 3),
0139     WCN36XX_CFG_VAL(ATH_DISABLE, 0),
0140     WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 60000),
0141     WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 90000),
0142     WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN, 30000),
0143     WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN, 30000),
0144     WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL, 50),
0145     WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD, -60),
0146     WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD, 3),
0147     WCN36XX_CFG_VAL(BTC_CTS2S_ON_STA_DURING_SCO, 0),
0148     WCN36XX_CFG_VAL(RA_FILTER_ENABLE, 0),
0149     WCN36XX_CFG_VAL(RA_RATE_LIMIT_INTERVAL, 60),
0150     WCN36XX_CFG_VAL(BTC_FATAL_HID_NSNIFF_BLK, 2),
0151     WCN36XX_CFG_VAL(BTC_CRITICAL_HID_NSNIFF_BLK, 1),
0152     WCN36XX_CFG_VAL(BTC_DYN_A2DP_TX_QUEUE_THOLD, 0),
0153     WCN36XX_CFG_VAL(BTC_DYN_OPP_TX_QUEUE_THOLD, 1),
0154     WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_SP, 10),
0155     WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT, 50),
0156     WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT, 50),
0157     WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW, 500),
0158     WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW, 500),
0159     WCN36XX_CFG_VAL(MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE, 0),
0160     WCN36XX_CFG_VAL(MAX_UAPSD_INACTIVITY_INTERVALS, 10),
0161     WCN36XX_CFG_VAL(ENABLE_DYNAMIC_WMMPS, 1),
0162     WCN36XX_CFG_VAL(BURST_MODE_BE_TXOP_VALUE, 0),
0163     WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 136),
0164     WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1),
0165     WCN36XX_CFG_VAL(ENABLE_RTSCTS_HTVHT, 0),
0166     WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000),
0167     WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000),
0168     WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
0169     WCN36XX_CFG_VAL(TOGGLE_ARP_BDRATES, 0),
0170     WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT, 0),
0171     WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE, 0),
0172     WCN36XX_CFG_VAL(BAR_WAKEUP_HOST_DISABLE, 0),
0173     WCN36XX_CFG_VAL(SAR_BOFFSET_CORRECTION_ENABLE, 0),
0174     WCN36XX_CFG_VAL(BTC_DISABLE_WLAN_LINK_CRITICAL, 5),
0175     WCN36XX_CFG_VAL(DISABLE_SCAN_DURING_SCO, 2),
0176     WCN36XX_CFG_VAL(CONS_BCNMISS_COUNT, 0),
0177     WCN36XX_CFG_VAL(UNITS_OF_BCN_WAIT_TIME, 0),
0178     WCN36XX_CFG_VAL(TRIGGER_NULLFRAME_BEFORE_HB, 0),
0179     WCN36XX_CFG_VAL(ENABLE_POWERSAVE_OFFLOAD, 0),
0180 };
0181 
0182 static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
0183 {
0184     struct wcn36xx_hal_cfg *entry;
0185     u32 *val;
0186 
0187     if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
0188         wcn36xx_err("Not enough room for TLV entry\n");
0189         return -ENOMEM;
0190     }
0191 
0192     entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
0193     entry->id = id;
0194     entry->len = sizeof(u32);
0195     entry->pad_bytes = 0;
0196     entry->reserve = 0;
0197 
0198     val = (u32 *) (entry + 1);
0199     *val = value;
0200 
0201     *len += sizeof(*entry) + sizeof(u32);
0202 
0203     return 0;
0204 }
0205 
0206 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
0207         struct ieee80211_sta *sta,
0208         struct wcn36xx_hal_config_bss_params *bss_params)
0209 {
0210     if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn))
0211         bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
0212     else if (sta && sta->deflink.ht_cap.ht_supported)
0213         bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
0214     else if (sta && (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0x7f))
0215         bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
0216     else
0217         bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
0218 }
0219 
0220 static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
0221 {
0222     return caps & flag ? 1 : 0;
0223 }
0224 
0225 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
0226         struct ieee80211_sta *sta,
0227         struct wcn36xx_hal_config_bss_params *bss_params)
0228 {
0229     if (sta && sta->deflink.ht_cap.ht_supported) {
0230         unsigned long caps = sta->deflink.ht_cap.cap;
0231 
0232         bss_params->ht = sta->deflink.ht_cap.ht_supported;
0233         bss_params->tx_channel_width_set = is_cap_supported(caps,
0234             IEEE80211_HT_CAP_SUP_WIDTH_20_40);
0235         bss_params->lsig_tx_op_protection_full_support =
0236             is_cap_supported(caps,
0237                      IEEE80211_HT_CAP_LSIG_TXOP_PROT);
0238 
0239         bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
0240         bss_params->lln_non_gf_coexist =
0241             !!(vif->bss_conf.ht_operation_mode &
0242                IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
0243         /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
0244         bss_params->dual_cts_protection = 0;
0245         /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
0246         bss_params->ht20_coexist = 0;
0247     }
0248 }
0249 
0250 static void
0251 wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif *vif,
0252                    struct ieee80211_sta *sta,
0253                    struct wcn36xx_hal_config_bss_params_v1 *bss)
0254 {
0255     if (sta && sta->deflink.vht_cap.vht_supported)
0256         bss->vht_capable = 1;
0257 }
0258 
0259 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
0260         struct wcn36xx_hal_config_sta_params *sta_params)
0261 {
0262     if (sta->deflink.ht_cap.ht_supported) {
0263         unsigned long caps = sta->deflink.ht_cap.cap;
0264 
0265         sta_params->ht_capable = sta->deflink.ht_cap.ht_supported;
0266         sta_params->tx_channel_width_set = is_cap_supported(caps,
0267             IEEE80211_HT_CAP_SUP_WIDTH_20_40);
0268         sta_params->lsig_txop_protection = is_cap_supported(caps,
0269             IEEE80211_HT_CAP_LSIG_TXOP_PROT);
0270 
0271         sta_params->max_ampdu_size = sta->deflink.ht_cap.ampdu_factor;
0272         sta_params->max_ampdu_density = sta->deflink.ht_cap.ampdu_density;
0273         /* max_amsdu_size: 1 : 3839 bytes, 0 : 7935 bytes (max) */
0274         sta_params->max_amsdu_size = !is_cap_supported(caps,
0275             IEEE80211_HT_CAP_MAX_AMSDU);
0276         sta_params->sgi_20Mhz = is_cap_supported(caps,
0277             IEEE80211_HT_CAP_SGI_20);
0278         sta_params->sgi_40mhz = is_cap_supported(caps,
0279             IEEE80211_HT_CAP_SGI_40);
0280         sta_params->green_field_capable = is_cap_supported(caps,
0281             IEEE80211_HT_CAP_GRN_FLD);
0282         sta_params->delayed_ba_support = is_cap_supported(caps,
0283             IEEE80211_HT_CAP_DELAY_BA);
0284         sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
0285             IEEE80211_HT_CAP_DSSSCCK40);
0286     }
0287 }
0288 
0289 static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn,
0290         struct ieee80211_sta *sta,
0291         struct wcn36xx_hal_config_sta_params_v1 *sta_params)
0292 {
0293     if (sta->deflink.vht_cap.vht_supported) {
0294         unsigned long caps = sta->deflink.vht_cap.cap;
0295 
0296         sta_params->vht_capable = sta->deflink.vht_cap.vht_supported;
0297         sta_params->vht_ldpc_enabled =
0298             is_cap_supported(caps, IEEE80211_VHT_CAP_RXLDPC);
0299         if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, MU_MIMO)) {
0300             sta_params->vht_tx_mu_beamformee_capable =
0301                 is_cap_supported(caps, IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
0302             if (sta_params->vht_tx_mu_beamformee_capable)
0303                    sta_params->vht_tx_bf_enabled = 1;
0304         } else {
0305             sta_params->vht_tx_mu_beamformee_capable = 0;
0306         }
0307         sta_params->vht_tx_channel_width_set = 0;
0308     }
0309 }
0310 
0311 static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta *sta,
0312         struct wcn36xx_hal_config_sta_params_v1 *sta_params)
0313 {
0314     if (sta->deflink.ht_cap.ht_supported) {
0315         sta_params->ht_ldpc_enabled =
0316             is_cap_supported(sta->deflink.ht_cap.cap,
0317                      IEEE80211_HT_CAP_LDPC_CODING);
0318     }
0319 }
0320 
0321 static void wcn36xx_smd_set_sta_default_ht_params(
0322         struct wcn36xx_hal_config_sta_params *sta_params)
0323 {
0324     sta_params->ht_capable = 1;
0325     sta_params->tx_channel_width_set = 1;
0326     sta_params->lsig_txop_protection = 1;
0327     sta_params->max_ampdu_size = 3;
0328     sta_params->max_ampdu_density = 5;
0329     sta_params->max_amsdu_size = 0;
0330     sta_params->sgi_20Mhz = 1;
0331     sta_params->sgi_40mhz = 1;
0332     sta_params->green_field_capable = 1;
0333     sta_params->delayed_ba_support = 0;
0334     sta_params->dsss_cck_mode_40mhz = 1;
0335 }
0336 
0337 static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx *wcn,
0338         struct wcn36xx_hal_config_sta_params_v1 *sta_params)
0339 {
0340     if (wcn->rf_id == RF_IRIS_WCN3680) {
0341         sta_params->vht_capable = 1;
0342         sta_params->vht_tx_mu_beamformee_capable = 1;
0343     } else {
0344         sta_params->vht_capable = 0;
0345         sta_params->vht_tx_mu_beamformee_capable = 0;
0346     }
0347 
0348     sta_params->vht_ldpc_enabled = 0;
0349     sta_params->vht_tx_channel_width_set = 0;
0350     sta_params->vht_tx_bf_enabled = 0;
0351 }
0352 
0353 static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx *wcn,
0354         struct wcn36xx_hal_config_sta_params_v1 *sta_params)
0355 {
0356     if (wcn->rf_id == RF_IRIS_WCN3680)
0357         sta_params->ht_ldpc_enabled = 1;
0358     else
0359         sta_params->ht_ldpc_enabled = 0;
0360 }
0361 
0362 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
0363         struct ieee80211_vif *vif,
0364         struct ieee80211_sta *sta,
0365         struct wcn36xx_hal_config_sta_params *sta_params)
0366 {
0367     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
0368     struct wcn36xx_sta *sta_priv = NULL;
0369     if (vif->type == NL80211_IFTYPE_ADHOC ||
0370         vif->type == NL80211_IFTYPE_AP ||
0371         vif->type == NL80211_IFTYPE_MESH_POINT) {
0372         sta_params->type = 1;
0373         sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
0374     } else {
0375         sta_params->type = 0;
0376         sta_params->sta_index = vif_priv->self_sta_index;
0377     }
0378 
0379     sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
0380 
0381     /*
0382      * In STA mode ieee80211_sta contains bssid and ieee80211_vif
0383      * contains our mac address. In  AP mode we are bssid so vif
0384      * contains bssid and ieee80211_sta contains mac.
0385      */
0386     if (NL80211_IFTYPE_STATION == vif->type)
0387         memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
0388     else
0389         memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
0390 
0391     sta_params->encrypt_type = vif_priv->encrypt_type;
0392     sta_params->short_preamble_supported = true;
0393 
0394     sta_params->rifs_mode = 0;
0395     sta_params->rmf = 0;
0396     sta_params->action = 0;
0397     sta_params->uapsd = 0;
0398     sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
0399     sta_params->max_ampdu_duration = 0;
0400     sta_params->bssid_index = vif_priv->bss_index;
0401     sta_params->p2p = 0;
0402 
0403     if (sta) {
0404         sta_priv = wcn36xx_sta_to_priv(sta);
0405         if (NL80211_IFTYPE_STATION == vif->type)
0406             memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
0407         else
0408             memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
0409         sta_params->wmm_enabled = sta->wme;
0410         sta_params->max_sp_len = sta->max_sp;
0411         sta_params->aid = sta_priv->aid;
0412         wcn36xx_smd_set_sta_ht_params(sta, sta_params);
0413         memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
0414             sizeof(struct wcn36xx_hal_supported_rates));
0415     } else {
0416         wcn36xx_set_default_rates((struct wcn36xx_hal_supported_rates *)
0417                       &sta_params->supported_rates);
0418         wcn36xx_smd_set_sta_default_ht_params(sta_params);
0419     }
0420 }
0421 
0422 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
0423 {
0424     int ret;
0425     unsigned long start;
0426     struct wcn36xx_hal_msg_header *hdr =
0427         (struct wcn36xx_hal_msg_header *)wcn->hal_buf;
0428     u16 req_type = hdr->msg_type;
0429 
0430     wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
0431 
0432     init_completion(&wcn->hal_rsp_compl);
0433     start = jiffies;
0434     ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len);
0435     if (ret) {
0436         wcn36xx_err("HAL TX failed for req %d\n", req_type);
0437         goto out;
0438     }
0439     if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
0440         msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
0441         wcn36xx_err("Timeout! No SMD response to req %d in %dms\n",
0442                 req_type, HAL_MSG_TIMEOUT);
0443         ret = -ETIME;
0444         goto out;
0445     }
0446     wcn36xx_dbg(WCN36XX_DBG_SMD,
0447             "SMD command (req %d, rsp %d) completed in %dms\n",
0448             req_type, hdr->msg_type,
0449             jiffies_to_msecs(jiffies - start));
0450 out:
0451     return ret;
0452 }
0453 
0454 #define __INIT_HAL_MSG(msg_body, type, version) \
0455     do {                                \
0456         memset(&(msg_body), 0, sizeof(msg_body));       \
0457         (msg_body).header.msg_type = type;          \
0458         (msg_body).header.msg_version = version;        \
0459         (msg_body).header.len = sizeof(msg_body);       \
0460     } while (0)                         \
0461 
0462 #define INIT_HAL_MSG(msg_body, type)    \
0463     __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0)
0464 
0465 #define INIT_HAL_MSG_V1(msg_body, type) \
0466     __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1)
0467 
0468 #define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
0469     do { \
0470         memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
0471         p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \
0472         p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
0473         p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \
0474     } while (0)
0475 
0476 #define PREPARE_HAL_BUF(send_buf, msg_body) \
0477     do {                            \
0478         memset(send_buf, 0, msg_body.header.len);   \
0479         memcpy(send_buf, &msg_body, sizeof(msg_body));  \
0480     } while (0)                     \
0481 
0482 #define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
0483     do {                            \
0484         memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
0485     } while (0)
0486 
0487 static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
0488 {
0489     struct wcn36xx_fw_msg_status_rsp *rsp;
0490 
0491     if (len < sizeof(struct wcn36xx_hal_msg_header) +
0492         sizeof(struct wcn36xx_fw_msg_status_rsp))
0493         return -EIO;
0494 
0495     rsp = (struct wcn36xx_fw_msg_status_rsp *)
0496         (buf + sizeof(struct wcn36xx_hal_msg_header));
0497 
0498     if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
0499         return rsp->status;
0500 
0501     return 0;
0502 }
0503 
0504 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
0505 {
0506     struct nv_data *nv_d;
0507     struct wcn36xx_hal_nv_img_download_req_msg msg_body;
0508     int fw_bytes_left;
0509     int ret;
0510     u16 fm_offset = 0;
0511 
0512     if (!wcn->nv) {
0513         ret = request_firmware(&wcn->nv, wcn->nv_file, wcn->dev);
0514         if (ret) {
0515             wcn36xx_err("Failed to load nv file %s: %d\n",
0516                     wcn->nv_file, ret);
0517             goto out;
0518         }
0519     }
0520 
0521     nv_d = (struct nv_data *)wcn->nv->data;
0522     INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
0523 
0524     msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
0525 
0526     msg_body.frag_number = 0;
0527     /* hal_buf must be protected with  mutex */
0528     mutex_lock(&wcn->hal_mutex);
0529 
0530     do {
0531         fw_bytes_left = wcn->nv->size - fm_offset - 4;
0532         if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
0533             msg_body.last_fragment = 0;
0534             msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
0535         } else {
0536             msg_body.last_fragment = 1;
0537             msg_body.nv_img_buffer_size = fw_bytes_left;
0538 
0539             /* Do not forget update general message len */
0540             msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
0541 
0542         }
0543 
0544         /* Add load NV request message header */
0545         memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body));
0546 
0547         /* Add NV body itself */
0548         memcpy(wcn->hal_buf + sizeof(msg_body),
0549                &nv_d->table + fm_offset,
0550                msg_body.nv_img_buffer_size);
0551 
0552         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
0553         if (ret)
0554             goto out_unlock;
0555         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
0556                            wcn->hal_rsp_len);
0557         if (ret) {
0558             wcn36xx_err("hal_load_nv response failed err=%d\n",
0559                     ret);
0560             goto out_unlock;
0561         }
0562         msg_body.frag_number++;
0563         fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
0564 
0565     } while (msg_body.last_fragment != 1);
0566 
0567 out_unlock:
0568     mutex_unlock(&wcn->hal_mutex);
0569 out:    return ret;
0570 }
0571 
0572 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
0573 {
0574     struct wcn36xx_hal_mac_start_rsp_msg *rsp;
0575 
0576     if (len < sizeof(*rsp))
0577         return -EIO;
0578 
0579     rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf;
0580 
0581     if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
0582         return -EIO;
0583 
0584     memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
0585            WCN36XX_HAL_VERSION_LENGTH);
0586     memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
0587            WCN36XX_HAL_VERSION_LENGTH);
0588 
0589     /* null terminate the strings, just in case */
0590     wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
0591     wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
0592 
0593     wcn->fw_revision = rsp->start_rsp_params.version.revision;
0594     wcn->fw_version = rsp->start_rsp_params.version.version;
0595     wcn->fw_minor = rsp->start_rsp_params.version.minor;
0596     wcn->fw_major = rsp->start_rsp_params.version.major;
0597 
0598     if (wcn->first_boot) {
0599         wcn->first_boot = false;
0600         wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
0601                  wcn->wlan_version, wcn->crm_version);
0602 
0603         wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
0604                  wcn->fw_major, wcn->fw_minor,
0605                  wcn->fw_version, wcn->fw_revision,
0606                  rsp->start_rsp_params.stations,
0607                  rsp->start_rsp_params.bssids);
0608     }
0609     return 0;
0610 }
0611 
0612 int wcn36xx_smd_start(struct wcn36xx *wcn)
0613 {
0614     struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
0615     int ret;
0616     int i;
0617     size_t len;
0618     int cfg_elements;
0619     static struct wcn36xx_cfg_val *cfg_vals;
0620 
0621     mutex_lock(&wcn->hal_mutex);
0622     INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
0623 
0624     msg_body.params.type = DRIVER_TYPE_PRODUCTION;
0625     msg_body.params.len = 0;
0626 
0627     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
0628 
0629     body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
0630     len = body->header.len;
0631 
0632     if (wcn->rf_id == RF_IRIS_WCN3680) {
0633         cfg_vals = wcn3680_cfg_vals;
0634         cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals);
0635     } else {
0636         cfg_vals = wcn36xx_cfg_vals;
0637         cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals);
0638     }
0639 
0640     for (i = 0; i < cfg_elements; i++) {
0641         ret = put_cfg_tlv_u32(wcn, &len, cfg_vals[i].cfg_id,
0642                       cfg_vals[i].value);
0643         if (ret)
0644             goto out;
0645     }
0646     body->header.len = len;
0647     body->params.len = len - sizeof(*body);
0648 
0649     wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
0650             msg_body.params.type);
0651 
0652     ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
0653     if (ret) {
0654         wcn36xx_err("Sending hal_start failed\n");
0655         goto out;
0656     }
0657 
0658     ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
0659     if (ret) {
0660         wcn36xx_err("hal_start response failed err=%d\n", ret);
0661         goto out;
0662     }
0663 
0664 out:
0665     mutex_unlock(&wcn->hal_mutex);
0666     return ret;
0667 }
0668 
0669 int wcn36xx_smd_stop(struct wcn36xx *wcn)
0670 {
0671     struct wcn36xx_hal_mac_stop_req_msg msg_body;
0672     int ret;
0673 
0674     mutex_lock(&wcn->hal_mutex);
0675     INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
0676 
0677     msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
0678 
0679     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
0680 
0681     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
0682     if (ret) {
0683         wcn36xx_err("Sending hal_stop failed\n");
0684         goto out;
0685     }
0686     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
0687     if (ret) {
0688         wcn36xx_err("hal_stop response failed err=%d\n", ret);
0689         goto out;
0690     }
0691 out:
0692     mutex_unlock(&wcn->hal_mutex);
0693     return ret;
0694 }
0695 
0696 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode,
0697               struct ieee80211_vif *vif)
0698 {
0699     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
0700     struct wcn36xx_hal_init_scan_req_msg msg_body;
0701     int ret;
0702 
0703     mutex_lock(&wcn->hal_mutex);
0704     INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
0705 
0706     msg_body.mode = mode;
0707     if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
0708         /* Notify BSSID with null DATA packet */
0709         msg_body.frame_type = 2;
0710         msg_body.notify = 1;
0711         msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
0712         msg_body.scan_entry.active_bss_count = 1;
0713     }
0714 
0715     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
0716 
0717     wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
0718 
0719     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
0720     if (ret) {
0721         wcn36xx_err("Sending hal_init_scan failed\n");
0722         goto out;
0723     }
0724     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
0725     if (ret) {
0726         wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
0727         goto out;
0728     }
0729     wcn->sw_scan_init = true;
0730 out:
0731     mutex_unlock(&wcn->hal_mutex);
0732     return ret;
0733 }
0734 
0735 int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
0736 {
0737     struct wcn36xx_hal_start_scan_req_msg msg_body;
0738     int ret;
0739 
0740     mutex_lock(&wcn->hal_mutex);
0741     INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
0742 
0743     msg_body.scan_channel = scan_channel;
0744 
0745     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
0746 
0747     wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
0748             msg_body.scan_channel);
0749 
0750     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
0751     if (ret) {
0752         wcn36xx_err("Sending hal_start_scan failed\n");
0753         goto out;
0754     }
0755     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
0756     if (ret) {
0757         wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
0758         goto out;
0759     }
0760     wcn->sw_scan_channel = scan_channel;
0761 out:
0762     mutex_unlock(&wcn->hal_mutex);
0763     return ret;
0764 }
0765 
0766 int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
0767 {
0768     struct wcn36xx_hal_end_scan_req_msg msg_body;
0769     int ret;
0770 
0771     mutex_lock(&wcn->hal_mutex);
0772     INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
0773 
0774     msg_body.scan_channel = scan_channel;
0775 
0776     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
0777 
0778     wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
0779             msg_body.scan_channel);
0780 
0781     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
0782     if (ret) {
0783         wcn36xx_err("Sending hal_end_scan failed\n");
0784         goto out;
0785     }
0786     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
0787     if (ret) {
0788         wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
0789         goto out;
0790     }
0791     wcn->sw_scan_channel = 0;
0792 out:
0793     mutex_unlock(&wcn->hal_mutex);
0794     return ret;
0795 }
0796 
0797 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
0798                 enum wcn36xx_hal_sys_mode mode,
0799                 struct ieee80211_vif *vif)
0800 {
0801     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
0802     struct wcn36xx_hal_finish_scan_req_msg msg_body;
0803     int ret;
0804 
0805     mutex_lock(&wcn->hal_mutex);
0806     INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
0807 
0808     msg_body.mode = mode;
0809     msg_body.oper_channel = WCN36XX_HW_CHANNEL(wcn);
0810     if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
0811         /* Notify BSSID with null data packet */
0812         msg_body.notify = 1;
0813         msg_body.frame_type = 2;
0814         msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
0815         msg_body.scan_entry.active_bss_count = 1;
0816     }
0817 
0818     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
0819 
0820     wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
0821             msg_body.mode);
0822 
0823     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
0824     if (ret) {
0825         wcn36xx_err("Sending hal_finish_scan failed\n");
0826         goto out;
0827     }
0828     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
0829     if (ret) {
0830         wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
0831         goto out;
0832     }
0833     wcn->sw_scan_init = false;
0834 out:
0835     mutex_unlock(&wcn->hal_mutex);
0836     return ret;
0837 }
0838 
0839 int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
0840                   struct cfg80211_scan_request *req)
0841 {
0842     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
0843     struct wcn36xx_hal_start_scan_offload_req_msg *msg_body;
0844     int ret, i;
0845 
0846     if (req->ie_len > WCN36XX_MAX_SCAN_IE_LEN)
0847         return -EINVAL;
0848 
0849     mutex_lock(&wcn->hal_mutex);
0850     msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
0851     if (!msg_body) {
0852         ret = -ENOMEM;
0853         goto out;
0854     }
0855 
0856     INIT_HAL_MSG((*msg_body), WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
0857 
0858     msg_body->scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
0859     msg_body->min_ch_time = 30;
0860     msg_body->max_ch_time = 100;
0861     msg_body->scan_hidden = 1;
0862     memcpy(msg_body->mac, vif->addr, ETH_ALEN);
0863     msg_body->bss_type = vif_priv->bss_type;
0864     msg_body->p2p_search = vif->p2p;
0865 
0866     msg_body->num_ssid = min_t(u8, req->n_ssids, ARRAY_SIZE(msg_body->ssids));
0867     for (i = 0; i < msg_body->num_ssid; i++) {
0868         msg_body->ssids[i].length = min_t(u8, req->ssids[i].ssid_len,
0869                         sizeof(msg_body->ssids[i].ssid));
0870         memcpy(msg_body->ssids[i].ssid, req->ssids[i].ssid,
0871                msg_body->ssids[i].length);
0872     }
0873 
0874     msg_body->num_channel = min_t(u8, req->n_channels,
0875                      sizeof(msg_body->channels));
0876     for (i = 0; i < msg_body->num_channel; i++) {
0877         msg_body->channels[i] =
0878             HW_VALUE_CHANNEL(req->channels[i]->hw_value);
0879     }
0880 
0881     msg_body->header.len -= WCN36XX_MAX_SCAN_IE_LEN;
0882 
0883     if (req->ie_len > 0) {
0884         msg_body->ie_len = req->ie_len;
0885         msg_body->header.len += req->ie_len;
0886         memcpy(msg_body->ie, req->ie, req->ie_len);
0887     }
0888 
0889     PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
0890 
0891     wcn36xx_dbg(WCN36XX_DBG_HAL,
0892             "hal start hw-scan (channels: %u; ssids: %u; p2p: %s)\n",
0893             msg_body->num_channel, msg_body->num_ssid,
0894             msg_body->p2p_search ? "yes" : "no");
0895 
0896     ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
0897     if (ret) {
0898         wcn36xx_err("Sending hal_start_scan_offload failed\n");
0899         goto out;
0900     }
0901     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
0902     if (ret) {
0903         wcn36xx_err("hal_start_scan_offload response failed err=%d\n",
0904                 ret);
0905         goto out;
0906     }
0907 out:
0908     kfree(msg_body);
0909     mutex_unlock(&wcn->hal_mutex);
0910     return ret;
0911 }
0912 
0913 int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn)
0914 {
0915     struct wcn36xx_hal_stop_scan_offload_req_msg msg_body;
0916     int ret;
0917 
0918     mutex_lock(&wcn->hal_mutex);
0919     INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ);
0920     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
0921 
0922     wcn36xx_dbg(WCN36XX_DBG_HAL, "hal stop hw-scan\n");
0923 
0924     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
0925     if (ret) {
0926         wcn36xx_err("Sending hal_stop_scan_offload failed\n");
0927         goto out;
0928     }
0929     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
0930     if (ret) {
0931         wcn36xx_err("hal_stop_scan_offload response failed err=%d\n",
0932                 ret);
0933         goto out;
0934     }
0935 out:
0936     mutex_unlock(&wcn->hal_mutex);
0937     return ret;
0938 }
0939 
0940 int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req)
0941 {
0942     struct wcn36xx_hal_update_channel_list_req_msg *msg_body;
0943     int ret, i;
0944 
0945     msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
0946     if (!msg_body)
0947         return -ENOMEM;
0948 
0949     INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ);
0950 
0951     msg_body->num_channel = min_t(u8, req->n_channels, ARRAY_SIZE(msg_body->channels));
0952     for (i = 0; i < msg_body->num_channel; i++) {
0953         struct wcn36xx_hal_channel_param *param = &msg_body->channels[i];
0954         u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER;
0955         u32 ant_gain = WCN36XX_HAL_DEFAULT_ANT_GAIN;
0956 
0957         param->mhz = req->channels[i]->center_freq;
0958         param->band_center_freq1 = req->channels[i]->center_freq;
0959         param->band_center_freq2 = 0;
0960 
0961         if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR)
0962             param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE;
0963 
0964         if (req->channels[i]->flags & IEEE80211_CHAN_RADAR)
0965             param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_DFS;
0966 
0967         if (req->channels[i]->band == NL80211_BAND_5GHZ) {
0968             param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_HT;
0969             param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_VHT;
0970             param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11A;
0971         } else {
0972             param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11BG;
0973         }
0974 
0975         if (min_power > req->channels[i]->max_power)
0976             min_power = req->channels[i]->max_power;
0977 
0978         if (req->channels[i]->max_antenna_gain)
0979             ant_gain = req->channels[i]->max_antenna_gain;
0980 
0981         u32p_replace_bits(&param->reg_info_1, min_power,
0982                   WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK);
0983         u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_power,
0984                   WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK);
0985         u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_reg_power,
0986                   WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK);
0987         u32p_replace_bits(&param->reg_info_1, 0,
0988                   WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK);
0989         u32p_replace_bits(&param->reg_info_2, ant_gain,
0990                   WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK);
0991 
0992         wcn36xx_dbg(WCN36XX_DBG_HAL,
0993                 "%s: freq=%u, channel_info=%08x, reg_info1=%08x, reg_info2=%08x\n",
0994                 __func__, param->mhz, param->channel_info, param->reg_info_1,
0995                 param->reg_info_2);
0996     }
0997 
0998     mutex_lock(&wcn->hal_mutex);
0999 
1000     PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1001 
1002     ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1003     if (ret) {
1004         wcn36xx_err("Sending hal_update_channel_list failed\n");
1005         goto out;
1006     }
1007 
1008     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1009     if (ret) {
1010         wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret);
1011         goto out;
1012     }
1013 
1014 out:
1015     kfree(msg_body);
1016     mutex_unlock(&wcn->hal_mutex);
1017     return ret;
1018 }
1019 
1020 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
1021 {
1022     struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
1023     int ret;
1024 
1025     ret = wcn36xx_smd_rsp_status_check(buf, len);
1026     if (ret)
1027         return ret;
1028     rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf;
1029     wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
1030             rsp->channel_number, rsp->status);
1031     return ret;
1032 }
1033 
1034 int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
1035                    struct ieee80211_vif *vif, int ch)
1036 {
1037     struct wcn36xx_hal_switch_channel_req_msg msg_body;
1038     int ret;
1039 
1040     mutex_lock(&wcn->hal_mutex);
1041     INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
1042 
1043     msg_body.channel_number = (u8)ch;
1044     msg_body.tx_mgmt_power = 0xbf;
1045     msg_body.max_tx_power = 0xbf;
1046     memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
1047 
1048     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1049 
1050     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1051     if (ret) {
1052         wcn36xx_err("Sending hal_switch_channel failed\n");
1053         goto out;
1054     }
1055     ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1056     if (ret) {
1057         wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
1058         goto out;
1059     }
1060 out:
1061     mutex_unlock(&wcn->hal_mutex);
1062     return ret;
1063 }
1064 
1065 static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len,
1066                        void **p_ptt_rsp_msg)
1067 {
1068     struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp;
1069     int ret;
1070 
1071     ret = wcn36xx_smd_rsp_status_check(buf, len);
1072     if (ret)
1073         return ret;
1074 
1075     rsp = (struct wcn36xx_hal_process_ptt_msg_rsp_msg *)buf;
1076 
1077     wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length %d\n",
1078             rsp->header.len);
1079     wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg,
1080              rsp->header.len - sizeof(rsp->ptt_msg_resp_status));
1081 
1082     if (rsp->header.len > 0) {
1083         *p_ptt_rsp_msg = kmemdup(rsp->ptt_msg, rsp->header.len,
1084                      GFP_ATOMIC);
1085         if (!*p_ptt_rsp_msg)
1086             return -ENOMEM;
1087     }
1088     return ret;
1089 }
1090 
1091 int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn,
1092                 struct ieee80211_vif *vif, void *ptt_msg, size_t len,
1093         void **ptt_rsp_msg)
1094 {
1095     struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body;
1096     int ret;
1097 
1098     mutex_lock(&wcn->hal_mutex);
1099     p_msg_body = kmalloc(
1100         sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len,
1101         GFP_ATOMIC);
1102     if (!p_msg_body) {
1103         ret = -ENOMEM;
1104         goto out_nomem;
1105     }
1106     INIT_HAL_PTT_MSG(p_msg_body, len);
1107 
1108     memcpy(&p_msg_body->ptt_msg, ptt_msg, len);
1109 
1110     PREPARE_HAL_PTT_MSG_BUF(wcn->hal_buf, p_msg_body);
1111 
1112     ret = wcn36xx_smd_send_and_wait(wcn, p_msg_body->header.len);
1113     if (ret) {
1114         wcn36xx_err("Sending hal_process_ptt_msg failed\n");
1115         goto out;
1116     }
1117     ret = wcn36xx_smd_process_ptt_msg_rsp(wcn->hal_buf, wcn->hal_rsp_len,
1118                           ptt_rsp_msg);
1119     if (ret) {
1120         wcn36xx_err("process_ptt_msg response failed err=%d\n", ret);
1121         goto out;
1122     }
1123 out:
1124     kfree(p_msg_body);
1125 out_nomem:
1126     mutex_unlock(&wcn->hal_mutex);
1127     return ret;
1128 }
1129 
1130 static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
1131 {
1132     struct wcn36xx_hal_update_scan_params_resp *rsp;
1133 
1134     rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf;
1135 
1136     /* Remove the PNO version bit */
1137     rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
1138 
1139     if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
1140         wcn36xx_warn("error response from update scan\n");
1141         return rsp->status;
1142     }
1143 
1144     return 0;
1145 }
1146 
1147 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
1148                    u8 *channels, size_t channel_count)
1149 {
1150     struct wcn36xx_hal_update_scan_params_req_ex msg_body;
1151     int ret;
1152 
1153     mutex_lock(&wcn->hal_mutex);
1154     INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
1155 
1156     msg_body.dot11d_enabled = false;
1157     msg_body.dot11d_resolved = true;
1158 
1159     msg_body.channel_count = channel_count;
1160     memcpy(msg_body.channels, channels, channel_count);
1161     msg_body.active_min_ch_time = 60;
1162     msg_body.active_max_ch_time = 120;
1163     msg_body.passive_min_ch_time = 60;
1164     msg_body.passive_max_ch_time = 110;
1165     msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
1166 
1167     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1168 
1169     wcn36xx_dbg(WCN36XX_DBG_HAL,
1170             "hal update scan params channel_count %d\n",
1171             msg_body.channel_count);
1172 
1173     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1174     if (ret) {
1175         wcn36xx_err("Sending hal_update_scan_params failed\n");
1176         goto out;
1177     }
1178     ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
1179                          wcn->hal_rsp_len);
1180     if (ret) {
1181         wcn36xx_err("hal_update_scan_params response failed err=%d\n",
1182                 ret);
1183         goto out;
1184     }
1185 out:
1186     mutex_unlock(&wcn->hal_mutex);
1187     return ret;
1188 }
1189 
1190 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
1191                     struct ieee80211_vif *vif,
1192                     void *buf,
1193                     size_t len)
1194 {
1195     struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
1196     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1197 
1198     if (len < sizeof(*rsp))
1199         return -EINVAL;
1200 
1201     rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
1202 
1203     if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1204         wcn36xx_warn("hal add sta self failure: %d\n",
1205                  rsp->status);
1206         return rsp->status;
1207     }
1208 
1209     wcn36xx_dbg(WCN36XX_DBG_HAL,
1210             "hal add sta self status %d self_sta_index %d dpu_index %d\n",
1211             rsp->status, rsp->self_sta_index, rsp->dpu_index);
1212 
1213     vif_priv->self_sta_index = rsp->self_sta_index;
1214     vif_priv->self_dpu_desc_index = rsp->dpu_index;
1215 
1216     return 0;
1217 }
1218 
1219 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1220 {
1221     struct wcn36xx_hal_add_sta_self_req msg_body;
1222     int ret;
1223 
1224     mutex_lock(&wcn->hal_mutex);
1225     INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
1226 
1227     memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
1228 
1229     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1230 
1231     wcn36xx_dbg(WCN36XX_DBG_HAL,
1232             "hal add sta self self_addr %pM status %d\n",
1233             msg_body.self_addr, msg_body.status);
1234 
1235     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1236     if (ret) {
1237         wcn36xx_err("Sending hal_add_sta_self failed\n");
1238         goto out;
1239     }
1240     ret = wcn36xx_smd_add_sta_self_rsp(wcn,
1241                        vif,
1242                        wcn->hal_buf,
1243                        wcn->hal_rsp_len);
1244     if (ret) {
1245         wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
1246         goto out;
1247     }
1248 out:
1249     mutex_unlock(&wcn->hal_mutex);
1250     return ret;
1251 }
1252 
1253 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
1254 {
1255     struct wcn36xx_hal_del_sta_self_req_msg msg_body;
1256     int ret;
1257 
1258     mutex_lock(&wcn->hal_mutex);
1259     INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
1260 
1261     memcpy(&msg_body.self_addr, addr, ETH_ALEN);
1262 
1263     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1264 
1265     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1266     if (ret) {
1267         wcn36xx_err("Sending hal_delete_sta_self failed\n");
1268         goto out;
1269     }
1270     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1271     if (ret) {
1272         wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
1273                 ret);
1274         goto out;
1275     }
1276 out:
1277     mutex_unlock(&wcn->hal_mutex);
1278     return ret;
1279 }
1280 
1281 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
1282 {
1283     struct wcn36xx_hal_delete_sta_req_msg msg_body;
1284     int ret;
1285 
1286     mutex_lock(&wcn->hal_mutex);
1287     INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
1288 
1289     msg_body.sta_index = sta_index;
1290 
1291     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1292 
1293     wcn36xx_dbg(WCN36XX_DBG_HAL,
1294             "hal delete sta sta_index %d\n",
1295             msg_body.sta_index);
1296 
1297     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1298     if (ret) {
1299         wcn36xx_err("Sending hal_delete_sta failed\n");
1300         goto out;
1301     }
1302     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1303     if (ret) {
1304         wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
1305         goto out;
1306     }
1307 out:
1308     mutex_unlock(&wcn->hal_mutex);
1309     return ret;
1310 }
1311 
1312 static int wcn36xx_smd_join_rsp(void *buf, size_t len)
1313 {
1314     struct wcn36xx_hal_join_rsp_msg *rsp;
1315 
1316     if (wcn36xx_smd_rsp_status_check(buf, len))
1317         return -EIO;
1318 
1319     rsp = (struct wcn36xx_hal_join_rsp_msg *)buf;
1320 
1321     wcn36xx_dbg(WCN36XX_DBG_HAL,
1322             "hal rsp join status %d tx_mgmt_power %d\n",
1323             rsp->status, rsp->tx_mgmt_power);
1324 
1325     return 0;
1326 }
1327 
1328 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
1329 {
1330     struct wcn36xx_hal_join_req_msg msg_body;
1331     int ret;
1332 
1333     mutex_lock(&wcn->hal_mutex);
1334     INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
1335 
1336     memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1337     memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
1338     msg_body.channel = ch;
1339 
1340     if (conf_is_ht40_minus(&wcn->hw->conf))
1341         msg_body.secondary_channel_offset =
1342             PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
1343     else if (conf_is_ht40_plus(&wcn->hw->conf))
1344         msg_body.secondary_channel_offset =
1345             PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
1346     else
1347         msg_body.secondary_channel_offset =
1348             PHY_SINGLE_CHANNEL_CENTERED;
1349 
1350     msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
1351 
1352     msg_body.max_tx_power = 0xbf;
1353     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1354 
1355     wcn36xx_dbg(WCN36XX_DBG_HAL,
1356             "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1357             msg_body.bssid, msg_body.self_sta_mac_addr,
1358             msg_body.channel, msg_body.link_state);
1359 
1360     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1361     if (ret) {
1362         wcn36xx_err("Sending hal_join failed\n");
1363         goto out;
1364     }
1365     ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1366     if (ret) {
1367         wcn36xx_err("hal_join response failed err=%d\n", ret);
1368         goto out;
1369     }
1370 out:
1371     mutex_unlock(&wcn->hal_mutex);
1372     return ret;
1373 }
1374 
1375 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
1376                 const u8 *sta_mac,
1377                 enum wcn36xx_hal_link_state state)
1378 {
1379     struct wcn36xx_hal_set_link_state_req_msg msg_body;
1380     int ret;
1381 
1382     mutex_lock(&wcn->hal_mutex);
1383     INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
1384 
1385     memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1386     memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
1387     msg_body.state = state;
1388 
1389     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1390 
1391     wcn36xx_dbg(WCN36XX_DBG_HAL,
1392             "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1393             msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
1394 
1395     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1396     if (ret) {
1397         wcn36xx_err("Sending hal_set_link_st failed\n");
1398         goto out;
1399     }
1400     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1401     if (ret) {
1402         wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
1403         goto out;
1404     }
1405 out:
1406     mutex_unlock(&wcn->hal_mutex);
1407     return ret;
1408 }
1409 
1410 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
1411             const struct wcn36xx_hal_config_sta_params *orig,
1412             struct wcn36xx_hal_config_sta_params_v1 *v1)
1413 {
1414     /* convert orig to v1 format */
1415     memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
1416     memcpy(&v1->mac, orig->mac, ETH_ALEN);
1417     v1->aid = orig->aid;
1418     v1->type = orig->type;
1419     v1->short_preamble_supported = orig->short_preamble_supported;
1420     v1->listen_interval = orig->listen_interval;
1421     v1->wmm_enabled = orig->wmm_enabled;
1422     v1->ht_capable = orig->ht_capable;
1423     v1->tx_channel_width_set = orig->tx_channel_width_set;
1424     v1->rifs_mode = orig->rifs_mode;
1425     v1->lsig_txop_protection = orig->lsig_txop_protection;
1426     v1->max_ampdu_size = orig->max_ampdu_size;
1427     v1->max_ampdu_density = orig->max_ampdu_density;
1428     v1->sgi_40mhz = orig->sgi_40mhz;
1429     v1->sgi_20Mhz = orig->sgi_20Mhz;
1430     v1->rmf = orig->rmf;
1431     v1->encrypt_type = orig->encrypt_type;
1432     v1->action = orig->action;
1433     v1->uapsd = orig->uapsd;
1434     v1->max_sp_len = orig->max_sp_len;
1435     v1->green_field_capable = orig->green_field_capable;
1436     v1->mimo_ps = orig->mimo_ps;
1437     v1->delayed_ba_support = orig->delayed_ba_support;
1438     v1->max_ampdu_duration = orig->max_ampdu_duration;
1439     v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
1440     memcpy(&v1->supported_rates, &orig->supported_rates,
1441            sizeof(orig->supported_rates));
1442     v1->sta_index = orig->sta_index;
1443     v1->bssid_index = orig->bssid_index;
1444     v1->p2p = orig->p2p;
1445 }
1446 
1447 static void
1448 wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn,
1449                   struct ieee80211_vif *vif,
1450                   struct ieee80211_sta *sta,
1451                   struct wcn36xx_hal_config_sta_params_v1 *sta_par)
1452 {
1453     struct wcn36xx_sta *sta_priv = NULL;
1454     struct wcn36xx_hal_config_sta_params sta_par_v0;
1455 
1456     wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0);
1457     wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par);
1458 
1459     if (sta) {
1460         sta_priv = wcn36xx_sta_to_priv(sta);
1461         wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par);
1462         wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par);
1463         memcpy(&sta_par->supported_rates, &sta_priv->supported_rates,
1464                sizeof(sta_par->supported_rates));
1465     } else {
1466         wcn36xx_set_default_rates_v1(&sta_par->supported_rates);
1467         wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par);
1468         wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par);
1469     }
1470 }
1471 
1472 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
1473                       struct ieee80211_sta *sta,
1474                       void *buf,
1475                       size_t len)
1476 {
1477     struct wcn36xx_hal_config_sta_rsp_msg *rsp;
1478     struct config_sta_rsp_params *params;
1479     struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1480 
1481     if (len < sizeof(*rsp))
1482         return -EINVAL;
1483 
1484     rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf;
1485     params = &rsp->params;
1486 
1487     if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1488         wcn36xx_warn("hal config sta response failure: %d\n",
1489                  params->status);
1490         return -EIO;
1491     }
1492 
1493     sta_priv->sta_index = params->sta_index;
1494     sta_priv->dpu_desc_index = params->dpu_index;
1495     sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
1496 
1497     wcn36xx_dbg(WCN36XX_DBG_HAL,
1498             "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1499             params->status, params->sta_index, params->bssid_index,
1500             params->uc_ucast_sig, params->p2p);
1501 
1502     return 0;
1503 }
1504 
1505 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
1506                      struct ieee80211_vif *vif,
1507                      struct ieee80211_sta *sta)
1508 {
1509     struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1510     struct wcn36xx_hal_config_sta_params_v1 *sta_params;
1511 
1512     if (wcn->rf_id == RF_IRIS_WCN3680) {
1513         INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1514     } else {
1515         INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1516         msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT;
1517     }
1518 
1519     sta_params = &msg_body.sta_params;
1520 
1521     wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params);
1522 
1523     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1524 
1525     wcn36xx_dbg(WCN36XX_DBG_HAL,
1526             "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1527             sta_params->action, sta_params->sta_index, sta_params->bssid_index,
1528             sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid);
1529 
1530     return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1531 }
1532 
1533 static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn,
1534                      struct ieee80211_vif *vif,
1535                      struct ieee80211_sta *sta)
1536 {
1537     struct wcn36xx_hal_config_sta_req_msg msg;
1538     struct wcn36xx_hal_config_sta_params *sta_params;
1539 
1540     INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1541 
1542     sta_params = &msg.sta_params;
1543 
1544     wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1545 
1546     PREPARE_HAL_BUF(wcn->hal_buf, msg);
1547 
1548     wcn36xx_dbg(WCN36XX_DBG_HAL,
1549             "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1550             sta_params->action, sta_params->sta_index,
1551             sta_params->bssid_index, sta_params->bssid,
1552             sta_params->type, sta_params->mac, sta_params->aid);
1553 
1554     return wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1555 }
1556 
1557 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1558                struct ieee80211_sta *sta)
1559 {
1560     int ret;
1561 
1562     mutex_lock(&wcn->hal_mutex);
1563 
1564     if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1565         ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta);
1566     else
1567         ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta);
1568 
1569     if (ret) {
1570         wcn36xx_err("Sending hal_config_sta failed\n");
1571         goto out;
1572     }
1573     ret = wcn36xx_smd_config_sta_rsp(wcn,
1574                      sta,
1575                      wcn->hal_buf,
1576                      wcn->hal_rsp_len);
1577     if (ret) {
1578         wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1579         goto out;
1580     }
1581 out:
1582     mutex_unlock(&wcn->hal_mutex);
1583     return ret;
1584 }
1585 
1586 static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn,
1587                        struct ieee80211_vif *vif,
1588                        struct ieee80211_sta *sta,
1589                        const u8 *bssid,
1590                        bool update,
1591                        struct wcn36xx_hal_config_bss_params *bss)
1592 {
1593     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1594 
1595     WARN_ON(is_zero_ether_addr(bssid));
1596 
1597     memcpy(&bss->bssid, bssid, ETH_ALEN);
1598 
1599     memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1600 
1601     if (vif->type == NL80211_IFTYPE_STATION) {
1602         bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1603 
1604         /* STA */
1605         bss->oper_mode = 1;
1606         bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1607     } else if (vif->type == NL80211_IFTYPE_AP ||
1608            vif->type == NL80211_IFTYPE_MESH_POINT) {
1609         bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1610 
1611         /* AP */
1612         bss->oper_mode = 0;
1613         bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1614     } else if (vif->type == NL80211_IFTYPE_ADHOC) {
1615         bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1616 
1617         /* STA */
1618         bss->oper_mode = 1;
1619     } else {
1620         wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1621     }
1622 
1623     if (vif->type == NL80211_IFTYPE_STATION)
1624         wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1625     else
1626         bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1627 
1628     bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1629     bss->lla_coexist = 0;
1630     bss->llb_coexist = 0;
1631     bss->llg_coexist = 0;
1632     bss->rifs_mode = 0;
1633     bss->beacon_interval = vif->bss_conf.beacon_int;
1634     bss->dtim_period = vif_priv->dtim_period;
1635 
1636     wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1637 
1638     bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1639 
1640     if (conf_is_ht40_minus(&wcn->hw->conf))
1641         bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1642     else if (conf_is_ht40_plus(&wcn->hw->conf))
1643         bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1644     else
1645         bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1646 
1647     bss->reserved = 0;
1648 
1649     /* wcn->ssid is only valid in AP and IBSS mode */
1650     bss->ssid.length = vif_priv->ssid.length;
1651     memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1652 
1653     bss->obss_prot_enabled = 0;
1654     bss->rmf = 0;
1655     bss->max_probe_resp_retry_limit = 0;
1656     bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1657     bss->proxy_probe_resp = 0;
1658     bss->edca_params_valid = 0;
1659 
1660     /* FIXME: set acbe, acbk, acvi and acvo */
1661 
1662     bss->ext_set_sta_key_param_valid = 0;
1663 
1664     /* FIXME: set ext_set_sta_key_param */
1665 
1666     bss->spectrum_mgt_enable = 0;
1667     bss->tx_mgmt_power = 0;
1668     bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1669     bss->action = update;
1670 
1671     vif_priv->bss_type = bss->bss_type;
1672 }
1673 
1674 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1675                      struct ieee80211_vif *vif,
1676                      struct ieee80211_sta *sta_80211,
1677                      const u8 *bssid,
1678                      bool update)
1679 {
1680     struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body;
1681     struct wcn36xx_hal_config_bss_params_v1 *bss;
1682     struct wcn36xx_hal_config_bss_params bss_v0;
1683     struct wcn36xx_hal_config_sta_params_v1 *sta;
1684     struct cfg80211_chan_def *chandef;
1685     int ret;
1686 
1687     msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
1688     if (!msg_body)
1689         return -ENOMEM;
1690 
1691     if (wcn->rf_id == RF_IRIS_WCN3680) {
1692         INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1693     } else {
1694         INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1695         msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT;
1696     }
1697 
1698     bss = &msg_body->bss_params;
1699     sta = &bss->sta;
1700 
1701     memset(&bss_v0, 0x00, sizeof(bss_v0));
1702     wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0);
1703     wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta);
1704 
1705     /* convert orig to v1 */
1706     memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN);
1707     memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN);
1708 
1709     bss->bss_type = bss_v0.bss_type;
1710     bss->oper_mode = bss_v0.oper_mode;
1711     bss->nw_type = bss_v0.nw_type;
1712 
1713     bss->short_slot_time_supported =
1714         bss_v0.short_slot_time_supported;
1715     bss->lla_coexist = bss_v0.lla_coexist;
1716     bss->llb_coexist = bss_v0.llb_coexist;
1717     bss->llg_coexist = bss_v0.llg_coexist;
1718     bss->ht20_coexist = bss_v0.ht20_coexist;
1719     bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist;
1720 
1721     bss->lsig_tx_op_protection_full_support =
1722         bss_v0.lsig_tx_op_protection_full_support;
1723     bss->rifs_mode = bss_v0.rifs_mode;
1724     bss->beacon_interval = bss_v0.beacon_interval;
1725     bss->dtim_period = bss_v0.dtim_period;
1726     bss->tx_channel_width_set = bss_v0.tx_channel_width_set;
1727     bss->oper_channel = bss_v0.oper_channel;
1728 
1729     if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) {
1730         chandef = &wcn->hw->conf.chandef;
1731         bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value);
1732     } else {
1733         bss->ext_channel = bss_v0.ext_channel;
1734     }
1735 
1736     bss->reserved = bss_v0.reserved;
1737 
1738     memcpy(&bss->ssid, &bss_v0.ssid,
1739            sizeof(bss_v0.ssid));
1740 
1741     bss->action = bss_v0.action;
1742     bss->rateset = bss_v0.rateset;
1743     bss->ht = bss_v0.ht;
1744     bss->obss_prot_enabled = bss_v0.obss_prot_enabled;
1745     bss->rmf = bss_v0.rmf;
1746     bss->ht_oper_mode = bss_v0.ht_oper_mode;
1747     bss->dual_cts_protection = bss_v0.dual_cts_protection;
1748 
1749     bss->max_probe_resp_retry_limit =
1750         bss_v0.max_probe_resp_retry_limit;
1751     bss->hidden_ssid = bss_v0.hidden_ssid;
1752     bss->proxy_probe_resp = bss_v0.proxy_probe_resp;
1753     bss->edca_params_valid = bss_v0.edca_params_valid;
1754 
1755     memcpy(&bss->acbe, &bss_v0.acbe,
1756            sizeof(bss_v0.acbe));
1757     memcpy(&bss->acbk, &bss_v0.acbk,
1758            sizeof(bss_v0.acbk));
1759     memcpy(&bss->acvi, &bss_v0.acvi,
1760            sizeof(bss_v0.acvi));
1761     memcpy(&bss->acvo, &bss_v0.acvo,
1762            sizeof(bss_v0.acvo));
1763 
1764     bss->ext_set_sta_key_param_valid =
1765         bss_v0.ext_set_sta_key_param_valid;
1766 
1767     memcpy(&bss->ext_set_sta_key_param,
1768            &bss_v0.ext_set_sta_key_param,
1769            sizeof(bss_v0.acvo));
1770 
1771     bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona;
1772     bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable;
1773     bss->tx_mgmt_power = bss_v0.tx_mgmt_power;
1774     bss->max_tx_power = bss_v0.max_tx_power;
1775 
1776     wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss);
1777 
1778     PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1779 
1780     wcn36xx_dbg(WCN36XX_DBG_HAL,
1781             "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1782             bss->bssid, bss->self_mac_addr, bss->bss_type,
1783             bss->oper_mode, bss->nw_type);
1784 
1785     wcn36xx_dbg(WCN36XX_DBG_HAL,
1786             "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1787             sta->bssid, sta->action, sta->sta_index,
1788             sta->bssid_index, sta->aid, sta->type, sta->mac);
1789 
1790     ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1791     kfree(msg_body);
1792 
1793     return ret;
1794 }
1795 
1796 static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn,
1797                      struct ieee80211_vif *vif,
1798                      struct ieee80211_sta *sta,
1799                      const u8 *bssid,
1800                      bool update)
1801 {
1802     struct wcn36xx_hal_config_bss_req_msg *msg;
1803     struct wcn36xx_hal_config_bss_params *bss;
1804     struct wcn36xx_hal_config_sta_params *sta_params;
1805     int ret;
1806 
1807     msg = kzalloc(sizeof(*msg), GFP_KERNEL);
1808     if (!msg)
1809         return -ENOMEM;
1810 
1811     INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ);
1812 
1813     bss = &msg->bss_params;
1814     sta_params = &bss->sta;
1815 
1816     wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss);
1817     wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1818 
1819     PREPARE_HAL_BUF(wcn->hal_buf, (*msg));
1820 
1821     wcn36xx_dbg(WCN36XX_DBG_HAL,
1822             "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1823             bss->bssid, bss->self_mac_addr, bss->bss_type,
1824             bss->oper_mode, bss->nw_type);
1825 
1826     wcn36xx_dbg(WCN36XX_DBG_HAL,
1827             "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1828             sta_params->bssid, sta_params->action,
1829             sta_params->sta_index, sta_params->bssid_index,
1830             sta_params->aid, sta_params->type,
1831             sta_params->mac);
1832 
1833     ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len);
1834     kfree(msg);
1835 
1836     return ret;
1837 }
1838 
1839 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1840                       struct ieee80211_vif *vif,
1841                       struct ieee80211_sta *sta,
1842                       void *buf,
1843                       size_t len)
1844 {
1845     struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1846     struct wcn36xx_hal_config_bss_rsp_params *params;
1847     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1848 
1849     if (len < sizeof(*rsp))
1850         return -EINVAL;
1851 
1852     rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
1853     params = &rsp->bss_rsp_params;
1854 
1855     if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1856         wcn36xx_warn("hal config bss response failure: %d\n",
1857                  params->status);
1858         return -EIO;
1859     }
1860 
1861     wcn36xx_dbg(WCN36XX_DBG_HAL,
1862             "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1863             " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1864             " power %d ucast_dpu_signature %d\n",
1865             params->status, params->bss_index, params->dpu_desc_index,
1866             params->bss_sta_index, params->bss_self_sta_index,
1867             params->bss_bcast_sta_idx, params->mac,
1868             params->tx_mgmt_power, params->ucast_dpu_signature);
1869 
1870     vif_priv->bss_index = params->bss_index;
1871 
1872     if (sta) {
1873         struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1874         sta_priv->bss_sta_index = params->bss_sta_index;
1875         sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
1876     }
1877 
1878     vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
1879 
1880     return 0;
1881 }
1882 
1883 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1884                struct ieee80211_sta *sta, const u8 *bssid,
1885                bool update)
1886 {
1887     int ret;
1888 
1889     mutex_lock(&wcn->hal_mutex);
1890 
1891     if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1892         ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update);
1893     else
1894         ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update);
1895 
1896     if (ret) {
1897         wcn36xx_err("Sending hal_config_bss failed\n");
1898         goto out;
1899     }
1900     ret = wcn36xx_smd_config_bss_rsp(wcn,
1901                      vif,
1902                      sta,
1903                      wcn->hal_buf,
1904                      wcn->hal_rsp_len);
1905     if (ret)
1906         wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1907 
1908 out:
1909     mutex_unlock(&wcn->hal_mutex);
1910     return ret;
1911 }
1912 
1913 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1914 {
1915     struct wcn36xx_hal_delete_bss_req_msg msg_body;
1916     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1917     int ret = 0;
1918 
1919     mutex_lock(&wcn->hal_mutex);
1920 
1921     if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX)
1922         goto out;
1923 
1924     INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1925 
1926     msg_body.bss_index = vif_priv->bss_index;
1927 
1928     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1929 
1930     wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1931 
1932     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1933     if (ret) {
1934         wcn36xx_err("Sending hal_delete_bss failed\n");
1935         goto out;
1936     }
1937     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1938     if (ret) {
1939         wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1940         goto out;
1941     }
1942 
1943     vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1944 out:
1945     mutex_unlock(&wcn->hal_mutex);
1946     return ret;
1947 }
1948 
1949 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1950                 struct sk_buff *skb_beacon, u16 tim_off,
1951                 u16 p2p_off)
1952 {
1953     struct wcn36xx_hal_send_beacon_req_msg msg_body;
1954     int ret, pad, pvm_len;
1955 
1956     mutex_lock(&wcn->hal_mutex);
1957     INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1958 
1959     pvm_len = skb_beacon->data[tim_off + 1] - 3;
1960     pad = TIM_MIN_PVM_SIZE - pvm_len;
1961 
1962     /* Padding is irrelevant to mesh mode since tim_off is always 0. */
1963     if (vif->type == NL80211_IFTYPE_MESH_POINT)
1964         pad = 0;
1965 
1966     msg_body.beacon_length = skb_beacon->len + pad;
1967     /* TODO need to find out why + 6 is needed */
1968     msg_body.beacon_length6 = msg_body.beacon_length + 6;
1969 
1970     if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
1971         wcn36xx_err("Beacon is too big: beacon size=%d\n",
1972                   msg_body.beacon_length);
1973         ret = -ENOMEM;
1974         goto out;
1975     }
1976     memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
1977     memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1978 
1979     if (pad > 0) {
1980         /*
1981          * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1982          * given the beacon template from mac80211 with a PVM shorter
1983          * than the FW expectes it will overwrite the data after the
1984          * TIM.
1985          */
1986         wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
1987                 pad, pvm_len);
1988         memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
1989             &msg_body.beacon[tim_off + 5 + pvm_len],
1990             skb_beacon->len - (tim_off + 5 + pvm_len));
1991         memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
1992         msg_body.beacon[tim_off + 1] += pad;
1993     }
1994 
1995     /* TODO need to find out why this is needed? */
1996     if (vif->type == NL80211_IFTYPE_MESH_POINT)
1997         /* mesh beacon don't need this, so push further down */
1998         msg_body.tim_ie_offset = 256;
1999     else
2000         msg_body.tim_ie_offset = tim_off+4;
2001     msg_body.p2p_ie_offset = p2p_off;
2002     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2003 
2004     wcn36xx_dbg(WCN36XX_DBG_HAL,
2005             "hal send beacon beacon_length %d\n",
2006             msg_body.beacon_length);
2007 
2008     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2009     if (ret) {
2010         wcn36xx_err("Sending hal_send_beacon failed\n");
2011         goto out;
2012     }
2013     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2014     if (ret) {
2015         wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
2016         goto out;
2017     }
2018 out:
2019     mutex_unlock(&wcn->hal_mutex);
2020     return ret;
2021 }
2022 
2023 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
2024                       struct ieee80211_vif *vif,
2025                       struct sk_buff *skb)
2026 {
2027     struct wcn36xx_hal_send_probe_resp_req_msg msg;
2028     int ret;
2029 
2030     mutex_lock(&wcn->hal_mutex);
2031     INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
2032 
2033     if (skb->len > BEACON_TEMPLATE_SIZE) {
2034         wcn36xx_warn("probe response template is too big: %d\n",
2035                  skb->len);
2036         ret = -E2BIG;
2037         goto out;
2038     }
2039 
2040     msg.probe_resp_template_len = skb->len;
2041     memcpy(&msg.probe_resp_template, skb->data, skb->len);
2042 
2043     memcpy(msg.bssid, vif->addr, ETH_ALEN);
2044 
2045     PREPARE_HAL_BUF(wcn->hal_buf, msg);
2046 
2047     wcn36xx_dbg(WCN36XX_DBG_HAL,
2048             "hal update probe rsp len %d bssid %pM\n",
2049             msg.probe_resp_template_len, msg.bssid);
2050 
2051     ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
2052     if (ret) {
2053         wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
2054         goto out;
2055     }
2056     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2057     if (ret) {
2058         wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
2059                 ret);
2060         goto out;
2061     }
2062 out:
2063     mutex_unlock(&wcn->hal_mutex);
2064     return ret;
2065 }
2066 
2067 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
2068                enum ani_ed_type enc_type,
2069                u8 keyidx,
2070                u8 keylen,
2071                u8 *key,
2072                u8 sta_index)
2073 {
2074     struct wcn36xx_hal_set_sta_key_req_msg msg_body;
2075     int ret;
2076 
2077     mutex_lock(&wcn->hal_mutex);
2078     INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
2079 
2080     msg_body.set_sta_key_params.sta_index = sta_index;
2081     msg_body.set_sta_key_params.enc_type = enc_type;
2082 
2083     if (enc_type == WCN36XX_HAL_ED_WEP104 ||
2084         enc_type == WCN36XX_HAL_ED_WEP40) {
2085         /* Use bss key for wep (static) */
2086         msg_body.set_sta_key_params.def_wep_idx = keyidx;
2087         msg_body.set_sta_key_params.wep_type = 0;
2088     } else {
2089         msg_body.set_sta_key_params.key[0].id = keyidx;
2090         msg_body.set_sta_key_params.key[0].unicast = 1;
2091         msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
2092         msg_body.set_sta_key_params.key[0].pae_role = 0;
2093         msg_body.set_sta_key_params.key[0].length = keylen;
2094         memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
2095     }
2096 
2097     msg_body.set_sta_key_params.single_tid_rc = 1;
2098 
2099     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2100 
2101     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2102     if (ret) {
2103         wcn36xx_err("Sending hal_set_stakey failed\n");
2104         goto out;
2105     }
2106     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2107     if (ret) {
2108         wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
2109         goto out;
2110     }
2111 out:
2112     mutex_unlock(&wcn->hal_mutex);
2113     return ret;
2114 }
2115 
2116 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
2117                enum ani_ed_type enc_type,
2118                u8 bssidx,
2119                u8 keyidx,
2120                u8 keylen,
2121                u8 *key)
2122 {
2123     struct wcn36xx_hal_set_bss_key_req_msg msg_body;
2124     int ret;
2125 
2126     mutex_lock(&wcn->hal_mutex);
2127     INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
2128     msg_body.bss_idx = bssidx;
2129     msg_body.enc_type = enc_type;
2130     msg_body.num_keys = 1;
2131     msg_body.keys[0].id = keyidx;
2132     msg_body.keys[0].unicast = 0;
2133     msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
2134     msg_body.keys[0].pae_role = 0;
2135     msg_body.keys[0].length = keylen;
2136     memcpy(msg_body.keys[0].key, key, keylen);
2137 
2138     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2139 
2140     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2141     if (ret) {
2142         wcn36xx_err("Sending hal_set_bsskey failed\n");
2143         goto out;
2144     }
2145     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2146     if (ret) {
2147         wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
2148         goto out;
2149     }
2150 out:
2151     mutex_unlock(&wcn->hal_mutex);
2152     return ret;
2153 }
2154 
2155 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
2156                   enum ani_ed_type enc_type,
2157                   u8 keyidx,
2158                   u8 sta_index)
2159 {
2160     struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
2161     int ret;
2162 
2163     mutex_lock(&wcn->hal_mutex);
2164     INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
2165 
2166     msg_body.sta_idx = sta_index;
2167     msg_body.enc_type = enc_type;
2168     msg_body.key_id = keyidx;
2169 
2170     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2171 
2172     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2173     if (ret) {
2174         wcn36xx_err("Sending hal_remove_stakey failed\n");
2175         goto out;
2176     }
2177     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2178     if (ret) {
2179         wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
2180         goto out;
2181     }
2182 out:
2183     mutex_unlock(&wcn->hal_mutex);
2184     return ret;
2185 }
2186 
2187 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
2188                   enum ani_ed_type enc_type,
2189                   u8 bssidx,
2190                   u8 keyidx)
2191 {
2192     struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
2193     int ret;
2194 
2195     mutex_lock(&wcn->hal_mutex);
2196     INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
2197     msg_body.bss_idx = bssidx;
2198     msg_body.enc_type = enc_type;
2199     msg_body.key_id = keyidx;
2200 
2201     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2202 
2203     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2204     if (ret) {
2205         wcn36xx_err("Sending hal_remove_bsskey failed\n");
2206         goto out;
2207     }
2208     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2209     if (ret) {
2210         wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
2211         goto out;
2212     }
2213 out:
2214     mutex_unlock(&wcn->hal_mutex);
2215     return ret;
2216 }
2217 
2218 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2219 {
2220     struct wcn36xx_hal_enter_bmps_req_msg msg_body;
2221     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2222     int ret;
2223 
2224     mutex_lock(&wcn->hal_mutex);
2225     INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
2226 
2227     msg_body.bss_index = vif_priv->bss_index;
2228     msg_body.tbtt = vif->bss_conf.sync_tsf;
2229     msg_body.dtim_period = vif_priv->dtim_period;
2230 
2231     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2232 
2233     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2234     if (ret) {
2235         wcn36xx_err("Sending hal_enter_bmps failed\n");
2236         goto out;
2237     }
2238     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2239     if (ret) {
2240         wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
2241         goto out;
2242     }
2243 out:
2244     mutex_unlock(&wcn->hal_mutex);
2245     return ret;
2246 }
2247 
2248 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2249 {
2250     struct wcn36xx_hal_exit_bmps_req_msg msg_body;
2251     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2252     int ret;
2253 
2254     mutex_lock(&wcn->hal_mutex);
2255     INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
2256 
2257     msg_body.bss_index = vif_priv->bss_index;
2258     msg_body.send_data_null = 1;
2259 
2260     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2261 
2262     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2263     if (ret) {
2264         wcn36xx_err("Sending hal_exit_bmps failed\n");
2265         goto out;
2266     }
2267     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2268     if (ret) {
2269         wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
2270         goto out;
2271     }
2272 out:
2273     mutex_unlock(&wcn->hal_mutex);
2274     return ret;
2275 }
2276 
2277 int wcn36xx_smd_enter_imps(struct wcn36xx *wcn)
2278 {
2279     struct wcn36xx_hal_enter_imps_req_msg msg_body;
2280     int ret;
2281 
2282     mutex_lock(&wcn->hal_mutex);
2283     INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_IMPS_REQ);
2284 
2285     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2286 
2287     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2288     if (ret) {
2289         wcn36xx_err("Sending hal_enter_imps failed\n");
2290         goto out;
2291     }
2292     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2293     if (ret) {
2294         wcn36xx_err("hal_enter_imps response failed err=%d\n", ret);
2295         goto out;
2296     }
2297 
2298     wcn36xx_dbg(WCN36XX_DBG_HAL, "Entered idle mode\n");
2299 out:
2300     mutex_unlock(&wcn->hal_mutex);
2301     return ret;
2302 }
2303 
2304 int wcn36xx_smd_exit_imps(struct wcn36xx *wcn)
2305 {
2306     struct wcn36xx_hal_exit_imps_req_msg msg_body;
2307     int ret;
2308 
2309     mutex_lock(&wcn->hal_mutex);
2310     INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_IMPS_REQ);
2311 
2312     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2313 
2314     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2315     if (ret) {
2316         wcn36xx_err("Sending hal_exit_imps failed\n");
2317         goto out;
2318     }
2319     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2320     if (ret) {
2321         wcn36xx_err("hal_exit_imps response failed err=%d\n", ret);
2322         goto out;
2323     }
2324     wcn36xx_dbg(WCN36XX_DBG_HAL, "Exited idle mode\n");
2325 out:
2326     mutex_unlock(&wcn->hal_mutex);
2327     return ret;
2328 }
2329 
2330 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
2331 {
2332     struct wcn36xx_hal_set_power_params_req_msg msg_body;
2333     int ret;
2334 
2335     mutex_lock(&wcn->hal_mutex);
2336     INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
2337 
2338     /*
2339      * When host is down ignore every second dtim
2340      */
2341     if (ignore_dtim) {
2342         msg_body.ignore_dtim = 1;
2343         msg_body.dtim_period = 2;
2344     }
2345     msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
2346 
2347     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2348 
2349     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2350     if (ret) {
2351         wcn36xx_err("Sending hal_set_power_params failed\n");
2352         goto out;
2353     }
2354 
2355 out:
2356     mutex_unlock(&wcn->hal_mutex);
2357     return ret;
2358 }
2359 
2360 /* Notice: This function should be called after associated, or else it
2361  * will be invalid
2362  */
2363 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
2364                    struct ieee80211_vif *vif,
2365                    int packet_type)
2366 {
2367     struct wcn36xx_hal_keep_alive_req_msg msg_body;
2368     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2369     int ret;
2370 
2371     mutex_lock(&wcn->hal_mutex);
2372     INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
2373 
2374     if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
2375         msg_body.bss_index = vif_priv->bss_index;
2376         msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
2377         msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
2378     } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
2379         /* TODO: it also support ARP response type */
2380     } else {
2381         wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
2382         ret = -EINVAL;
2383         goto out;
2384     }
2385 
2386     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2387 
2388     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2389     if (ret) {
2390         wcn36xx_err("Sending hal_keep_alive failed\n");
2391         goto out;
2392     }
2393     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2394     if (ret) {
2395         wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
2396         goto out;
2397     }
2398 out:
2399     mutex_unlock(&wcn->hal_mutex);
2400     return ret;
2401 }
2402 
2403 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
2404                  u32 arg3, u32 arg4, u32 arg5)
2405 {
2406     struct wcn36xx_hal_dump_cmd_req_msg msg_body;
2407     int ret;
2408 
2409     mutex_lock(&wcn->hal_mutex);
2410     INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
2411 
2412     msg_body.arg1 = arg1;
2413     msg_body.arg2 = arg2;
2414     msg_body.arg3 = arg3;
2415     msg_body.arg4 = arg4;
2416     msg_body.arg5 = arg5;
2417 
2418     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2419 
2420     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2421     if (ret) {
2422         wcn36xx_err("Sending hal_dump_cmd failed\n");
2423         goto out;
2424     }
2425     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2426     if (ret) {
2427         wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
2428         goto out;
2429     }
2430 out:
2431     mutex_unlock(&wcn->hal_mutex);
2432     return ret;
2433 }
2434 
2435 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
2436 {
2437     struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
2438     int ret, i;
2439 
2440     mutex_lock(&wcn->hal_mutex);
2441     INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
2442 
2443     wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
2444     if (wcn->rf_id == RF_IRIS_WCN3680) {
2445         wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC);
2446         wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144);
2447         wcn36xx_firmware_set_feat_caps(msg_body.feat_caps,
2448                            ANTENNA_DIVERSITY_SELECTION);
2449     }
2450 
2451     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2452 
2453     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2454     if (ret) {
2455         wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2456         goto out;
2457     }
2458     if (wcn->hal_rsp_len != sizeof(*rsp)) {
2459         wcn36xx_err("Invalid hal_feature_caps_exchange response");
2460         goto out;
2461     }
2462 
2463     rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
2464 
2465     for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
2466         wcn->fw_feat_caps[i] = rsp->feat_caps[i];
2467 out:
2468     mutex_unlock(&wcn->hal_mutex);
2469     return ret;
2470 }
2471 
2472 static int wcn36xx_smd_add_ba_session_rsp(void *buf, int len, u8 *session)
2473 {
2474     struct wcn36xx_hal_add_ba_session_rsp_msg *rsp;
2475 
2476     if (len < sizeof(*rsp))
2477         return -EINVAL;
2478 
2479     rsp = (struct wcn36xx_hal_add_ba_session_rsp_msg *)buf;
2480     if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS)
2481         return rsp->status;
2482 
2483     *session = rsp->ba_session_id;
2484 
2485     return 0;
2486 }
2487 
2488 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
2489         struct ieee80211_sta *sta,
2490         u16 tid,
2491         u16 *ssn,
2492         u8 direction,
2493         u8 sta_index)
2494 {
2495     struct wcn36xx_hal_add_ba_session_req_msg msg_body;
2496     u8 session_id;
2497     int ret;
2498 
2499     mutex_lock(&wcn->hal_mutex);
2500     INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
2501 
2502     msg_body.sta_index = sta_index;
2503     memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
2504     msg_body.dialog_token = 0x10;
2505     msg_body.tid = tid;
2506 
2507     /* Immediate BA because Delayed BA is not supported */
2508     msg_body.policy = 1;
2509     msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
2510     msg_body.timeout = 0;
2511     if (ssn)
2512         msg_body.ssn = *ssn;
2513     msg_body.direction = direction;
2514 
2515     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2516 
2517     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2518     if (ret) {
2519         wcn36xx_err("Sending hal_add_ba_session failed\n");
2520         goto out;
2521     }
2522     ret = wcn36xx_smd_add_ba_session_rsp(wcn->hal_buf, wcn->hal_rsp_len,
2523                          &session_id);
2524     if (ret) {
2525         wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
2526         ret = -EINVAL;
2527         goto out;
2528     }
2529 
2530     ret = session_id;
2531 out:
2532     mutex_unlock(&wcn->hal_mutex);
2533     return ret;
2534 }
2535 
2536 int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id)
2537 {
2538     struct wcn36xx_hal_add_ba_req_msg msg_body;
2539     int ret;
2540 
2541     mutex_lock(&wcn->hal_mutex);
2542     INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
2543 
2544     msg_body.session_id = session_id;
2545     msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
2546 
2547     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2548 
2549     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2550     if (ret) {
2551         wcn36xx_err("Sending hal_add_ba failed\n");
2552         goto out;
2553     }
2554     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2555     if (ret) {
2556         wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
2557         goto out;
2558     }
2559 out:
2560     mutex_unlock(&wcn->hal_mutex);
2561     return ret;
2562 }
2563 
2564 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index)
2565 {
2566     struct wcn36xx_hal_del_ba_req_msg msg_body;
2567     int ret;
2568 
2569     mutex_lock(&wcn->hal_mutex);
2570     INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
2571 
2572     msg_body.sta_index = sta_index;
2573     msg_body.tid = tid;
2574     msg_body.direction = direction;
2575     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2576 
2577     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2578     if (ret) {
2579         wcn36xx_err("Sending hal_del_ba failed\n");
2580         goto out;
2581     }
2582     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2583     if (ret) {
2584         wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
2585         goto out;
2586     }
2587 out:
2588     mutex_unlock(&wcn->hal_mutex);
2589     return ret;
2590 }
2591 
2592 int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask,
2593               struct station_info *sinfo)
2594 {
2595     struct wcn36xx_hal_stats_req_msg msg_body;
2596     struct wcn36xx_hal_stats_rsp_msg *rsp;
2597     void *rsp_body;
2598     int ret;
2599 
2600     if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) {
2601         wcn36xx_err("stats_mask 0x%x contains unimplemented types\n",
2602                 stats_mask);
2603         return -EINVAL;
2604     }
2605 
2606     mutex_lock(&wcn->hal_mutex);
2607     INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ);
2608 
2609     msg_body.sta_id = sta_index;
2610     msg_body.stats_mask = stats_mask;
2611 
2612     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2613 
2614     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2615     if (ret) {
2616         wcn36xx_err("sending hal_get_stats failed\n");
2617         goto out;
2618     }
2619 
2620     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2621     if (ret) {
2622         wcn36xx_err("hal_get_stats response failed err=%d\n", ret);
2623         goto out;
2624     }
2625 
2626     rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf;
2627     rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg));
2628 
2629     if (rsp->stats_mask != stats_mask) {
2630         wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n",
2631                 rsp->stats_mask, stats_mask);
2632         goto out;
2633     }
2634 
2635     if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) {
2636         struct ani_global_class_a_stats_info *stats_info = rsp_body;
2637 
2638         wcn36xx_process_tx_rate(stats_info, &sinfo->txrate);
2639         sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
2640         rsp_body += sizeof(struct ani_global_class_a_stats_info);
2641     }
2642 out:
2643     mutex_unlock(&wcn->hal_mutex);
2644 
2645     return ret;
2646 }
2647 
2648 static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
2649 {
2650     struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
2651     struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
2652     int i;
2653 
2654     if (len < sizeof(*rsp))
2655         return -EINVAL;
2656 
2657     rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
2658 
2659     if (rsp->candidate_cnt < 1)
2660         return rsp->status ? rsp->status : -EINVAL;
2661 
2662     candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp));
2663 
2664     for (i = 0; i < STACFG_MAX_TC; i++) {
2665         ba_info[i] = candidate->ba_info[i];
2666     }
2667 
2668     return rsp->status;
2669 }
2670 
2671 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn)
2672 {
2673     struct wcn36xx_hal_trigger_ba_req_msg msg_body;
2674     struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
2675     struct add_ba_info ba_info[STACFG_MAX_TC];
2676     int ret;
2677 
2678     if (tid >= STACFG_MAX_TC)
2679         return -EINVAL;
2680 
2681     mutex_lock(&wcn->hal_mutex);
2682     INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
2683 
2684     msg_body.session_id = 0; /* not really used */
2685     msg_body.candidate_cnt = 1;
2686     msg_body.header.len += sizeof(*candidate);
2687     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2688 
2689     candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
2690         (wcn->hal_buf + sizeof(msg_body));
2691     candidate->sta_index = sta_index;
2692     candidate->tid_bitmap = 1 << tid;
2693 
2694     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2695     if (ret) {
2696         wcn36xx_err("Sending hal_trigger_ba failed\n");
2697         goto out;
2698     }
2699     ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info);
2700     if (ret) {
2701         wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
2702         goto out;
2703     }
2704 out:
2705     mutex_unlock(&wcn->hal_mutex);
2706 
2707     if (ssn)
2708         *ssn = ba_info[tid].starting_seq_num;
2709 
2710     return ret;
2711 }
2712 
2713 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
2714 {
2715     struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
2716 
2717     if (len != sizeof(*rsp)) {
2718         wcn36xx_warn("Bad TX complete indication\n");
2719         return -EIO;
2720     }
2721 
2722     wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
2723 
2724     return 0;
2725 }
2726 
2727 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len)
2728 {
2729     struct wcn36xx_hal_scan_offload_ind *rsp = buf;
2730     struct cfg80211_scan_info scan_info = {};
2731 
2732     if (len != sizeof(*rsp)) {
2733         wcn36xx_warn("Corrupted delete scan indication\n");
2734         return -EIO;
2735     }
2736 
2737     wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type);
2738 
2739     switch (rsp->type) {
2740     case WCN36XX_HAL_SCAN_IND_FAILED:
2741     case WCN36XX_HAL_SCAN_IND_DEQUEUED:
2742         scan_info.aborted = true;
2743         fallthrough;
2744     case WCN36XX_HAL_SCAN_IND_COMPLETED:
2745         mutex_lock(&wcn->scan_lock);
2746         wcn->scan_req = NULL;
2747         if (wcn->scan_aborted)
2748             scan_info.aborted = true;
2749         mutex_unlock(&wcn->scan_lock);
2750         ieee80211_scan_completed(wcn->hw, &scan_info);
2751         break;
2752     case WCN36XX_HAL_SCAN_IND_STARTED:
2753     case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL:
2754     case WCN36XX_HAL_SCAN_IND_PREEMPTED:
2755     case WCN36XX_HAL_SCAN_IND_RESTARTED:
2756         break;
2757     default:
2758         wcn36xx_warn("Unknown scan indication type %x\n", rsp->type);
2759     }
2760 
2761     return 0;
2762 }
2763 
2764 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2765                      void *buf,
2766                      size_t len)
2767 {
2768     struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2769     struct ieee80211_vif *vif = NULL;
2770     struct wcn36xx_vif *tmp;
2771 
2772     /* Old FW does not have bss index */
2773     if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2774         list_for_each_entry(tmp, &wcn->vif_list, list) {
2775             wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2776                     tmp->bss_index);
2777             vif = wcn36xx_priv_to_vif(tmp);
2778             ieee80211_beacon_loss(vif);
2779         }
2780         return 0;
2781     }
2782 
2783     if (len != sizeof(*rsp)) {
2784         wcn36xx_warn("Corrupted missed beacon indication\n");
2785         return -EIO;
2786     }
2787 
2788     list_for_each_entry(tmp, &wcn->vif_list, list) {
2789         if (tmp->bss_index == rsp->bss_index) {
2790             wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2791                     rsp->bss_index);
2792             vif = wcn36xx_priv_to_vif(tmp);
2793             ieee80211_beacon_loss(vif);
2794             return 0;
2795         }
2796     }
2797 
2798     wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2799     return -ENOENT;
2800 }
2801 
2802 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2803                           void *buf,
2804                           size_t len)
2805 {
2806     struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2807     struct wcn36xx_vif *vif_priv;
2808     struct ieee80211_vif *vif;
2809     struct ieee80211_bss_conf *bss_conf;
2810     struct ieee80211_sta *sta;
2811     bool found = false;
2812 
2813     if (len != sizeof(*rsp)) {
2814         wcn36xx_warn("Corrupted delete sta indication\n");
2815         return -EIO;
2816     }
2817 
2818     wcn36xx_dbg(WCN36XX_DBG_HAL,
2819             "delete station indication %pM index %d reason %d\n",
2820             rsp->addr2, rsp->sta_id, rsp->reason_code);
2821 
2822     list_for_each_entry(vif_priv, &wcn->vif_list, list) {
2823         rcu_read_lock();
2824         vif = wcn36xx_priv_to_vif(vif_priv);
2825 
2826         if (vif->type == NL80211_IFTYPE_STATION) {
2827             /* We could call ieee80211_find_sta too, but checking
2828              * bss_conf is clearer.
2829              */
2830             bss_conf = &vif->bss_conf;
2831             if (vif_priv->sta_assoc &&
2832                 !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
2833                 found = true;
2834                 wcn36xx_dbg(WCN36XX_DBG_HAL,
2835                         "connection loss bss_index %d\n",
2836                         vif_priv->bss_index);
2837                 ieee80211_connection_loss(vif);
2838             }
2839         } else {
2840             sta = ieee80211_find_sta(vif, rsp->addr2);
2841             if (sta) {
2842                 found = true;
2843                 ieee80211_report_low_ack(sta, 0);
2844             }
2845         }
2846 
2847         rcu_read_unlock();
2848         if (found)
2849             return 0;
2850     }
2851 
2852     wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
2853     return -ENOENT;
2854 }
2855 
2856 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
2857                       void *buf,
2858                       size_t len)
2859 {
2860     struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
2861     int i;
2862 
2863     if (len < sizeof(*rsp)) {
2864         wcn36xx_warn("Corrupted print reg info indication\n");
2865         return -EIO;
2866     }
2867 
2868     wcn36xx_dbg(WCN36XX_DBG_HAL,
2869             "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2870             rsp->scenario, rsp->reason);
2871 
2872     for (i = 0; i < rsp->count; i++) {
2873         wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
2874                 rsp->regs[i].addr, rsp->regs[i].value);
2875     }
2876 
2877     return 0;
2878 }
2879 
2880 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2881 {
2882     struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2883     size_t len;
2884     int ret;
2885 
2886     mutex_lock(&wcn->hal_mutex);
2887     INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2888 
2889     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2890 
2891     body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2892     len = msg_body.header.len;
2893 
2894     put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2895     body->header.len = len;
2896     body->len = len - sizeof(*body);
2897 
2898     ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2899     if (ret) {
2900         wcn36xx_err("Sending hal_update_cfg failed\n");
2901         goto out;
2902     }
2903     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2904     if (ret) {
2905         wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2906         goto out;
2907     }
2908 out:
2909     mutex_unlock(&wcn->hal_mutex);
2910     return ret;
2911 }
2912 
2913 int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
2914                 struct ieee80211_vif *vif,
2915                 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
2916 {
2917     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2918     struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
2919     int ret;
2920 
2921     mutex_lock(&wcn->hal_mutex);
2922 
2923     msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
2924            wcn->hal_buf;
2925     INIT_HAL_MSG(*msg_body, WCN36XX_HAL_8023_MULTICAST_LIST_REQ);
2926 
2927     /* An empty list means all mc traffic will be received */
2928     if (fp)
2929         memcpy(&msg_body->mc_addr_list, fp,
2930                sizeof(msg_body->mc_addr_list));
2931     else
2932         msg_body->mc_addr_list.mc_addr_count = 0;
2933 
2934     msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
2935 
2936     ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
2937     if (ret) {
2938         wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2939         goto out;
2940     }
2941     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2942     if (ret) {
2943         wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
2944         goto out;
2945     }
2946 out:
2947     mutex_unlock(&wcn->hal_mutex);
2948     return ret;
2949 }
2950 
2951 int wcn36xx_smd_arp_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2952                 bool enable)
2953 {
2954     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2955     struct wcn36xx_hal_host_offload_req_msg msg_body;
2956     int ret;
2957 
2958     mutex_lock(&wcn->hal_mutex);
2959 
2960     INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
2961     msg_body.host_offload_params.offload_type =
2962         WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD;
2963     if (enable) {
2964         msg_body.host_offload_params.enable =
2965             WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
2966         memcpy(&msg_body.host_offload_params.u,
2967                &vif->cfg.arp_addr_list[0], sizeof(__be32));
2968     }
2969     msg_body.ns_offload_params.bss_index = vif_priv->bss_index;
2970 
2971     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2972 
2973     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2974     if (ret) {
2975         wcn36xx_err("Sending host_offload_arp failed\n");
2976         goto out;
2977     }
2978     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2979     if (ret) {
2980         wcn36xx_err("host_offload_arp failed err=%d\n", ret);
2981         goto out;
2982     }
2983 out:
2984     mutex_unlock(&wcn->hal_mutex);
2985     return ret;
2986 }
2987 
2988 #if IS_ENABLED(CONFIG_IPV6)
2989 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2990                 bool enable)
2991 {
2992     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2993     struct wcn36xx_hal_host_offload_req_msg msg_body;
2994     struct wcn36xx_hal_ns_offload_params *ns_params;
2995     struct wcn36xx_hal_host_offload_req *ho_params;
2996     int ret;
2997 
2998     mutex_lock(&wcn->hal_mutex);
2999 
3000     INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
3001     ho_params = &msg_body.host_offload_params;
3002     ns_params = &msg_body.ns_offload_params;
3003 
3004     ho_params->offload_type = WCN36XX_HAL_IPV6_NS_OFFLOAD;
3005     if (enable) {
3006         ho_params->enable =
3007             WCN36XX_HAL_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
3008         if (vif_priv->num_target_ipv6_addrs) {
3009             memcpy(&ho_params->u,
3010                    &vif_priv->target_ipv6_addrs[0].in6_u,
3011                    sizeof(struct in6_addr));
3012             memcpy(&ns_params->target_ipv6_addr1,
3013                    &vif_priv->target_ipv6_addrs[0].in6_u,
3014                    sizeof(struct in6_addr));
3015             ns_params->target_ipv6_addr1_valid = 1;
3016         }
3017         if (vif_priv->num_target_ipv6_addrs > 1) {
3018             memcpy(&ns_params->target_ipv6_addr2,
3019                    &vif_priv->target_ipv6_addrs[1].in6_u,
3020                    sizeof(struct in6_addr));
3021             ns_params->target_ipv6_addr2_valid = 1;
3022         }
3023     }
3024     memcpy(&ns_params->self_addr, vif->addr, ETH_ALEN);
3025     ns_params->bss_index = vif_priv->bss_index;
3026 
3027     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3028 
3029     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3030     if (ret) {
3031         wcn36xx_err("Sending host_offload_arp failed\n");
3032         goto out;
3033     }
3034     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3035     if (ret) {
3036         wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3037         goto out;
3038     }
3039 out:
3040     mutex_unlock(&wcn->hal_mutex);
3041     return ret;
3042 }
3043 #else
3044 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
3045                 bool enable)
3046 {
3047     return 0;
3048 }
3049 #endif
3050 
3051 int wcn36xx_smd_gtk_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
3052                 bool enable)
3053 {
3054     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3055     struct wcn36xx_hal_gtk_offload_req_msg msg_body;
3056     int ret;
3057 
3058     mutex_lock(&wcn->hal_mutex);
3059 
3060     INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_REQ);
3061 
3062     if (enable) {
3063         memcpy(&msg_body.kek, vif_priv->rekey_data.kek, NL80211_KEK_LEN);
3064         memcpy(&msg_body.kck, vif_priv->rekey_data.kck, NL80211_KCK_LEN);
3065         msg_body.key_replay_counter =
3066             le64_to_cpu(vif_priv->rekey_data.replay_ctr);
3067         msg_body.bss_index = vif_priv->bss_index;
3068     } else {
3069         msg_body.flags = WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE;
3070     }
3071 
3072     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3073 
3074     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3075     if (ret) {
3076         wcn36xx_err("Sending host_offload_arp failed\n");
3077         goto out;
3078     }
3079     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3080     if (ret) {
3081         wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3082         goto out;
3083     }
3084 out:
3085     mutex_unlock(&wcn->hal_mutex);
3086     return ret;
3087 }
3088 
3089 static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx *wcn,
3090                         struct ieee80211_vif *vif)
3091 {
3092     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3093     struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *rsp;
3094     __be64 replay_ctr;
3095 
3096     if (wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len))
3097         return -EIO;
3098 
3099     rsp = (struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *)wcn->hal_buf;
3100 
3101     if (rsp->bss_index != vif_priv->bss_index) {
3102         wcn36xx_err("gtk_offload_info invalid response bss index %d\n",
3103                 rsp->bss_index);
3104         return -ENOENT;
3105     }
3106 
3107     if (vif_priv->rekey_data.replay_ctr != cpu_to_le64(rsp->key_replay_counter)) {
3108         replay_ctr = cpu_to_be64(rsp->key_replay_counter);
3109         vif_priv->rekey_data.replay_ctr =
3110             cpu_to_le64(rsp->key_replay_counter);
3111         ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
3112                        (void *)&replay_ctr, GFP_KERNEL);
3113         wcn36xx_dbg(WCN36XX_DBG_HAL,
3114                 "GTK replay counter increment %llu\n",
3115                 rsp->key_replay_counter);
3116     }
3117 
3118     wcn36xx_dbg(WCN36XX_DBG_HAL,
3119             "gtk offload info status %d last_rekey_status %d "
3120             "replay_counter %llu total_rekey_count %d gtk_rekey_count %d "
3121             "igtk_rekey_count %d bss_index %d\n",
3122             rsp->status, rsp->last_rekey_status,
3123             rsp->key_replay_counter, rsp->total_rekey_count,
3124             rsp->gtk_rekey_count, rsp->igtk_rekey_count,
3125             rsp->bss_index);
3126 
3127     return 0;
3128 }
3129 
3130 int wcn36xx_smd_gtk_offload_get_info(struct wcn36xx *wcn,
3131                      struct ieee80211_vif *vif)
3132 {
3133     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3134     struct wcn36xx_hal_gtk_offload_get_info_req_msg msg_body;
3135     int ret;
3136 
3137     mutex_lock(&wcn->hal_mutex);
3138 
3139     INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ);
3140 
3141     msg_body.bss_index = vif_priv->bss_index;
3142 
3143     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3144 
3145     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3146     if (ret) {
3147         wcn36xx_err("Sending gtk_offload_get_info failed\n");
3148         goto out;
3149     }
3150     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3151     if (ret) {
3152         wcn36xx_err("gtk_offload_get_info failed err=%d\n", ret);
3153         goto out;
3154     }
3155     ret = wcn36xx_smd_gtk_offload_get_info_rsp(wcn, vif);
3156 out:
3157     mutex_unlock(&wcn->hal_mutex);
3158     return ret;
3159 }
3160 
3161 int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx *wcn)
3162 {
3163     struct wcn36xx_hal_wlan_host_suspend_ind_msg msg_body;
3164     int ret;
3165 
3166     mutex_lock(&wcn->hal_mutex);
3167 
3168     INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_SUSPEND_IND);
3169     msg_body.configured_mcst_bcst_filter_setting = 0;
3170     msg_body.active_session_count = 1;
3171     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3172 
3173     ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, msg_body.header.len);
3174 
3175     mutex_unlock(&wcn->hal_mutex);
3176 
3177     return ret;
3178 }
3179 
3180 int wcn36xx_smd_host_resume(struct wcn36xx *wcn)
3181 {
3182     struct wcn36xx_hal_wlan_host_resume_req_msg msg_body;
3183     struct wcn36xx_hal_host_resume_rsp_msg *rsp;
3184     int ret;
3185 
3186     mutex_lock(&wcn->hal_mutex);
3187 
3188     INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_RESUME_REQ);
3189     msg_body.configured_mcst_bcst_filter_setting = 0;
3190 
3191     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3192 
3193     ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3194     if (ret) {
3195         wcn36xx_err("Sending wlan_host_resume failed\n");
3196         goto out;
3197     }
3198     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3199     if (ret) {
3200         wcn36xx_err("wlan_host_resume err=%d\n", ret);
3201         goto out;
3202     }
3203 
3204     rsp = (struct wcn36xx_hal_host_resume_rsp_msg *)wcn->hal_buf;
3205     if (rsp->status)
3206         wcn36xx_warn("wlan_host_resume status=%d\n", rsp->status);
3207 
3208 out:
3209     mutex_unlock(&wcn->hal_mutex);
3210 
3211     return ret;
3212 }
3213 
3214 #define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \
3215     {                   \
3216         .element_id = eid,      \
3217         .check_ie_presence = presence,  \
3218         .offset = offs,         \
3219         .value = val,           \
3220         .bitmask = mask,        \
3221         .ref = ref_val,         \
3222     }
3223 
3224 static const struct beacon_filter_ie bcn_filter_ies[] = {
3225     BEACON_FILTER(WLAN_EID_DS_PARAMS, 0, 0, 0,
3226               WCN36XX_FILTER_IE_DS_CHANNEL_MASK, 0),
3227     BEACON_FILTER(WLAN_EID_ERP_INFO, 0, 0, 0,
3228               WCN36XX_FILTER_IE_ERP_FILTER_MASK, 0),
3229     BEACON_FILTER(WLAN_EID_EDCA_PARAM_SET, 0, 0, 0,
3230               WCN36XX_FILTER_IE_EDCA_FILTER_MASK, 0),
3231     BEACON_FILTER(WLAN_EID_QOS_CAPA, 0, 0, 0,
3232               WCN36XX_FILTER_IE_QOS_FILTER_MASK, 0),
3233     BEACON_FILTER(WLAN_EID_CHANNEL_SWITCH, 1, 0, 0,
3234               WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK, 0),
3235     BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 0, 0,
3236               WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK, 0),
3237     BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 2, 0,
3238               WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK, 0),
3239     BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 5, 0,
3240               WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK, 0),
3241     BEACON_FILTER(WLAN_EID_PWR_CONSTRAINT, 0, 0, 0,
3242               WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK, 0),
3243     BEACON_FILTER(WLAN_EID_OPMODE_NOTIF, 0, 0, 0,
3244               WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK, 0),
3245     BEACON_FILTER(WLAN_EID_VHT_OPERATION, 0, 0, 0,
3246               WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK, 0),
3247     BEACON_FILTER(WLAN_EID_RSN, 1, 0, 0,
3248               WCN36XX_FILTER_IE_RSN_MASK, 0),
3249     BEACON_FILTER(WLAN_EID_VENDOR_SPECIFIC, 1, 0, 0,
3250               WCN36XX_FILTER_IE_VENDOR_MASK, 0),
3251 };
3252 
3253 int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn,
3254                   struct ieee80211_vif *vif)
3255 {
3256     struct wcn36xx_hal_add_bcn_filter_req_msg msg_body, *body;
3257     struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3258     u8 *payload;
3259     size_t payload_size;
3260     int ret;
3261 
3262     if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, BCN_FILTER))
3263         return -EOPNOTSUPP;
3264 
3265     mutex_lock(&wcn->hal_mutex);
3266     INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BCN_FILTER_REQ);
3267 
3268     PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3269 
3270     body = (struct wcn36xx_hal_add_bcn_filter_req_msg *)wcn->hal_buf;
3271     body->capability_info = vif->bss_conf.assoc_capability;
3272     body->capability_mask = WCN36XX_FILTER_CAPABILITY_MASK;
3273     body->beacon_interval = vif->bss_conf.beacon_int;
3274     body->ie_num = ARRAY_SIZE(bcn_filter_ies);
3275     body->bss_index = vif_priv->bss_index;
3276 
3277     payload = ((u8 *)body) + body->header.len;
3278     payload_size = sizeof(bcn_filter_ies);
3279     memcpy(payload, &bcn_filter_ies, payload_size);
3280 
3281     body->header.len += payload_size;
3282 
3283     ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
3284     if (ret) {
3285         wcn36xx_err("Sending add bcn_filter failed\n");
3286         goto out;
3287     }
3288 
3289     ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3290     if (ret) {
3291         wcn36xx_err("add bcn filter response failed err=%d\n", ret);
3292         goto out;
3293     }
3294 out:
3295     mutex_unlock(&wcn->hal_mutex);
3296     return ret;
3297 }
3298 
3299 int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
3300                 void *buf, int len, void *priv, u32 addr)
3301 {
3302     const struct wcn36xx_hal_msg_header *msg_header = buf;
3303     struct ieee80211_hw *hw = priv;
3304     struct wcn36xx *wcn = hw->priv;
3305     struct wcn36xx_hal_ind_msg *msg_ind;
3306     wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
3307 
3308     switch (msg_header->msg_type) {
3309     case WCN36XX_HAL_START_RSP:
3310     case WCN36XX_HAL_CONFIG_STA_RSP:
3311     case WCN36XX_HAL_CONFIG_BSS_RSP:
3312     case WCN36XX_HAL_ADD_STA_SELF_RSP:
3313     case WCN36XX_HAL_STOP_RSP:
3314     case WCN36XX_HAL_DEL_STA_SELF_RSP:
3315     case WCN36XX_HAL_DELETE_STA_RSP:
3316     case WCN36XX_HAL_INIT_SCAN_RSP:
3317     case WCN36XX_HAL_START_SCAN_RSP:
3318     case WCN36XX_HAL_END_SCAN_RSP:
3319     case WCN36XX_HAL_FINISH_SCAN_RSP:
3320     case WCN36XX_HAL_DOWNLOAD_NV_RSP:
3321     case WCN36XX_HAL_DELETE_BSS_RSP:
3322     case WCN36XX_HAL_SEND_BEACON_RSP:
3323     case WCN36XX_HAL_SET_LINK_ST_RSP:
3324     case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
3325     case WCN36XX_HAL_SET_BSSKEY_RSP:
3326     case WCN36XX_HAL_SET_STAKEY_RSP:
3327     case WCN36XX_HAL_RMV_STAKEY_RSP:
3328     case WCN36XX_HAL_RMV_BSSKEY_RSP:
3329     case WCN36XX_HAL_ENTER_BMPS_RSP:
3330     case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
3331     case WCN36XX_HAL_EXIT_BMPS_RSP:
3332     case WCN36XX_HAL_KEEP_ALIVE_RSP:
3333     case WCN36XX_HAL_DUMP_COMMAND_RSP:
3334     case WCN36XX_HAL_ADD_BA_SESSION_RSP:
3335     case WCN36XX_HAL_ADD_BA_RSP:
3336     case WCN36XX_HAL_DEL_BA_RSP:
3337     case WCN36XX_HAL_GET_STATS_RSP:
3338     case WCN36XX_HAL_TRIGGER_BA_RSP:
3339     case WCN36XX_HAL_UPDATE_CFG_RSP:
3340     case WCN36XX_HAL_JOIN_RSP:
3341     case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
3342     case WCN36XX_HAL_CH_SWITCH_RSP:
3343     case WCN36XX_HAL_PROCESS_PTT_RSP:
3344     case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
3345     case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
3346     case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP:
3347     case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP:
3348     case WCN36XX_HAL_HOST_OFFLOAD_RSP:
3349     case WCN36XX_HAL_GTK_OFFLOAD_RSP:
3350     case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP:
3351     case WCN36XX_HAL_HOST_RESUME_RSP:
3352     case WCN36XX_HAL_ENTER_IMPS_RSP:
3353     case WCN36XX_HAL_EXIT_IMPS_RSP:
3354     case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP:
3355     case WCN36XX_HAL_ADD_BCN_FILTER_RSP:
3356         memcpy(wcn->hal_buf, buf, len);
3357         wcn->hal_rsp_len = len;
3358         complete(&wcn->hal_rsp_compl);
3359         break;
3360 
3361     case WCN36XX_HAL_COEX_IND:
3362     case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3363     case WCN36XX_HAL_DEL_BA_IND:
3364     case WCN36XX_HAL_OTA_TX_COMPL_IND:
3365     case WCN36XX_HAL_MISSED_BEACON_IND:
3366     case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3367     case WCN36XX_HAL_PRINT_REG_INFO_IND:
3368     case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3369         msg_ind = kmalloc(struct_size(msg_ind, msg, len), GFP_ATOMIC);
3370         if (!msg_ind) {
3371             wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
3372                     msg_header->msg_type);
3373             return -ENOMEM;
3374         }
3375 
3376         msg_ind->msg_len = len;
3377         memcpy(msg_ind->msg, buf, len);
3378 
3379         spin_lock(&wcn->hal_ind_lock);
3380         list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
3381         queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
3382         spin_unlock(&wcn->hal_ind_lock);
3383         wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
3384         break;
3385     default:
3386         wcn36xx_err("SMD_EVENT (%d) not supported\n",
3387                   msg_header->msg_type);
3388     }
3389 
3390     return 0;
3391 }
3392 
3393 static void wcn36xx_ind_smd_work(struct work_struct *work)
3394 {
3395     struct wcn36xx *wcn =
3396         container_of(work, struct wcn36xx, hal_ind_work);
3397 
3398     for (;;) {
3399         struct wcn36xx_hal_msg_header *msg_header;
3400         struct wcn36xx_hal_ind_msg *hal_ind_msg;
3401         unsigned long flags;
3402 
3403         spin_lock_irqsave(&wcn->hal_ind_lock, flags);
3404 
3405         if (list_empty(&wcn->hal_ind_queue)) {
3406             spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3407             return;
3408         }
3409 
3410         hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
3411                            struct wcn36xx_hal_ind_msg,
3412                            list);
3413         list_del(&hal_ind_msg->list);
3414         spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3415 
3416         msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
3417 
3418         switch (msg_header->msg_type) {
3419         case WCN36XX_HAL_COEX_IND:
3420         case WCN36XX_HAL_DEL_BA_IND:
3421         case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3422             break;
3423         case WCN36XX_HAL_OTA_TX_COMPL_IND:
3424             wcn36xx_smd_tx_compl_ind(wcn,
3425                          hal_ind_msg->msg,
3426                          hal_ind_msg->msg_len);
3427             break;
3428         case WCN36XX_HAL_MISSED_BEACON_IND:
3429             wcn36xx_smd_missed_beacon_ind(wcn,
3430                               hal_ind_msg->msg,
3431                               hal_ind_msg->msg_len);
3432             break;
3433         case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3434             wcn36xx_smd_delete_sta_context_ind(wcn,
3435                                hal_ind_msg->msg,
3436                                hal_ind_msg->msg_len);
3437             break;
3438         case WCN36XX_HAL_PRINT_REG_INFO_IND:
3439             wcn36xx_smd_print_reg_info_ind(wcn,
3440                                hal_ind_msg->msg,
3441                                hal_ind_msg->msg_len);
3442             break;
3443         case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3444             wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
3445                         hal_ind_msg->msg_len);
3446             break;
3447         default:
3448             wcn36xx_err("SMD_EVENT (%d) not supported\n",
3449                     msg_header->msg_type);
3450         }
3451 
3452         kfree(hal_ind_msg);
3453     }
3454 }
3455 
3456 int wcn36xx_smd_open(struct wcn36xx *wcn)
3457 {
3458     wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
3459     if (!wcn->hal_ind_wq)
3460         return -ENOMEM;
3461 
3462     INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
3463     INIT_LIST_HEAD(&wcn->hal_ind_queue);
3464     spin_lock_init(&wcn->hal_ind_lock);
3465 
3466     return 0;
3467 }
3468 
3469 void wcn36xx_smd_close(struct wcn36xx *wcn)
3470 {
3471     struct wcn36xx_hal_ind_msg *msg, *tmp;
3472 
3473     cancel_work_sync(&wcn->hal_ind_work);
3474     destroy_workqueue(wcn->hal_ind_wq);
3475 
3476     list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list)
3477         kfree(msg);
3478 }