Merge remote-tracking branch 'remotes/aosp/android-3.0' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / rc80211_minstrel_ht.c
index 2a18d6602d4ade8bc385fecc4bca919811875ba1..333b5118be6d54472e349bbce059a13eda5f418b 100644 (file)
@@ -259,7 +259,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
                }
        }
 
-       /* try to sample up to half of the availble rates during each interval */
+       /* try to sample up to half of the available rates during each interval */
        mi->sample_count *= 4;
 
        cur_prob = 0;
@@ -371,7 +371,10 @@ minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, stru
        if (likely(sta->ampdu_mlme.tid_tx[tid]))
                return;
 
-       ieee80211_start_tx_ba_session(pubsta, tid);
+       if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
+               return;
+
+       ieee80211_start_tx_ba_session(pubsta, tid, 5000);
 }
 
 static void
@@ -407,15 +410,13 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
        mi->ampdu_len += info->status.ampdu_len;
 
        if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
-               mi->sample_wait = 4 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
-               mi->sample_tries = 3;
+               mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
+               mi->sample_tries = 2;
                mi->sample_count--;
        }
 
-       if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
+       if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
                mi->sample_packets += info->status.ampdu_len;
-               minstrel_next_sample_idx(mi);
-       }
 
        for (i = 0; !last; i++) {
                last = (i == IEEE80211_TX_MAX_RATES - 1) ||
@@ -463,6 +464,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
        const struct mcs_group *group;
        unsigned int tx_time, tx_time_rtscts, tx_time_data;
        unsigned int cw = mp->cw_min;
+       unsigned int ctime = 0;
        unsigned int t_slot = 9; /* FIXME */
        unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len);
 
@@ -479,13 +481,27 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 
        group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
        tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len;
-       tx_time = 2 * (t_slot + mi->overhead + tx_time_data);
-       tx_time_rtscts = 2 * (t_slot + mi->overhead_rtscts + tx_time_data);
+
+       /* Contention time for first 2 tries */
+       ctime = (t_slot * cw) >> 1;
+       cw = min((cw << 1) | 1, mp->cw_max);
+       ctime += (t_slot * cw) >> 1;
+       cw = min((cw << 1) | 1, mp->cw_max);
+
+       /* Total TX time for data and Contention after first 2 tries */
+       tx_time = ctime + 2 * (mi->overhead + tx_time_data);
+       tx_time_rtscts = ctime + 2 * (mi->overhead_rtscts + tx_time_data);
+
+       /* See how many more tries we can fit inside segment size */
        do {
-               cw = (cw << 1) | 1;
-               cw = min(cw, mp->cw_max);
-               tx_time += cw + t_slot + mi->overhead;
-               tx_time_rtscts += cw + t_slot + mi->overhead_rtscts;
+               /* Contention time for this try */
+               ctime = (t_slot * cw) >> 1;
+               cw = min((cw << 1) | 1, mp->cw_max);
+
+               /* Total TX time after this try */
+               tx_time += ctime + mi->overhead + tx_time_data;
+               tx_time_rtscts += ctime + mi->overhead_rtscts + tx_time_data;
+
                if (tx_time_rtscts < mp->segment_size)
                        mr->retry_count_rtscts++;
        } while ((tx_time < mp->segment_size) &&
@@ -506,7 +522,9 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
        if (!mr->retry_updated)
                minstrel_calc_retransmit(mp, mi, index);
 
-       if (mr->probability < MINSTREL_FRAC(20, 100))
+       if (sample)
+               rate->count = 1;
+       else if (mr->probability < MINSTREL_FRAC(20, 100))
                rate->count = 2;
        else if (rtscts)
                rate->count = mr->retry_count_rtscts;
@@ -514,9 +532,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
                rate->count = mr->retry_count;
 
        rate->flags = IEEE80211_TX_RC_MCS | group->flags;
-       if (txrc->short_preamble)
-               rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
-       if (txrc->rts || rtscts)
+       if (rtscts)
                rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
        rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES;
 }
