tcp: fix TCP_DEFER_ACCEPT retrans calculation
[safe/jmp/linux-2.6] / net / mac80211 / rate.c
index 5d78672..b33efc4 100644 (file)
@@ -198,49 +198,76 @@ 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 ieee80211_supported_band *sband,
-                          struct sta_info *sta, struct sk_buff *skb,
-                          struct rate_selection *sel)
+                          struct sta_info *sta,
+                          struct ieee80211_tx_rate_control *txrc)
 {
        struct rate_control_ref *ref = sdata->local->rate_ctrl;
        void *priv_sta = NULL;
        struct ieee80211_sta *ista = NULL;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
        int i;
 
-       sel->rate_idx = -1;
-       sel->nonerp_idx = -1;
-       sel->probe_idx = -1;
-       sel->max_rate_idx = sdata->max_ratectrl_rateidx;
-
        if (sta) {
                ista = &sta->sta;
                priv_sta = sta->rate_ctrl_priv;
        }
 
-       if (sta && sdata->force_unicast_rateidx > -1)
-               sel->rate_idx = sdata->force_unicast_rateidx;
-       else
-               ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel);
-
-       if (sdata->max_ratectrl_rateidx > -1 &&
-           sel->rate_idx > sdata->max_ratectrl_rateidx)
-               sel->rate_idx = sdata->max_ratectrl_rateidx;
-
-       BUG_ON(sel->rate_idx < 0);
+       for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+               info->control.rates[i].idx = -1;
+               info->control.rates[i].flags = 0;
+               info->control.rates[i].count = 1;
+       }
 
-       /* Select a non-ERP backup rate. */
-       if (sel->nonerp_idx < 0) {
-               for (i = 0; i < sband->n_bitrates; i++) {
-                       struct ieee80211_rate *rate = &sband->bitrates[i];
-                       if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate)
-                               break;
+       if (sta && sdata->force_unicast_rateidx > -1) {
+               info->control.rates[0].idx = sdata->force_unicast_rateidx;
+       } else {
+               ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
+               info->flags |= IEEE80211_TX_INTFL_RCALGO;
+       }
 
-                       if (rate_supported(ista, sband->band, i) &&
-                           !(rate->flags & IEEE80211_RATE_ERP_G))
-                               sel->nonerp_idx = i;
-               }
+       /*
+        * try to enforce the maximum rate the user wanted
+        */
+       if (sdata->max_ratectrl_rateidx > -1)
+               for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+                       if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS)
+                               continue;
+                       info->control.rates[i].idx =
+                               min_t(s8, info->control.rates[i].idx,
+                                     sdata->max_ratectrl_rateidx);
        }
+
+       BUG_ON(info->control.rates[0].idx < 0);
 }
 
 struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
@@ -260,7 +287,7 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
        struct rate_control_ref *ref, *old;
 
        ASSERT_RTNL();
-       if (local->open_count || netif_running(local->mdev))
+       if (local->open_count)
                return -EBUSY;
 
        ref = rate_control_alloc(name, local);