@@ -438,15 +438,15 @@ struct ath12k_wbm_tx_stats {
u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
};
-struct ath12k_sta {
+struct ath12k_link_sta {
struct ath12k_link_vif *arvif;
+ struct ath12k_sta *ahsta;
/* the following are protected by ar->data_lock */
u32 changed; /* IEEE80211_RC_* */
u32 bw;
u32 nss;
u32 smps;
- enum hal_pn_type pn_type;
struct work_struct update_wk;
struct rate_info txrate;
@@ -454,11 +454,20 @@ struct ath12k_sta {
u64 rx_duration;
u64 tx_duration;
u8 rssi_comb;
+ u8 link_id;
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_wbm_tx_stats *wbm_tx_stats;
u32 bw_prev;
};
+struct ath12k_sta {
+ enum hal_pn_type pn_type;
+ struct ath12k_link_sta deflink;
+ struct ath12k_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+ /* indicates bitmap of link sta created in FW */
+ u16 links_map;
+};
+
#define ATH12K_MIN_5G_FREQ 4150
#define ATH12K_MIN_6G_FREQ 5925
#define ATH12K_MAX_6G_FREQ 7115
@@ -653,8 +662,8 @@ struct ath12k_hw {
bool regd_updated;
bool use_6ghz_regd;
- /* To synchronize concurrent access of ahvif->link[]
- * between mac80211 operations.
+ /* To synchronize concurrent access of ahvif->link[] and
+ * ahsta->link[] between mac80211 operations.
*/
struct mutex conf_mutex;
u8 num_radio;
@@ -1018,11 +1027,16 @@ static inline struct ath12k_vif *ath12k_vif_to_ahvif(struct ieee80211_vif *vif)
return (struct ath12k_vif *)vif->drv_priv;
}
-static inline struct ath12k_sta *ath12k_sta_to_arsta(struct ieee80211_sta *sta)
+static inline struct ath12k_sta *ath12k_sta_to_ahsta(struct ieee80211_sta *sta)
{
return (struct ath12k_sta *)sta->drv_priv;
}
+static inline struct ieee80211_sta *ath12k_sta_to_sta(struct ath12k_sta *ahsta)
+{
+ return container_of((void *)ahsta, struct ieee80211_sta, drv_priv);
+}
+
static inline struct ieee80211_vif *ath12k_vif_to_vif(struct ath12k_vif *ahvif)
{
return container_of((void *)ahvif, struct ieee80211_vif, drv_priv);
@@ -2165,7 +2165,7 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st
}
static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
- struct ath12k_sta *arsta,
+ struct ath12k_link_sta *arsta,
struct hal_rx_mon_ppdu_info *ppdu_info)
{
struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
@@ -2321,7 +2321,8 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
struct hal_rx_mon_ppdu_info *ppdu_info,
u32 uid)
{
- struct ath12k_sta *arsta = NULL;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
struct ath12k_rx_peer_stats *rx_stats = NULL;
struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid];
struct ath12k_peer *peer;
@@ -2338,7 +2339,8 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
return;
}
- arsta = ath12k_sta_to_arsta(peer->sta);
+ ahsta = ath12k_sta_to_ahsta(peer->sta);
+ arsta = &ahsta->deflink;
rx_stats = arsta->rx_stats;
if (!rx_stats)
@@ -2445,7 +2447,8 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
struct dp_srng *mon_dst_ring;
struct hal_srng *srng;
struct dp_rxdma_mon_ring *buf_ring;
- struct ath12k_sta *arsta = NULL;
+ struct ath12k_sta *ahsta = NULL;
+ struct ath12k_link_sta *arsta;
struct ath12k_peer *peer;
u64 cookie;
int num_buffs_reaped = 0, srng_id, buf_id;
@@ -2514,7 +2517,8 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
}
if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
- arsta = ath12k_sta_to_arsta(peer->sta);
+ ahsta = ath12k_sta_to_ahsta(peer->sta);
+ arsta = &ahsta->deflink;
ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta,
ppdu_info);
} else if ((ppdu_info->fc_valid) &&
@@ -1040,13 +1040,14 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ieee80211_ampdu_params *params)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
int vdev_id = arsta->arvif->vdev_id;
int ret;
ret = ath12k_dp_rx_peer_tid_setup(ar, params->sta->addr, vdev_id,
params->tid, params->buf_size,
- params->ssn, arsta->pn_type);
+ params->ssn, arsta->ahsta->pn_type);
if (ret)
ath12k_warn(ab, "failed to setup rx tid %d\n", ret);
@@ -1058,7 +1059,8 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
{
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
int vdev_id = arsta->arvif->vdev_id;
bool active;
int ret;
@@ -1312,7 +1314,8 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
struct ieee80211_sta *sta;
- struct ath12k_sta *arsta;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
struct htt_ppdu_stats_user_rate *user_rate;
struct ath12k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats;
struct htt_ppdu_user_stats *usr_stats = &ppdu_stats->user_stats[user];
@@ -1393,7 +1396,8 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
}
sta = peer->sta;
- arsta = ath12k_sta_to_arsta(sta);
+ ahsta = ath12k_sta_to_ahsta(sta);
+ arsta = &ahsta->deflink;
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
@@ -1657,10 +1657,11 @@ static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work)
static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
u32 aid;
@@ -1683,10 +1684,11 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ieee80211_bss_conf *info = &vif->bss_conf;
struct cfg80211_chan_def def;
struct cfg80211_bss *bss;
@@ -1745,10 +1747,11 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
struct cfg80211_chan_def def;
const struct ieee80211_supported_band *sband;
@@ -1808,10 +1811,11 @@ ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
struct cfg80211_chan_def def;
enum nl80211_band band;
@@ -1969,10 +1973,11 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
struct cfg80211_chan_def def;
enum nl80211_band band;
@@ -2064,10 +2069,11 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
static void ath12k_peer_assoc_h_he(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
int i;
u8 ampdu_factor, rx_mcs_80, rx_mcs_160, max_nss;
@@ -2219,11 +2225,12 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
+ const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
struct cfg80211_chan_def def;
enum nl80211_band band;
u8 ampdu_factor, mpdu_density;
@@ -2291,9 +2298,10 @@ static int ath12k_get_smps_from_capa(const struct ieee80211_sta_ht_cap *ht_cap,
return 0;
}
-static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
+static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
const struct ieee80211_he_6ghz_capa *he_6ghz_capa = &sta->deflink.he_6ghz_capa;
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
int smps;
@@ -2318,9 +2326,11 @@ static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
+
switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
if (sta->wme) {
@@ -2352,8 +2362,9 @@ static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ath12k_wmi_ap_ps_arg arg;
u32 max_sp;
u32 uapsd;
@@ -2514,7 +2525,7 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct cfg80211_chan_def def;
@@ -2523,6 +2534,7 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
const u16 *vht_mcs_mask;
enum wmi_phy_mode phymode = MODE_UNKNOWN;
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
return;
@@ -2659,9 +2671,10 @@ static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,
static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
@@ -2741,7 +2754,7 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
static void ath12k_peer_assoc_prepare(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg,
bool reassoc)
{
@@ -2752,17 +2765,17 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar,
reinit_completion(&ar->peer_assoc_done);
arg->peer_new_assoc = !reassoc;
- ath12k_peer_assoc_h_basic(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_crypto(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_rates(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_ht(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_vht(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_he(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_he_6ghz(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_eht(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_qos(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_phymode(ar, arvif, sta, arg);
- ath12k_peer_assoc_h_smps(sta, arg);
+ ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_rates(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_ht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_vht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_he(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_he_6ghz(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_eht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_qos(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_smps(arsta, arg);
/* TODO: amsdu_disable req? */
}
@@ -2791,7 +2804,9 @@ static void ath12k_bss_assoc(struct ath12k *ar,
struct ieee80211_vif *vif = ath12k_vif_to_vif(ahvif);
struct ath12k_wmi_vdev_up_params params = {};
struct ath12k_wmi_peer_assoc_arg peer_arg;
+ struct ath12k_link_sta *arsta;
struct ieee80211_sta *ap_sta;
+ struct ath12k_sta *ahsta;
struct ath12k_peer *peer;
bool is_auth = false;
int ret;
@@ -2811,7 +2826,15 @@ static void ath12k_bss_assoc(struct ath12k *ar,
return;
}
- ath12k_peer_assoc_prepare(ar, arvif, ap_sta, &peer_arg, false);
+ ahsta = ath12k_sta_to_ahsta(ap_sta);
+ arsta = &ahsta->deflink;
+
+ if (WARN_ON(!arsta)) {
+ rcu_read_unlock();
+ return;
+ }
+
+ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, false);
rcu_read_unlock();
@@ -3908,20 +3931,25 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif,
}
static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
- struct ath12k_link_vif *arvif, struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ieee80211_key_conf *key)
{
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_vif_to_vif(ahvif);
+ struct ieee80211_sta *sta = NULL;
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
- struct ath12k_sta *arsta;
+ struct ath12k_sta *ahsta;
const u8 *peer_addr;
int ret = 0;
u32 flags = 0;
lockdep_assert_held(&ar->conf_mutex);
+ if (arsta)
+ sta = ath12k_sta_to_sta(arsta->ahsta);
+
if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags))
return 1;
@@ -3994,7 +4022,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);
if (sta) {
- arsta = ath12k_sta_to_arsta(sta);
+ ahsta = ath12k_sta_to_ahsta(sta);
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
@@ -4003,12 +4031,12 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
if (cmd == SET_KEY)
- arsta->pn_type = HAL_PN_TYPE_WPA;
+ ahsta->pn_type = HAL_PN_TYPE_WPA;
else
- arsta->pn_type = HAL_PN_TYPE_NONE;
+ ahsta->pn_type = HAL_PN_TYPE_NONE;
break;
default:
- arsta->pn_type = HAL_PN_TYPE_NONE;
+ ahsta->pn_type = HAL_PN_TYPE_NONE;
break;
}
}
@@ -4026,7 +4054,9 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta = NULL;
struct ath12k_vif_cache *cache;
+ struct ath12k_sta *ahsta;
struct ath12k *ar;
int ret;
@@ -4067,14 +4097,19 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return 0;
}
- /* Note: Currently only deflink of ahvif is used here, once MLO
- * support is added the allocated links (i.e ahvif->links[])
+ if (sta) {
+ ahsta = ath12k_sta_to_ahsta(sta);
+ arsta = &ahsta->deflink;
+ }
+
+ /* Note: Currently only deflink of ahvif and ahsta are used here,
+ * once MLO support is added the allocated links (i.e ahvif->links[])
* should be use based on link id passed from mac80211 and such link
* access needs to be protected with ah->conf_mutex.
*/
mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_set_key(ar, cmd, arvif, sta, key);
+ ret = ath12k_mac_set_key(ar, cmd, arvif, arsta, key);
mutex_unlock(&ar->conf_mutex);
mutex_unlock(&ah->conf_mutex);
return ret;
@@ -4096,10 +4131,11 @@ ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,
static int
ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
const struct cfg80211_bitrate_mask *mask,
enum nl80211_band band)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
u8 vht_rate, nss;
u32 rate_code;
@@ -4142,10 +4178,11 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
static int ath12k_station_assoc(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_sta *arsta,
bool reassoc)
{
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_assoc_arg peer_arg;
int ret;
struct cfg80211_chan_def def;
@@ -4161,7 +4198,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
band = def.chan->band;
mask = &arvif->bitrate_mask;
- ath12k_peer_assoc_prepare(ar, arvif, sta, &peer_arg, reassoc);
+ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, reassoc);
ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
if (ret) {
@@ -4184,7 +4221,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
* Note that all other rates and NSS will be disabled for this peer.
*/
if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
- ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
+ ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
if (ret)
return ret;
@@ -4213,7 +4250,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
}
if (sta->wme && sta->uapsd_queues) {
- ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta);
+ ret = ath12k_peer_assoc_qos_ap(ar, arvif, arsta);
if (ret) {
ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
sta->addr, arvif->vdev_id, ret);
@@ -4226,8 +4263,9 @@ static int ath12k_station_assoc(struct ath12k *ar,
static int ath12k_station_disassoc(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
int ret;
lockdep_assert_held(&ar->conf_mutex);
@@ -4251,7 +4289,6 @@ static int ath12k_station_disassoc(struct ath12k *ar,
static void ath12k_sta_rc_update_wk(struct work_struct *wk)
{
struct ath12k *ar;
- struct ath12k_sta *arsta;
struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
struct cfg80211_chan_def def;
@@ -4263,10 +4300,11 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
const struct cfg80211_bitrate_mask *mask;
struct ath12k_wmi_peer_assoc_arg peer_arg;
enum wmi_phy_mode peer_phymode;
+ struct ath12k_link_sta *arsta;
struct ieee80211_vif *vif;
- arsta = container_of(wk, struct ath12k_sta, update_wk);
- sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
+ arsta = container_of(wk, struct ath12k_link_sta, update_wk);
+ sta = ath12k_sta_to_sta(arsta->ahsta);
arvif = arsta->arvif;
vif = ath12k_vif_to_vif(arvif->ahvif);
ar = arvif->ar;
@@ -4297,7 +4335,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
ath12k_mac_max_vht_nss(vht_mcs_mask)));
if (changed & IEEE80211_RC_BW_CHANGED) {
- ath12k_peer_assoc_h_phymode(ar, arvif, sta, &peer_arg);
+ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, &peer_arg);
peer_phymode = peer_arg.peer_phymode;
if (bw > bw_prev) {
@@ -4385,14 +4423,14 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
* across HT/VHT and for multiple VHT MCS support.
*/
if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
- ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
+ ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
} else {
/* If the peer is non-VHT or no fixed VHT rate
* is provided in the new bitrate mask we set the
* other rates using peer_assoc command.
*/
- ath12k_peer_assoc_prepare(ar, arvif, sta,
+ ath12k_peer_assoc_prepare(ar, arvif, arsta,
&peer_arg, true);
err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
@@ -4410,8 +4448,9 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
}
static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
lockdep_assert_held(&ar->conf_mutex);
@@ -4428,8 +4467,9 @@ static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif,
}
static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
lockdep_assert_held(&ar->conf_mutex);
@@ -4442,17 +4482,17 @@ static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif,
static int ath12k_mac_station_add(struct ath12k *ar,
struct ath12k_link_vif *arvif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_sta *arsta)
{
struct ath12k_base *ab = ar->ab;
struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ieee80211_sta *sta = ath12k_sta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_create_arg peer_param;
int ret;
lockdep_assert_held(&ar->conf_mutex);
- ret = ath12k_mac_inc_num_stations(arvif, sta);
+ ret = ath12k_mac_inc_num_stations(arvif, arsta);
if (ret) {
ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n",
ar->max_num_stations);
@@ -4511,7 +4551,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
free_peer:
ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
dec_num_station:
- ath12k_mac_dec_num_stations(arvif, sta);
+ ath12k_mac_dec_num_stations(arvif, arsta);
exit:
return ret;
}
@@ -4555,14 +4595,16 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k *ar;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta;
struct ath12k_peer *peer;
int ret = 0;
mutex_lock(&ah->conf_mutex);
arvif = &ahvif->deflink;
+ arsta = &ahsta->deflink;
/* cancel must be done outside the mutex to avoid deadlock */
if ((old_state == IEEE80211_STA_NONE &&
@@ -4580,10 +4622,15 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE) {
memset(arsta, 0, sizeof(*arsta));
+ rcu_assign_pointer(ahsta->link[0], arsta);
+ /* TODO use appropriate link id once MLO support is added */
+ arsta->link_id = ATH12K_DEFAULT_LINK_ID;
+ ahsta->links_map = BIT(arsta->link_id);
+ arsta->ahsta = ahsta;
arsta->arvif = arvif;
INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk);
- ret = ath12k_mac_station_add(ar, arvif, sta);
+ ret = ath12k_mac_station_add(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
sta->addr, arvif->vdev_id);
@@ -4606,7 +4653,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
sta->addr, arvif->vdev_id);
- ath12k_mac_dec_num_stations(arvif, sta);
+ ath12k_mac_dec_num_stations(arvif, arsta);
spin_lock_bh(&ar->ab->base_lock);
peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
if (peer && peer->sta == sta) {
@@ -4621,12 +4668,20 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
kfree(arsta->rx_stats);
arsta->rx_stats = NULL;
+
+ if (arsta->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ rcu_assign_pointer(ahsta->link[arsta->link_id], NULL);
+ synchronize_rcu();
+ ahsta->links_map &= ~(BIT(arsta->link_id));
+ arsta->link_id = ATH12K_INVALID_LINK_ID;
+ arsta->ahsta = NULL;
+ }
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_assoc(ar, arvif, sta, false);
+ ret = ath12k_station_assoc(ar, arvif, arsta, false);
if (ret)
ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
sta->addr);
@@ -4670,7 +4725,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_disassoc(ar, arvif, sta);
+ ret = ath12k_station_disassoc(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",
sta->addr);
@@ -4735,8 +4790,9 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
u32 changed)
{
struct ath12k *ar;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_sta *arsta;
struct ath12k_link_vif *arvif;
struct ath12k_peer *peer;
u32 bw, smps;
@@ -4748,6 +4804,7 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
}
rcu_read_lock();
+ arsta = &ahsta->deflink;
arvif = &ahvif->deflink;
spin_lock_bh(&ar->ab->base_lock);
@@ -8205,7 +8262,8 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data,
struct ieee80211_sta *sta)
{
struct ath12k_link_vif *arvif = data;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
struct ath12k *ar = arvif->ar;
if (arsta->arvif != arvif)
@@ -8222,7 +8280,8 @@ static void ath12k_mac_disable_peer_fixed_rate(void *data,
struct ieee80211_sta *sta)
{
struct ath12k_link_vif *arvif = data;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
struct ath12k *ar = arvif->ar;
int ret;
@@ -8544,16 +8603,22 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta;
+ mutex_lock(&ah->conf_mutex);
+ arsta = &ahsta->deflink;
sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
sinfo->tx_duration = arsta->tx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
- if (!arsta->txrate.legacy && !arsta->txrate.nss)
+ if (!arsta->txrate.legacy && !arsta->txrate.nss) {
+ mutex_unlock(&ah->conf_mutex);
return;
+ }
if (arsta->txrate.legacy) {
sinfo->txrate.legacy = arsta->txrate.legacy;
@@ -8571,6 +8636,7 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
/* TODO: Use real NF instead of default one. */
sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+ mutex_unlock(&ah->conf_mutex);
}
static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,