Commit a8566662 authored by Felix Fietkau's avatar Felix Fietkau Committed by Johannes Berg

mac80211/minstrel_ht: use the new rate control API

Pass the rate selection table to mac80211 from minstrel_ht_update_stats.
Only rates for sample attempts are set in info->control.rates.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 0d528d85
...@@ -126,6 +126,9 @@ const struct mcs_group minstrel_mcs_groups[] = { ...@@ -126,6 +126,9 @@ const struct mcs_group minstrel_mcs_groups[] = {
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
static void
minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
/* /*
* Look up an MCS group index based on mac80211 rate information * Look up an MCS group index based on mac80211 rate information
*/ */
...@@ -465,7 +468,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, ...@@ -465,7 +468,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_tx_rate *ar = info->status.rates; struct ieee80211_tx_rate *ar = info->status.rates;
struct minstrel_rate_stats *rate, *rate2; struct minstrel_rate_stats *rate, *rate2;
struct minstrel_priv *mp = priv; struct minstrel_priv *mp = priv;
bool last; bool last, update = false;
int i; int i;
if (!msp->is_ht) if (!msp->is_ht)
...@@ -514,21 +517,29 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, ...@@ -514,21 +517,29 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
rate = minstrel_get_ratestats(mi, mi->max_tp_rate); rate = minstrel_get_ratestats(mi, mi->max_tp_rate);
if (rate->attempts > 30 && if (rate->attempts > 30 &&
MINSTREL_FRAC(rate->success, rate->attempts) < MINSTREL_FRAC(rate->success, rate->attempts) <
MINSTREL_FRAC(20, 100)) MINSTREL_FRAC(20, 100)) {
minstrel_downgrade_rate(mi, &mi->max_tp_rate, true); minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
update = true;
}
rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2); rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
if (rate2->attempts > 30 && if (rate2->attempts > 30 &&
MINSTREL_FRAC(rate2->success, rate2->attempts) < MINSTREL_FRAC(rate2->success, rate2->attempts) <
MINSTREL_FRAC(20, 100)) MINSTREL_FRAC(20, 100)) {
minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false); minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
update = true;
}
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
update = true;
minstrel_ht_update_stats(mp, mi); minstrel_ht_update_stats(mp, mi);
if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
minstrel_aggr_check(sta, skb); minstrel_aggr_check(sta, skb);
} }
if (update)
minstrel_ht_update_rates(mp, mi);
} }
static void static void
...@@ -592,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, ...@@ -592,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
static void static void
minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
struct ieee80211_tx_rate *rate, int index, struct ieee80211_sta_rates *ratetbl, int offset, int index)
bool sample, bool rtscts)
{ {
const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
struct minstrel_rate_stats *mr; struct minstrel_rate_stats *mr;
u8 idx;
u16 flags;
mr = minstrel_get_ratestats(mi, index); mr = minstrel_get_ratestats(mi, index);
if (!mr->retry_updated) if (!mr->retry_updated)
minstrel_calc_retransmit(mp, mi, index); minstrel_calc_retransmit(mp, mi, index);
if (sample) if (mr->probability < MINSTREL_FRAC(20, 100) || !mr->retry_count) {
rate->count = 1; ratetbl->rate[offset].count = 2;
else if (mr->probability < MINSTREL_FRAC(20, 100)) ratetbl->rate[offset].count_rts = 2;
rate->count = 2; ratetbl->rate[offset].count_cts = 2;
else if (rtscts) } else {
rate->count = mr->retry_count_rtscts; ratetbl->rate[offset].count = mr->retry_count;
else ratetbl->rate[offset].count_cts = mr->retry_count;
rate->count = mr->retry_count; ratetbl->rate[offset].count_rts = mr->retry_count_rtscts;
}
rate->flags = 0;
if (rtscts)
rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) { if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
rate->idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
flags = 0;
} else {
idx = index % MCS_GROUP_RATES +
(group->streams - 1) * MCS_GROUP_RATES;
flags = IEEE80211_TX_RC_MCS | group->flags;
}
if (offset > 0) {
ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
flags |= IEEE80211_TX_RC_USE_RTS_CTS;
}
ratetbl->rate[offset].idx = idx;
ratetbl->rate[offset].flags = flags;
}
static void
minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
{
struct ieee80211_sta_rates *rates;
int i = 0;
rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
if (!rates)
return; return;
/* Start with max_tp_rate */
minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate);
if (mp->hw->max_rates >= 3) {
/* At least 3 tx rates supported, use max_tp_rate2 next */
minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate2);
}
if (mp->hw->max_rates >= 2) {
/*
* At least 2 tx rates supported, use max_prob_rate next */
minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
} }
rate->flags |= IEEE80211_TX_RC_MCS | group->flags; rates->rate[i].idx = -1;
rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES; rate_control_set_rates(mp->hw, mi->sta, rates);
} }
static inline int static inline int
...@@ -711,13 +757,13 @@ static void ...@@ -711,13 +757,13 @@ static void
minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate_control *txrc) struct ieee80211_tx_rate_control *txrc)
{ {
const struct mcs_group *sample_group;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
struct ieee80211_tx_rate *ar = info->status.rates; struct ieee80211_tx_rate *rate = &info->status.rates[0];
struct minstrel_ht_sta_priv *msp = priv_sta; struct minstrel_ht_sta_priv *msp = priv_sta;
struct minstrel_ht_sta *mi = &msp->ht; struct minstrel_ht_sta *mi = &msp->ht;
struct minstrel_priv *mp = priv; struct minstrel_priv *mp = priv;
int sample_idx; int sample_idx;
bool sample = false;
if (rate_control_send_low(sta, priv_sta, txrc)) if (rate_control_send_low(sta, priv_sta, txrc))
return; return;
...@@ -745,51 +791,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, ...@@ -745,51 +791,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
} }
#endif #endif
if (sample_idx >= 0) {
sample = true;
minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
true, false);
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
false, false);
}
if (mp->hw->max_rates >= 3) {
/*
* At least 3 tx rates supported, use
* sample_rate -> max_tp_rate -> max_prob_rate for sampling and
* max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
*/
if (sample_idx >= 0)
minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
false, false);
else
minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
false, true);
minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
false, !sample);
ar[3].count = 0;
ar[3].idx = -1;
} else if (mp->hw->max_rates == 2) {
/*
* Only 2 tx rates supported, use
* sample_rate -> max_prob_rate for sampling and
* max_tp_rate -> max_prob_rate by default.
*/
minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
false, !sample);
ar[2].count = 0;
ar[2].idx = -1;
} else {
/* Not using MRR, only use the first rate */
ar[1].count = 0;
ar[1].idx = -1;
}
mi->total_packets++; mi->total_packets++;
/* wraparound */ /* wraparound */
...@@ -797,6 +798,16 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, ...@@ -797,6 +798,16 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
mi->total_packets = 0; mi->total_packets = 0;
mi->sample_packets = 0; mi->sample_packets = 0;
} }
if (sample_idx < 0)
return;
sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
rate->idx = sample_idx % MCS_GROUP_RATES +
(sample_group->streams - 1) * MCS_GROUP_RATES;
rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
rate->count = 1;
} }
static void static void
...@@ -846,6 +857,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, ...@@ -846,6 +857,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
msp->is_ht = true; msp->is_ht = true;
memset(mi, 0, sizeof(*mi)); memset(mi, 0, sizeof(*mi));
mi->sta = sta;
mi->stats_update = jiffies; mi->stats_update = jiffies;
ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1); ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1);
...@@ -907,8 +920,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, ...@@ -907,8 +920,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
if (!n_supported) if (!n_supported)
goto use_legacy; goto use_legacy;
/* init {mi,mi->groups[*]}->{max_tp_rate,max_tp_rate2,max_prob_rate} */ /* create an initial rate table with the lowest supported rates */
minstrel_ht_update_stats(mp, mi); minstrel_ht_update_stats(mp, mi);
minstrel_ht_update_rates(mp, mi);
return; return;
......
...@@ -65,6 +65,8 @@ struct minstrel_mcs_group_data { ...@@ -65,6 +65,8 @@ struct minstrel_mcs_group_data {
}; };
struct minstrel_ht_sta { struct minstrel_ht_sta {
struct ieee80211_sta *sta;
/* ampdu length (average, per sampling interval) */ /* ampdu length (average, per sampling interval) */
unsigned int ampdu_len; unsigned int ampdu_len;
unsigned int ampdu_packets; unsigned int ampdu_packets;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment