@@ -443,15 +443,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;
@@ -459,11 +459,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
@@ -652,8 +661,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;
@@ -1011,11 +1020,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);
@@ -2203,7 +2203,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;
@@ -2359,7 +2359,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;
@@ -2376,7 +2377,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)
@@ -2483,7 +2485,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;
@@ -2552,7 +2555,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) &&
@@ -1064,13 +1064,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);
@@ -1082,7 +1083,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;
@@ -1336,7 +1338,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];
@@ -1417,7 +1420,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));
@@ -1479,10 +1479,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;
@@ -1505,10 +1506,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 ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_bss_conf *info = &vif->bss_conf;
struct cfg80211_chan_def def;
@@ -1568,10 +1570,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;
@@ -1631,10 +1634,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;
@@ -1792,10 +1796,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;
@@ -1887,10 +1892,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;
@@ -2040,9 +2046,10 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
}
}
-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_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
int smps;
@@ -2069,9 +2076,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) {
@@ -2103,8 +2112,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;
@@ -2265,7 +2275,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;
@@ -2274,6 +2284,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;
@@ -2410,9 +2421,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;
@@ -2492,7 +2504,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)
{
@@ -2503,16 +2515,16 @@ 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_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_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? */
}
@@ -2544,7 +2556,9 @@ static void ath12k_bss_assoc(struct ath12k *ar,
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_vif_to_vif(ahvif);
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;
@@ -2564,7 +2578,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();
@@ -3657,20 +3679,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;
@@ -3743,7 +3770,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:
@@ -3752,12 +3779,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;
}
}
@@ -3775,7 +3802,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;
@@ -3816,14 +3845,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;
@@ -3845,10 +3879,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;
@@ -3891,10 +3926,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;
@@ -3910,7 +3946,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) {
@@ -3933,7 +3969,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;
@@ -3961,7 +3997,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);
@@ -3974,8 +4010,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);
@@ -3999,7 +4036,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;
@@ -4011,10 +4047,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;
@@ -4045,7 +4082,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) {
@@ -4133,14 +4170,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);
@@ -4158,8 +4195,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);
@@ -4176,8 +4214,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);
@@ -4190,17 +4229,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);
@@ -4259,7 +4298,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;
}
@@ -4303,14 +4342,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 &&
@@ -4328,10 +4369,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);
@@ -4354,7 +4400,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) {
@@ -4369,12 +4415,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);
@@ -4418,7 +4472,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);
@@ -4483,8 +4537,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;
@@ -4496,6 +4551,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);
@@ -7918,7 +7974,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)
@@ -7935,7 +7992,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;
@@ -8237,16 +8295,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;
@@ -8264,6 +8328,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,