diff options
-rw-r--r-- | include/net/cfg80211.h | 13 | ||||
-rw-r--r-- | include/net/mac80211.h | 8 | ||||
-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 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 34 |
10 files changed, 122 insertions, 79 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a8d5d04314b9..22e062afb5a1 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -857,20 +857,11 @@ enum tx_power_setting { | |||
857 | * cfg80211_bitrate_mask - masks for bitrate control | 857 | * cfg80211_bitrate_mask - masks for bitrate control |
858 | */ | 858 | */ |
859 | struct cfg80211_bitrate_mask { | 859 | struct cfg80211_bitrate_mask { |
860 | /* | ||
861 | * As discussed in Berlin, this struct really | ||
862 | * should look like this: | ||
863 | |||
864 | struct { | 860 | struct { |
865 | u32 legacy; | 861 | u32 legacy; |
866 | u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; | 862 | /* TODO: add support for masking MCS rates; e.g.: */ |
863 | /* u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; */ | ||
867 | } control[IEEE80211_NUM_BANDS]; | 864 | } control[IEEE80211_NUM_BANDS]; |
868 | |||
869 | * Since we can always fix in-kernel users, let's keep | ||
870 | * it simpler for now: | ||
871 | */ | ||
872 | u32 fixed; /* fixed bitrate, 0 == not fixed */ | ||
873 | u32 maxrate; /* in kbps, 0 == no limit */ | ||
874 | }; | 865 | }; |
875 | /** | 866 | /** |
876 | * struct cfg80211_pmksa - PMK Security Association | 867 | * struct cfg80211_pmksa - PMK Security Association |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 39c516c352be..7e5af6d90b93 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -255,9 +255,6 @@ struct ieee80211_bss_conf { | |||
255 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be | 255 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be |
256 | * set by rate control algorithms to indicate probe rate, will | 256 | * set by rate control algorithms to indicate probe rate, will |
257 | * be cleared for fragmented frames (except on the last fragment) | 257 | * be cleared for fragmented frames (except on the last fragment) |
258 | * @IEEE80211_TX_INTFL_RCALGO: mac80211 internal flag, do not test or | ||
259 | * set this flag in the driver; indicates that the rate control | ||
260 | * algorithm was used and should be notified of TX status | ||
261 | * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, | 258 | * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, |
262 | * used to indicate that a pending frame requires TX processing before | 259 | * used to indicate that a pending frame requires TX processing before |
263 | * it can be sent out. | 260 | * it can be sent out. |
@@ -287,7 +284,6 @@ enum mac80211_tx_control_flags { | |||
287 | IEEE80211_TX_STAT_AMPDU = BIT(10), | 284 | IEEE80211_TX_STAT_AMPDU = BIT(10), |
288 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), | 285 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), |
289 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), | 286 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), |
290 | IEEE80211_TX_INTFL_RCALGO = BIT(13), | ||
291 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), | 287 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), |
292 | IEEE80211_TX_INTFL_RETRIED = BIT(15), | 288 | IEEE80211_TX_INTFL_RETRIED = BIT(15), |
293 | IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), | 289 | IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), |
@@ -2297,6 +2293,9 @@ enum rate_control_changed { | |||
2297 | * @short_preamble: whether mac80211 will request short-preamble transmission | 2293 | * @short_preamble: whether mac80211 will request short-preamble transmission |
2298 | * if the selected rate supports it | 2294 | * if the selected rate supports it |
2299 | * @max_rate_idx: user-requested maximum rate (not MCS for now) | 2295 | * @max_rate_idx: user-requested maximum rate (not MCS for now) |
2296 | * (deprecated; this will be removed once drivers get updated to use | ||
2297 | * rate_idx_mask) | ||
2298 | * @rate_idx_mask: user-requested rate mask (not MCS for now) | ||
2300 | * @skb: the skb that will be transmitted, the control information in it needs | 2299 | * @skb: the skb that will be transmitted, the control information in it needs |
2301 | * to be filled in | 2300 | * to be filled in |
2302 | * @ap: whether this frame is sent out in AP mode | 2301 | * @ap: whether this frame is sent out in AP mode |
@@ -2309,6 +2308,7 @@ struct ieee80211_tx_rate_control { | |||
2309 | struct ieee80211_tx_rate reported_rate; | 2308 | struct ieee80211_tx_rate reported_rate; |
2310 | bool rts, short_preamble; | 2309 | bool rts, short_preamble; |
2311 | u8 max_rate_idx; | 2310 | u8 max_rate_idx; |
2311 | u32 rate_idx_mask; | ||
2312 | bool ap; | 2312 | bool ap; |
2313 | }; | 2313 | }; |
2314 | 2314 | ||
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 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 4198243a3dff..966d2f01beac 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -1204,21 +1204,47 @@ int cfg80211_wext_siwrate(struct net_device *dev, | |||
1204 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1204 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1205 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 1205 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
1206 | struct cfg80211_bitrate_mask mask; | 1206 | struct cfg80211_bitrate_mask mask; |
1207 | u32 fixed, maxrate; | ||
1208 | struct ieee80211_supported_band *sband; | ||
1209 | int band, ridx; | ||
1210 | bool match = false; | ||
1207 | 1211 | ||
1208 | if (!rdev->ops->set_bitrate_mask) | 1212 | if (!rdev->ops->set_bitrate_mask) |
1209 | return -EOPNOTSUPP; | 1213 | return -EOPNOTSUPP; |
1210 | 1214 | ||
1211 | mask.fixed = 0; | 1215 | memset(&mask, 0, sizeof(mask)); |
1212 | mask.maxrate = 0; | 1216 | fixed = 0; |
1217 | maxrate = 0; | ||
1213 | 1218 | ||
1214 | if (rate->value < 0) { | 1219 | if (rate->value < 0) { |
1215 | /* nothing */ | 1220 | /* nothing */ |
1216 | } else if (rate->fixed) { | 1221 | } else if (rate->fixed) { |
1217 | mask.fixed = rate->value / 1000; /* kbps */ | 1222 | fixed = rate->value / 100000; |
1218 | } else { | 1223 | } else { |
1219 | mask.maxrate = rate->value / 1000; /* kbps */ | 1224 | maxrate = rate->value / 100000; |
1225 | } | ||
1226 | |||
1227 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1228 | sband = wdev->wiphy->bands[band]; | ||
1229 | if (sband == NULL) | ||
1230 | continue; | ||
1231 | for (ridx = 0; ridx < sband->n_bitrates; ridx++) { | ||
1232 | struct ieee80211_rate *srate = &sband->bitrates[ridx]; | ||
1233 | if (fixed == srate->bitrate) { | ||
1234 | mask.control[band].legacy = 1 << ridx; | ||
1235 | match = true; | ||
1236 | break; | ||
1237 | } | ||
1238 | if (srate->bitrate <= maxrate) { | ||
1239 | mask.control[band].legacy |= 1 << ridx; | ||
1240 | match = true; | ||
1241 | } | ||
1242 | } | ||
1220 | } | 1243 | } |
1221 | 1244 | ||
1245 | if (!match) | ||
1246 | return -EINVAL; | ||
1247 | |||
1222 | return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask); | 1248 | return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask); |
1223 | } | 1249 | } |
1224 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate); | 1250 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate); |