aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h8
-rw-r--r--net/mac80211/mlme.c6
-rw-r--r--net/mac80211/rate.c12
-rw-r--r--net/mac80211/rate.h25
-rw-r--r--net/mac80211/rc80211_pid_algo.c6
-rw-r--r--net/mac80211/tx.c104
-rw-r--r--net/mac80211/util.c10
7 files changed, 93 insertions, 78 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ed0d9b3..a4cccd1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -159,11 +159,11 @@ struct ieee80211_tx_data {
struct ieee80211_tx_control *control;
struct ieee80211_channel *channel;
- struct ieee80211_rate *rate;
+ s8 rate_idx;
/* use this rate (if set) for last fragment; rate can
* be set to lower rate for the first fragments, e.g.,
* when using CTS protection with IEEE 802.11g. */
- struct ieee80211_rate *last_frag_rate;
+ s8 last_frag_rate_idx;
/* Extra fragments (in addition to the first fragment
* in skb) */
@@ -225,9 +225,9 @@ struct ieee80211_tx_stored_packet {
struct ieee80211_tx_control control;
struct sk_buff *skb;
struct sk_buff **extra_frag;
- struct ieee80211_rate *last_frag_rate;
+ s8 last_frag_rate_idx;
int num_extra_frag;
- unsigned int last_frag_rate_ctrl_probe;
+ bool last_frag_rate_ctrl_probe;
};
struct beacon_data {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7877d3b..6041493 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2406,15 +2406,15 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
memset(&control, 0, sizeof(control));
rate_control_get_rate(dev, sband, skb, &ratesel);
- if (!ratesel.rate) {
+ if (ratesel.rate_idx < 0) {
printk(KERN_DEBUG "%s: Failed to determine TX rate "
"for IBSS beacon\n", dev->name);
break;
}
control.vif = &sdata->vif;
- control.tx_rate = ratesel.rate;
+ control.tx_rate_idx = ratesel.rate_idx;
if (sdata->bss_conf.use_short_preamble &&
- ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+ sband->bitrates[ratesel.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;
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 841df93..0388c09 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -176,20 +176,24 @@ void rate_control_get_rate(struct net_device *dev,
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
- memset(sel, 0, sizeof(struct rate_selection));
+ sel->rate_idx = -1;
+ sel->nonerp_idx = -1;
+ sel->probe_idx = -1;
ref->ops->get_rate(ref->priv, dev, sband, skb, sel);
+ BUG_ON(sel->rate_idx < 0);
+
/* Select a non-ERP backup rate. */
- if (!sel->nonerp) {
+ if (sel->nonerp_idx < 0) {
for (i = 0; i < sband->n_bitrates; i++) {
struct ieee80211_rate *rate = &sband->bitrates[i];
- if (sel->rate->bitrate < rate->bitrate)
+ if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate)
break;
if (rate_supported(sta, sband->band, i) &&
!(rate->flags & IEEE80211_RATE_ERP_G))
- sel->nonerp = rate;
+ sel->nonerp_idx = i;
}
}
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 5b45f33..a29148d 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -19,14 +19,15 @@
#include "ieee80211_i.h"
#include "sta_info.h"
-/* TODO: kdoc */
+/**
+ * struct rate_selection - rate selection for rate control algos
+ * @rate: selected transmission rate index
+ * @nonerp: Non-ERP rate to use instead if ERP cannot be used
+ * @probe: rate for probing (or -1)
+ *
+ */
struct rate_selection {
- /* Selected transmission rate */
- struct ieee80211_rate *rate;
- /* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */
- struct ieee80211_rate *nonerp;
- /* probe with this rate, or NULL for no probing */
- struct ieee80211_rate *probe;
+ s8 rate_idx, nonerp_idx, probe_idx;
};
struct rate_control_ops {
@@ -138,7 +139,7 @@ static inline int rate_supported(struct sta_info *sta,
return (sta == NULL || sta->supp_rates[band] & BIT(index));
}
-static inline int
+static inline s8
rate_lowest_index(struct ieee80211_local *local,
struct ieee80211_supported_band *sband,
struct sta_info *sta)
@@ -155,14 +156,6 @@ rate_lowest_index(struct ieee80211_local *local,
return 0;
}
-static inline struct ieee80211_rate *
-rate_lowest(struct ieee80211_local *local,
- struct ieee80211_supported_band *sband,
- struct sta_info *sta)
-{
- return &sband->bitrates[rate_lowest_index(local, sband, sta)];
-}
-
/* functions for rate control related to a device */
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index a849b74..14cde36 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -266,7 +266,7 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
/* Ignore all frames that were sent with a different rate than the rate
* we currently advise mac80211 to use. */
- if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx])
+ if (status->control.tx_rate_idx != sta->txrate_idx)
goto unlock;
spinfo = sta->rate_ctrl_priv;
@@ -330,7 +330,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
fc = le16_to_cpu(hdr->frame_control);
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1) || !sta) {
- sel->rate = rate_lowest(local, sband, sta);
+ sel->rate_idx = rate_lowest_index(local, sband, sta);
rcu_read_unlock();
return;
}
@@ -349,7 +349,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
rcu_read_unlock();
- sel->rate = &sband->bitrates[rateidx];
+ sel->rate_idx = rateidx;
#ifdef CONFIG_MAC80211_DEBUGFS
rate_control_pid_event_tx_rate(
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 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
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 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
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 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
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 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
* 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 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
* 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 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
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 @@ ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
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 @@ ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
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 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
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 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
r = &sband->bitrates[i];
if (r->bitrate == target_rate) {
- tx->rate = r;
+ tx->rate_idx = i;
break;
}
}
@@ -1097,7 +1105,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
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 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
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 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
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 @@ retry:
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 @@ void ieee80211_tx_pending(unsigned long data)
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 sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
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 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
}
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 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
}
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 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
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);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 800c15a..65a34fd 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -266,10 +266,13 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
bool short_preamble;
int erp;
u16 dur;
+ struct ieee80211_supported_band *sband;
+
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
short_preamble = sdata->bss_conf.use_short_preamble;
- rate = frame_txctl->rts_cts_rate;
+ rate = &sband->bitrates[frame_txctl->rts_cts_rate_idx];
erp = 0;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
@@ -300,10 +303,13 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
bool short_preamble;
int erp;
u16 dur;
+ struct ieee80211_supported_band *sband;
+
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
short_preamble = sdata->bss_conf.use_short_preamble;
- rate = frame_txctl->rts_cts_rate;
+ rate = &sband->bitrates[frame_txctl->rts_cts_rate_idx];
erp = 0;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;