diff options
author | David S. Miller <davem@davemloft.net> | 2016-02-24 16:58:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-02-24 16:58:12 -0500 |
commit | 25ac3417b79b0aafd2401c96503716901be4533b (patch) | |
tree | 75f6f62924ef0e5f91f4268260dc352646554d01 /net | |
parent | 2da897e51d7f23f872224218b9a4314503b0d360 (diff) | |
parent | b86071528f3261ab592fad5b9b1a02aea3dcabf3 (diff) |
Merge tag 'mac80211-for-davem-2016-02-23' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Johannes Berg says:
====================
Another small set of fixes:
* stop critical protocol session on disconnect to avoid
it getting stuck
* wext: fix two RTNL message ordering issues
* fix an uninitialized value (found by KASAN)
* fix an out-of-bounds access (also found by KASAN)
* clear connection keys when freeing them in all cases
(IBSS, all other places already did so)
* fix expected throughput unit to get consistent values
* set default TX aggregation timeout to 0 in minstrel
to avoid (really just hide) issues and perform better
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/agg-rx.c | 2 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 2 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 14 | ||||
-rw-r--r-- | net/wireless/core.c | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 2 | ||||
-rw-r--r-- | net/wireless/sme.c | 6 | ||||
-rw-r--r-- | net/wireless/wext-core.c | 52 |
7 files changed, 60 insertions, 20 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 10ad4ac1fa0b..367784be5df2 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -291,7 +291,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
291 | } | 291 | } |
292 | 292 | ||
293 | /* prepare A-MPDU MLME for Rx aggregation */ | 293 | /* prepare A-MPDU MLME for Rx aggregation */ |
294 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); | 294 | tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL); |
295 | if (!tid_agg_rx) | 295 | if (!tid_agg_rx) |
296 | goto end; | 296 | goto end; |
297 | 297 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 3ece7d1034c8..b54f398cda5d 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -711,7 +711,7 @@ static u32 minstrel_get_expected_throughput(void *priv_sta) | |||
711 | * computing cur_tp | 711 | * computing cur_tp |
712 | */ | 712 | */ |
713 | tmp_mrs = &mi->r[idx].stats; | 713 | tmp_mrs = &mi->r[idx].stats; |
714 | tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma); | 714 | tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10; |
715 | tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; | 715 | tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; |
716 | 716 | ||
717 | return tmp_cur_tp; | 717 | return tmp_cur_tp; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 3928dbd24e25..409b3640da6c 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -414,15 +414,16 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index) | |||
414 | (max_tp_group != MINSTREL_CCK_GROUP)) | 414 | (max_tp_group != MINSTREL_CCK_GROUP)) |
415 | return; | 415 | return; |
416 | 416 | ||
417 | max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; | ||
418 | max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; | ||
419 | max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma; | ||
420 | |||
417 | if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) { | 421 | if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) { |
418 | cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, | 422 | cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, |
419 | mrs->prob_ewma); | 423 | mrs->prob_ewma); |
420 | if (cur_tp_avg > tmp_tp_avg) | 424 | if (cur_tp_avg > tmp_tp_avg) |
421 | mi->max_prob_rate = index; | 425 | mi->max_prob_rate = index; |
422 | 426 | ||
423 | max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; | ||
424 | max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; | ||
425 | max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma; | ||
426 | max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group, | 427 | max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group, |
427 | max_gpr_idx, | 428 | max_gpr_idx, |
428 | max_gpr_prob); | 429 | max_gpr_prob); |
@@ -431,7 +432,7 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index) | |||
431 | } else { | 432 | } else { |
432 | if (mrs->prob_ewma > tmp_prob) | 433 | if (mrs->prob_ewma > tmp_prob) |
433 | mi->max_prob_rate = index; | 434 | mi->max_prob_rate = index; |
434 | if (mrs->prob_ewma > mg->rates[mg->max_group_prob_rate].prob_ewma) | 435 | if (mrs->prob_ewma > max_gpr_prob) |
435 | mg->max_group_prob_rate = index; | 436 | mg->max_group_prob_rate = index; |
436 | } | 437 | } |
437 | } | 438 | } |
@@ -691,7 +692,7 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb) | |||
691 | if (likely(sta->ampdu_mlme.tid_tx[tid])) | 692 | if (likely(sta->ampdu_mlme.tid_tx[tid])) |
692 | return; | 693 | return; |
693 | 694 | ||
694 | ieee80211_start_tx_ba_session(pubsta, tid, 5000); | 695 | ieee80211_start_tx_ba_session(pubsta, tid, 0); |
695 | } | 696 | } |
696 | 697 | ||
697 | static void | 698 | static void |
@@ -1334,7 +1335,8 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta) | |||
1334 | prob = mi->groups[i].rates[j].prob_ewma; | 1335 | prob = mi->groups[i].rates[j].prob_ewma; |
1335 | 1336 | ||
1336 | /* convert tp_avg from pkt per second in kbps */ | 1337 | /* convert tp_avg from pkt per second in kbps */ |
1337 | tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * AVG_PKT_SIZE * 8 / 1024; | 1338 | tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10; |
1339 | tp_avg = tp_avg * AVG_PKT_SIZE * 8 / 1024; | ||
1338 | 1340 | ||
1339 | return tp_avg; | 1341 | return tp_avg; |
1340 | } | 1342 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index b0915515640e..8f0bac7e03c4 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -1147,6 +1147,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
1147 | return NOTIFY_DONE; | 1147 | return NOTIFY_DONE; |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | wireless_nlevent_flush(); | ||
1151 | |||
1150 | return NOTIFY_OK; | 1152 | return NOTIFY_OK; |
1151 | } | 1153 | } |
1152 | 1154 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d4786f2802aa..711cb7ad6ae0 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -7547,7 +7547,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
7547 | 7547 | ||
7548 | if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) && | 7548 | if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) && |
7549 | no_ht) { | 7549 | no_ht) { |
7550 | kfree(connkeys); | 7550 | kzfree(connkeys); |
7551 | return -EINVAL; | 7551 | return -EINVAL; |
7552 | } | 7552 | } |
7553 | } | 7553 | } |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 8020b5b094d4..d49ed7666d4c 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -917,6 +917,12 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
917 | 917 | ||
918 | nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); | 918 | nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); |
919 | 919 | ||
920 | /* stop critical protocol if supported */ | ||
921 | if (rdev->ops->crit_proto_stop && rdev->crit_proto_nlportid) { | ||
922 | rdev->crit_proto_nlportid = 0; | ||
923 | rdev_crit_proto_stop(rdev, wdev); | ||
924 | } | ||
925 | |||
920 | /* | 926 | /* |
921 | * Delete all the keys ... pairwise keys can't really | 927 | * Delete all the keys ... pairwise keys can't really |
922 | * exist any more anyway, but default keys might. | 928 | * exist any more anyway, but default keys might. |
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index c8717c1d082e..b50ee5d622e1 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c | |||
@@ -342,6 +342,40 @@ static const int compat_event_type_size[] = { | |||
342 | 342 | ||
343 | /* IW event code */ | 343 | /* IW event code */ |
344 | 344 | ||
345 | void wireless_nlevent_flush(void) | ||
346 | { | ||
347 | struct sk_buff *skb; | ||
348 | struct net *net; | ||
349 | |||
350 | ASSERT_RTNL(); | ||
351 | |||
352 | for_each_net(net) { | ||
353 | while ((skb = skb_dequeue(&net->wext_nlevents))) | ||
354 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, | ||
355 | GFP_KERNEL); | ||
356 | } | ||
357 | } | ||
358 | EXPORT_SYMBOL_GPL(wireless_nlevent_flush); | ||
359 | |||
360 | static int wext_netdev_notifier_call(struct notifier_block *nb, | ||
361 | unsigned long state, void *ptr) | ||
362 | { | ||
363 | /* | ||
364 | * When a netdev changes state in any way, flush all pending messages | ||
365 | * to avoid them going out in a strange order, e.g. RTM_NEWLINK after | ||
366 | * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close() | ||
367 | * or similar - all of which could otherwise happen due to delays from | ||
368 | * schedule_work(). | ||
369 | */ | ||
370 | wireless_nlevent_flush(); | ||
371 | |||
372 | return NOTIFY_OK; | ||
373 | } | ||
374 | |||
375 | static struct notifier_block wext_netdev_notifier = { | ||
376 | .notifier_call = wext_netdev_notifier_call, | ||
377 | }; | ||
378 | |||
345 | static int __net_init wext_pernet_init(struct net *net) | 379 | static int __net_init wext_pernet_init(struct net *net) |
346 | { | 380 | { |
347 | skb_queue_head_init(&net->wext_nlevents); | 381 | skb_queue_head_init(&net->wext_nlevents); |
@@ -360,7 +394,12 @@ static struct pernet_operations wext_pernet_ops = { | |||
360 | 394 | ||
361 | static int __init wireless_nlevent_init(void) | 395 | static int __init wireless_nlevent_init(void) |
362 | { | 396 | { |
363 | return register_pernet_subsys(&wext_pernet_ops); | 397 | int err = register_pernet_subsys(&wext_pernet_ops); |
398 | |||
399 | if (err) | ||
400 | return err; | ||
401 | |||
402 | return register_netdevice_notifier(&wext_netdev_notifier); | ||
364 | } | 403 | } |
365 | 404 | ||
366 | subsys_initcall(wireless_nlevent_init); | 405 | subsys_initcall(wireless_nlevent_init); |
@@ -368,17 +407,8 @@ subsys_initcall(wireless_nlevent_init); | |||
368 | /* Process events generated by the wireless layer or the driver. */ | 407 | /* Process events generated by the wireless layer or the driver. */ |
369 | static void wireless_nlevent_process(struct work_struct *work) | 408 | static void wireless_nlevent_process(struct work_struct *work) |
370 | { | 409 | { |
371 | struct sk_buff *skb; | ||
372 | struct net *net; | ||
373 | |||
374 | rtnl_lock(); | 410 | rtnl_lock(); |
375 | 411 | wireless_nlevent_flush(); | |
376 | for_each_net(net) { | ||
377 | while ((skb = skb_dequeue(&net->wext_nlevents))) | ||
378 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, | ||
379 | GFP_KERNEL); | ||
380 | } | ||
381 | |||
382 | rtnl_unlock(); | 412 | rtnl_unlock(); |
383 | } | 413 | } |
384 | 414 | ||