mac80211: use rate index in TX control
This patch modifies struct ieee80211_tx_control to give band
info and the rate index (instead of rate pointers) to drivers.
This mostly serves to reduce the TX control structure size to
make it fit into skb->cb so that the fragmentation code can
put it there and we can think about passing it to drivers that
way in the future.
The rt2x00 driver update was done by Ivo, thanks.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index aecec2a..99c3860 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -91,11 +91,12 @@
int next_frag_len)
{
int rate, mrate, erp, dur, i;
- struct ieee80211_rate *txrate = tx->rate;
+ struct ieee80211_rate *txrate;
struct ieee80211_local *local = tx->local;
struct ieee80211_supported_band *sband;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ sband = local->hw.wiphy->bands[tx->channel->band];
+ txrate = &sband->bitrates[tx->rate_idx];
erp = 0;
if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
@@ -610,40 +611,40 @@
struct rate_selection rsel;
struct ieee80211_supported_band *sband;
- sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
+ sband = tx->local->hw.wiphy->bands[tx->channel->band];
- if (likely(!tx->rate)) {
+ if (likely(tx->rate_idx < 0)) {
rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
- tx->rate = rsel.rate;
- if (unlikely(rsel.probe)) {
+ tx->rate_idx = rsel.rate_idx;
+ if (unlikely(rsel.probe_idx >= 0)) {
tx->control->flags |=
IEEE80211_TXCTL_RATE_CTRL_PROBE;
tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
- tx->control->alt_retry_rate = tx->rate;
- tx->rate = rsel.probe;
+ tx->control->alt_retry_rate_idx = tx->rate_idx;
+ tx->rate_idx = rsel.probe_idx;
} else
- tx->control->alt_retry_rate = NULL;
+ tx->control->alt_retry_rate_idx = -1;
- if (!tx->rate)
+ if (unlikely(tx->rate_idx < 0))
return TX_DROP;
} else
- tx->control->alt_retry_rate = NULL;
+ tx->control->alt_retry_rate_idx = -1;
if (tx->sdata->bss_conf.use_cts_prot &&
- (tx->flags & IEEE80211_TX_FRAGMENTED) && rsel.nonerp) {
- tx->last_frag_rate = tx->rate;
- if (rsel.probe)
+ (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) {
+ tx->last_frag_rate_idx = tx->rate_idx;
+ if (rsel.probe_idx >= 0)
tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG;
else
tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
- tx->rate = rsel.nonerp;
- tx->control->tx_rate = rsel.nonerp;
+ tx->rate_idx = rsel.nonerp_idx;
+ tx->control->tx_rate_idx = rsel.nonerp_idx;
tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
} else {
- tx->last_frag_rate = tx->rate;
- tx->control->tx_rate = tx->rate;
+ tx->last_frag_rate_idx = tx->rate_idx;
+ tx->control->tx_rate_idx = tx->rate_idx;
}
- tx->control->tx_rate = tx->rate;
+ tx->control->tx_rate_idx = tx->rate_idx;
return TX_CONTINUE;
}
@@ -655,6 +656,9 @@
u16 fc = le16_to_cpu(hdr->frame_control);
u16 dur;
struct ieee80211_tx_control *control = tx->control;
+ struct ieee80211_supported_band *sband;
+
+ sband = tx->local->hw.wiphy->bands[tx->channel->band];
if (!control->retry_limit) {
if (!is_multicast_ether_addr(hdr->addr1)) {
@@ -681,14 +685,14 @@
* frames.
* TODO: The last fragment could still use multiple retry
* rates. */
- control->alt_retry_rate = NULL;
+ control->alt_retry_rate_idx = -1;
}
/* Use CTS protection for unicast frames sent using extended rates if
* there are associated non-ERP stations and RTS/CTS is not configured
* for the frame. */
if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) &&
- (tx->rate->flags & IEEE80211_RATE_ERP_G) &&
+ (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) &&
(tx->flags & IEEE80211_TX_UNICAST) &&
tx->sdata->bss_conf.use_cts_prot &&
!(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
@@ -698,7 +702,7 @@
* short preambles at the selected rate and short preambles are
* available on the network at the current point in time. */
if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
- (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
+ (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
tx->sdata->bss_conf.use_short_preamble &&
(!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) {
tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
@@ -715,32 +719,32 @@
if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
(control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
struct ieee80211_supported_band *sband;
- struct ieee80211_rate *rate, *baserate;
+ struct ieee80211_rate *rate;
+ s8 baserate = -1;
int idx;
- sband = tx->local->hw.wiphy->bands[
- tx->local->hw.conf.channel->band];
+ sband = tx->local->hw.wiphy->bands[tx->channel->band];
/* Do not use multiple retry rates when using RTS/CTS */
- control->alt_retry_rate = NULL;
+ control->alt_retry_rate_idx = -1;
/* Use min(data rate, max base rate) as CTS/RTS rate */
- rate = tx->rate;
- baserate = NULL;
+ rate = &sband->bitrates[tx->rate_idx];
for (idx = 0; idx < sband->n_bitrates; idx++) {
if (sband->bitrates[idx].bitrate > rate->bitrate)
continue;
if (tx->sdata->basic_rates & BIT(idx) &&
- (!baserate ||
- (baserate->bitrate < sband->bitrates[idx].bitrate)))
- baserate = &sband->bitrates[idx];
+ (baserate < 0 ||
+ (sband->bitrates[baserate].bitrate
+ < sband->bitrates[idx].bitrate)))
+ baserate = idx;
}
- if (baserate)
- control->rts_cts_rate = baserate;
+ if (baserate >= 0)
+ control->rts_cts_rate_idx = baserate;
else
- control->rts_cts_rate = &sband->bitrates[0];
+ control->rts_cts_rate_idx = 0;
}
if (tx->sta) {
@@ -768,7 +772,11 @@
struct sk_buff *skb = tx->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u32 load = 0, hdrtime;
- struct ieee80211_rate *rate = tx->rate;
+ struct ieee80211_rate *rate;
+ struct ieee80211_supported_band *sband;
+
+ sband = tx->local->hw.wiphy->bands[tx->channel->band];
+ rate = &sband->bitrates[tx->rate_idx];
/* TODO: this could be part of tx_status handling, so that the number
* of retries would be known; TX rate should in that case be stored
@@ -803,7 +811,7 @@
for (i = 0; i < tx->num_extra_frag; i++) {
load += 2 * hdrtime;
load += tx->extra_frag[i]->len *
- tx->rate->bitrate;
+ rate->bitrate;
}
}
@@ -859,7 +867,7 @@
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
struct ieee80211_tx_control *control = tx->control;
- sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
+ sband = tx->local->hw.wiphy->bands[tx->channel->band];
control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
tx->flags |= IEEE80211_TX_INJECTED;
@@ -899,7 +907,7 @@
r = &sband->bitrates[i];
if (r->bitrate == target_rate) {
- tx->rate = r;
+ tx->rate_idx = i;
break;
}
}
@@ -1097,7 +1105,7 @@
if (__ieee80211_queue_stopped(local, control->queue))
return IEEE80211_TX_FRAG_AGAIN;
if (i == tx->num_extra_frag) {
- control->tx_rate = tx->last_frag_rate;
+ control->tx_rate_idx = tx->last_frag_rate_idx;
if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
control->flags |=
@@ -1155,6 +1163,7 @@
sta = tx.sta;
tx.channel = local->hw.conf.channel;
+ control->band = tx.channel->band;
for (handler = ieee80211_tx_handlers; *handler != NULL;
handler++) {
@@ -1187,7 +1196,7 @@
next_len = tx.extra_frag[i + 1]->len;
} else {
next_len = 0;
- tx.rate = tx.last_frag_rate;
+ tx.rate_idx = tx.last_frag_rate_idx;
}
dur = ieee80211_duration(&tx, 0, next_len);
hdr->duration_id = cpu_to_le16(dur);
@@ -1224,7 +1233,7 @@
store->skb = skb;
store->extra_frag = tx.extra_frag;
store->num_extra_frag = tx.num_extra_frag;
- store->last_frag_rate = tx.last_frag_rate;
+ store->last_frag_rate_idx = tx.last_frag_rate_idx;
store->last_frag_rate_ctrl_probe =
!!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
}
@@ -1685,7 +1694,7 @@
tx.control = &store->control;
tx.extra_frag = store->extra_frag;
tx.num_extra_frag = store->num_extra_frag;
- tx.last_frag_rate = store->last_frag_rate;
+ tx.last_frag_rate_idx = store->last_frag_rate_idx;
tx.flags = 0;
if (store->last_frag_rate_ctrl_probe)
tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG;
@@ -1789,9 +1798,10 @@
struct ieee80211_mgmt *mgmt;
int *num_beacons;
bool err = true;
+ enum ieee80211_band band = local->hw.conf.channel->band;
u8 *pos;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ sband = local->hw.wiphy->bands[band];
rcu_read_lock();
@@ -1885,8 +1895,9 @@
}
if (control) {
+ control->band = band;
rate_control_get_rate(local->mdev, sband, skb, &rsel);
- if (!rsel.rate) {
+ if (unlikely(rsel.rate_idx < 0)) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
"no rate found\n",
@@ -1898,9 +1909,9 @@
}
control->vif = vif;
- control->tx_rate = rsel.rate;
+ control->tx_rate_idx = rsel.rate_idx;
if (sdata->bss_conf.use_short_preamble &&
- rsel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+ sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
control->flags |= IEEE80211_TXCTL_NO_ACK;
@@ -2006,6 +2017,7 @@
sta = tx.sta;
tx.flags |= IEEE80211_TX_PS_BUFFERED;
tx.channel = local->hw.conf.channel;
+ control->band = tx.channel->band;
for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
res = (*handler)(&tx);