OSDN Git Service

mac80211: fix contention time computation in minstrel, minstrel_ht
authorDaniel Halperin <dhalperi@cs.washington.edu>
Wed, 11 May 2011 02:00:45 +0000 (19:00 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 12 May 2011 18:10:48 +0000 (14:10 -0400)
When transmitting a frame, the transmitter waits a random number of
slots between 0 and cw. Thus, the contention time is (cw / 2) * t_slot
which we can represent instead as (cw * t_slot) >> 1. Also fix a few
other accounting bugs around contention time, and add comments.

Signed-off-by: Daniel Halperin <dhalperi@cs.washington.edu>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel_ht.c

index 778c604..8adac67 100644 (file)
@@ -417,8 +417,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
                        tx_time_single = mr->ack_time + mr->perfect_tx_time;
 
                        /* contention window */
-                       tx_time_single += t_slot + min(cw, mp->cw_max);
-                       cw = (cw << 1) | 1;
+                       tx_time_single += (t_slot * cw) >> 1;
+                       cw = min((cw << 1) | 1, mp->cw_max);
 
                        tx_time += tx_time_single;
                        tx_time_cts += tx_time_single + mi->sp_ack_dur;
index dbdebed..3d09c58 100644 (file)
@@ -464,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);
 
@@ -480,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) &&