@@ -548,13 +564,14 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
        sample_idx = sample_table[mg->column][mg->index];
        mr = &mg->rates[sample_idx];
        sample_idx += mi->sample_group * MCS_GROUP_RATES;
+       minstrel_next_sample_idx(mi);
 
        /*
         * When not using MRR, do not sample if the probability is already
         * higher than 95% to avoid wasting airtime
         */
        if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
-               goto next;
+               return -1;
 
        /*
         * Make sure that lower rates get sampled only occasionally,
@@ -562,18 +579,14 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
         */
        if (minstrel_get_duration(sample_idx) >
            minstrel_get_duration(mi->max_tp_rate)) {
-               if (mr->sample_skipped < 10)
-                       goto next;
+               if (mr->sample_skipped < 20)
+                       return -1;
 
                if (mi->sample_slow++ > 2)
-                       goto next;
+                       return -1;
        }
 
        return sample_idx;
-
-next:
-       minstrel_next_sample_idx(mi);
-       return -1;
 }
 
 static void
@@ -586,6 +599,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
        struct minstrel_ht_sta *mi = &msp->ht;
        struct minstrel_priv *mp = priv;
        int sample_idx;
+       bool sample = false;
 
        if (rate_control_send_low(sta, priv_sta, txrc))
                return;
@@ -596,21 +610,49 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
        info->flags |= mi->tx_flags;
        sample_idx = minstrel_get_sample_rate(mp, mi);
        if (sample_idx >= 0) {
+               sample = true;
                minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
                        txrc, true, false);
-               minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
-                       txrc, false, true);
                info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
        } else {
                minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
                        txrc, false, false);
-               minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
-                       txrc, false, true);
        }
-       minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, true);
 
-       ar[3].count = 0;
-       ar[3].idx = -1;
+       if (mp->hw->max_rates >= 3) {
+               /*
+                * At least 3 tx rates supported, use
+                * sample_rate -> max_tp_rate -> max_prob_rate for sampling and
+                * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
+                */
+               if (sample_idx >= 0)
+                       minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
+                               txrc, false, false);
+               else
+                       minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
+                               txrc, false, true);
+
+               minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
+                                    txrc, false, !sample);
+
+               ar[3].count = 0;
+               ar[3].idx = -1;
+       } else if (mp->hw->max_rates == 2) {
+               /*
+                * Only 2 tx rates supported, use
+                * sample_rate -> max_prob_rate for sampling and
+                * max_tp_rate -> max_prob_rate by default.
+                */
+               minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
+                                    txrc, false, !sample);
+
+               ar[2].count = 0;
+               ar[2].idx = -1;
+       } else {
+               /* Not using MRR, only use the first rate */
+               ar[1].count = 0;
+               ar[1].idx = -1;
+       }
 
        mi->total_packets++;
 
@@ -632,18 +674,14 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
        struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
        struct ieee80211_local *local = hw_to_local(mp->hw);
        u16 sta_cap = sta->ht_cap.cap;
+       int n_supported = 0;
        int ack_dur;
        int stbc;
        int i;
 
        /* fall back to the old minstrel for legacy stations */
-       if (!sta->ht_cap.ht_supported) {
-               msp->is_ht = false;
-               memset(&msp->legacy, 0, sizeof(msp->legacy));
-               msp->legacy.r = msp->ratelist;
-               msp->legacy.sample_table = msp->sample_table;
-               return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
-       }
+       if (!sta->ht_cap.ht_supported)
+               goto use_legacy;
 
        BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) !=
                MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS);
@@ -698,7 +736,22 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
 
                mi->groups[i].supported =
                        mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
+
+               if (mi->groups[i].supported)
+                       n_supported++;
        }
+
+       if (!n_supported)
+               goto use_legacy;
+
+       return;
+
+use_legacy:
+       msp->is_ht = false;
+       memset(&msp->legacy, 0, sizeof(msp->legacy));
+       msp->legacy.r = msp->ratelist;
+       msp->legacy.sample_table = msp->sample_table;
+       return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
 }
 
 static void