Changeset 20035


Ignore:
Timestamp:
2010-03-07T17:29:41+01:00 (7 years ago)
Author:
nbd
Message:

mac80211: simplify minstrel_ht code, rewrite packet sampling algorithm for improved performance and a-mpdu length

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/mac80211/patches/560-minstrel_ht.patch

    r20034 r20035  
    6969--- /dev/null 
    7070+++ b/net/mac80211/rc80211_minstrel_ht.c 
    71 @@ -0,0 +1,824 @@ 
     71@@ -0,0 +1,800 @@ 
    7272+/* 
    7373+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org> 
     
    126126+} 
    127127+ 
    128 +#define MINSTREL_INTFL_SAMPLE_SLOT0    BIT(30) 
    129 +#define MINSTREL_INTFL_SAMPLE_SLOT1    BIT(31) 
    130 + 
    131128+/* 
    132129+ * To enable sufficiently targeted rate sampling, MCS rates are divided into 
     
    207204+minstrel_calc_rate_ewma(struct minstrel_priv *mp, struct minstrel_rate_stats *mr) 
    208205+{ 
    209 +       if (mr->attempts) { 
     206+       if (unlikely(mr->attempts > 0)) { 
     207+               mr->sample_skipped = 0; 
    210208+               mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts); 
    211209+               if (!mr->att_hist) 
     
    216214+               mr->att_hist += mr->attempts; 
    217215+               mr->succ_hist += mr->success; 
     216+       } else { 
     217+               mr->sample_skipped++; 
    218218+       } 
    219219+       mr->last_success = mr->success; 
     
    263263+       int group, i, index; 
    264264+ 
     265+       mi->sample_count = 0; 
    265266+       mi->max_tp_rate = 0; 
    266267+       mi->max_tp_rate2 = 0; 
     
    280281+               mg->max_tp_rate2 = 0; 
    281282+               mg->max_prob_rate = 0; 
     283+               mi->sample_count++; 
    282284+ 
    283285+               for (i = 0; i < MCS_GROUP_RATES; i++) { 
     
    310312+                       } 
    311313+ 
    312 +                       if (index == mg->max_tp_rate) 
     314+                       if (index >= mg->max_tp_rate) 
    313315+                               continue; 
    314316+ 
     
    319321+               } 
    320322+       } 
     323+ 
     324+       /* try to sample up to half of the availble rates during each interval */ 
     325+       mi->sample_count *= 4; 
    321326+ 
    322327+       cur_prob = 0; 
     
    387392+ 
    388393+static void 
    389 +minstrel_downgrade_rate(struct minstrel_ht_sta *mi, int *idx, int type) 
     394+minstrel_downgrade_rate(struct minstrel_ht_sta *mi, int *idx, bool primary) 
    390395+{ 
    391396+       int group, orig_group; 
     
    398403+                       continue; 
    399404+ 
    400 +               if (minstrel_mcs_groups[group].streams >= 
     405+               if (minstrel_mcs_groups[group].streams > 
    401406+                   minstrel_mcs_groups[orig_group].streams) 
    402407+                       continue; 
    403408+ 
    404 +               switch(type) { 
    405 +               case 0: 
     409+               if (primary) 
    406410+                       *idx = mi->groups[group].max_tp_rate; 
    407 +                       break; 
    408 +               case 1: 
     411+               else 
    409412+                       *idx = mi->groups[group].max_tp_rate2; 
    410 +                       break; 
    411 +               } 
    412413+               break; 
    413414+       } 
     
    446447+               MINSTREL_FRAC(info->status.ampdu_len, 1), 90); 
    447448+ 
     449+       if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { 
     450+               mi->sample_wait = 4 + MINSTREL_TRUNC(mi->avg_ampdu_len); 
     451+               mi->sample_tries = 3; 
     452+               mi->sample_count--; 
     453+       } 
     454+ 
     455+       if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { 
     456+               mi->sample_packets += info->status.ampdu_len; 
     457+               minstrel_next_sample_idx(mi); 
     458+       } 
     459+ 
    448460+       for (i = 0; !last; i++) { 
    449461+               last = (i == IEEE80211_TX_MAX_RATES - 1) || 
     
    453465+                       break; 
    454466+ 
    455 +               if ((i == 0 && (info->flags & MINSTREL_INTFL_SAMPLE_SLOT0)) || 
    456 +                   (i == 1 && (info->flags & MINSTREL_INTFL_SAMPLE_SLOT1))) { 
    457 +                       if (mi->sample_pending > 0) 
    458 +                               mi->sample_pending--; 
    459 +                       mi->sample_packets++; 
    460 +                       minstrel_next_sample_idx(mi); 
    461 +               } 
    462 + 
    463467+               group = minstrel_ht_get_group_idx(&ar[i]); 
    464468+               rate = &mi->groups[group].rates[ar[i].idx % 8]; 
     
    469473+               rate->attempts += ar[i].count * info->status.ampdu_len; 
    470474+       } 
    471 + 
    472475+ 
    473476+       /* 
     
    477480+       rate = minstrel_get_ratestats(mi, mi->max_tp_rate); 
    478481+       if (MINSTREL_FRAC(rate->success, rate->attempts) < 
    479 +           MINSTREL_FRAC(20, 100) && rate->attempts > 15) 
    480 +               minstrel_downgrade_rate(mi, &mi->max_tp_rate, 0); 
     482+           MINSTREL_FRAC(20, 100) && rate->attempts > 30) 
     483+               minstrel_downgrade_rate(mi, &mi->max_tp_rate, true); 
    481484+ 
    482485+       rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2); 
    483486+       if (MINSTREL_FRAC(rate->success, rate->attempts) < 
    484 +           MINSTREL_FRAC(20, 100) && rate->attempts > 15) 
    485 +               minstrel_downgrade_rate(mi, &mi->max_tp_rate2, 1); 
     487+           MINSTREL_FRAC(20, 100) && rate->attempts > 30) 
     488+               minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false); 
    486489+ 
    487490+       if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) 
     
    561564+ 
    562565+static int 
    563 +minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, 
    564 +                         bool *defer) 
     566+minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) 
    565567+{ 
    566568+       struct minstrel_rate_stats *mr; 
    567569+       struct minstrel_mcs_group_data *mg; 
    568570+       int sample_idx = 0; 
    569 +       int sample_rate; 
    570 +       int delta; 
    571 + 
    572 +       if (mp->has_mrr) 
    573 +               sample_rate = mp->lookaround_rate_mrr; 
    574 +       else 
    575 +               sample_rate = mp->lookaround_rate; 
    576 + 
    577 +       delta = (mi->total_packets * sample_rate) / 100 - mi->sample_packets; 
    578 +       delta -= mi->sample_pending / 2; 
    579 + 
    580 +       if (delta <= 0) 
     571+ 
     572+       if (mi->sample_wait > 0) { 
     573+               mi->sample_wait--; 
    581574+               return -1; 
    582 + 
    583 +       delta -= 16; 
    584 +       if (delta > 1) { 
    585 +               /* With multi-rate retry, not every planned sample 
    586 +               * attempt actually gets used, due to the way the retry 
    587 +               * chain is set up - [max_tp,sample,prob,lowest] for 
    588 +               * sample_rate < max_tp. 
    589 +               * 
    590 +               * If there's too much sampling backlog and the link 
    591 +               * starts getting worse, minstrel would start bursting 
    592 +               * out lots of sampling frames, which would result 
    593 +               * in a large throughput loss. 
    594 +               */ 
    595 +               mi->sample_packets += delta - 1; 
    596 +       } 
    597 + 
     575+       } 
     576+ 
     577+       if (!mi->sample_tries) 
     578+               return -1; 
     579+ 
     580+       mi->sample_tries--; 
    598581+       mg = &mi->groups[mi->sample_group]; 
    599582+       sample_idx = sample_table[mg->column][mg->index]; 
     
    606589+        */ 
    607590+       if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100))) 
    608 +               return -1; 
    609 + 
     591+               goto next; 
     592+ 
     593+       /* 
     594+        * Make sure that lower rates get sampled only occasionally, 
     595+        * if the link is working perfectly. 
     596+        */ 
    610597+       if (minstrel_get_duration(sample_idx) > 
    611 +           minstrel_get_duration(mi->max_tp_rate)) { 
    612 +               /* 
    613 +                * Make sure that lower rates get sampled occasionally, even 
    614 +                * if the link is working perfectly. Some drivers such as ath9k 
    615 +                * severely limit aggregation size if the MRR chain contains low 
    616 +                * rates 
    617 +                * 
    618 +                * If the lower rate has already been tried a few times, there's 
    619 +                * no point in forcing it to be sampled again, so skip to the 
    620 +                * next sampling index after applying this one in the tx control 
    621 +                */ 
    622 +               if (mr->att_hist > 15) { 
    623 +                       *defer = true; 
    624 +                       minstrel_next_sample_idx(mi); 
    625 +               } 
    626 +       } 
     598+           minstrel_get_duration(mi->max_tp_rate) && 
     599+           mr->sample_skipped < 10) 
     600+               goto next; 
    627601+ 
    628602+       return sample_idx; 
     603+ 
     604+next: 
     605+       minstrel_next_sample_idx(mi); 
     606+       return -1; 
    629607+} 
    630608+ 
     
    658636+       struct minstrel_ht_sta *mi = &msp->ht; 
    659637+       struct minstrel_priv *mp = priv; 
    660 +       bool sample_defer = false; 
    661638+       int sample_idx; 
    662639+ 
     
    669646+       minstrel_aggr_check(mp, sta, txrc->skb); 
    670647+ 
    671 +       sample_idx = minstrel_get_sample_rate(mp, mi, &sample_defer); 
     648+       sample_idx = minstrel_get_sample_rate(mp, mi); 
    672649+       if (sample_idx >= 0) { 
    673 +               if (sample_defer) { 
    674 +                       minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, 
    675 +                               txrc, false, false); 
    676 +                       minstrel_ht_set_rate(mp, mi, &ar[1], sample_idx, 
    677 +                               txrc, true, true); 
    678 +                       info->flags |= MINSTREL_INTFL_SAMPLE_SLOT1; 
    679 +               } else { 
    680 +                       minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, 
    681 +                               txrc, true, false); 
    682 +                       minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, 
    683 +                               txrc, false, true); 
    684 +                       info->flags |= MINSTREL_INTFL_SAMPLE_SLOT0; 
    685 +               } 
    686 +               mi->sample_pending++; 
     650+               minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, 
     651+                       txrc, true, false); 
     652+               minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, 
     653+                       txrc, false, true); 
     654+               info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; 
    687655+       } else { 
    688656+               minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, 
     
    699667+ 
    700668+       /* wraparound */ 
    701 +       if (mi->total_packets >= 100000) { 
     669+       if (mi->total_packets == ~0) { 
    702670+               mi->total_packets = 0; 
    703671+               mi->sample_packets = 0; 
    704 +               mi->sample_pending = 0; 
    705 +       } 
    706 +} 
    707 + 
    708 +static void 
    709 +minstrel_ht_update_cap(struct minstrel_ht_sta *mi, struct ieee80211_sta *sta, 
    710 +                       enum nl80211_channel_type oper_chan_type) 
    711 +{ 
     672+       } 
     673+} 
     674+ 
     675+static void 
     676+minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, 
     677+                        struct ieee80211_sta *sta, void *priv_sta, 
     678+                       enum nl80211_channel_type oper_chan_type) 
     679+{ 
     680+       struct minstrel_priv *mp = priv; 
     681+       struct minstrel_ht_sta_priv *msp = priv_sta; 
     682+       struct minstrel_ht_sta *mi = &msp->ht; 
    712683+       struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; 
     684+       struct ieee80211_local *local = hw_to_local(mp->hw); 
    713685+       u16 sta_cap = sta->ht_cap.cap; 
     686+       int ack_dur; 
    714687+       int i; 
     688+ 
     689+       /* fall back to the old minstrel for legacy stations */ 
     690+       if (sta && !sta->ht_cap.ht_supported) { 
     691+               msp->is_ht = false; 
     692+               memset(&msp->legacy, 0, sizeof(msp->legacy)); 
     693+               msp->legacy.r = msp->ratelist; 
     694+               msp->legacy.sample_table = msp->sample_table; 
     695+               return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy); 
     696+       } 
     697+ 
     698+       BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != 
     699+               MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS); 
     700+ 
     701+       msp->is_ht = true; 
     702+       memset(mi, 0, sizeof(*mi)); 
     703+       mi->stats_update = jiffies; 
     704+ 
     705+       ack_dur = ieee80211_frame_duration(local, 10, 60, 1, 1); 
     706+       mi->overhead = ieee80211_frame_duration(local, 0, 60, 1, 1) + ack_dur; 
     707+       mi->overhead_rtscts = mi->overhead + 2 * ack_dur; 
     708+ 
     709+       mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); 
     710+ 
     711+       /* When using MRR, sample more on the first attempt, without delay */ 
     712+       if (mp->has_mrr) { 
     713+               mi->sample_count = 16; 
     714+               mi->sample_wait = 0; 
     715+       } else { 
     716+               mi->sample_count = 8; 
     717+               mi->sample_wait = 8; 
     718+       } 
     719+       mi->sample_tries = 4; 
    715720+ 
    716721+       if (oper_chan_type != NL80211_CHAN_HT40MINUS && 
     
    745750+{ 
    746751+       struct minstrel_priv *mp = priv; 
    747 +       struct minstrel_ht_sta_priv *msp = priv_sta; 
    748 +       struct minstrel_ht_sta *mi = &msp->ht; 
    749 +       struct ieee80211_local *local = hw_to_local(mp->hw); 
    750 +       int ack_dur; 
    751 + 
    752 +       /* fall back to the old minstrel for legacy stations */ 
    753 +       if (sta && !sta->ht_cap.ht_supported) { 
    754 +               msp->is_ht = false; 
    755 +               memset(&msp->legacy, 0, sizeof(msp->legacy)); 
    756 +               msp->legacy.r = msp->ratelist; 
    757 +               msp->legacy.sample_table = msp->sample_table; 
    758 +               return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy); 
    759 +       } 
    760 + 
    761 +       BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != 
    762 +               MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS); 
    763 + 
    764 +       msp->is_ht = true; 
    765 +       memset(mi, 0, sizeof(*mi)); 
    766 +       mi->stats_update = jiffies; 
    767 + 
    768 +       ack_dur = ieee80211_frame_duration(local, 10, 60, 1, 1); 
    769 +       mi->overhead = ieee80211_frame_duration(local, 0, 60, 1, 1) + ack_dur; 
    770 +       mi->overhead_rtscts = mi->overhead + 2 * ack_dur; 
    771 + 
    772 +       mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); 
    773 + 
    774 +       minstrel_ht_update_cap(mi, sta, mp->hw->conf.channel_type); 
     752+ 
     753+       minstrel_ht_update_caps(priv, sband, sta, priv_sta, mp->hw->conf.channel_type); 
    775754+} 
    776755+ 
     
    780759+                        u32 changed, enum nl80211_channel_type oper_chan_type) 
    781760+{ 
    782 +       struct minstrel_ht_sta_priv *msp = priv_sta; 
    783 +       struct minstrel_ht_sta *mi = &msp->ht; 
    784 + 
    785 +       minstrel_ht_update_cap(mi, sta, oper_chan_type); 
     761+       minstrel_ht_update_caps(priv, sband, sta, priv_sta, oper_chan_type); 
    786762+} 
    787763+ 
     
    896872--- /dev/null 
    897873+++ b/net/mac80211/rc80211_minstrel_ht.h 
    898 @@ -0,0 +1,115 @@ 
     874@@ -0,0 +1,120 @@ 
    899875+/* 
    900876+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org> 
     
    943919+ 
    944920+       /* maximum retry counts */ 
    945 +       bool retry_updated; 
    946921+       unsigned int retry_count; 
    947922+       unsigned int retry_count_rtscts; 
     923+ 
     924+       bool retry_updated; 
     925+       u8 sample_skipped; 
    948926+}; 
    949927+ 
     
    986964+       unsigned int total_packets; 
    987965+       unsigned int sample_packets; 
    988 +       unsigned int sample_pending; 
     966+ 
     967+       u8 sample_wait; 
     968+       u8 sample_tries; 
     969+       u8 sample_count; 
    989970+ 
    990971+       /* current MCS group to be sampled */ 
    991 +       unsigned int sample_group; 
     972+       u8 sample_group; 
    992973+ 
    993974+       /* MCS rate group info and statistics */ 
Note: See TracChangeset for help on using the changeset viewer.