diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2010-01-06 06:09:08 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-12 13:50:11 -0500 |
commit | 37eb0b164cf9fa9f70c8500926f5cde7c652f48e (patch) | |
tree | 9260e7045f32268c8c4ded718677711d371cd5ed /net/mac80211 | |
parent | e00cfce0cb2a397859607bf515c6de9ce064b64a (diff) |
cfg80211/mac80211: Use more generic bitrate mask for rate control
Extend struct cfg80211_bitrate_mask to actually use a bitfield mask
instead of just a single fixed or maximum rate index. This change
itself does not modify the behavior (except for debugfs files), but it
prepares cfg80211 and mac80211 for a new nl80211 command for setting
which rates can be used in TX rate control.
Since frames are now going through the rate control algorithm
unconditionally, the internal IEEE80211_TX_INTFL_RCALGO flag can now
be removed. The RC implementations can use the rate_idx_mask value to
optimize their behavior if only a single rate is enabled.
The old max_rate_idx in struct ieee80211_tx_rate_control is maintained
(but commented as deprecated) for backwards compatibility with existing
RC implementations. Once these implementations have been updated to
use the more generic rate_idx_mask, the max_rate_idx value can be
removed.
Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 32 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 22 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/iface.c | 8 | ||||
-rw-r--r-- | net/mac80211/rate.c | 63 | ||||
-rw-r--r-- | net/mac80211/rate.h | 5 | ||||
-rw-r--r-- | net/mac80211/tx.c | 12 |
7 files changed, 86 insertions, 60 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 976014c5e742..e5dda6fb8dff 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1406,8 +1406,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1406 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1406 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1407 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1407 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1408 | int i; | 1408 | int i; |
1409 | u32 target_rate; | ||
1410 | struct ieee80211_supported_band *sband; | ||
1411 | 1409 | ||
1412 | /* | 1410 | /* |
1413 | * This _could_ be supported by providing a hook for | 1411 | * This _could_ be supported by providing a hook for |
@@ -1417,35 +1415,11 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1417 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | 1415 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) |
1418 | return -EOPNOTSUPP; | 1416 | return -EOPNOTSUPP; |
1419 | 1417 | ||
1420 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1421 | |||
1422 | /* | ||
1423 | * target_rate = -1, rate->fixed = 0 means auto only, so use all rates | ||
1424 | * target_rate = X, rate->fixed = 1 means only rate X | ||
1425 | * target_rate = X, rate->fixed = 0 means all rates <= X | ||
1426 | */ | ||
1427 | sdata->max_ratectrl_rateidx = -1; | ||
1428 | sdata->force_unicast_rateidx = -1; | ||
1429 | 1418 | ||
1430 | if (mask->fixed) | 1419 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
1431 | target_rate = mask->fixed / 100; | 1420 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
1432 | else if (mask->maxrate) | ||
1433 | target_rate = mask->maxrate / 100; | ||
1434 | else | ||
1435 | return 0; | ||
1436 | 1421 | ||
1437 | for (i = 0; i< sband->n_bitrates; i++) { | 1422 | return 0; |
1438 | if (target_rate != sband->bitrates[i].bitrate) | ||
1439 | continue; | ||
1440 | |||
1441 | /* requested bitrate found */ | ||
1442 | sdata->max_ratectrl_rateidx = i; | ||
1443 | if (mask->fixed) | ||
1444 | sdata->force_unicast_rateidx = i; | ||
1445 | return 0; | ||
1446 | } | ||
1447 | |||
1448 | return -EINVAL; | ||
1449 | } | 1423 | } |
1450 | 1424 | ||
1451 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 1425 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 59f6e3bcbd09..1481049f0f71 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -127,8 +127,10 @@ __IEEE80211_IF_FILE(name, ieee80211_if_write_##name) | |||
127 | 127 | ||
128 | /* common attributes */ | 128 | /* common attributes */ |
129 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 129 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
130 | IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); | 130 | IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], |
131 | IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | 131 | HEX); |
132 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | ||
133 | HEX); | ||
132 | 134 | ||
133 | /* STA attributes */ | 135 | /* STA attributes */ |
134 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 136 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
@@ -264,8 +266,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | |||
264 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 266 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
265 | { | 267 | { |
266 | DEBUGFS_ADD(drop_unencrypted, sta); | 268 | DEBUGFS_ADD(drop_unencrypted, sta); |
267 | DEBUGFS_ADD(force_unicast_rateidx, sta); | 269 | DEBUGFS_ADD(rc_rateidx_mask_2ghz, sta); |
268 | DEBUGFS_ADD(max_ratectrl_rateidx, sta); | 270 | DEBUGFS_ADD(rc_rateidx_mask_5ghz, sta); |
269 | 271 | ||
270 | DEBUGFS_ADD(bssid, sta); | 272 | DEBUGFS_ADD(bssid, sta); |
271 | DEBUGFS_ADD(aid, sta); | 273 | DEBUGFS_ADD(aid, sta); |
@@ -275,8 +277,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
275 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 277 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
276 | { | 278 | { |
277 | DEBUGFS_ADD(drop_unencrypted, ap); | 279 | DEBUGFS_ADD(drop_unencrypted, ap); |
278 | DEBUGFS_ADD(force_unicast_rateidx, ap); | 280 | DEBUGFS_ADD(rc_rateidx_mask_2ghz, ap); |
279 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | 281 | DEBUGFS_ADD(rc_rateidx_mask_5ghz, ap); |
280 | 282 | ||
281 | DEBUGFS_ADD(num_sta_ps, ap); | 283 | DEBUGFS_ADD(num_sta_ps, ap); |
282 | DEBUGFS_ADD(dtim_count, ap); | 284 | DEBUGFS_ADD(dtim_count, ap); |
@@ -286,8 +288,8 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
286 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 288 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
287 | { | 289 | { |
288 | DEBUGFS_ADD(drop_unencrypted, wds); | 290 | DEBUGFS_ADD(drop_unencrypted, wds); |
289 | DEBUGFS_ADD(force_unicast_rateidx, wds); | 291 | DEBUGFS_ADD(rc_rateidx_mask_2ghz, wds); |
290 | DEBUGFS_ADD(max_ratectrl_rateidx, wds); | 292 | DEBUGFS_ADD(rc_rateidx_mask_5ghz, wds); |
291 | 293 | ||
292 | DEBUGFS_ADD(peer, wds); | 294 | DEBUGFS_ADD(peer, wds); |
293 | } | 295 | } |
@@ -295,8 +297,8 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) | |||
295 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 297 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
296 | { | 298 | { |
297 | DEBUGFS_ADD(drop_unencrypted, vlan); | 299 | DEBUGFS_ADD(drop_unencrypted, vlan); |
298 | DEBUGFS_ADD(force_unicast_rateidx, vlan); | 300 | DEBUGFS_ADD(rc_rateidx_mask_2ghz, vlan); |
299 | DEBUGFS_ADD(max_ratectrl_rateidx, vlan); | 301 | DEBUGFS_ADD(rc_rateidx_mask_5ghz, vlan); |
300 | } | 302 | } |
301 | 303 | ||
302 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 304 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a27921ee6e63..3e4ac3f30857 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -494,8 +494,8 @@ struct ieee80211_sub_if_data { | |||
494 | */ | 494 | */ |
495 | struct ieee80211_if_ap *bss; | 495 | struct ieee80211_if_ap *bss; |
496 | 496 | ||
497 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | 497 | /* bitmap of allowed (non-MCS) rate indexes for rate control */ |
498 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | 498 | u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; |
499 | 499 | ||
500 | union { | 500 | union { |
501 | struct ieee80211_if_ap ap; | 501 | struct ieee80211_if_ap ap; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 264a6c975f8b..fe140bf033f9 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -856,8 +856,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
856 | 856 | ||
857 | INIT_LIST_HEAD(&sdata->key_list); | 857 | INIT_LIST_HEAD(&sdata->key_list); |
858 | 858 | ||
859 | sdata->force_unicast_rateidx = -1; | 859 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
860 | sdata->max_ratectrl_rateidx = -1; | 860 | struct ieee80211_supported_band *sband; |
861 | sband = local->hw.wiphy->bands[i]; | ||
862 | sdata->rc_rateidx_mask[i] = | ||
863 | sband ? (1 << sband->n_bitrates) - 1 : 0; | ||
864 | } | ||
861 | 865 | ||
862 | /* setup type-dependent data */ | 866 | /* setup type-dependent data */ |
863 | ieee80211_setup_sdata(sdata, type); | 867 | ieee80211_setup_sdata(sdata, type); |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6349e7f4dcae..c74b7c85403c 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -249,6 +249,38 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
249 | } | 249 | } |
250 | EXPORT_SYMBOL(rate_control_send_low); | 250 | EXPORT_SYMBOL(rate_control_send_low); |
251 | 251 | ||
252 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | ||
253 | int n_bitrates, u32 mask) | ||
254 | { | ||
255 | int j; | ||
256 | |||
257 | /* See whether the selected rate or anything below it is allowed. */ | ||
258 | for (j = rate->idx; j >= 0; j--) { | ||
259 | if (mask & (1 << j)) { | ||
260 | /* Okay, found a suitable rate. Use it. */ | ||
261 | rate->idx = j; | ||
262 | return; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | /* Try to find a higher rate that would be allowed */ | ||
267 | for (j = rate->idx + 1; j < n_bitrates; j++) { | ||
268 | if (mask & (1 << j)) { | ||
269 | /* Okay, found a suitable rate. Use it. */ | ||
270 | rate->idx = j; | ||
271 | return; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | * Uh.. No suitable rate exists. This should not really happen with | ||
277 | * sane TX rate mask configurations. However, should someone manage to | ||
278 | * configure supported rates and TX rate mask in incompatible way, | ||
279 | * allow the frame to be transmitted with whatever the rate control | ||
280 | * selected. | ||
281 | */ | ||
282 | } | ||
283 | |||
252 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 284 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
253 | struct sta_info *sta, | 285 | struct sta_info *sta, |
254 | struct ieee80211_tx_rate_control *txrc) | 286 | struct ieee80211_tx_rate_control *txrc) |
@@ -258,6 +290,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
258 | struct ieee80211_sta *ista = NULL; | 290 | struct ieee80211_sta *ista = NULL; |
259 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | 291 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
260 | int i; | 292 | int i; |
293 | u32 mask; | ||
261 | 294 | ||
262 | if (sta) { | 295 | if (sta) { |
263 | ista = &sta->sta; | 296 | ista = &sta->sta; |
@@ -270,23 +303,31 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
270 | info->control.rates[i].count = 1; | 303 | info->control.rates[i].count = 1; |
271 | } | 304 | } |
272 | 305 | ||
273 | if (sta && sdata->force_unicast_rateidx > -1) { | 306 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); |
274 | info->control.rates[0].idx = sdata->force_unicast_rateidx; | ||
275 | } else { | ||
276 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); | ||
277 | info->flags |= IEEE80211_TX_INTFL_RCALGO; | ||
278 | } | ||
279 | 307 | ||
280 | /* | 308 | /* |
281 | * try to enforce the maximum rate the user wanted | 309 | * Try to enforce the rateidx mask the user wanted. skip this if the |
310 | * default mask (allow all rates) is used to save some processing for | ||
311 | * the common case. | ||
282 | */ | 312 | */ |
283 | if (sdata->max_ratectrl_rateidx > -1) | 313 | mask = sdata->rc_rateidx_mask[info->band]; |
314 | if (mask != (1 << txrc->sband->n_bitrates) - 1) { | ||
315 | if (sta) { | ||
316 | /* Filter out rates that the STA does not support */ | ||
317 | mask &= sta->sta.supp_rates[info->band]; | ||
318 | } | ||
319 | /* | ||
320 | * Make sure the rate index selected for each TX rate is | ||
321 | * included in the configured mask and change the rate indexes | ||
322 | * if needed. | ||
323 | */ | ||
284 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 324 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
325 | /* Rate masking supports only legacy rates for now */ | ||
285 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) | 326 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) |
286 | continue; | 327 | continue; |
287 | info->control.rates[i].idx = | 328 | rate_idx_match_mask(&info->control.rates[i], |
288 | min_t(s8, info->control.rates[i].idx, | 329 | txrc->sband->n_bitrates, mask); |
289 | sdata->max_ratectrl_rateidx); | 330 | } |
290 | } | 331 | } |
291 | 332 | ||
292 | BUG_ON(info->control.rates[0].idx < 0); | 333 | BUG_ON(info->control.rates[0].idx < 0); |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index cb9bd1f65e27..669dddd40521 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -44,10 +44,7 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, | |||
44 | struct rate_control_ref *ref = local->rate_ctrl; | 44 | struct rate_control_ref *ref = local->rate_ctrl; |
45 | struct ieee80211_sta *ista = &sta->sta; | 45 | struct ieee80211_sta *ista = &sta->sta; |
46 | void *priv_sta = sta->rate_ctrl_priv; | 46 | void *priv_sta = sta->rate_ctrl_priv; |
47 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 47 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
48 | |||
49 | if (likely(info->flags & IEEE80211_TX_INTFL_RCALGO)) | ||
50 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | ||
51 | } | 48 | } |
52 | 49 | ||
53 | 50 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4961168f5091..d3a44812f8bf 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -519,7 +519,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
519 | txrc.bss_conf = &tx->sdata->vif.bss_conf; | 519 | txrc.bss_conf = &tx->sdata->vif.bss_conf; |
520 | txrc.skb = tx->skb; | 520 | txrc.skb = tx->skb; |
521 | txrc.reported_rate.idx = -1; | 521 | txrc.reported_rate.idx = -1; |
522 | txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; | 522 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[tx->channel->band]; |
523 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | ||
524 | txrc.max_rate_idx = -1; | ||
525 | else | ||
526 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | ||
523 | txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP; | 527 | txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP; |
524 | 528 | ||
525 | /* set up RTS protection if desired */ | 529 | /* set up RTS protection if desired */ |
@@ -2178,7 +2182,11 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2178 | txrc.bss_conf = &sdata->vif.bss_conf; | 2182 | txrc.bss_conf = &sdata->vif.bss_conf; |
2179 | txrc.skb = skb; | 2183 | txrc.skb = skb; |
2180 | txrc.reported_rate.idx = -1; | 2184 | txrc.reported_rate.idx = -1; |
2181 | txrc.max_rate_idx = sdata->max_ratectrl_rateidx; | 2185 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
2186 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | ||
2187 | txrc.max_rate_idx = -1; | ||
2188 | else | ||
2189 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | ||
2182 | txrc.ap = true; | 2190 | txrc.ap = true; |
2183 | rate_control_get_rate(sdata, NULL, &txrc); | 2191 | rate_control_get_rate(sdata, NULL, &txrc); |
2184 | 2192 | ||