forked from Minki/linux
mac80211/minstrel: use the new rate control API
Pass the rate selection table to mac80211 from minstrel_update_stats. Only rates for sample attempts are set in info->control.rates, with deferred sampling, only the second slot gets changed. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
a85666627b
commit
06d961a8e2
@ -83,6 +83,50 @@ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
|
|||||||
tp_list[j] = i;
|
tp_list[j] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
minstrel_set_rate(struct minstrel_sta_info *mi, struct ieee80211_sta_rates *ratetbl,
|
||||||
|
int offset, int idx)
|
||||||
|
{
|
||||||
|
struct minstrel_rate *r = &mi->r[idx];
|
||||||
|
|
||||||
|
ratetbl->rate[offset].idx = r->rix;
|
||||||
|
ratetbl->rate[offset].count = r->adjusted_retry_count;
|
||||||
|
ratetbl->rate[offset].count_cts = r->retry_count_cts;
|
||||||
|
ratetbl->rate[offset].count_rts = r->retry_count_rtscts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
|
||||||
|
{
|
||||||
|
struct ieee80211_sta_rates *ratetbl;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC);
|
||||||
|
if (!ratetbl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Start with max_tp_rate */
|
||||||
|
minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[0]);
|
||||||
|
|
||||||
|
if (mp->hw->max_rates >= 3) {
|
||||||
|
/* At least 3 tx rates supported, use max_tp_rate2 next */
|
||||||
|
minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp->hw->max_rates >= 2) {
|
||||||
|
/* At least 2 tx rates supported, use max_prob_rate next */
|
||||||
|
minstrel_set_rate(mi, ratetbl, i++, mi->max_prob_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use lowest rate last */
|
||||||
|
ratetbl->rate[i].idx = mi->lowest_rix;
|
||||||
|
ratetbl->rate[i].count = mp->max_retry;
|
||||||
|
ratetbl->rate[i].count_cts = mp->max_retry;
|
||||||
|
ratetbl->rate[i].count_rts = mp->max_retry;
|
||||||
|
|
||||||
|
rate_control_set_rates(mp->hw, mi->sta, ratetbl);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
|
minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
|
||||||
{
|
{
|
||||||
@ -161,6 +205,8 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
|
|||||||
|
|
||||||
/* Reset update timer */
|
/* Reset update timer */
|
||||||
mi->stats_update = jiffies;
|
mi->stats_update = jiffies;
|
||||||
|
|
||||||
|
minstrel_update_rates(mp, mi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -240,13 +286,12 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
|
|||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
struct minstrel_sta_info *mi = priv_sta;
|
struct minstrel_sta_info *mi = priv_sta;
|
||||||
struct minstrel_priv *mp = priv;
|
struct minstrel_priv *mp = priv;
|
||||||
struct ieee80211_tx_rate *ar = info->control.rates;
|
struct ieee80211_tx_rate *rate = &info->control.rates[0];
|
||||||
unsigned int ndx, sample_ndx = 0;
|
struct minstrel_rate *msr, *mr;
|
||||||
|
unsigned int ndx;
|
||||||
bool mrr_capable;
|
bool mrr_capable;
|
||||||
bool indirect_rate_sampling = false;
|
bool prev_sample = mi->prev_sample;
|
||||||
bool rate_sampling = false;
|
int delta;
|
||||||
int i, delta;
|
|
||||||
int mrr_ndx[3];
|
|
||||||
int sampling_ratio;
|
int sampling_ratio;
|
||||||
|
|
||||||
/* management/no-ack frames do not use rate control */
|
/* management/no-ack frames do not use rate control */
|
||||||
@ -262,107 +307,75 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
|
|||||||
else
|
else
|
||||||
sampling_ratio = mp->lookaround_rate;
|
sampling_ratio = mp->lookaround_rate;
|
||||||
|
|
||||||
/* init rateindex [ndx] with max throughput rate */
|
|
||||||
ndx = mi->max_tp_rate[0];
|
|
||||||
|
|
||||||
/* increase sum packet counter */
|
/* increase sum packet counter */
|
||||||
mi->packet_count++;
|
mi->packet_count++;
|
||||||
|
|
||||||
delta = (mi->packet_count * sampling_ratio / 100) -
|
delta = (mi->packet_count * sampling_ratio / 100) -
|
||||||
(mi->sample_count + mi->sample_deferred / 2);
|
(mi->sample_count + mi->sample_deferred / 2);
|
||||||
|
|
||||||
/* delta > 0: sampling required */
|
/* delta < 0: no sampling required */
|
||||||
if ((delta > 0) && (mrr_capable || !mi->prev_sample)) {
|
mi->prev_sample = false;
|
||||||
struct minstrel_rate *msr;
|
if (delta < 0 || (!mrr_capable && prev_sample))
|
||||||
if (mi->packet_count >= 10000) {
|
return;
|
||||||
mi->sample_deferred = 0;
|
|
||||||
mi->sample_count = 0;
|
|
||||||
mi->packet_count = 0;
|
|
||||||
} else if (delta > mi->n_rates * 2) {
|
|
||||||
/* With multi-rate retry, not every planned sample
|
|
||||||
* attempt actually gets used, due to the way the retry
|
|
||||||
* chain is set up - [max_tp,sample,prob,lowest] for
|
|
||||||
* sample_rate < max_tp.
|
|
||||||
*
|
|
||||||
* If there's too much sampling backlog and the link
|
|
||||||
* starts getting worse, minstrel would start bursting
|
|
||||||
* out lots of sampling frames, which would result
|
|
||||||
* in a large throughput loss. */
|
|
||||||
mi->sample_count += (delta - mi->n_rates * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get next random rate sample */
|
if (mi->packet_count >= 10000) {
|
||||||
sample_ndx = minstrel_get_next_sample(mi);
|
mi->sample_deferred = 0;
|
||||||
msr = &mi->r[sample_ndx];
|
mi->sample_count = 0;
|
||||||
rate_sampling = true;
|
mi->packet_count = 0;
|
||||||
|
} else if (delta > mi->n_rates * 2) {
|
||||||
/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
|
/* With multi-rate retry, not every planned sample
|
||||||
* rate sampling method should be used.
|
* attempt actually gets used, due to the way the retry
|
||||||
* Respect such rates that are not sampled for 20 interations.
|
* chain is set up - [max_tp,sample,prob,lowest] for
|
||||||
*/
|
* sample_rate < max_tp.
|
||||||
if (mrr_capable &&
|
*
|
||||||
msr->perfect_tx_time > mi->r[ndx].perfect_tx_time &&
|
* If there's too much sampling backlog and the link
|
||||||
msr->sample_skipped < 20)
|
* starts getting worse, minstrel would start bursting
|
||||||
indirect_rate_sampling = true;
|
* out lots of sampling frames, which would result
|
||||||
|
* in a large throughput loss. */
|
||||||
if (!indirect_rate_sampling) {
|
mi->sample_count += (delta - mi->n_rates * 2);
|
||||||
if (msr->sample_limit != 0) {
|
}
|
||||||
ndx = sample_ndx;
|
|
||||||
mi->sample_count++;
|
/* get next random rate sample */
|
||||||
if (msr->sample_limit > 0)
|
ndx = minstrel_get_next_sample(mi);
|
||||||
msr->sample_limit--;
|
msr = &mi->r[ndx];
|
||||||
} else
|
mr = &mi->r[mi->max_tp_rate[0]];
|
||||||
rate_sampling = false;
|
|
||||||
} else {
|
/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
|
||||||
/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
|
* rate sampling method should be used.
|
||||||
* packets that have the sampling rate deferred to the
|
* Respect such rates that are not sampled for 20 interations.
|
||||||
* second MRR stage. Increase the sample counter only
|
*/
|
||||||
* if the deferred sample rate was actually used.
|
if (mrr_capable &&
|
||||||
* Use the sample_deferred counter to make sure that
|
msr->perfect_tx_time > mr->perfect_tx_time &&
|
||||||
* the sampling is not done in large bursts */
|
msr->sample_skipped < 20) {
|
||||||
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
|
/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
|
||||||
mi->sample_deferred++;
|
* packets that have the sampling rate deferred to the
|
||||||
}
|
* second MRR stage. Increase the sample counter only
|
||||||
|
* if the deferred sample rate was actually used.
|
||||||
|
* Use the sample_deferred counter to make sure that
|
||||||
|
* the sampling is not done in large bursts */
|
||||||
|
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
|
||||||
|
rate++;
|
||||||
|
mi->sample_deferred++;
|
||||||
|
} else {
|
||||||
|
if (!msr->sample_limit != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mi->sample_count++;
|
||||||
|
if (msr->sample_limit > 0)
|
||||||
|
msr->sample_limit--;
|
||||||
}
|
}
|
||||||
mi->prev_sample = rate_sampling;
|
|
||||||
|
|
||||||
/* If we're not using MRR and the sampling rate already
|
/* If we're not using MRR and the sampling rate already
|
||||||
* has a probability of >95%, we shouldn't be attempting
|
* has a probability of >95%, we shouldn't be attempting
|
||||||
* to use it, as this only wastes precious airtime */
|
* to use it, as this only wastes precious airtime */
|
||||||
if (!mrr_capable && rate_sampling &&
|
if (!mrr_capable &&
|
||||||
(mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))
|
(mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))
|
||||||
ndx = mi->max_tp_rate[0];
|
|
||||||
|
|
||||||
/* mrr setup for 1st stage */
|
|
||||||
ar[0].idx = mi->r[ndx].rix;
|
|
||||||
ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
|
|
||||||
|
|
||||||
/* non mrr setup for 2nd stage */
|
|
||||||
if (!mrr_capable) {
|
|
||||||
if (!rate_sampling)
|
|
||||||
ar[0].count = mp->max_retry;
|
|
||||||
ar[1].idx = mi->lowest_rix;
|
|
||||||
ar[1].count = mp->max_retry;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* mrr setup for 2nd stage */
|
mi->prev_sample = true;
|
||||||
if (rate_sampling) {
|
|
||||||
if (indirect_rate_sampling)
|
|
||||||
mrr_ndx[0] = sample_ndx;
|
|
||||||
else
|
|
||||||
mrr_ndx[0] = mi->max_tp_rate[0];
|
|
||||||
} else {
|
|
||||||
mrr_ndx[0] = mi->max_tp_rate[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mrr setup for 3rd & 4th stage */
|
rate->idx = mi->r[ndx].rix;
|
||||||
mrr_ndx[1] = mi->max_prob_rate;
|
rate->count = minstrel_get_retry_count(&mi->r[ndx], info);
|
||||||
mrr_ndx[2] = 0;
|
|
||||||
for (i = 1; i < 4; i++) {
|
|
||||||
ar[i].idx = mi->r[mrr_ndx[i - 1]].rix;
|
|
||||||
ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -412,12 +425,16 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
|||||||
unsigned int i, n = 0;
|
unsigned int i, n = 0;
|
||||||
unsigned int t_slot = 9; /* FIXME: get real slot time */
|
unsigned int t_slot = 9; /* FIXME: get real slot time */
|
||||||
|
|
||||||
|
mi->sta = sta;
|
||||||
mi->lowest_rix = rate_lowest_index(sband, sta);
|
mi->lowest_rix = rate_lowest_index(sband, sta);
|
||||||
ctl_rate = &sband->bitrates[mi->lowest_rix];
|
ctl_rate = &sband->bitrates[mi->lowest_rix];
|
||||||
mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
|
mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
|
||||||
ctl_rate->bitrate,
|
ctl_rate->bitrate,
|
||||||
!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
|
!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
|
||||||
|
|
||||||
|
memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate));
|
||||||
|
mi->max_prob_rate = 0;
|
||||||
|
|
||||||
for (i = 0; i < sband->n_bitrates; i++) {
|
for (i = 0; i < sband->n_bitrates; i++) {
|
||||||
struct minstrel_rate *mr = &mi->r[n];
|
struct minstrel_rate *mr = &mi->r[n];
|
||||||
unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
|
unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
|
||||||
@ -473,6 +490,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
|||||||
mi->stats_update = jiffies;
|
mi->stats_update = jiffies;
|
||||||
|
|
||||||
init_sample_table(mi);
|
init_sample_table(mi);
|
||||||
|
minstrel_update_rates(mp, mi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -63,6 +63,8 @@ struct minstrel_rate {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct minstrel_sta_info {
|
struct minstrel_sta_info {
|
||||||
|
struct ieee80211_sta *sta;
|
||||||
|
|
||||||
unsigned long stats_update;
|
unsigned long stats_update;
|
||||||
unsigned int sp_ack_dur;
|
unsigned int sp_ack_dur;
|
||||||
unsigned int rate_avg;
|
unsigned int rate_avg;
|
||||||
|
Loading…
Reference in New Issue
Block a user