|
@@ -91,11 +91,12 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
|
|
int next_frag_len)
|
|
int next_frag_len)
|
|
{
|
|
{
|
|
int rate, mrate, erp, dur, i;
|
|
int rate, mrate, erp, dur, i;
|
|
- struct ieee80211_rate *txrate = tx->rate;
|
|
|
|
|
|
+ struct ieee80211_rate *txrate;
|
|
struct ieee80211_local *local = tx->local;
|
|
struct ieee80211_local *local = tx->local;
|
|
struct ieee80211_supported_band *sband;
|
|
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;
|
|
erp = 0;
|
|
if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
|
|
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 rate_selection rsel;
|
|
struct ieee80211_supported_band *sband;
|
|
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);
|
|
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 |=
|
|
tx->control->flags |=
|
|
IEEE80211_TXCTL_RATE_CTRL_PROBE;
|
|
IEEE80211_TXCTL_RATE_CTRL_PROBE;
|
|
tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
|
|
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
|
|
} 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;
|
|
return TX_DROP;
|
|
} else
|
|
} else
|
|
- tx->control->alt_retry_rate = NULL;
|
|
|
|
|
|
+ tx->control->alt_retry_rate_idx = -1;
|
|
|
|
|
|
if (tx->sdata->bss_conf.use_cts_prot &&
|
|
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;
|
|
tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG;
|
|
else
|
|
else
|
|
tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
|
|
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;
|
|
tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
|
|
} else {
|
|
} 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;
|
|
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 fc = le16_to_cpu(hdr->frame_control);
|
|
u16 dur;
|
|
u16 dur;
|
|
struct ieee80211_tx_control *control = tx->control;
|
|
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 (!control->retry_limit) {
|
|
if (!is_multicast_ether_addr(hdr->addr1)) {
|
|
if (!is_multicast_ether_addr(hdr->addr1)) {
|
|
@@ -681,14 +685,14 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
|
* frames.
|
|
* frames.
|
|
* TODO: The last fragment could still use multiple retry
|
|
* TODO: The last fragment could still use multiple retry
|
|
* rates. */
|
|
* rates. */
|
|
- control->alt_retry_rate = NULL;
|
|
|
|
|
|
+ control->alt_retry_rate_idx = -1;
|
|
}
|
|
}
|
|
|
|
|
|
/* Use CTS protection for unicast frames sent using extended rates if
|
|
/* Use CTS protection for unicast frames sent using extended rates if
|
|
* there are associated non-ERP stations and RTS/CTS is not configured
|
|
* there are associated non-ERP stations and RTS/CTS is not configured
|
|
* for the frame. */
|
|
* for the frame. */
|
|
if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) &&
|
|
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->flags & IEEE80211_TX_UNICAST) &&
|
|
tx->sdata->bss_conf.use_cts_prot &&
|
|
tx->sdata->bss_conf.use_cts_prot &&
|
|
!(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
|
|
!(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
|
|
* short preambles at the selected rate and short preambles are
|
|
* available on the network at the current point in time. */
|
|
* available on the network at the current point in time. */
|
|
if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
|
|
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->sdata->bss_conf.use_short_preamble &&
|
|
(!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) {
|
|
(!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) {
|
|
tx->control->flags |= IEEE80211_TXCTL_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) ||
|
|
if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
|
|
(control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
|
|
(control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
|
|
struct ieee80211_supported_band *sband;
|
|
struct ieee80211_supported_band *sband;
|
|
- struct ieee80211_rate *rate, *baserate;
|
|
|
|
|
|
+ struct ieee80211_rate *rate;
|
|
|
|
+ s8 baserate = -1;
|
|
int idx;
|
|
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 */
|
|
/* 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 */
|
|
/* 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++) {
|
|
for (idx = 0; idx < sband->n_bitrates; idx++) {
|
|
if (sband->bitrates[idx].bitrate > rate->bitrate)
|
|
if (sband->bitrates[idx].bitrate > rate->bitrate)
|
|
continue;
|
|
continue;
|
|
if (tx->sdata->basic_rates & BIT(idx) &&
|
|
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
|
|
else
|
|
- control->rts_cts_rate = &sband->bitrates[0];
|
|
|
|
|
|
+ control->rts_cts_rate_idx = 0;
|
|
}
|
|
}
|
|
|
|
|
|
if (tx->sta) {
|
|
if (tx->sta) {
|
|
@@ -768,7 +772,11 @@ ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
|
|
struct sk_buff *skb = tx->skb;
|
|
struct sk_buff *skb = tx->skb;
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
u32 load = 0, hdrtime;
|
|
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
|
|
/* 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
|
|
* 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++) {
|
|
for (i = 0; i < tx->num_extra_frag; i++) {
|
|
load += 2 * hdrtime;
|
|
load += 2 * hdrtime;
|
|
load += tx->extra_frag[i]->len *
|
|
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);
|
|
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
|
|
struct ieee80211_tx_control *control = tx->control;
|
|
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;
|
|
control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
|
|
tx->flags |= IEEE80211_TX_INJECTED;
|
|
tx->flags |= IEEE80211_TX_INJECTED;
|
|
@@ -899,7 +907,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
|
r = &sband->bitrates[i];
|
|
r = &sband->bitrates[i];
|
|
|
|
|
|
if (r->bitrate == target_rate) {
|
|
if (r->bitrate == target_rate) {
|
|
- tx->rate = r;
|
|
|
|
|
|
+ tx->rate_idx = i;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1097,7 +1105,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
|
|
if (__ieee80211_queue_stopped(local, control->queue))
|
|
if (__ieee80211_queue_stopped(local, control->queue))
|
|
return IEEE80211_TX_FRAG_AGAIN;
|
|
return IEEE80211_TX_FRAG_AGAIN;
|
|
if (i == tx->num_extra_frag) {
|
|
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)
|
|
if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
|
|
control->flags |=
|
|
control->flags |=
|
|
@@ -1155,6 +1163,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
|
|
|
|
|
|
sta = tx.sta;
|
|
sta = tx.sta;
|
|
tx.channel = local->hw.conf.channel;
|
|
tx.channel = local->hw.conf.channel;
|
|
|
|
+ control->band = tx.channel->band;
|
|
|
|
|
|
for (handler = ieee80211_tx_handlers; *handler != NULL;
|
|
for (handler = ieee80211_tx_handlers; *handler != NULL;
|
|
handler++) {
|
|
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;
|
|
next_len = tx.extra_frag[i + 1]->len;
|
|
} else {
|
|
} else {
|
|
next_len = 0;
|
|
next_len = 0;
|
|
- tx.rate = tx.last_frag_rate;
|
|
|
|
|
|
+ tx.rate_idx = tx.last_frag_rate_idx;
|
|
}
|
|
}
|
|
dur = ieee80211_duration(&tx, 0, next_len);
|
|
dur = ieee80211_duration(&tx, 0, next_len);
|
|
hdr->duration_id = cpu_to_le16(dur);
|
|
hdr->duration_id = cpu_to_le16(dur);
|
|
@@ -1224,7 +1233,7 @@ retry:
|
|
store->skb = skb;
|
|
store->skb = skb;
|
|
store->extra_frag = tx.extra_frag;
|
|
store->extra_frag = tx.extra_frag;
|
|
store->num_extra_frag = tx.num_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 =
|
|
store->last_frag_rate_ctrl_probe =
|
|
!!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
|
|
!!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
|
|
}
|
|
}
|
|
@@ -1685,7 +1694,7 @@ void ieee80211_tx_pending(unsigned long data)
|
|
tx.control = &store->control;
|
|
tx.control = &store->control;
|
|
tx.extra_frag = store->extra_frag;
|
|
tx.extra_frag = store->extra_frag;
|
|
tx.num_extra_frag = store->num_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;
|
|
tx.flags = 0;
|
|
if (store->last_frag_rate_ctrl_probe)
|
|
if (store->last_frag_rate_ctrl_probe)
|
|
tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG;
|
|
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;
|
|
struct ieee80211_mgmt *mgmt;
|
|
int *num_beacons;
|
|
int *num_beacons;
|
|
bool err = true;
|
|
bool err = true;
|
|
|
|
+ enum ieee80211_band band = local->hw.conf.channel->band;
|
|
u8 *pos;
|
|
u8 *pos;
|
|
|
|
|
|
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
|
|
|
|
|
|
+ sband = local->hw.wiphy->bands[band];
|
|
|
|
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
|
|
|
|
@@ -1885,8 +1895,9 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
}
|
|
}
|
|
|
|
|
|
if (control) {
|
|
if (control) {
|
|
|
|
+ control->band = band;
|
|
rate_control_get_rate(local->mdev, sband, skb, &rsel);
|
|
rate_control_get_rate(local->mdev, sband, skb, &rsel);
|
|
- if (!rsel.rate) {
|
|
|
|
|
|
+ if (unlikely(rsel.rate_idx < 0)) {
|
|
if (net_ratelimit()) {
|
|
if (net_ratelimit()) {
|
|
printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
|
|
printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
|
|
"no rate found\n",
|
|
"no rate found\n",
|
|
@@ -1898,9 +1909,9 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
}
|
|
}
|
|
|
|
|
|
control->vif = vif;
|
|
control->vif = vif;
|
|
- control->tx_rate = rsel.rate;
|
|
|
|
|
|
+ control->tx_rate_idx = rsel.rate_idx;
|
|
if (sdata->bss_conf.use_short_preamble &&
|
|
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->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
|
|
control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
|
|
control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
|
|
control->flags |= IEEE80211_TXCTL_NO_ACK;
|
|
control->flags |= IEEE80211_TXCTL_NO_ACK;
|
|
@@ -2006,6 +2017,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
|
|
sta = tx.sta;
|
|
sta = tx.sta;
|
|
tx.flags |= IEEE80211_TX_PS_BUFFERED;
|
|
tx.flags |= IEEE80211_TX_PS_BUFFERED;
|
|
tx.channel = local->hw.conf.channel;
|
|
tx.channel = local->hw.conf.channel;
|
|
|
|
+ control->band = tx.channel->band;
|
|
|
|
|
|
for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
|
|
for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
|
|
res = (*handler)(&tx);
|
|
res = (*handler)(&tx);
|