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