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