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