From 2e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 May 2008 12:55:27 +0200 Subject: 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 Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 8 ++-- net/mac80211/mlme.c | 6 +-- net/mac80211/rate.c | 12 +++-- net/mac80211/rate.h | 25 ++++------ net/mac80211/rc80211_pid_algo.c | 6 +-- net/mac80211/tx.c | 104 ++++++++++++++++++++++------------------ net/mac80211/util.c | 10 +++- 7 files changed, 93 insertions(+), 78 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ed0d9b35ae6..a4cccd1b7d5 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 7877d3b3f4c..604149369dc 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 841df93807f..0388c090dfe 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 5b45f33cb76..a29148dcca9 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 a849b745bdb..14cde36f507 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 aecec2a72b0..99c3860bc0e 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 800c15aff6e..65a34fddeb0 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; -- cgit v1.2.3-70-g09d2