From 4c6d4f5c33fbe19b134c1af43af166fee79eb986 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Jul 2009 10:05:41 -0700 Subject: [PATCH] mac80211: add helper for management / no-ack frame rate decision All current rate control algorithms agree to send management and no-ack frames at the lowest rate. They also agree to do this when sta and the private rate control data is NULL. We add a hlper to mac80211 for this and simplify the rate control algorithm code. Developers wishing to make enhancements to rate control algorithms are for broadcast/multicast can opt to not use this in their gate_rate() mac80211 callback. Cc: Zhu Yi Acked-by: Reinette Chatre Cc: ipw3945-devel@lists.sourceforge.net Cc: Gabor Juhos Acked-by: Felix Fietkau Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 14 +---------- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 13 +++------- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 7 +----- include/net/mac80211.h | 23 +++++++++++++++++ net/mac80211/rate.c | 29 ++++++++++++++++++++++ net/mac80211/rc80211_minstrel.c | 22 +--------------- net/mac80211/rc80211_pid_algo.c | 11 +------- 7 files changed, 59 insertions(+), 60 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 2c72901adbee..630fcf46e0dd 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1518,23 +1518,11 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) { - struct ieee80211_supported_band *sband = txrc->sband; - struct sk_buff *skb = txrc->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - __le16 fc = hdr->frame_control; - /* lowest rate for management and NO_ACK frames */ - if (!ieee80211_is_data(fc) || - tx_info->flags & IEEE80211_TX_CTL_NO_ACK || !sta) { - tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); - tx_info->control.rates[0].count = - (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ? - 1 : ATH_MGT_TXMAXTRY; + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } /* Find tx rate for unicast frames */ ath_rc_ratefind(sc, ath_rc_priv, txrc); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 2b776924d5e7..a16bd4147eac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -673,7 +673,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, s8 scale_action = 0; unsigned long flags; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc; u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; s8 max_rate_idx = -1; struct iwl_priv *priv = (struct iwl_priv *)priv_r; @@ -681,16 +680,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "enter\n"); - /* Send management frames and NO_ACK data using lowest rate. */ - fc = hdr->frame_control; - if (!ieee80211_is_data(fc) || info->flags & IEEE80211_TX_CTL_NO_ACK || - !sta || !priv_sta) { - IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); - info->control.rates[0].idx = rate_lowest_index(sband, sta); - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - info->control.rates[0].count = 1; + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } + + rate_mask = sta->supp_rates[sband->band]; /* get user max rate if set */ max_rate_idx = txrc->max_rate_idx; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3fea027f35d1..63280411fd58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2481,13 +2481,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, } /* Send management frames and NO_ACK data using lowest rate. */ - if (!ieee80211_is_data(hdr->frame_control) || - info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !lq_sta) { - info->control.rates[0].idx = rate_lowest_index(sband, sta); - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - info->control.rates[0].count = 1; + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } rate_idx = lq_sta->last_txrate_idx; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d98fac54577b..a861259c3050 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2094,6 +2094,29 @@ static inline int rate_supported(struct ieee80211_sta *sta, return (sta == NULL || sta->supp_rates[band] & BIT(index)); } +/** + * rate_control_send_low - helper for drivers for management/no-ack frames + * + * Rate control algorithms that agree to use the lowest rate to + * send management frames and NO_ACK data with the respective hw + * retries should use this in the beginning of their mac80211 get_rate + * callback. If true is returned the rate control can simply return. + * If false is returned we guarantee that sta and sta and priv_sta is + * not null. + * + * Rate control algorithms wishing to do more intelligent selection of + * rate for multicast/broadcast frames may choose to not use this. + * + * @sta: &struct ieee80211_sta pointer to the target destination. Note + * that this may be null. + * @priv_sta: private rate control structure. This may be null. + * @txrc: rate control information we sholud populate for mac80211. + */ +bool rate_control_send_low(struct ieee80211_sta *sta, + void *priv_sta, + struct ieee80211_tx_rate_control *txrc); + + static inline s8 rate_lowest_index(struct ieee80211_supported_band *sband, struct ieee80211_sta *sta) diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 4641f00a1e5c..8ac7a984d886 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -198,6 +198,35 @@ static void rate_control_release(struct kref *kref) kfree(ctrl_ref); } +static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) +{ + struct sk_buff *skb = txrc->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + __le16 fc; + + fc = hdr->frame_control; + + return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); +} + +bool rate_control_send_low(struct ieee80211_sta *sta, + void *priv_sta, + struct ieee80211_tx_rate_control *txrc) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); + + if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { + info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); + info->control.rates[0].count = + (info->flags & IEEE80211_TX_CTL_NO_ACK) ? + 1 : txrc->hw->max_rate_tries; + return true; + } + return false; +} +EXPORT_SYMBOL(rate_control_send_low); + void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee80211_tx_rate_control *txrc) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 5bdce0c951dd..7c5142988bbb 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -70,19 +70,6 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) return i; } -static inline bool -use_low_rate(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - __le16 fc; - - fc = hdr->frame_control; - - return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); -} - - static void minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) { @@ -231,7 +218,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) { struct sk_buff *skb = txrc->skb; - struct ieee80211_supported_band *sband = txrc->sband; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct minstrel_sta_info *mi = priv_sta; struct minstrel_priv *mp = priv; @@ -244,14 +230,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, int mrr_ndx[3]; int sample_rate; - if (!sta || !mi || use_low_rate(skb)) { - ar[0].idx = rate_lowest_index(sband, sta); - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - ar[0].count = 1; - else - ar[0].count = mp->max_retry; + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 549607703bd8..8c053be9dc24 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -276,11 +276,9 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, { struct sk_buff *skb = txrc->skb; struct ieee80211_supported_band *sband = txrc->sband; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rc_pid_sta_info *spinfo = priv_sta; int rateidx; - __le16 fc; if (txrc->rts) info->control.rates[0].count = @@ -290,15 +288,8 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, txrc->hw->conf.short_frame_max_tx_count; /* Send management frames and NO_ACK data using lowest rate. */ - fc = hdr->frame_control; - if (!sta || !spinfo || !ieee80211_is_data(fc) || - info->flags & IEEE80211_TX_CTL_NO_ACK) { - info->control.rates[0].idx = rate_lowest_index(sband, sta); - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - info->control.rates[0].count = 1; - + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } rateidx = spinfo->txrate_idx;