for (i = rix; i >= 0; i--)
if (mi->r[i].rix == rix)
break;
- WARN_ON(mi->r[i].rix != rix);
+ WARN_ON(i < 0);
return i;
}
fc = le16_to_cpu(hdr->frame_control);
return ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
- (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
- is_multicast_ether_addr(hdr->addr1));
+ (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA);
}
mr->adjusted_retry_count = mr->retry_count >> 1;
if (mr->adjusted_retry_count > 2)
mr->adjusted_retry_count = 2;
+ mr->sample_limit = 4;
} else {
+ mr->sample_limit = -1;
mr->adjusted_retry_count = mr->retry_count;
}
if (!mr->adjusted_retry_count)
break;
ndx = rix_to_ndx(mi, ar[i].idx);
+ if (ndx < 0)
+ continue;
+
mi->r[ndx].attempts += ar[i].count;
if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
unsigned int sample_ndx;
sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column);
mi->sample_idx++;
- if (mi->sample_idx > (mi->n_rates - 2)) {
+ if ((int) mi->sample_idx > (mi->n_rates - 2)) {
mi->sample_idx = 0;
mi->sample_column++;
if (mi->sample_column >= SAMPLE_COLUMNS)
return sample_ndx;
}
-void
+static void
minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
void *priv_sta, struct ieee80211_tx_rate_control *txrc)
{
if (!sta || !mi || use_low_rate(skb)) {
ar[0].idx = rate_lowest_index(sband, sta);
- ar[0].count = mp->max_retry;
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ ar[0].count = 1;
+ else
+ ar[0].count = mp->max_retry;
return;
}
(mi->sample_count + mi->sample_deferred / 2);
/* delta > 0: sampling required */
- if (delta > 0) {
+ if ((delta > 0) && (mrr || !mi->prev_sample)) {
+ struct minstrel_rate *msr;
if (mi->packet_count >= 10000) {
mi->sample_deferred = 0;
mi->sample_count = 0;
}
sample_ndx = minstrel_get_next_sample(mi);
+ msr = &mi->r[sample_ndx];
sample = true;
- sample_slower = mrr && (mi->r[sample_ndx].perfect_tx_time >
+ sample_slower = mrr && (msr->perfect_tx_time >
mi->r[ndx].perfect_tx_time);
if (!sample_slower) {
- ndx = sample_ndx;
- mi->sample_count++;
+ if (msr->sample_limit != 0) {
+ ndx = sample_ndx;
+ mi->sample_count++;
+ if (msr->sample_limit > 0)
+ msr->sample_limit--;
+ } else {
+ sample = false;
+ }
} else {
/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
* packets that have the sampling rate deferred to the
mi->sample_deferred++;
}
}
+ mi->prev_sample = sample;
+
+ /* If we're not using MRR and the sampling rate already
+ * has a probability of >95%, we shouldn't be attempting
+ * to use it, as this only wastes precious airtime */
+ if (!mrr && sample && (mi->r[ndx].probability > 17100))
+ ndx = mi->max_tp_rate;
+
ar[0].idx = mi->r[ndx].rix;
ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
if (!mrr) {
+ if (!sample)
+ ar[0].count = mp->max_retry;
ar[1].idx = mi->lowest_rix;
ar[1].count = mp->max_retry;
return;
{
struct minstrel_sta_info *mi = priv_sta;
struct minstrel_priv *mp = priv;
- struct minstrel_rate *mr_ctl;
+ struct ieee80211_local *local = hw_to_local(mp->hw);
+ struct ieee80211_rate *ctl_rate;
unsigned int i, n = 0;
unsigned int t_slot = 9; /* FIXME: get real slot time */
mi->lowest_rix = rate_lowest_index(sband, sta);
- mr_ctl = &mi->r[rix_to_ndx(mi, mi->lowest_rix)];
- mi->sp_ack_dur = mr_ctl->ack_time;
+ ctl_rate = &sband->bitrates[mi->lowest_rix];
+ mi->sp_ack_dur = ieee80211_frame_duration(local, 10, ctl_rate->bitrate,
+ !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
for (i = 0; i < sband->n_bitrates; i++) {
struct minstrel_rate *mr = &mi->r[n];
mr->rix = i;
mr->bitrate = sband->bitrates[i].bitrate / 5;
- calc_rate_durations(mi, hw_to_local(mp->hw), mr,
+ calc_rate_durations(mi, local, mr,
&sband->bitrates[i]);
/* calculate maximum number of retransmissions before
* fallback (based on maximum segment size) */
+ mr->sample_limit = -1;
mr->retry_count = 1;
mr->retry_count_cts = 1;
mr->retry_count_rtscts = 1;
return NULL;
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
- sband = hw->wiphy->bands[hw->conf.channel->band];
- if (sband->n_bitrates > max_rates)
+ sband = hw->wiphy->bands[i];
+ if (sband && sband->n_bitrates > max_rates)
max_rates = sband->n_bitrates;
}
kfree(mi);
}
-static void
-minstrel_clear(void *priv)
-{
-}
-
static void *
minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
.tx_status = minstrel_tx_status,
.get_rate = minstrel_get_rate,
.rate_init = minstrel_rate_init,
- .clear = minstrel_clear,
.alloc = minstrel_alloc,
.free = minstrel_free,
.alloc_sta = minstrel_alloc_sta,