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