aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-02-24 16:58:12 -0500
committerDavid S. Miller <davem@davemloft.net>2016-02-24 16:58:12 -0500
commit25ac3417b79b0aafd2401c96503716901be4533b (patch)
tree75f6f62924ef0e5f91f4268260dc352646554d01 /net
parent2da897e51d7f23f872224218b9a4314503b0d360 (diff)
parentb86071528f3261ab592fad5b9b1a02aea3dcabf3 (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.c2
-rw-r--r--net/mac80211/rc80211_minstrel.c2
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c14
-rw-r--r--net/wireless/core.c2
-rw-r--r--net/wireless/nl80211.c2
-rw-r--r--net/wireless/sme.c6
-rw-r--r--net/wireless/wext-core.c52
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
697static void 698static 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
345void 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}
358EXPORT_SYMBOL_GPL(wireless_nlevent_flush);
359
360static 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
375static struct notifier_block wext_netdev_notifier = {
376 .notifier_call = wext_netdev_notifier_call,
377};
378
345static int __net_init wext_pernet_init(struct net *net) 379static 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
361static int __init wireless_nlevent_init(void) 395static 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
366subsys_initcall(wireless_nlevent_init); 405subsys_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. */
369static void wireless_nlevent_process(struct work_struct *work) 408static 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