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