@@ -1276,7 +1276,6 @@ struct ieee80211_sta_rates {
* notifications and capabilities. The value is only valid after
* the station moves to associated state.
* @smps_mode: current SMPS mode (off, static or dynamic)
- * @tx_rates: rate control selection table
*/
struct ieee80211_sta {
u32 supp_rates[IEEE80211_NUM_BANDS];
@@ -1290,7 +1289,6 @@ struct ieee80211_sta {
u8 rx_nss;
enum ieee80211_sta_rx_bandwidth bandwidth;
enum ieee80211_smps_mode smps_mode;
- struct ieee80211_sta_rates __rcu *rates;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
@@ -530,7 +530,7 @@ static void rate_fixup_ratelist(struct ieee80211_vif *vif,
}
-static void rate_control_fill_sta_table(struct ieee80211_sta *sta,
+static void rate_control_fill_sta_table(struct ieee80211_sta *pubsta,
struct ieee80211_tx_info *info,
struct ieee80211_tx_rate *rates,
int max_rates)
@@ -538,8 +538,11 @@ static void rate_control_fill_sta_table(struct ieee80211_sta *sta,
struct ieee80211_sta_rates *ratetbl = NULL;
int i;
- if (sta && !info->control.skip_table)
+ if (pubsta && !info->control.skip_table) {
+ struct sta_info *sta = container_of(pubsta, struct sta_info,
+ sta);
ratetbl = rcu_dereference(sta->rates);
+ }
/* Fill remaining rate slots with data from the sta rate table. */
max_rates = min_t(int, max_rates, IEEE80211_TX_RATE_TABLE_SIZE);
@@ -688,9 +691,18 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
struct ieee80211_sta *pubsta,
struct ieee80211_sta_rates *rates)
{
- struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates);
+ struct sta_info *sta;
+ struct ieee80211_sta_rates *old;
+
+ sta = container_of(pubsta, struct sta_info, sta);
+
+ spin_lock_bh(&sta->lock);
+ old = rcu_dereference_check(sta->rates,
+ rcu_access_pointer(sta->hnext) != NULL);
+
+ rcu_assign_pointer(sta->rates, rates);
+ spin_unlock_bh(&sta->lock);
- rcu_assign_pointer(pubsta->rates, rates);
if (old)
kfree_rcu(old, rcu_head);
@@ -234,6 +234,7 @@ struct sta_ampdu_mlme {
* @gtk: group keys negotiated with this station, if any
* @rate_ctrl: rate control algorithm reference
* @rate_ctrl_priv: rate control private per-STA pointer
+ * @rates: rate control selection table
* @last_tx_rate: rate used for last transmit, to report to userspace as
* "the" transmit rate
* @last_rx_rate_idx: rx status rate index of the last data packet
@@ -309,6 +310,7 @@ struct sta_info {
struct ieee80211_key __rcu *ptk;
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
+ struct ieee80211_sta_rates __rcu *rates;
spinlock_t lock;
struct work_struct drv_unblock_wk;
@@ -693,7 +693,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
rate_control_get_rate(tx->sdata, tx->sta, &txrc);
if (tx->sta && !info->control.skip_table)
- ratetbl = rcu_dereference(tx->sta->sta.rates);
+ ratetbl = rcu_dereference(tx->sta->rates);
if (unlikely(info->control.rates[0].idx < 0)) {
if (ratetbl) {