aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSimon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>2013-07-08 10:55:51 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-07-16 02:58:04 -0400
commit438b61b77082e70d2a408cc77b8c5faac312e940 (patch)
tree2a4575f29605a16fc051a6b81c71d0f3b31d7d77 /net
parent3de805cf965d69c8d3d7d69368d5fd2c925a2d5a (diff)
mac80211: fix timing for 5 MHz and 10 MHz channels
according to IEEE 802.11-2012 section 18, various timings change when using 5 MHz and 10 MHz. Reflect this by using a "shift" when calculating durations. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h31
-rw-r--r--net/mac80211/rc80211_minstrel.c30
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c5
-rw-r--r--net/mac80211/tx.c10
-rw-r--r--net/mac80211/util.c39
5 files changed, 90 insertions, 25 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 683751a1eceb..338e7ca21ea5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -812,6 +812,34 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
812 return band; 812 return band;
813} 813}
814 814
815static inline int
816ieee80211_chandef_get_shift(struct cfg80211_chan_def *chandef)
817{
818 switch (chandef->width) {
819 case NL80211_CHAN_WIDTH_5:
820 return 2;
821 case NL80211_CHAN_WIDTH_10:
822 return 1;
823 default:
824 return 0;
825 }
826}
827
828static inline int
829ieee80211_vif_get_shift(struct ieee80211_vif *vif)
830{
831 struct ieee80211_chanctx_conf *chanctx_conf;
832 int shift = 0;
833
834 rcu_read_lock();
835 chanctx_conf = rcu_dereference(vif->chanctx_conf);
836 if (chanctx_conf)
837 shift = ieee80211_chandef_get_shift(&chanctx_conf->def);
838 rcu_read_unlock();
839
840 return shift;
841}
842
815enum sdata_queue_type { 843enum sdata_queue_type {
816 IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, 844 IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0,
817 IEEE80211_SDATA_QUEUE_AGG_START = 1, 845 IEEE80211_SDATA_QUEUE_AGG_START = 1,
@@ -1468,7 +1496,8 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */
1468u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, 1496u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
1469 enum nl80211_iftype type); 1497 enum nl80211_iftype type);
1470int ieee80211_frame_duration(enum ieee80211_band band, size_t len, 1498int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
1471 int rate, int erp, int short_preamble); 1499 int rate, int erp, int short_preamble,
1500 int shift);
1472void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, 1501void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
1473 struct ieee80211_hdr *hdr, const u8 *tsc, 1502 struct ieee80211_hdr *hdr, const u8 *tsc,
1474 gfp_t gfp); 1503 gfp_t gfp);
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 5b25966add10..a507376d5316 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -382,14 +382,18 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
382static void 382static void
383calc_rate_durations(enum ieee80211_band band, 383calc_rate_durations(enum ieee80211_band band,
384 struct minstrel_rate *d, 384 struct minstrel_rate *d,
385 struct ieee80211_rate *rate) 385 struct ieee80211_rate *rate,
386 struct cfg80211_chan_def *chandef)
386{ 387{
387 int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); 388 int erp = !!(rate->flags & IEEE80211_RATE_ERP_G);
389 int shift = ieee80211_chandef_get_shift(chandef);
388 390
389 d->perfect_tx_time = ieee80211_frame_duration(band, 1200, 391 d->perfect_tx_time = ieee80211_frame_duration(band, 1200,
390 rate->bitrate, erp, 1); 392 DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1,
393 shift);
391 d->ack_time = ieee80211_frame_duration(band, 10, 394 d->ack_time = ieee80211_frame_duration(band, 10,
392 rate->bitrate, erp, 1); 395 DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1,
396 shift);
393} 397}
394 398
395static void 399static void
@@ -425,14 +429,17 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
425 struct ieee80211_rate *ctl_rate; 429 struct ieee80211_rate *ctl_rate;
426 unsigned int i, n = 0; 430 unsigned int i, n = 0;
427 unsigned int t_slot = 9; /* FIXME: get real slot time */ 431 unsigned int t_slot = 9; /* FIXME: get real slot time */
432 u32 rate_flags;
428 433
429 mi->sta = sta; 434 mi->sta = sta;
430 mi->lowest_rix = rate_lowest_index(sband, sta); 435 mi->lowest_rix = rate_lowest_index(sband, sta);
431 ctl_rate = &sband->bitrates[mi->lowest_rix]; 436 ctl_rate = &sband->bitrates[mi->lowest_rix];
432 mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10, 437 mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
433 ctl_rate->bitrate, 438 ctl_rate->bitrate,
434 !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1); 439 !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1,
440 ieee80211_chandef_get_shift(chandef));
435 441
442 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
436 memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate)); 443 memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate));
437 mi->max_prob_rate = 0; 444 mi->max_prob_rate = 0;
438 445
@@ -441,15 +448,22 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
441 unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; 448 unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
442 unsigned int tx_time_single; 449 unsigned int tx_time_single;
443 unsigned int cw = mp->cw_min; 450 unsigned int cw = mp->cw_min;
451 int shift;
444 452
445 if (!rate_supported(sta, sband->band, i)) 453 if (!rate_supported(sta, sband->band, i))
446 continue; 454 continue;
455 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
456 continue;
457
447 n++; 458 n++;
448 memset(mr, 0, sizeof(*mr)); 459 memset(mr, 0, sizeof(*mr));
449 460
450 mr->rix = i; 461 mr->rix = i;
451 mr->bitrate = sband->bitrates[i].bitrate / 5; 462 shift = ieee80211_chandef_get_shift(chandef);
452 calc_rate_durations(sband->band, mr, &sband->bitrates[i]); 463 mr->bitrate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
464 (1 << shift) * 5);
465 calc_rate_durations(sband->band, mr, &sband->bitrates[i],
466 chandef);
453 467
454 /* calculate maximum number of retransmissions before 468 /* calculate maximum number of retransmissions before
455 * fallback (based on maximum segment size) */ 469 * fallback (based on maximum segment size) */
@@ -547,6 +561,7 @@ minstrel_init_cck_rates(struct minstrel_priv *mp)
547{ 561{
548 static const int bitrates[4] = { 10, 20, 55, 110 }; 562 static const int bitrates[4] = { 10, 20, 55, 110 };
549 struct ieee80211_supported_band *sband; 563 struct ieee80211_supported_band *sband;
564 u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
550 int i, j; 565 int i, j;
551 566
552 sband = mp->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; 567 sband = mp->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -559,6 +574,9 @@ minstrel_init_cck_rates(struct minstrel_priv *mp)
559 if (rate->flags & IEEE80211_RATE_ERP_G) 574 if (rate->flags & IEEE80211_RATE_ERP_G)
560 continue; 575 continue;
561 576
577 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
578 continue;
579
562 for (j = 0; j < ARRAY_SIZE(bitrates); j++) { 580 for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
563 if (rate->bitrate != bitrates[j]) 581 if (rate->bitrate != bitrates[j])
564 continue; 582 continue;
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 52562973fbd1..7475a7a33797 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -862,8 +862,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
862 mi->sta = sta; 862 mi->sta = sta;
863 mi->stats_update = jiffies; 863 mi->stats_update = jiffies;
864 864
865 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1); 865 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0);
866 mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1) + ack_dur; 866 mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0);
867 mi->overhead += ack_dur;
867 mi->overhead_rtscts = mi->overhead + 2 * ack_dur; 868 mi->overhead_rtscts = mi->overhead + 2 * ack_dur;
868 869
869 mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); 870 mi->avg_ampdu_len = MINSTREL_FRAC(1, 1);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4105d0ca963e..3523daa0b15c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -40,7 +40,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
40 struct sk_buff *skb, int group_addr, 40 struct sk_buff *skb, int group_addr,
41 int next_frag_len) 41 int next_frag_len)
42{ 42{
43 int rate, mrate, erp, dur, i; 43 int rate, mrate, erp, dur, i, shift;
44 struct ieee80211_rate *txrate; 44 struct ieee80211_rate *txrate;
45 struct ieee80211_local *local = tx->local; 45 struct ieee80211_local *local = tx->local;
46 struct ieee80211_supported_band *sband; 46 struct ieee80211_supported_band *sband;
@@ -153,6 +153,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
153 rate = mrate; 153 rate = mrate;
154 } 154 }
155 155
156 shift = ieee80211_vif_get_shift(&tx->sdata->vif);
157
156 /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ 158 /* Don't calculate ACKs for QoS Frames with NoAck Policy set */
157 if (ieee80211_is_data_qos(hdr->frame_control) && 159 if (ieee80211_is_data_qos(hdr->frame_control) &&
158 *(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK) 160 *(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
@@ -162,7 +164,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
162 * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up 164 * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
163 * to closest integer */ 165 * to closest integer */
164 dur = ieee80211_frame_duration(sband->band, 10, rate, erp, 166 dur = ieee80211_frame_duration(sband->band, 10, rate, erp,
165 tx->sdata->vif.bss_conf.use_short_preamble); 167 tx->sdata->vif.bss_conf.use_short_preamble,
168 shift);
166 169
167 if (next_frag_len) { 170 if (next_frag_len) {
168 /* Frame is fragmented: duration increases with time needed to 171 /* Frame is fragmented: duration increases with time needed to
@@ -171,7 +174,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
171 /* next fragment */ 174 /* next fragment */
172 dur += ieee80211_frame_duration(sband->band, next_frag_len, 175 dur += ieee80211_frame_duration(sband->band, next_frag_len,
173 txrate->bitrate, erp, 176 txrate->bitrate, erp,
174 tx->sdata->vif.bss_conf.use_short_preamble); 177 tx->sdata->vif.bss_conf.use_short_preamble,
178 shift);
175 } 179 }
176 180
177 return cpu_to_le16(dur); 181 return cpu_to_le16(dur);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 22654452a561..61856e17a1e4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -107,7 +107,8 @@ void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
107} 107}
108 108
109int ieee80211_frame_duration(enum ieee80211_band band, size_t len, 109int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
110 int rate, int erp, int short_preamble) 110 int rate, int erp, int short_preamble,
111 int shift)
111{ 112{
112 int dur; 113 int dur;
113 114
@@ -118,6 +119,9 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
118 * 119 *
119 * rate is in 100 kbps, so divident is multiplied by 10 in the 120 * rate is in 100 kbps, so divident is multiplied by 10 in the
120 * DIV_ROUND_UP() operations. 121 * DIV_ROUND_UP() operations.
122 *
123 * shift may be 2 for 5 MHz channels or 1 for 10 MHz channels, and
124 * is assumed to be 0 otherwise.
121 */ 125 */
122 126
123 if (band == IEEE80211_BAND_5GHZ || erp) { 127 if (band == IEEE80211_BAND_5GHZ || erp) {
@@ -130,15 +134,21 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
130 * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext 134 * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
131 * 135 *
132 * T_SYM = 4 usec 136 * T_SYM = 4 usec
133 * 802.11a - 17.5.2: aSIFSTime = 16 usec 137 * 802.11a - 18.5.2: aSIFSTime = 16 usec
134 * 802.11g - 19.8.4: aSIFSTime = 10 usec + 138 * 802.11g - 19.8.4: aSIFSTime = 10 usec +
135 * signal ext = 6 usec 139 * signal ext = 6 usec
136 */ 140 */
137 dur = 16; /* SIFS + signal ext */ 141 dur = 16; /* SIFS + signal ext */
138 dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ 142 dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */
139 dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ 143 dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */
140 dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, 144 dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
141 4 * rate); /* T_SYM x N_SYM */ 145 4 * rate); /* T_SYM x N_SYM */
146
147 /* IEEE 802.11-2012 18.3.2.4: all values above are:
148 * * times 4 for 5 MHz
149 * * times 2 for 10 MHz
150 */
151 dur *= 1 << shift;
142 } else { 152 } else {
143 /* 153 /*
144 * 802.11b or 802.11g with 802.11b compatibility: 154 * 802.11b or 802.11g with 802.11b compatibility:
@@ -168,7 +178,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
168{ 178{
169 struct ieee80211_sub_if_data *sdata; 179 struct ieee80211_sub_if_data *sdata;
170 u16 dur; 180 u16 dur;
171 int erp; 181 int erp, shift = 0;
172 bool short_preamble = false; 182 bool short_preamble = false;
173 183
174 erp = 0; 184 erp = 0;
@@ -177,10 +187,11 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
177 short_preamble = sdata->vif.bss_conf.use_short_preamble; 187 short_preamble = sdata->vif.bss_conf.use_short_preamble;
178 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 188 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
179 erp = rate->flags & IEEE80211_RATE_ERP_G; 189 erp = rate->flags & IEEE80211_RATE_ERP_G;
190 shift = ieee80211_vif_get_shift(vif);
180 } 191 }
181 192
182 dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp, 193 dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp,
183 short_preamble); 194 short_preamble, shift);
184 195
185 return cpu_to_le16(dur); 196 return cpu_to_le16(dur);
186} 197}
@@ -194,7 +205,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
194 struct ieee80211_rate *rate; 205 struct ieee80211_rate *rate;
195 struct ieee80211_sub_if_data *sdata; 206 struct ieee80211_sub_if_data *sdata;
196 bool short_preamble; 207 bool short_preamble;
197 int erp; 208 int erp, shift = 0;
198 u16 dur; 209 u16 dur;
199 struct ieee80211_supported_band *sband; 210 struct ieee80211_supported_band *sband;
200 211
@@ -210,17 +221,18 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
210 short_preamble = sdata->vif.bss_conf.use_short_preamble; 221 short_preamble = sdata->vif.bss_conf.use_short_preamble;
211 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 222 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
212 erp = rate->flags & IEEE80211_RATE_ERP_G; 223 erp = rate->flags & IEEE80211_RATE_ERP_G;
224 shift = ieee80211_vif_get_shift(vif);
213 } 225 }
214 226
215 /* CTS duration */ 227 /* CTS duration */
216 dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate, 228 dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate,
217 erp, short_preamble); 229 erp, short_preamble, shift);
218 /* Data frame duration */ 230 /* Data frame duration */
219 dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, 231 dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
220 erp, short_preamble); 232 erp, short_preamble, shift);
221 /* ACK duration */ 233 /* ACK duration */
222 dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, 234 dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
223 erp, short_preamble); 235 erp, short_preamble, shift);
224 236
225 return cpu_to_le16(dur); 237 return cpu_to_le16(dur);
226} 238}
@@ -235,7 +247,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
235 struct ieee80211_rate *rate; 247 struct ieee80211_rate *rate;
236 struct ieee80211_sub_if_data *sdata; 248 struct ieee80211_sub_if_data *sdata;
237 bool short_preamble; 249 bool short_preamble;
238 int erp; 250 int erp, shift = 0;
239 u16 dur; 251 u16 dur;
240 struct ieee80211_supported_band *sband; 252 struct ieee80211_supported_band *sband;
241 253
@@ -250,15 +262,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
250 short_preamble = sdata->vif.bss_conf.use_short_preamble; 262 short_preamble = sdata->vif.bss_conf.use_short_preamble;
251 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 263 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
252 erp = rate->flags & IEEE80211_RATE_ERP_G; 264 erp = rate->flags & IEEE80211_RATE_ERP_G;
265 shift = ieee80211_vif_get_shift(vif);
253 } 266 }
254 267
255 /* Data frame duration */ 268 /* Data frame duration */
256 dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, 269 dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
257 erp, short_preamble); 270 erp, short_preamble, shift);
258 if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { 271 if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) {
259 /* ACK duration */ 272 /* ACK duration */
260 dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, 273 dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
261 erp, short_preamble); 274 erp, short_preamble, shift);
262 } 275 }
263 276
264 return cpu_to_le16(dur); 277 return cpu_to_le16(dur);