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_update_scan_params_rsp(void *buf, size_t len) 1131 { 1132 struct wcn36xx_hal_update_scan_params_resp *rsp; 1133 1134 rsp = buf; 1135 1136 /* Remove the PNO version bit */ 1137 rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK)); 1138 1139 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) { 1140 wcn36xx_warn("error response from update scan\n"); 1141 return rsp->status; 1142 } 1143 1144 return 0; 1145 } 1146 1147 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, 1148 u8 *channels, size_t channel_count) 1149 { 1150 struct wcn36xx_hal_update_scan_params_req_ex msg_body; 1151 int ret; 1152 1153 mutex_lock(&wcn->hal_mutex); 1154 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ); 1155 1156 msg_body.dot11d_enabled = false; 1157 msg_body.dot11d_resolved = true; 1158 1159 msg_body.channel_count = channel_count; 1160 memcpy(msg_body.channels, channels, channel_count); 1161 msg_body.active_min_ch_time = 60; 1162 msg_body.active_max_ch_time = 120; 1163 msg_body.passive_min_ch_time = 60; 1164 msg_body.passive_max_ch_time = 110; 1165 msg_body.state = PHY_SINGLE_CHANNEL_CENTERED; 1166 1167 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1168 1169 wcn36xx_dbg(WCN36XX_DBG_HAL, 1170 "hal update scan params channel_count %d\n", 1171 msg_body.channel_count); 1172 1173 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1174 if (ret) { 1175 wcn36xx_err("Sending hal_update_scan_params failed\n"); 1176 goto out; 1177 } 1178 ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf, 1179 wcn->hal_rsp_len); 1180 if (ret) { 1181 wcn36xx_err("hal_update_scan_params response failed err=%d\n", 1182 ret); 1183 goto out; 1184 } 1185 out: 1186 mutex_unlock(&wcn->hal_mutex); 1187 return ret; 1188 } 1189 1190 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, 1191 struct ieee80211_vif *vif, 1192 void *buf, 1193 size_t len) 1194 { 1195 struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; 1196 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 1197 1198 if (len < sizeof(*rsp)) 1199 return -EINVAL; 1200 1201 rsp = buf; 1202 1203 if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 1204 wcn36xx_warn("hal add sta self failure: %d\n", 1205 rsp->status); 1206 return rsp->status; 1207 } 1208 1209 wcn36xx_dbg(WCN36XX_DBG_HAL, 1210 "hal add sta self status %d self_sta_index %d dpu_index %d\n", 1211 rsp->status, rsp->self_sta_index, rsp->dpu_index); 1212 1213 vif_priv->self_sta_index = rsp->self_sta_index; 1214 vif_priv->self_dpu_desc_index = rsp->dpu_index; 1215 1216 return 0; 1217 } 1218 1219 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1220 { 1221 struct wcn36xx_hal_add_sta_self_req msg_body; 1222 int ret; 1223 1224 mutex_lock(&wcn->hal_mutex); 1225 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ); 1226 1227 memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN); 1228 1229 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1230 1231 wcn36xx_dbg(WCN36XX_DBG_HAL, 1232 "hal add sta self self_addr %pM status %d\n", 1233 msg_body.self_addr, msg_body.status); 1234 1235 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1236 if (ret) { 1237 wcn36xx_err("Sending hal_add_sta_self failed\n"); 1238 goto out; 1239 } 1240 ret = wcn36xx_smd_add_sta_self_rsp(wcn, 1241 vif, 1242 wcn->hal_buf, 1243 wcn->hal_rsp_len); 1244 if (ret) { 1245 wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret); 1246 goto out; 1247 } 1248 out: 1249 mutex_unlock(&wcn->hal_mutex); 1250 return ret; 1251 } 1252 1253 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr) 1254 { 1255 struct wcn36xx_hal_del_sta_self_req_msg msg_body; 1256 int ret; 1257 1258 mutex_lock(&wcn->hal_mutex); 1259 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ); 1260 1261 memcpy(&msg_body.self_addr, addr, ETH_ALEN); 1262 1263 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1264 1265 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1266 if (ret) { 1267 wcn36xx_err("Sending hal_delete_sta_self failed\n"); 1268 goto out; 1269 } 1270 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1271 if (ret) { 1272 wcn36xx_err("hal_delete_sta_self response failed err=%d\n", 1273 ret); 1274 goto out; 1275 } 1276 out: 1277 mutex_unlock(&wcn->hal_mutex); 1278 return ret; 1279 } 1280 1281 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index) 1282 { 1283 struct wcn36xx_hal_delete_sta_req_msg msg_body; 1284 int ret; 1285 1286 mutex_lock(&wcn->hal_mutex); 1287 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ); 1288 1289 msg_body.sta_index = sta_index; 1290 1291 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1292 1293 wcn36xx_dbg(WCN36XX_DBG_HAL, 1294 "hal delete sta sta_index %d\n", 1295 msg_body.sta_index); 1296 1297 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1298 if (ret) { 1299 wcn36xx_err("Sending hal_delete_sta failed\n"); 1300 goto out; 1301 } 1302 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1303 if (ret) { 1304 wcn36xx_err("hal_delete_sta response failed err=%d\n", ret); 1305 goto out; 1306 } 1307 out: 1308 mutex_unlock(&wcn->hal_mutex); 1309 return ret; 1310 } 1311 1312 static int wcn36xx_smd_join_rsp(void *buf, size_t len) 1313 { 1314 struct wcn36xx_hal_join_rsp_msg *rsp; 1315 1316 if (wcn36xx_smd_rsp_status_check(buf, len)) 1317 return -EIO; 1318 1319 rsp = buf; 1320 1321 wcn36xx_dbg(WCN36XX_DBG_HAL, 1322 "hal rsp join status %d tx_mgmt_power %d\n", 1323 rsp->status, rsp->tx_mgmt_power); 1324 1325 return 0; 1326 } 1327 1328 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch) 1329 { 1330 struct wcn36xx_hal_join_req_msg msg_body; 1331 int ret; 1332 1333 mutex_lock(&wcn->hal_mutex); 1334 INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ); 1335 1336 memcpy(&msg_body.bssid, bssid, ETH_ALEN); 1337 memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN); 1338 msg_body.channel = ch; 1339 1340 if (conf_is_ht40_minus(&wcn->hw->conf)) 1341 msg_body.secondary_channel_offset = 1342 PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; 1343 else if (conf_is_ht40_plus(&wcn->hw->conf)) 1344 msg_body.secondary_channel_offset = 1345 PHY_DOUBLE_CHANNEL_LOW_PRIMARY; 1346 else 1347 msg_body.secondary_channel_offset = 1348 PHY_SINGLE_CHANNEL_CENTERED; 1349 1350 msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE; 1351 1352 msg_body.max_tx_power = 0xbf; 1353 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1354 1355 wcn36xx_dbg(WCN36XX_DBG_HAL, 1356 "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n", 1357 msg_body.bssid, msg_body.self_sta_mac_addr, 1358 msg_body.channel, msg_body.link_state); 1359 1360 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1361 if (ret) { 1362 wcn36xx_err("Sending hal_join failed\n"); 1363 goto out; 1364 } 1365 ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len); 1366 if (ret) { 1367 wcn36xx_err("hal_join response failed err=%d\n", ret); 1368 goto out; 1369 } 1370 out: 1371 mutex_unlock(&wcn->hal_mutex); 1372 return ret; 1373 } 1374 1375 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, 1376 const u8 *sta_mac, 1377 enum wcn36xx_hal_link_state state) 1378 { 1379 struct wcn36xx_hal_set_link_state_req_msg msg_body; 1380 int ret; 1381 1382 mutex_lock(&wcn->hal_mutex); 1383 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ); 1384 1385 memcpy(&msg_body.bssid, bssid, ETH_ALEN); 1386 memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN); 1387 msg_body.state = state; 1388 1389 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1390 1391 wcn36xx_dbg(WCN36XX_DBG_HAL, 1392 "hal set link state bssid %pM self_mac_addr %pM state %d\n", 1393 msg_body.bssid, msg_body.self_mac_addr, msg_body.state); 1394 1395 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1396 if (ret) { 1397 wcn36xx_err("Sending hal_set_link_st failed\n"); 1398 goto out; 1399 } 1400 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1401 if (ret) { 1402 wcn36xx_err("hal_set_link_st response failed err=%d\n", ret); 1403 goto out; 1404 } 1405 out: 1406 mutex_unlock(&wcn->hal_mutex); 1407 return ret; 1408 } 1409 1410 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, 1411 const struct wcn36xx_hal_config_sta_params *orig, 1412 struct wcn36xx_hal_config_sta_params_v1 *v1) 1413 { 1414 /* convert orig to v1 format */ 1415 memcpy(&v1->bssid, orig->bssid, ETH_ALEN); 1416 memcpy(&v1->mac, orig->mac, ETH_ALEN); 1417 v1->aid = orig->aid; 1418 v1->type = orig->type; 1419 v1->short_preamble_supported = orig->short_preamble_supported; 1420 v1->listen_interval = orig->listen_interval; 1421 v1->wmm_enabled = orig->wmm_enabled; 1422 v1->ht_capable = orig->ht_capable; 1423 v1->tx_channel_width_set = orig->tx_channel_width_set; 1424 v1->rifs_mode = orig->rifs_mode; 1425 v1->lsig_txop_protection = orig->lsig_txop_protection; 1426 v1->max_ampdu_size = orig->max_ampdu_size; 1427 v1->max_ampdu_density = orig->max_ampdu_density; 1428 v1->sgi_40mhz = orig->sgi_40mhz; 1429 v1->sgi_20Mhz = orig->sgi_20Mhz; 1430 v1->rmf = orig->rmf; 1431 v1->encrypt_type = orig->encrypt_type; 1432 v1->action = orig->action; 1433 v1->uapsd = orig->uapsd; 1434 v1->max_sp_len = orig->max_sp_len; 1435 v1->green_field_capable = orig->green_field_capable; 1436 v1->mimo_ps = orig->mimo_ps; 1437 v1->delayed_ba_support = orig->delayed_ba_support; 1438 v1->max_ampdu_duration = orig->max_ampdu_duration; 1439 v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz; 1440 memcpy(&v1->supported_rates, &orig->supported_rates, 1441 sizeof(orig->supported_rates)); 1442 v1->sta_index = orig->sta_index; 1443 v1->bssid_index = orig->bssid_index; 1444 v1->p2p = orig->p2p; 1445 } 1446 1447 static void 1448 wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn, 1449 struct ieee80211_vif *vif, 1450 struct ieee80211_sta *sta, 1451 struct wcn36xx_hal_config_sta_params_v1 *sta_par) 1452 { 1453 struct wcn36xx_sta *sta_priv = NULL; 1454 struct wcn36xx_hal_config_sta_params sta_par_v0; 1455 1456 wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0); 1457 wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par); 1458 1459 if (sta) { 1460 sta_priv = wcn36xx_sta_to_priv(sta); 1461 wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par); 1462 wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par); 1463 memcpy(&sta_par->supported_rates, &sta_priv->supported_rates, 1464 sizeof(sta_par->supported_rates)); 1465 } else { 1466 wcn36xx_set_default_rates_v1(&sta_par->supported_rates); 1467 wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par); 1468 wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par); 1469 } 1470 } 1471 1472 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, 1473 struct ieee80211_sta *sta, 1474 void *buf, 1475 size_t len) 1476 { 1477 struct wcn36xx_hal_config_sta_rsp_msg *rsp; 1478 struct config_sta_rsp_params *params; 1479 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); 1480 1481 if (len < sizeof(*rsp)) 1482 return -EINVAL; 1483 1484 rsp = buf; 1485 params = &rsp->params; 1486 1487 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 1488 wcn36xx_warn("hal config sta response failure: %d\n", 1489 params->status); 1490 return -EIO; 1491 } 1492 1493 sta_priv->sta_index = params->sta_index; 1494 sta_priv->dpu_desc_index = params->dpu_index; 1495 sta_priv->ucast_dpu_sign = params->uc_ucast_sig; 1496 1497 wcn36xx_dbg(WCN36XX_DBG_HAL, 1498 "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n", 1499 params->status, params->sta_index, params->bssid_index, 1500 params->uc_ucast_sig, params->p2p); 1501 1502 return 0; 1503 } 1504 1505 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, 1506 struct ieee80211_vif *vif, 1507 struct ieee80211_sta *sta) 1508 { 1509 struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; 1510 struct wcn36xx_hal_config_sta_params_v1 *sta_params; 1511 1512 if (wcn->rf_id == RF_IRIS_WCN3680) { 1513 INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); 1514 } else { 1515 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); 1516 msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT; 1517 } 1518 1519 sta_params = &msg_body.sta_params; 1520 1521 wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params); 1522 1523 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1524 1525 wcn36xx_dbg(WCN36XX_DBG_HAL, 1526 "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", 1527 sta_params->action, sta_params->sta_index, sta_params->bssid_index, 1528 sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid); 1529 1530 return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1531 } 1532 1533 static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn, 1534 struct ieee80211_vif *vif, 1535 struct ieee80211_sta *sta) 1536 { 1537 struct wcn36xx_hal_config_sta_req_msg msg; 1538 struct wcn36xx_hal_config_sta_params *sta_params; 1539 1540 INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ); 1541 1542 sta_params = &msg.sta_params; 1543 1544 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); 1545 1546 PREPARE_HAL_BUF(wcn->hal_buf, msg); 1547 1548 wcn36xx_dbg(WCN36XX_DBG_HAL, 1549 "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", 1550 sta_params->action, sta_params->sta_index, 1551 sta_params->bssid_index, sta_params->bssid, 1552 sta_params->type, sta_params->mac, sta_params->aid); 1553 1554 return wcn36xx_smd_send_and_wait(wcn, msg.header.len); 1555 } 1556 1557 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, 1558 struct ieee80211_sta *sta) 1559 { 1560 int ret; 1561 1562 mutex_lock(&wcn->hal_mutex); 1563 1564 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) 1565 ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta); 1566 else 1567 ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta); 1568 1569 if (ret) { 1570 wcn36xx_err("Sending hal_config_sta failed\n"); 1571 goto out; 1572 } 1573 ret = wcn36xx_smd_config_sta_rsp(wcn, 1574 sta, 1575 wcn->hal_buf, 1576 wcn->hal_rsp_len); 1577 if (ret) { 1578 wcn36xx_err("hal_config_sta response failed err=%d\n", ret); 1579 goto out; 1580 } 1581 out: 1582 mutex_unlock(&wcn->hal_mutex); 1583 return ret; 1584 } 1585 1586 static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn, 1587 struct ieee80211_vif *vif, 1588 struct ieee80211_sta *sta, 1589 const u8 *bssid, 1590 bool update, 1591 struct wcn36xx_hal_config_bss_params *bss) 1592 { 1593 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 1594 1595 WARN_ON(is_zero_ether_addr(bssid)); 1596 1597 memcpy(&bss->bssid, bssid, ETH_ALEN); 1598 1599 memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN); 1600 1601 if (vif->type == NL80211_IFTYPE_STATION) { 1602 bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE; 1603 1604 /* STA */ 1605 bss->oper_mode = 1; 1606 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE; 1607 } else if (vif->type == NL80211_IFTYPE_AP || 1608 vif->type == NL80211_IFTYPE_MESH_POINT) { 1609 bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; 1610 1611 /* AP */ 1612 bss->oper_mode = 0; 1613 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE; 1614 } else if (vif->type == NL80211_IFTYPE_ADHOC) { 1615 bss->bss_type = WCN36XX_HAL_IBSS_MODE; 1616 1617 /* STA */ 1618 bss->oper_mode = 1; 1619 } else { 1620 wcn36xx_warn("Unknown type for bss config: %d\n", vif->type); 1621 } 1622 1623 if (vif->type == NL80211_IFTYPE_STATION) 1624 wcn36xx_smd_set_bss_nw_type(wcn, sta, bss); 1625 else 1626 bss->nw_type = WCN36XX_HAL_11N_NW_TYPE; 1627 1628 bss->short_slot_time_supported = vif->bss_conf.use_short_slot; 1629 bss->lla_coexist = 0; 1630 bss->llb_coexist = 0; 1631 bss->llg_coexist = 0; 1632 bss->rifs_mode = 0; 1633 bss->beacon_interval = vif->bss_conf.beacon_int; 1634 bss->dtim_period = vif_priv->dtim_period; 1635 1636 wcn36xx_smd_set_bss_ht_params(vif, sta, bss); 1637 1638 bss->oper_channel = WCN36XX_HW_CHANNEL(wcn); 1639 1640 if (conf_is_ht40_minus(&wcn->hw->conf)) 1641 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW; 1642 else if (conf_is_ht40_plus(&wcn->hw->conf)) 1643 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 1644 else 1645 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE; 1646 1647 bss->reserved = 0; 1648 1649 /* wcn->ssid is only valid in AP and IBSS mode */ 1650 bss->ssid.length = vif_priv->ssid.length; 1651 memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length); 1652 1653 bss->obss_prot_enabled = 0; 1654 bss->rmf = 0; 1655 bss->max_probe_resp_retry_limit = 0; 1656 bss->hidden_ssid = vif->bss_conf.hidden_ssid; 1657 bss->proxy_probe_resp = 0; 1658 bss->edca_params_valid = 0; 1659 1660 /* FIXME: set acbe, acbk, acvi and acvo */ 1661 1662 bss->ext_set_sta_key_param_valid = 0; 1663 1664 /* FIXME: set ext_set_sta_key_param */ 1665 1666 bss->spectrum_mgt_enable = 0; 1667 bss->tx_mgmt_power = 0; 1668 bss->max_tx_power = WCN36XX_MAX_POWER(wcn); 1669 bss->action = update; 1670 1671 vif_priv->bss_type = bss->bss_type; 1672 } 1673 1674 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, 1675 struct ieee80211_vif *vif, 1676 struct ieee80211_sta *sta_80211, 1677 const u8 *bssid, 1678 bool update) 1679 { 1680 struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body; 1681 struct wcn36xx_hal_config_bss_params_v1 *bss; 1682 struct wcn36xx_hal_config_bss_params bss_v0; 1683 struct wcn36xx_hal_config_sta_params_v1 *sta; 1684 struct cfg80211_chan_def *chandef; 1685 int ret; 1686 1687 msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL); 1688 if (!msg_body) 1689 return -ENOMEM; 1690 1691 if (wcn->rf_id == RF_IRIS_WCN3680) { 1692 INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ); 1693 } else { 1694 INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ); 1695 msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT; 1696 } 1697 1698 bss = &msg_body->bss_params; 1699 sta = &bss->sta; 1700 1701 memset(&bss_v0, 0x00, sizeof(bss_v0)); 1702 wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0); 1703 wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta); 1704 1705 /* convert orig to v1 */ 1706 memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN); 1707 memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN); 1708 1709 bss->bss_type = bss_v0.bss_type; 1710 bss->oper_mode = bss_v0.oper_mode; 1711 bss->nw_type = bss_v0.nw_type; 1712 1713 bss->short_slot_time_supported = 1714 bss_v0.short_slot_time_supported; 1715 bss->lla_coexist = bss_v0.lla_coexist; 1716 bss->llb_coexist = bss_v0.llb_coexist; 1717 bss->llg_coexist = bss_v0.llg_coexist; 1718 bss->ht20_coexist = bss_v0.ht20_coexist; 1719 bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist; 1720 1721 bss->lsig_tx_op_protection_full_support = 1722 bss_v0.lsig_tx_op_protection_full_support; 1723 bss->rifs_mode = bss_v0.rifs_mode; 1724 bss->beacon_interval = bss_v0.beacon_interval; 1725 bss->dtim_period = bss_v0.dtim_period; 1726 bss->tx_channel_width_set = bss_v0.tx_channel_width_set; 1727 bss->oper_channel = bss_v0.oper_channel; 1728 1729 if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) { 1730 chandef = &wcn->hw->conf.chandef; 1731 bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value); 1732 } else { 1733 bss->ext_channel = bss_v0.ext_channel; 1734 } 1735 1736 bss->reserved = bss_v0.reserved; 1737 1738 memcpy(&bss->ssid, &bss_v0.ssid, 1739 sizeof(bss_v0.ssid)); 1740 1741 bss->action = bss_v0.action; 1742 bss->rateset = bss_v0.rateset; 1743 bss->ht = bss_v0.ht; 1744 bss->obss_prot_enabled = bss_v0.obss_prot_enabled; 1745 bss->rmf = bss_v0.rmf; 1746 bss->ht_oper_mode = bss_v0.ht_oper_mode; 1747 bss->dual_cts_protection = bss_v0.dual_cts_protection; 1748 1749 bss->max_probe_resp_retry_limit = 1750 bss_v0.max_probe_resp_retry_limit; 1751 bss->hidden_ssid = bss_v0.hidden_ssid; 1752 bss->proxy_probe_resp = bss_v0.proxy_probe_resp; 1753 bss->edca_params_valid = bss_v0.edca_params_valid; 1754 1755 memcpy(&bss->acbe, &bss_v0.acbe, 1756 sizeof(bss_v0.acbe)); 1757 memcpy(&bss->acbk, &bss_v0.acbk, 1758 sizeof(bss_v0.acbk)); 1759 memcpy(&bss->acvi, &bss_v0.acvi, 1760 sizeof(bss_v0.acvi)); 1761 memcpy(&bss->acvo, &bss_v0.acvo, 1762 sizeof(bss_v0.acvo)); 1763 1764 bss->ext_set_sta_key_param_valid = 1765 bss_v0.ext_set_sta_key_param_valid; 1766 1767 memcpy(&bss->ext_set_sta_key_param, 1768 &bss_v0.ext_set_sta_key_param, 1769 sizeof(bss_v0.acvo)); 1770 1771 bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona; 1772 bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable; 1773 bss->tx_mgmt_power = bss_v0.tx_mgmt_power; 1774 bss->max_tx_power = bss_v0.max_tx_power; 1775 1776 wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss); 1777 1778 PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body)); 1779 1780 wcn36xx_dbg(WCN36XX_DBG_HAL, 1781 "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", 1782 bss->bssid, bss->self_mac_addr, bss->bss_type, 1783 bss->oper_mode, bss->nw_type); 1784 1785 wcn36xx_dbg(WCN36XX_DBG_HAL, 1786 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", 1787 sta->bssid, sta->action, sta->sta_index, 1788 sta->bssid_index, sta->aid, sta->type, sta->mac); 1789 1790 ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); 1791 kfree(msg_body); 1792 1793 return ret; 1794 } 1795 1796 static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn, 1797 struct ieee80211_vif *vif, 1798 struct ieee80211_sta *sta, 1799 const u8 *bssid, 1800 bool update) 1801 { 1802 struct wcn36xx_hal_config_bss_req_msg *msg; 1803 struct wcn36xx_hal_config_bss_params *bss; 1804 struct wcn36xx_hal_config_sta_params *sta_params; 1805 int ret; 1806 1807 msg = kzalloc(sizeof(*msg), GFP_KERNEL); 1808 if (!msg) 1809 return -ENOMEM; 1810 1811 INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ); 1812 1813 bss = &msg->bss_params; 1814 sta_params = &bss->sta; 1815 1816 wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss); 1817 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); 1818 1819 PREPARE_HAL_BUF(wcn->hal_buf, (*msg)); 1820 1821 wcn36xx_dbg(WCN36XX_DBG_HAL, 1822 "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", 1823 bss->bssid, bss->self_mac_addr, bss->bss_type, 1824 bss->oper_mode, bss->nw_type); 1825 1826 wcn36xx_dbg(WCN36XX_DBG_HAL, 1827 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", 1828 sta_params->bssid, sta_params->action, 1829 sta_params->sta_index, sta_params->bssid_index, 1830 sta_params->aid, sta_params->type, 1831 sta_params->mac); 1832 1833 ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len); 1834 kfree(msg); 1835 1836 return ret; 1837 } 1838 1839 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, 1840 struct ieee80211_vif *vif, 1841 struct ieee80211_sta *sta, 1842 void *buf, 1843 size_t len) 1844 { 1845 struct wcn36xx_hal_config_bss_rsp_msg *rsp; 1846 struct wcn36xx_hal_config_bss_rsp_params *params; 1847 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 1848 1849 if (len < sizeof(*rsp)) 1850 return -EINVAL; 1851 1852 rsp = buf; 1853 params = &rsp->bss_rsp_params; 1854 1855 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 1856 wcn36xx_warn("hal config bss response failure: %d\n", 1857 params->status); 1858 return -EIO; 1859 } 1860 1861 wcn36xx_dbg(WCN36XX_DBG_HAL, 1862 "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" 1863 " sta_idx %d self_idx %d bcast_idx %d mac %pM" 1864 " power %d ucast_dpu_signature %d\n", 1865 params->status, params->bss_index, params->dpu_desc_index, 1866 params->bss_sta_index, params->bss_self_sta_index, 1867 params->bss_bcast_sta_idx, params->mac, 1868 params->tx_mgmt_power, params->ucast_dpu_signature); 1869 1870 vif_priv->bss_index = params->bss_index; 1871 1872 if (sta) { 1873 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); 1874 sta_priv->bss_sta_index = params->bss_sta_index; 1875 sta_priv->bss_dpu_desc_index = params->dpu_desc_index; 1876 } 1877 1878 vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature; 1879 1880 return 0; 1881 } 1882 1883 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, 1884 struct ieee80211_sta *sta, const u8 *bssid, 1885 bool update) 1886 { 1887 int ret; 1888 1889 mutex_lock(&wcn->hal_mutex); 1890 1891 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) 1892 ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update); 1893 else 1894 ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update); 1895 1896 if (ret) { 1897 wcn36xx_err("Sending hal_config_bss failed\n"); 1898 goto out; 1899 } 1900 ret = wcn36xx_smd_config_bss_rsp(wcn, 1901 vif, 1902 sta, 1903 wcn->hal_buf, 1904 wcn->hal_rsp_len); 1905 if (ret) 1906 wcn36xx_err("hal_config_bss response failed err=%d\n", ret); 1907 1908 out: 1909 mutex_unlock(&wcn->hal_mutex); 1910 return ret; 1911 } 1912 1913 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1914 { 1915 struct wcn36xx_hal_delete_bss_req_msg msg_body; 1916 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 1917 int ret = 0; 1918 1919 mutex_lock(&wcn->hal_mutex); 1920 1921 if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX) 1922 goto out; 1923 1924 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); 1925 1926 msg_body.bss_index = vif_priv->bss_index; 1927 1928 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1929 1930 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index); 1931 1932 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1933 if (ret) { 1934 wcn36xx_err("Sending hal_delete_bss failed\n"); 1935 goto out; 1936 } 1937 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1938 if (ret) { 1939 wcn36xx_err("hal_delete_bss response failed err=%d\n", ret); 1940 goto out; 1941 } 1942 1943 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; 1944 out: 1945 mutex_unlock(&wcn->hal_mutex); 1946 return ret; 1947 } 1948 1949 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, 1950 struct sk_buff *skb_beacon, u16 tim_off, 1951 u16 p2p_off) 1952 { 1953 struct wcn36xx_hal_send_beacon_req_msg msg_body; 1954 int ret, pad, pvm_len; 1955 1956 mutex_lock(&wcn->hal_mutex); 1957 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); 1958 1959 pvm_len = skb_beacon->data[tim_off + 1] - 3; 1960 pad = TIM_MIN_PVM_SIZE - pvm_len; 1961 1962 /* Padding is irrelevant to mesh mode since tim_off is always 0. */ 1963 if (vif->type == NL80211_IFTYPE_MESH_POINT) 1964 pad = 0; 1965 1966 msg_body.beacon_length = skb_beacon->len + pad; 1967 /* TODO need to find out why + 6 is needed */ 1968 msg_body.beacon_length6 = msg_body.beacon_length + 6; 1969 1970 if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) { 1971 wcn36xx_err("Beacon is too big: beacon size=%d\n", 1972 msg_body.beacon_length); 1973 ret = -ENOMEM; 1974 goto out; 1975 } 1976 memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len); 1977 memcpy(msg_body.bssid, vif->addr, ETH_ALEN); 1978 1979 if (pad > 0) { 1980 /* 1981 * The wcn36xx FW has a fixed size for the PVM in the TIM. If 1982 * given the beacon template from mac80211 with a PVM shorter 1983 * than the FW expectes it will overwrite the data after the 1984 * TIM. 1985 */ 1986 wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n", 1987 pad, pvm_len); 1988 memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad], 1989 &msg_body.beacon[tim_off + 5 + pvm_len], 1990 skb_beacon->len - (tim_off + 5 + pvm_len)); 1991 memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad); 1992 msg_body.beacon[tim_off + 1] += pad; 1993 } 1994 1995 /* TODO need to find out why this is needed? */ 1996 if (vif->type == NL80211_IFTYPE_MESH_POINT) 1997 /* mesh beacon don't need this, so push further down */ 1998 msg_body.tim_ie_offset = 256; 1999 else 2000 msg_body.tim_ie_offset = tim_off+4; 2001 msg_body.p2p_ie_offset = p2p_off; 2002 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2003 2004 wcn36xx_dbg(WCN36XX_DBG_HAL, 2005 "hal send beacon beacon_length %d\n", 2006 msg_body.beacon_length); 2007 2008 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2009 if (ret) { 2010 wcn36xx_err("Sending hal_send_beacon failed\n"); 2011 goto out; 2012 } 2013 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2014 if (ret) { 2015 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret); 2016 goto out; 2017 } 2018 out: 2019 mutex_unlock(&wcn->hal_mutex); 2020 return ret; 2021 } 2022 2023 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, 2024 struct ieee80211_vif *vif, 2025 struct sk_buff *skb) 2026 { 2027 struct wcn36xx_hal_send_probe_resp_req_msg msg; 2028 int ret; 2029 2030 mutex_lock(&wcn->hal_mutex); 2031 INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ); 2032 2033 if (skb->len > BEACON_TEMPLATE_SIZE) { 2034 wcn36xx_warn("probe response template is too big: %d\n", 2035 skb->len); 2036 ret = -E2BIG; 2037 goto out; 2038 } 2039 2040 msg.probe_resp_template_len = skb->len; 2041 memcpy(&msg.probe_resp_template, skb->data, skb->len); 2042 2043 memcpy(msg.bssid, vif->addr, ETH_ALEN); 2044 2045 PREPARE_HAL_BUF(wcn->hal_buf, msg); 2046 2047 wcn36xx_dbg(WCN36XX_DBG_HAL, 2048 "hal update probe rsp len %d bssid %pM\n", 2049 msg.probe_resp_template_len, msg.bssid); 2050 2051 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); 2052 if (ret) { 2053 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n"); 2054 goto out; 2055 } 2056 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2057 if (ret) { 2058 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n", 2059 ret); 2060 goto out; 2061 } 2062 out: 2063 mutex_unlock(&wcn->hal_mutex); 2064 return ret; 2065 } 2066 2067 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, 2068 enum ani_ed_type enc_type, 2069 u8 keyidx, 2070 u8 keylen, 2071 u8 *key, 2072 u8 sta_index) 2073 { 2074 struct wcn36xx_hal_set_sta_key_req_msg msg_body; 2075 int ret; 2076 2077 mutex_lock(&wcn->hal_mutex); 2078 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ); 2079 2080 msg_body.set_sta_key_params.sta_index = sta_index; 2081 msg_body.set_sta_key_params.enc_type = enc_type; 2082 2083 if (enc_type == WCN36XX_HAL_ED_WEP104 || 2084 enc_type == WCN36XX_HAL_ED_WEP40) { 2085 /* Use bss key for wep (static) */ 2086 msg_body.set_sta_key_params.def_wep_idx = keyidx; 2087 msg_body.set_sta_key_params.wep_type = 0; 2088 } else { 2089 msg_body.set_sta_key_params.key[0].id = keyidx; 2090 msg_body.set_sta_key_params.key[0].unicast = 1; 2091 msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX; 2092 msg_body.set_sta_key_params.key[0].pae_role = 0; 2093 msg_body.set_sta_key_params.key[0].length = keylen; 2094 memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen); 2095 } 2096 2097 msg_body.set_sta_key_params.single_tid_rc = 1; 2098 2099 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2100 2101 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2102 if (ret) { 2103 wcn36xx_err("Sending hal_set_stakey failed\n"); 2104 goto out; 2105 } 2106 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2107 if (ret) { 2108 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret); 2109 goto out; 2110 } 2111 out: 2112 mutex_unlock(&wcn->hal_mutex); 2113 return ret; 2114 } 2115 2116 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, 2117 enum ani_ed_type enc_type, 2118 u8 bssidx, 2119 u8 keyidx, 2120 u8 keylen, 2121 u8 *key) 2122 { 2123 struct wcn36xx_hal_set_bss_key_req_msg msg_body; 2124 int ret; 2125 2126 mutex_lock(&wcn->hal_mutex); 2127 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ); 2128 msg_body.bss_idx = bssidx; 2129 msg_body.enc_type = enc_type; 2130 msg_body.num_keys = 1; 2131 msg_body.keys[0].id = keyidx; 2132 msg_body.keys[0].unicast = 0; 2133 msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY; 2134 msg_body.keys[0].pae_role = 0; 2135 msg_body.keys[0].length = keylen; 2136 memcpy(msg_body.keys[0].key, key, keylen); 2137 2138 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2139 2140 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2141 if (ret) { 2142 wcn36xx_err("Sending hal_set_bsskey failed\n"); 2143 goto out; 2144 } 2145 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2146 if (ret) { 2147 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret); 2148 goto out; 2149 } 2150 out: 2151 mutex_unlock(&wcn->hal_mutex); 2152 return ret; 2153 } 2154 2155 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, 2156 enum ani_ed_type enc_type, 2157 u8 keyidx, 2158 u8 sta_index) 2159 { 2160 struct wcn36xx_hal_remove_sta_key_req_msg msg_body; 2161 int ret; 2162 2163 mutex_lock(&wcn->hal_mutex); 2164 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ); 2165 2166 msg_body.sta_idx = sta_index; 2167 msg_body.enc_type = enc_type; 2168 msg_body.key_id = keyidx; 2169 2170 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2171 2172 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2173 if (ret) { 2174 wcn36xx_err("Sending hal_remove_stakey failed\n"); 2175 goto out; 2176 } 2177 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2178 if (ret) { 2179 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret); 2180 goto out; 2181 } 2182 out: 2183 mutex_unlock(&wcn->hal_mutex); 2184 return ret; 2185 } 2186 2187 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, 2188 enum ani_ed_type enc_type, 2189 u8 bssidx, 2190 u8 keyidx) 2191 { 2192 struct wcn36xx_hal_remove_bss_key_req_msg msg_body; 2193 int ret; 2194 2195 mutex_lock(&wcn->hal_mutex); 2196 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ); 2197 msg_body.bss_idx = bssidx; 2198 msg_body.enc_type = enc_type; 2199 msg_body.key_id = keyidx; 2200 2201 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2202 2203 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2204 if (ret) { 2205 wcn36xx_err("Sending hal_remove_bsskey failed\n"); 2206 goto out; 2207 } 2208 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2209 if (ret) { 2210 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); 2211 goto out; 2212 } 2213 out: 2214 mutex_unlock(&wcn->hal_mutex); 2215 return ret; 2216 } 2217 2218 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 2219 { 2220 struct wcn36xx_hal_enter_bmps_req_msg msg_body; 2221 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 2222 int ret; 2223 2224 mutex_lock(&wcn->hal_mutex); 2225 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ); 2226 2227 msg_body.bss_index = vif_priv->bss_index; 2228 msg_body.tbtt = vif->bss_conf.sync_tsf; 2229 msg_body.dtim_period = vif_priv->dtim_period; 2230 2231 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2232 2233 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2234 if (ret) { 2235 wcn36xx_err("Sending hal_enter_bmps failed\n"); 2236 goto out; 2237 } 2238 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2239 if (ret) { 2240 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret); 2241 goto out; 2242 } 2243 out: 2244 mutex_unlock(&wcn->hal_mutex); 2245 return ret; 2246 } 2247 2248 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 2249 { 2250 struct wcn36xx_hal_exit_bmps_req_msg msg_body; 2251 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 2252 int ret; 2253 2254 mutex_lock(&wcn->hal_mutex); 2255 INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ); 2256 2257 msg_body.bss_index = vif_priv->bss_index; 2258 msg_body.send_data_null = 1; 2259 2260 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2261 2262 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2263 if (ret) { 2264 wcn36xx_err("Sending hal_exit_bmps failed\n"); 2265 goto out; 2266 } 2267 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2268 if (ret) { 2269 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); 2270 goto out; 2271 } 2272 out: 2273 mutex_unlock(&wcn->hal_mutex); 2274 return ret; 2275 } 2276 2277 int wcn36xx_smd_enter_imps(struct wcn36xx *wcn) 2278 { 2279 struct wcn36xx_hal_enter_imps_req_msg msg_body; 2280 int ret; 2281 2282 mutex_lock(&wcn->hal_mutex); 2283 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_IMPS_REQ); 2284 2285 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2286 2287 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2288 if (ret) { 2289 wcn36xx_err("Sending hal_enter_imps failed\n"); 2290 goto out; 2291 } 2292 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2293 if (ret) { 2294 wcn36xx_err("hal_enter_imps response failed err=%d\n", ret); 2295 goto out; 2296 } 2297 2298 wcn36xx_dbg(WCN36XX_DBG_HAL, "Entered idle mode\n"); 2299 out: 2300 mutex_unlock(&wcn->hal_mutex); 2301 return ret; 2302 } 2303 2304 int wcn36xx_smd_exit_imps(struct wcn36xx *wcn) 2305 { 2306 struct wcn36xx_hal_exit_imps_req_msg msg_body; 2307 int ret; 2308 2309 mutex_lock(&wcn->hal_mutex); 2310 INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_IMPS_REQ); 2311 2312 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2313 2314 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2315 if (ret) { 2316 wcn36xx_err("Sending hal_exit_imps failed\n"); 2317 goto out; 2318 } 2319 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2320 if (ret) { 2321 wcn36xx_err("hal_exit_imps response failed err=%d\n", ret); 2322 goto out; 2323 } 2324 wcn36xx_dbg(WCN36XX_DBG_HAL, "Exited idle mode\n"); 2325 out: 2326 mutex_unlock(&wcn->hal_mutex); 2327 return ret; 2328 } 2329 2330 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) 2331 { 2332 struct wcn36xx_hal_set_power_params_req_msg msg_body; 2333 int ret; 2334 2335 mutex_lock(&wcn->hal_mutex); 2336 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ); 2337 2338 /* 2339 * When host is down ignore every second dtim 2340 */ 2341 if (ignore_dtim) { 2342 msg_body.ignore_dtim = 1; 2343 msg_body.dtim_period = 2; 2344 } 2345 msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); 2346 2347 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2348 2349 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2350 if (ret) { 2351 wcn36xx_err("Sending hal_set_power_params failed\n"); 2352 goto out; 2353 } 2354 2355 out: 2356 mutex_unlock(&wcn->hal_mutex); 2357 return ret; 2358 } 2359 2360 /* Notice: This function should be called after associated, or else it 2361 * will be invalid 2362 */ 2363 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, 2364 struct ieee80211_vif *vif, 2365 int packet_type) 2366 { 2367 struct wcn36xx_hal_keep_alive_req_msg msg_body; 2368 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 2369 int ret; 2370 2371 mutex_lock(&wcn->hal_mutex); 2372 INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ); 2373 2374 if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) { 2375 msg_body.bss_index = vif_priv->bss_index; 2376 msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT; 2377 msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD; 2378 } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { 2379 /* TODO: it also support ARP response type */ 2380 } else { 2381 wcn36xx_warn("unknown keep alive packet type %d\n", packet_type); 2382 ret = -EINVAL; 2383 goto out; 2384 } 2385 2386 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2387 2388 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2389 if (ret) { 2390 wcn36xx_err("Sending hal_keep_alive failed\n"); 2391 goto out; 2392 } 2393 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2394 if (ret) { 2395 wcn36xx_err("hal_keep_alive response failed err=%d\n", ret); 2396 goto out; 2397 } 2398 out: 2399 mutex_unlock(&wcn->hal_mutex); 2400 return ret; 2401 } 2402 2403 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, 2404 u32 arg3, u32 arg4, u32 arg5) 2405 { 2406 struct wcn36xx_hal_dump_cmd_req_msg msg_body; 2407 int ret; 2408 2409 mutex_lock(&wcn->hal_mutex); 2410 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ); 2411 2412 msg_body.arg1 = arg1; 2413 msg_body.arg2 = arg2; 2414 msg_body.arg3 = arg3; 2415 msg_body.arg4 = arg4; 2416 msg_body.arg5 = arg5; 2417 2418 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2419 2420 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2421 if (ret) { 2422 wcn36xx_err("Sending hal_dump_cmd failed\n"); 2423 goto out; 2424 } 2425 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2426 if (ret) { 2427 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret); 2428 goto out; 2429 } 2430 out: 2431 mutex_unlock(&wcn->hal_mutex); 2432 return ret; 2433 } 2434 2435 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) 2436 { 2437 struct wcn36xx_hal_feat_caps_msg msg_body, *rsp; 2438 int ret, i; 2439 2440 mutex_lock(&wcn->hal_mutex); 2441 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); 2442 2443 wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); 2444 if (wcn->rf_id == RF_IRIS_WCN3680) { 2445 wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC); 2446 wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144); 2447 wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, 2448 ANTENNA_DIVERSITY_SELECTION); 2449 } 2450 2451 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2452 2453 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2454 if (ret) { 2455 wcn36xx_err("Sending hal_feature_caps_exchange failed\n"); 2456 goto out; 2457 } 2458 if (wcn->hal_rsp_len != sizeof(*rsp)) { 2459 wcn36xx_err("Invalid hal_feature_caps_exchange response"); 2460 goto out; 2461 } 2462 2463 rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf; 2464 2465 for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++) 2466 wcn->fw_feat_caps[i] = rsp->feat_caps[i]; 2467 out: 2468 mutex_unlock(&wcn->hal_mutex); 2469 return ret; 2470 } 2471 2472 static int wcn36xx_smd_add_ba_session_rsp(void *buf, int len, u8 *session) 2473 { 2474 struct wcn36xx_hal_add_ba_session_rsp_msg *rsp; 2475 2476 if (len < sizeof(*rsp)) 2477 return -EINVAL; 2478 2479 rsp = buf; 2480 if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) 2481 return rsp->status; 2482 2483 *session = rsp->ba_session_id; 2484 2485 return 0; 2486 } 2487 2488 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, 2489 struct ieee80211_sta *sta, 2490 u16 tid, 2491 u16 *ssn, 2492 u8 direction, 2493 u8 sta_index) 2494 { 2495 struct wcn36xx_hal_add_ba_session_req_msg msg_body; 2496 u8 session_id; 2497 int ret; 2498 2499 mutex_lock(&wcn->hal_mutex); 2500 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ); 2501 2502 msg_body.sta_index = sta_index; 2503 memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN); 2504 msg_body.dialog_token = 0x10; 2505 msg_body.tid = tid; 2506 2507 /* Immediate BA because Delayed BA is not supported */ 2508 msg_body.policy = 1; 2509 msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE; 2510 msg_body.timeout = 0; 2511 if (ssn) 2512 msg_body.ssn = *ssn; 2513 msg_body.direction = direction; 2514 2515 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2516 2517 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2518 if (ret) { 2519 wcn36xx_err("Sending hal_add_ba_session failed\n"); 2520 goto out; 2521 } 2522 ret = wcn36xx_smd_add_ba_session_rsp(wcn->hal_buf, wcn->hal_rsp_len, 2523 &session_id); 2524 if (ret) { 2525 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); 2526 ret = -EINVAL; 2527 goto out; 2528 } 2529 2530 ret = session_id; 2531 out: 2532 mutex_unlock(&wcn->hal_mutex); 2533 return ret; 2534 } 2535 2536 int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id) 2537 { 2538 struct wcn36xx_hal_add_ba_req_msg msg_body; 2539 int ret; 2540 2541 mutex_lock(&wcn->hal_mutex); 2542 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); 2543 2544 msg_body.session_id = session_id; 2545 msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; 2546 2547 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2548 2549 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2550 if (ret) { 2551 wcn36xx_err("Sending hal_add_ba failed\n"); 2552 goto out; 2553 } 2554 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2555 if (ret) { 2556 wcn36xx_err("hal_add_ba response failed err=%d\n", ret); 2557 goto out; 2558 } 2559 out: 2560 mutex_unlock(&wcn->hal_mutex); 2561 return ret; 2562 } 2563 2564 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index) 2565 { 2566 struct wcn36xx_hal_del_ba_req_msg msg_body; 2567 int ret; 2568 2569 mutex_lock(&wcn->hal_mutex); 2570 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ); 2571 2572 msg_body.sta_index = sta_index; 2573 msg_body.tid = tid; 2574 msg_body.direction = direction; 2575 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2576 2577 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2578 if (ret) { 2579 wcn36xx_err("Sending hal_del_ba failed\n"); 2580 goto out; 2581 } 2582 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2583 if (ret) { 2584 wcn36xx_err("hal_del_ba response failed err=%d\n", ret); 2585 goto out; 2586 } 2587 out: 2588 mutex_unlock(&wcn->hal_mutex); 2589 return ret; 2590 } 2591 2592 int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask, 2593 struct station_info *sinfo) 2594 { 2595 struct wcn36xx_hal_stats_req_msg msg_body; 2596 struct wcn36xx_hal_stats_rsp_msg *rsp; 2597 void *rsp_body; 2598 int ret; 2599 2600 if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) { 2601 wcn36xx_err("stats_mask 0x%x contains unimplemented types\n", 2602 stats_mask); 2603 return -EINVAL; 2604 } 2605 2606 mutex_lock(&wcn->hal_mutex); 2607 INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ); 2608 2609 msg_body.sta_id = sta_index; 2610 msg_body.stats_mask = stats_mask; 2611 2612 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2613 2614 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2615 if (ret) { 2616 wcn36xx_err("sending hal_get_stats failed\n"); 2617 goto out; 2618 } 2619 2620 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2621 if (ret) { 2622 wcn36xx_err("hal_get_stats response failed err=%d\n", ret); 2623 goto out; 2624 } 2625 2626 rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf; 2627 rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg)); 2628 2629 if (rsp->stats_mask != stats_mask) { 2630 wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n", 2631 rsp->stats_mask, stats_mask); 2632 goto out; 2633 } 2634 2635 if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) { 2636 struct ani_global_class_a_stats_info *stats_info = rsp_body; 2637 2638 wcn36xx_process_tx_rate(stats_info, &sinfo->txrate); 2639 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); 2640 rsp_body += sizeof(struct ani_global_class_a_stats_info); 2641 } 2642 out: 2643 mutex_unlock(&wcn->hal_mutex); 2644 2645 return ret; 2646 } 2647 2648 static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info) 2649 { 2650 struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate; 2651 struct wcn36xx_hal_trigger_ba_rsp_msg *rsp; 2652 int i; 2653 2654 if (len < sizeof(*rsp)) 2655 return -EINVAL; 2656 2657 rsp = buf; 2658 2659 if (rsp->candidate_cnt < 1) 2660 return rsp->status ? rsp->status : -EINVAL; 2661 2662 candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp)); 2663 2664 for (i = 0; i < STACFG_MAX_TC; i++) { 2665 ba_info[i] = candidate->ba_info[i]; 2666 } 2667 2668 return rsp->status; 2669 } 2670 2671 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn) 2672 { 2673 struct wcn36xx_hal_trigger_ba_req_msg msg_body; 2674 struct wcn36xx_hal_trigger_ba_req_candidate *candidate; 2675 struct add_ba_info ba_info[STACFG_MAX_TC]; 2676 int ret; 2677 2678 if (tid >= STACFG_MAX_TC) 2679 return -EINVAL; 2680 2681 mutex_lock(&wcn->hal_mutex); 2682 INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); 2683 2684 msg_body.session_id = 0; /* not really used */ 2685 msg_body.candidate_cnt = 1; 2686 msg_body.header.len += sizeof(*candidate); 2687 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2688 2689 candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *) 2690 (wcn->hal_buf + sizeof(msg_body)); 2691 candidate->sta_index = sta_index; 2692 candidate->tid_bitmap = 1 << tid; 2693 2694 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2695 if (ret) { 2696 wcn36xx_err("Sending hal_trigger_ba failed\n"); 2697 goto out; 2698 } 2699 ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info); 2700 if (ret) { 2701 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); 2702 goto out; 2703 } 2704 out: 2705 mutex_unlock(&wcn->hal_mutex); 2706 2707 if (ssn) 2708 *ssn = ba_info[tid].starting_seq_num; 2709 2710 return ret; 2711 } 2712 2713 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len) 2714 { 2715 struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf; 2716 2717 if (len != sizeof(*rsp)) { 2718 wcn36xx_warn("Bad TX complete indication\n"); 2719 return -EIO; 2720 } 2721 2722 wcn36xx_dxe_tx_ack_ind(wcn, rsp->status); 2723 2724 return 0; 2725 } 2726 2727 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len) 2728 { 2729 struct wcn36xx_hal_scan_offload_ind *rsp = buf; 2730 struct cfg80211_scan_info scan_info = {}; 2731 2732 if (len != sizeof(*rsp)) { 2733 wcn36xx_warn("Corrupted delete scan indication\n"); 2734 return -EIO; 2735 } 2736 2737 wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type); 2738 2739 switch (rsp->type) { 2740 case WCN36XX_HAL_SCAN_IND_FAILED: 2741 case WCN36XX_HAL_SCAN_IND_DEQUEUED: 2742 scan_info.aborted = true; 2743 fallthrough; 2744 case WCN36XX_HAL_SCAN_IND_COMPLETED: 2745 mutex_lock(&wcn->scan_lock); 2746 wcn->scan_req = NULL; 2747 if (wcn->scan_aborted) 2748 scan_info.aborted = true; 2749 mutex_unlock(&wcn->scan_lock); 2750 ieee80211_scan_completed(wcn->hw, &scan_info); 2751 break; 2752 case WCN36XX_HAL_SCAN_IND_STARTED: 2753 case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL: 2754 case WCN36XX_HAL_SCAN_IND_PREEMPTED: 2755 case WCN36XX_HAL_SCAN_IND_RESTARTED: 2756 break; 2757 default: 2758 wcn36xx_warn("Unknown scan indication type %x\n", rsp->type); 2759 } 2760 2761 return 0; 2762 } 2763 2764 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, 2765 void *buf, 2766 size_t len) 2767 { 2768 struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf; 2769 struct ieee80211_vif *vif = NULL; 2770 struct wcn36xx_vif *tmp; 2771 2772 /* Old FW does not have bss index */ 2773 if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 2774 list_for_each_entry(tmp, &wcn->vif_list, list) { 2775 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 2776 tmp->bss_index); 2777 vif = wcn36xx_priv_to_vif(tmp); 2778 ieee80211_beacon_loss(vif); 2779 } 2780 return 0; 2781 } 2782 2783 if (len != sizeof(*rsp)) { 2784 wcn36xx_warn("Corrupted missed beacon indication\n"); 2785 return -EIO; 2786 } 2787 2788 list_for_each_entry(tmp, &wcn->vif_list, list) { 2789 if (tmp->bss_index == rsp->bss_index) { 2790 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 2791 rsp->bss_index); 2792 vif = wcn36xx_priv_to_vif(tmp); 2793 ieee80211_beacon_loss(vif); 2794 return 0; 2795 } 2796 } 2797 2798 wcn36xx_warn("BSS index %d not found\n", rsp->bss_index); 2799 return -ENOENT; 2800 } 2801 2802 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, 2803 void *buf, 2804 size_t len) 2805 { 2806 struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; 2807 struct wcn36xx_vif *vif_priv; 2808 struct ieee80211_vif *vif; 2809 struct ieee80211_bss_conf *bss_conf; 2810 struct ieee80211_sta *sta; 2811 bool found = false; 2812 2813 if (len != sizeof(*rsp)) { 2814 wcn36xx_warn("Corrupted delete sta indication\n"); 2815 return -EIO; 2816 } 2817 2818 wcn36xx_dbg(WCN36XX_DBG_HAL, 2819 "delete station indication %pM index %d reason %d\n", 2820 rsp->addr2, rsp->sta_id, rsp->reason_code); 2821 2822 list_for_each_entry(vif_priv, &wcn->vif_list, list) { 2823 rcu_read_lock(); 2824 vif = wcn36xx_priv_to_vif(vif_priv); 2825 2826 if (vif->type == NL80211_IFTYPE_STATION) { 2827 /* We could call ieee80211_find_sta too, but checking 2828 * bss_conf is clearer. 2829 */ 2830 bss_conf = &vif->bss_conf; 2831 if (vif_priv->sta_assoc && 2832 !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) { 2833 found = true; 2834 wcn36xx_dbg(WCN36XX_DBG_HAL, 2835 "connection loss bss_index %d\n", 2836 vif_priv->bss_index); 2837 ieee80211_connection_loss(vif); 2838 } 2839 } else { 2840 sta = ieee80211_find_sta(vif, rsp->addr2); 2841 if (sta) { 2842 found = true; 2843 ieee80211_report_low_ack(sta, 0); 2844 } 2845 } 2846 2847 rcu_read_unlock(); 2848 if (found) 2849 return 0; 2850 } 2851 2852 wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2); 2853 return -ENOENT; 2854 } 2855 2856 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn, 2857 void *buf, 2858 size_t len) 2859 { 2860 struct wcn36xx_hal_print_reg_info_ind *rsp = buf; 2861 int i; 2862 2863 if (len < sizeof(*rsp)) { 2864 wcn36xx_warn("Corrupted print reg info indication\n"); 2865 return -EIO; 2866 } 2867 2868 wcn36xx_dbg(WCN36XX_DBG_HAL, 2869 "reginfo indication, scenario: 0x%x reason: 0x%x\n", 2870 rsp->scenario, rsp->reason); 2871 2872 for (i = 0; i < rsp->count; i++) { 2873 wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n", 2874 rsp->regs[i].addr, rsp->regs[i].value); 2875 } 2876 2877 return 0; 2878 } 2879 2880 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) 2881 { 2882 struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; 2883 size_t len; 2884 int ret; 2885 2886 mutex_lock(&wcn->hal_mutex); 2887 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ); 2888 2889 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2890 2891 body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf; 2892 len = msg_body.header.len; 2893 2894 put_cfg_tlv_u32(wcn, &len, cfg_id, value); 2895 body->header.len = len; 2896 body->len = len - sizeof(*body); 2897 2898 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); 2899 if (ret) { 2900 wcn36xx_err("Sending hal_update_cfg failed\n"); 2901 goto out; 2902 } 2903 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2904 if (ret) { 2905 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret); 2906 goto out; 2907 } 2908 out: 2909 mutex_unlock(&wcn->hal_mutex); 2910 return ret; 2911 } 2912 2913 int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, 2914 struct ieee80211_vif *vif, 2915 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp) 2916 { 2917 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 2918 struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL; 2919 int ret; 2920 2921 mutex_lock(&wcn->hal_mutex); 2922 2923 msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *) 2924 wcn->hal_buf; 2925 INIT_HAL_MSG(*msg_body, WCN36XX_HAL_8023_MULTICAST_LIST_REQ); 2926 2927 /* An empty list means all mc traffic will be received */ 2928 if (fp) 2929 memcpy(&msg_body->mc_addr_list, fp, 2930 sizeof(msg_body->mc_addr_list)); 2931 else 2932 msg_body->mc_addr_list.mc_addr_count = 0; 2933 2934 msg_body->mc_addr_list.bss_index = vif_priv->bss_index; 2935 2936 ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); 2937 if (ret) { 2938 wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n"); 2939 goto out; 2940 } 2941 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2942 if (ret) { 2943 wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret); 2944 goto out; 2945 } 2946 out: 2947 mutex_unlock(&wcn->hal_mutex); 2948 return ret; 2949 } 2950 2951 int wcn36xx_smd_arp_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif, 2952 bool enable) 2953 { 2954 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 2955 struct wcn36xx_hal_host_offload_req_msg msg_body; 2956 int ret; 2957 2958 mutex_lock(&wcn->hal_mutex); 2959 2960 INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ); 2961 msg_body.host_offload_params.offload_type = 2962 WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD; 2963 if (enable) { 2964 msg_body.host_offload_params.enable = 2965 WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; 2966 memcpy(&msg_body.host_offload_params.u, 2967 &vif->cfg.arp_addr_list[0], sizeof(__be32)); 2968 } 2969 msg_body.ns_offload_params.bss_index = vif_priv->bss_index; 2970 2971 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2972 2973 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2974 if (ret) { 2975 wcn36xx_err("Sending host_offload_arp failed\n"); 2976 goto out; 2977 } 2978 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2979 if (ret) { 2980 wcn36xx_err("host_offload_arp failed err=%d\n", ret); 2981 goto out; 2982 } 2983 out: 2984 mutex_unlock(&wcn->hal_mutex); 2985 return ret; 2986 } 2987 2988 #if IS_ENABLED(CONFIG_IPV6) 2989 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif, 2990 bool enable) 2991 { 2992 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 2993 struct wcn36xx_hal_host_offload_req_msg msg_body; 2994 struct wcn36xx_hal_ns_offload_params *ns_params; 2995 struct wcn36xx_hal_host_offload_req *ho_params; 2996 int ret; 2997 2998 mutex_lock(&wcn->hal_mutex); 2999 3000 INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ); 3001 ho_params = &msg_body.host_offload_params; 3002 ns_params = &msg_body.ns_offload_params; 3003 3004 ho_params->offload_type = WCN36XX_HAL_IPV6_NS_OFFLOAD; 3005 if (enable) { 3006 ho_params->enable = 3007 WCN36XX_HAL_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE; 3008 if (vif_priv->num_target_ipv6_addrs) { 3009 memcpy(&ho_params->u, 3010 &vif_priv->target_ipv6_addrs[0].in6_u, 3011 sizeof(struct in6_addr)); 3012 memcpy(&ns_params->target_ipv6_addr1, 3013 &vif_priv->target_ipv6_addrs[0].in6_u, 3014 sizeof(struct in6_addr)); 3015 ns_params->target_ipv6_addr1_valid = 1; 3016 } 3017 if (vif_priv->num_target_ipv6_addrs > 1) { 3018 memcpy(&ns_params->target_ipv6_addr2, 3019 &vif_priv->target_ipv6_addrs[1].in6_u, 3020 sizeof(struct in6_addr)); 3021 ns_params->target_ipv6_addr2_valid = 1; 3022 } 3023 } 3024 memcpy(&ns_params->self_addr, vif->addr, ETH_ALEN); 3025 ns_params->bss_index = vif_priv->bss_index; 3026 3027 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 3028 3029 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 3030 if (ret) { 3031 wcn36xx_err("Sending host_offload_arp failed\n"); 3032 goto out; 3033 } 3034 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 3035 if (ret) { 3036 wcn36xx_err("host_offload_arp failed err=%d\n", ret); 3037 goto out; 3038 } 3039 out: 3040 mutex_unlock(&wcn->hal_mutex); 3041 return ret; 3042 } 3043 #else 3044 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif, 3045 bool enable) 3046 { 3047 return 0; 3048 } 3049 #endif 3050 3051 int wcn36xx_smd_gtk_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif, 3052 bool enable) 3053 { 3054 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 3055 struct wcn36xx_hal_gtk_offload_req_msg msg_body; 3056 int ret; 3057 3058 mutex_lock(&wcn->hal_mutex); 3059 3060 INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_REQ); 3061 3062 if (enable) { 3063 memcpy(&msg_body.kek, vif_priv->rekey_data.kek, NL80211_KEK_LEN); 3064 memcpy(&msg_body.kck, vif_priv->rekey_data.kck, NL80211_KCK_LEN); 3065 msg_body.key_replay_counter = 3066 le64_to_cpu(vif_priv->rekey_data.replay_ctr); 3067 msg_body.bss_index = vif_priv->bss_index; 3068 } else { 3069 msg_body.flags = WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE; 3070 } 3071 3072 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 3073 3074 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 3075 if (ret) { 3076 wcn36xx_err("Sending host_offload_arp failed\n"); 3077 goto out; 3078 } 3079 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 3080 if (ret) { 3081 wcn36xx_err("host_offload_arp failed err=%d\n", ret); 3082 goto out; 3083 } 3084 out: 3085 mutex_unlock(&wcn->hal_mutex); 3086 return ret; 3087 } 3088 3089 static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx *wcn, 3090 struct ieee80211_vif *vif) 3091 { 3092 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 3093 struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *rsp; 3094 __be64 replay_ctr; 3095 3096 if (wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len)) 3097 return -EIO; 3098 3099 rsp = (struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *)wcn->hal_buf; 3100 3101 if (rsp->bss_index != vif_priv->bss_index) { 3102 wcn36xx_err("gtk_offload_info invalid response bss index %d\n", 3103 rsp->bss_index); 3104 return -ENOENT; 3105 } 3106 3107 if (vif_priv->rekey_data.replay_ctr != cpu_to_le64(rsp->key_replay_counter)) { 3108 replay_ctr = cpu_to_be64(rsp->key_replay_counter); 3109 vif_priv->rekey_data.replay_ctr = 3110 cpu_to_le64(rsp->key_replay_counter); 3111 ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid, 3112 (void *)&replay_ctr, GFP_KERNEL); 3113 wcn36xx_dbg(WCN36XX_DBG_HAL, 3114 "GTK replay counter increment %llu\n", 3115 rsp->key_replay_counter); 3116 } 3117 3118 wcn36xx_dbg(WCN36XX_DBG_HAL, 3119 "gtk offload info status %d last_rekey_status %d " 3120 "replay_counter %llu total_rekey_count %d gtk_rekey_count %d " 3121 "igtk_rekey_count %d bss_index %d\n", 3122 rsp->status, rsp->last_rekey_status, 3123 rsp->key_replay_counter, rsp->total_rekey_count, 3124 rsp->gtk_rekey_count, rsp->igtk_rekey_count, 3125 rsp->bss_index); 3126 3127 return 0; 3128 } 3129 3130 int wcn36xx_smd_gtk_offload_get_info(struct wcn36xx *wcn, 3131 struct ieee80211_vif *vif) 3132 { 3133 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 3134 struct wcn36xx_hal_gtk_offload_get_info_req_msg msg_body; 3135 int ret; 3136 3137 mutex_lock(&wcn->hal_mutex); 3138 3139 INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ); 3140 3141 msg_body.bss_index = vif_priv->bss_index; 3142 3143 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 3144 3145 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 3146 if (ret) { 3147 wcn36xx_err("Sending gtk_offload_get_info failed\n"); 3148 goto out; 3149 } 3150 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 3151 if (ret) { 3152 wcn36xx_err("gtk_offload_get_info failed err=%d\n", ret); 3153 goto out; 3154 } 3155 ret = wcn36xx_smd_gtk_offload_get_info_rsp(wcn, vif); 3156 out: 3157 mutex_unlock(&wcn->hal_mutex); 3158 return ret; 3159 } 3160 3161 int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx *wcn) 3162 { 3163 struct wcn36xx_hal_wlan_host_suspend_ind_msg msg_body; 3164 int ret; 3165 3166 mutex_lock(&wcn->hal_mutex); 3167 3168 INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_SUSPEND_IND); 3169 msg_body.configured_mcst_bcst_filter_setting = 0; 3170 msg_body.active_session_count = 1; 3171 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 3172 3173 ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, msg_body.header.len); 3174 3175 mutex_unlock(&wcn->hal_mutex); 3176 3177 return ret; 3178 } 3179 3180 int wcn36xx_smd_host_resume(struct wcn36xx *wcn) 3181 { 3182 struct wcn36xx_hal_wlan_host_resume_req_msg msg_body; 3183 struct wcn36xx_hal_host_resume_rsp_msg *rsp; 3184 int ret; 3185 3186 mutex_lock(&wcn->hal_mutex); 3187 3188 INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_RESUME_REQ); 3189 msg_body.configured_mcst_bcst_filter_setting = 0; 3190 3191 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 3192 3193 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 3194 if (ret) { 3195 wcn36xx_err("Sending wlan_host_resume failed\n"); 3196 goto out; 3197 } 3198 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 3199 if (ret) { 3200 wcn36xx_err("wlan_host_resume err=%d\n", ret); 3201 goto out; 3202 } 3203 3204 rsp = (struct wcn36xx_hal_host_resume_rsp_msg *)wcn->hal_buf; 3205 if (rsp->status) 3206 wcn36xx_warn("wlan_host_resume status=%d\n", rsp->status); 3207 3208 out: 3209 mutex_unlock(&wcn->hal_mutex); 3210 3211 return ret; 3212 } 3213 3214 #define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \ 3215 { \ 3216 .element_id = eid, \ 3217 .check_ie_presence = presence, \ 3218 .offset = offs, \ 3219 .value = val, \ 3220 .bitmask = mask, \ 3221 .ref = ref_val, \ 3222 } 3223 3224 static const struct beacon_filter_ie bcn_filter_ies[] = { 3225 BEACON_FILTER(WLAN_EID_DS_PARAMS, 0, 0, 0, 3226 WCN36XX_FILTER_IE_DS_CHANNEL_MASK, 0), 3227 BEACON_FILTER(WLAN_EID_ERP_INFO, 0, 0, 0, 3228 WCN36XX_FILTER_IE_ERP_FILTER_MASK, 0), 3229 BEACON_FILTER(WLAN_EID_EDCA_PARAM_SET, 0, 0, 0, 3230 WCN36XX_FILTER_IE_EDCA_FILTER_MASK, 0), 3231 BEACON_FILTER(WLAN_EID_QOS_CAPA, 0, 0, 0, 3232 WCN36XX_FILTER_IE_QOS_FILTER_MASK, 0), 3233 BEACON_FILTER(WLAN_EID_CHANNEL_SWITCH, 1, 0, 0, 3234 WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK, 0), 3235 BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 0, 0, 3236 WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK, 0), 3237 BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 2, 0, 3238 WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK, 0), 3239 BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 5, 0, 3240 WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK, 0), 3241 BEACON_FILTER(WLAN_EID_PWR_CONSTRAINT, 0, 0, 0, 3242 WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK, 0), 3243 BEACON_FILTER(WLAN_EID_OPMODE_NOTIF, 0, 0, 0, 3244 WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK, 0), 3245 BEACON_FILTER(WLAN_EID_VHT_OPERATION, 0, 0, 0, 3246 WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK, 0), 3247 BEACON_FILTER(WLAN_EID_RSN, 1, 0, 0, 3248 WCN36XX_FILTER_IE_RSN_MASK, 0), 3249 BEACON_FILTER(WLAN_EID_VENDOR_SPECIFIC, 1, 0, 0, 3250 WCN36XX_FILTER_IE_VENDOR_MASK, 0), 3251 }; 3252 3253 int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn, 3254 struct ieee80211_vif *vif) 3255 { 3256 struct wcn36xx_hal_add_bcn_filter_req_msg msg_body, *body; 3257 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 3258 u8 *payload; 3259 size_t payload_size; 3260 int ret; 3261 3262 if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, BCN_FILTER)) 3263 return -EOPNOTSUPP; 3264 3265 mutex_lock(&wcn->hal_mutex); 3266 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BCN_FILTER_REQ); 3267 3268 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 3269 3270 body = (struct wcn36xx_hal_add_bcn_filter_req_msg *)wcn->hal_buf; 3271 body->capability_info = vif->bss_conf.assoc_capability; 3272 body->capability_mask = WCN36XX_FILTER_CAPABILITY_MASK; 3273 body->beacon_interval = vif->bss_conf.beacon_int; 3274 body->ie_num = ARRAY_SIZE(bcn_filter_ies); 3275 body->bss_index = vif_priv->bss_index; 3276 3277 payload = ((u8 *)body) + body->header.len; 3278 payload_size = sizeof(bcn_filter_ies); 3279 memcpy(payload, &bcn_filter_ies, payload_size); 3280 3281 body->header.len += payload_size; 3282 3283 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); 3284 if (ret) { 3285 wcn36xx_err("Sending add bcn_filter failed\n"); 3286 goto out; 3287 } 3288 3289 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 3290 if (ret) { 3291 wcn36xx_err("add bcn filter response failed err=%d\n", ret); 3292 goto out; 3293 } 3294 out: 3295 mutex_unlock(&wcn->hal_mutex); 3296 return ret; 3297 } 3298 3299 int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, 3300 void *buf, int len, void *priv, u32 addr) 3301 { 3302 const struct wcn36xx_hal_msg_header *msg_header = buf; 3303 struct ieee80211_hw *hw = priv; 3304 struct wcn36xx *wcn = hw->priv; 3305 struct wcn36xx_hal_ind_msg *msg_ind; 3306 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); 3307 3308 switch (msg_header->msg_type) { 3309 case WCN36XX_HAL_START_RSP: 3310 case WCN36XX_HAL_CONFIG_STA_RSP: 3311 case WCN36XX_HAL_CONFIG_BSS_RSP: 3312 case WCN36XX_HAL_ADD_STA_SELF_RSP: 3313 case WCN36XX_HAL_STOP_RSP: 3314 case WCN36XX_HAL_DEL_STA_SELF_RSP: 3315 case WCN36XX_HAL_DELETE_STA_RSP: 3316 case WCN36XX_HAL_INIT_SCAN_RSP: 3317 case WCN36XX_HAL_START_SCAN_RSP: 3318 case WCN36XX_HAL_END_SCAN_RSP: 3319 case WCN36XX_HAL_FINISH_SCAN_RSP: 3320 case WCN36XX_HAL_DOWNLOAD_NV_RSP: 3321 case WCN36XX_HAL_DELETE_BSS_RSP: 3322 case WCN36XX_HAL_SEND_BEACON_RSP: 3323 case WCN36XX_HAL_SET_LINK_ST_RSP: 3324 case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP: 3325 case WCN36XX_HAL_SET_BSSKEY_RSP: 3326 case WCN36XX_HAL_SET_STAKEY_RSP: 3327 case WCN36XX_HAL_RMV_STAKEY_RSP: 3328 case WCN36XX_HAL_RMV_BSSKEY_RSP: 3329 case WCN36XX_HAL_ENTER_BMPS_RSP: 3330 case WCN36XX_HAL_SET_POWER_PARAMS_RSP: 3331 case WCN36XX_HAL_EXIT_BMPS_RSP: 3332 case WCN36XX_HAL_KEEP_ALIVE_RSP: 3333 case WCN36XX_HAL_DUMP_COMMAND_RSP: 3334 case WCN36XX_HAL_ADD_BA_SESSION_RSP: 3335 case WCN36XX_HAL_ADD_BA_RSP: 3336 case WCN36XX_HAL_DEL_BA_RSP: 3337 case WCN36XX_HAL_GET_STATS_RSP: 3338 case WCN36XX_HAL_TRIGGER_BA_RSP: 3339 case WCN36XX_HAL_UPDATE_CFG_RSP: 3340 case WCN36XX_HAL_JOIN_RSP: 3341 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: 3342 case WCN36XX_HAL_CH_SWITCH_RSP: 3343 case WCN36XX_HAL_PROCESS_PTT_RSP: 3344 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: 3345 case WCN36XX_HAL_8023_MULTICAST_LIST_RSP: 3346 case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP: 3347 case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP: 3348 case WCN36XX_HAL_HOST_OFFLOAD_RSP: 3349 case WCN36XX_HAL_GTK_OFFLOAD_RSP: 3350 case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP: 3351 case WCN36XX_HAL_HOST_RESUME_RSP: 3352 case WCN36XX_HAL_ENTER_IMPS_RSP: 3353 case WCN36XX_HAL_EXIT_IMPS_RSP: 3354 case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP: 3355 case WCN36XX_HAL_ADD_BCN_FILTER_RSP: 3356 memcpy(wcn->hal_buf, buf, len); 3357 wcn->hal_rsp_len = len; 3358 complete(&wcn->hal_rsp_compl); 3359 break; 3360 3361 case WCN36XX_HAL_COEX_IND: 3362 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND: 3363 case WCN36XX_HAL_DEL_BA_IND: 3364 case WCN36XX_HAL_OTA_TX_COMPL_IND: 3365 case WCN36XX_HAL_MISSED_BEACON_IND: 3366 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 3367 case WCN36XX_HAL_PRINT_REG_INFO_IND: 3368 case WCN36XX_HAL_SCAN_OFFLOAD_IND: 3369 msg_ind = kmalloc(struct_size(msg_ind, msg, len), GFP_ATOMIC); 3370 if (!msg_ind) { 3371 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", 3372 msg_header->msg_type); 3373 return -ENOMEM; 3374 } 3375 3376 msg_ind->msg_len = len; 3377 memcpy(msg_ind->msg, buf, len); 3378 3379 spin_lock(&wcn->hal_ind_lock); 3380 list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); 3381 queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); 3382 spin_unlock(&wcn->hal_ind_lock); 3383 wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); 3384 break; 3385 default: 3386 wcn36xx_err("SMD_EVENT (%d) not supported\n", 3387 msg_header->msg_type); 3388 } 3389 3390 return 0; 3391 } 3392 3393 static void wcn36xx_ind_smd_work(struct work_struct *work) 3394 { 3395 struct wcn36xx *wcn = 3396 container_of(work, struct wcn36xx, hal_ind_work); 3397 3398 for (;;) { 3399 struct wcn36xx_hal_msg_header *msg_header; 3400 struct wcn36xx_hal_ind_msg *hal_ind_msg; 3401 unsigned long flags; 3402 3403 spin_lock_irqsave(&wcn->hal_ind_lock, flags); 3404 3405 if (list_empty(&wcn->hal_ind_queue)) { 3406 spin_unlock_irqrestore(&wcn->hal_ind_lock, flags); 3407 return; 3408 } 3409 3410 hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, 3411 struct wcn36xx_hal_ind_msg, 3412 list); 3413 list_del(&hal_ind_msg->list); 3414 spin_unlock_irqrestore(&wcn->hal_ind_lock, flags); 3415 3416 msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; 3417 3418 switch (msg_header->msg_type) { 3419 case WCN36XX_HAL_COEX_IND: 3420 case WCN36XX_HAL_DEL_BA_IND: 3421 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND: 3422 break; 3423 case WCN36XX_HAL_OTA_TX_COMPL_IND: 3424 wcn36xx_smd_tx_compl_ind(wcn, 3425 hal_ind_msg->msg, 3426 hal_ind_msg->msg_len); 3427 break; 3428 case WCN36XX_HAL_MISSED_BEACON_IND: 3429 wcn36xx_smd_missed_beacon_ind(wcn, 3430 hal_ind_msg->msg, 3431 hal_ind_msg->msg_len); 3432 break; 3433 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 3434 wcn36xx_smd_delete_sta_context_ind(wcn, 3435 hal_ind_msg->msg, 3436 hal_ind_msg->msg_len); 3437 break; 3438 case WCN36XX_HAL_PRINT_REG_INFO_IND: 3439 wcn36xx_smd_print_reg_info_ind(wcn, 3440 hal_ind_msg->msg, 3441 hal_ind_msg->msg_len); 3442 break; 3443 case WCN36XX_HAL_SCAN_OFFLOAD_IND: 3444 wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg, 3445 hal_ind_msg->msg_len); 3446 break; 3447 default: 3448 wcn36xx_err("SMD_EVENT (%d) not supported\n", 3449 msg_header->msg_type); 3450 } 3451 3452 kfree(hal_ind_msg); 3453 } 3454 } 3455 3456 int wcn36xx_smd_open(struct wcn36xx *wcn) 3457 { 3458 wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); 3459 if (!wcn->hal_ind_wq) 3460 return -ENOMEM; 3461 3462 INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); 3463 INIT_LIST_HEAD(&wcn->hal_ind_queue); 3464 spin_lock_init(&wcn->hal_ind_lock); 3465 3466 return 0; 3467 } 3468 3469 void wcn36xx_smd_close(struct wcn36xx *wcn) 3470 { 3471 struct wcn36xx_hal_ind_msg *msg, *tmp; 3472 3473 cancel_work_sync(&wcn->hal_ind_work); 3474 destroy_workqueue(wcn->hal_ind_wq); 3475 3476 list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list) 3477 kfree(msg); 3478 } 3479