cfg80211: remove enum ieee80211_band
[cascardo/linux.git] / net / mac80211 / rc80211_minstrel_ht.c
index 370d677..30fbabf 100644 (file)
@@ -883,6 +883,59 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
        ratetbl->rate[offset].flags = flags;
 }
 
+static inline int
+minstrel_ht_get_prob_ewma(struct minstrel_ht_sta *mi, int rate)
+{
+       int group = rate / MCS_GROUP_RATES;
+       rate %= MCS_GROUP_RATES;
+       return mi->groups[group].rates[rate].prob_ewma;
+}
+
+static int
+minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi)
+{
+       int group = mi->max_prob_rate / MCS_GROUP_RATES;
+       const struct mcs_group *g = &minstrel_mcs_groups[group];
+       int rate = mi->max_prob_rate % MCS_GROUP_RATES;
+
+       /* Disable A-MSDU if max_prob_rate is bad */
+       if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
+               return 1;
+
+       /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */
+       if (g->duration[rate] > MCS_DURATION(1, 0, 52))
+               return 500;
+
+       /*
+        * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
+        * data packet size
+        */
+       if (g->duration[rate] > MCS_DURATION(1, 0, 104))
+               return 1600;
+
+       /*
+        * If the rate is slower than single-stream MCS7, or if the max throughput
+        * rate success probability is less than 75%, limit A-MSDU to twice the usual
+        * data packet size
+        */
+       if (g->duration[rate] > MCS_DURATION(1, 0, 260) ||
+           (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
+            MINSTREL_FRAC(75, 100)))
+               return 3200;
+
+       /*
+        * HT A-MPDU limits maximum MPDU size under BA agreement to 4095 bytes.
+        * Since aggregation sessions are started/stopped without txq flush, use
+        * the limit here to avoid the complexity of having to de-aggregate
+        * packets in the queue.
+        */
+       if (!mi->sta->vht_cap.vht_supported)
+               return IEEE80211_MAX_MPDU_LEN_HT_BA;
+
+       /* unlimited */
+       return 0;
+}
+
 static void
 minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 {
@@ -907,6 +960,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
                minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
        }
 
+       mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi);
        rates->rate[i].idx = -1;
        rate_control_set_rates(mp->hw, mi->sta, rates);
 }
@@ -924,6 +978,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
        struct minstrel_rate_stats *mrs;
        struct minstrel_mcs_group_data *mg;
        unsigned int sample_dur, sample_group, cur_max_tp_streams;
+       int tp_rate1, tp_rate2;
        int sample_idx = 0;
 
        if (mi->sample_wait > 0) {
@@ -945,14 +1000,22 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
        mrs = &mg->rates[sample_idx];
        sample_idx += sample_group * MCS_GROUP_RATES;
 
+       /* Set tp_rate1, tp_rate2 to the highest / second highest max_tp_rate */
+       if (minstrel_get_duration(mi->max_tp_rate[0]) >
+           minstrel_get_duration(mi->max_tp_rate[1])) {
+               tp_rate1 = mi->max_tp_rate[1];
+               tp_rate2 = mi->max_tp_rate[0];
+       } else {
+               tp_rate1 = mi->max_tp_rate[0];
+               tp_rate2 = mi->max_tp_rate[1];
+       }
+
        /*
         * Sampling might add some overhead (RTS, no aggregation)
-        * to the frame. Hence, don't use sampling for the currently
-        * used rates.
+        * to the frame. Hence, don't use sampling for the highest currently
+        * used highest throughput or probability rate.
         */
-       if (sample_idx == mi->max_tp_rate[0] ||
-           sample_idx == mi->max_tp_rate[1] ||
-           sample_idx == mi->max_prob_rate)
+       if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate)
                return -1;
 
        /*
@@ -967,10 +1030,10 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
         * if the link is working perfectly.
         */
 
-       cur_max_tp_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
+       cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
                MCS_GROUP_RATES].streams;
        sample_dur = minstrel_get_duration(sample_idx);
-       if (sample_dur >= minstrel_get_duration(mi->max_tp_rate[1]) &&
+       if (sample_dur >= minstrel_get_duration(tp_rate2) &&
            (cur_max_tp_streams - 1 <
             minstrel_mcs_groups[sample_group].streams ||
             sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {
@@ -1074,7 +1137,7 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 {
        int i;
 
-       if (sband->band != IEEE80211_BAND_2GHZ)
+       if (sband->band != NL80211_BAND_2GHZ)
                return;
 
        if (!ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES))
@@ -1272,7 +1335,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
        int max_rates = 0;
        int i;
 
-       for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+       for (i = 0; i < NUM_NL80211_BANDS; i++) {
                sband = hw->wiphy->bands[i];
                if (sband && sband->n_bitrates > max_rates)
                        max_rates = sband->n_bitrates;