diff options
author | David S. Miller <davem@davemloft.net> | 2013-04-01 13:36:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-01 13:36:50 -0400 |
commit | a210576cf891e9e6d2c238eabcf5c1286b1e7526 (patch) | |
tree | 0fa81a901cf628b25e6ee79057700cf39e59818a /net | |
parent | 7d4c04fc170087119727119074e72445f2bb192b (diff) | |
parent | 3658f3604066d5500ebd73a04084f127dc779441 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
net/mac80211/sta_info.c
net/wireless/core.h
Two minor conflicts in wireless. Overlapping additions of extern
declarations in net/wireless/core.h and a bug fix overlapping with
the addition of a boolean parameter to __ieee80211_key_free().
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 7 | ||||
-rw-r--r-- | net/core/flow.c | 2 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 4 | ||||
-rw-r--r-- | net/core/scm.c | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 12 | ||||
-rw-r--r-- | net/key/af_key.c | 1 | ||||
-rw-r--r-- | net/mac80211/iface.c | 35 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 6 | ||||
-rw-r--r-- | net/mac80211/rx.c | 14 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 13 | ||||
-rw-r--r-- | net/sched/sch_fq_codel.c | 2 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 2 | ||||
-rw-r--r-- | net/wireless/core.c | 64 | ||||
-rw-r--r-- | net/wireless/core.h | 5 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 52 | ||||
-rw-r--r-- | net/wireless/scan.c | 24 | ||||
-rw-r--r-- | net/wireless/sme.c | 6 | ||||
-rw-r--r-- | net/wireless/trace.h | 5 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 6 | ||||
-rw-r--r-- | net/xfrm/xfrm_replay.c | 66 |
21 files changed, 250 insertions, 83 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 2db88dfa99d7..63e25332924d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1624,7 +1624,6 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) | |||
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | skb_orphan(skb); | 1626 | skb_orphan(skb); |
1627 | nf_reset(skb); | ||
1628 | 1627 | ||
1629 | if (unlikely(!is_skb_forwardable(dev, skb))) { | 1628 | if (unlikely(!is_skb_forwardable(dev, skb))) { |
1630 | atomic_long_inc(&dev->rx_dropped); | 1629 | atomic_long_inc(&dev->rx_dropped); |
@@ -3318,6 +3317,7 @@ int netdev_rx_handler_register(struct net_device *dev, | |||
3318 | if (dev->rx_handler) | 3317 | if (dev->rx_handler) |
3319 | return -EBUSY; | 3318 | return -EBUSY; |
3320 | 3319 | ||
3320 | /* Note: rx_handler_data must be set before rx_handler */ | ||
3321 | rcu_assign_pointer(dev->rx_handler_data, rx_handler_data); | 3321 | rcu_assign_pointer(dev->rx_handler_data, rx_handler_data); |
3322 | rcu_assign_pointer(dev->rx_handler, rx_handler); | 3322 | rcu_assign_pointer(dev->rx_handler, rx_handler); |
3323 | 3323 | ||
@@ -3338,6 +3338,11 @@ void netdev_rx_handler_unregister(struct net_device *dev) | |||
3338 | 3338 | ||
3339 | ASSERT_RTNL(); | 3339 | ASSERT_RTNL(); |
3340 | RCU_INIT_POINTER(dev->rx_handler, NULL); | 3340 | RCU_INIT_POINTER(dev->rx_handler, NULL); |
3341 | /* a reader seeing a non NULL rx_handler in a rcu_read_lock() | ||
3342 | * section has a guarantee to see a non NULL rx_handler_data | ||
3343 | * as well. | ||
3344 | */ | ||
3345 | synchronize_net(); | ||
3341 | RCU_INIT_POINTER(dev->rx_handler_data, NULL); | 3346 | RCU_INIT_POINTER(dev->rx_handler_data, NULL); |
3342 | } | 3347 | } |
3343 | EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); | 3348 | EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); |
diff --git a/net/core/flow.c b/net/core/flow.c index 707fb7b952e8..7102f166482d 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
@@ -346,7 +346,7 @@ static void flow_cache_flush_per_cpu(void *data) | |||
346 | struct flow_flush_info *info = data; | 346 | struct flow_flush_info *info = data; |
347 | struct tasklet_struct *tasklet; | 347 | struct tasklet_struct *tasklet; |
348 | 348 | ||
349 | tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet); | 349 | tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet; |
350 | tasklet->data = (unsigned long)info; | 350 | tasklet->data = (unsigned long)info; |
351 | tasklet_schedule(tasklet); | 351 | tasklet_schedule(tasklet); |
352 | } | 352 | } |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d2322d7f0f7b..589d0abb34a0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -496,8 +496,10 @@ static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) | |||
496 | } | 496 | } |
497 | if (ops->fill_info) { | 497 | if (ops->fill_info) { |
498 | data = nla_nest_start(skb, IFLA_INFO_DATA); | 498 | data = nla_nest_start(skb, IFLA_INFO_DATA); |
499 | if (data == NULL) | 499 | if (data == NULL) { |
500 | err = -EMSGSIZE; | ||
500 | goto err_cancel_link; | 501 | goto err_cancel_link; |
502 | } | ||
501 | err = ops->fill_info(skb, dev); | 503 | err = ops->fill_info(skb, dev); |
502 | if (err < 0) | 504 | if (err < 0) |
503 | goto err_cancel_data; | 505 | goto err_cancel_data; |
diff --git a/net/core/scm.c b/net/core/scm.c index 905dcc6ad1e3..2dc6cdaaae8a 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
26 | #include <linux/security.h> | 26 | #include <linux/security.h> |
27 | #include <linux/pid_namespace.h> | ||
27 | #include <linux/pid.h> | 28 | #include <linux/pid.h> |
28 | #include <linux/nsproxy.h> | 29 | #include <linux/nsproxy.h> |
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
@@ -52,7 +53,8 @@ static __inline__ int scm_check_creds(struct ucred *creds) | |||
52 | if (!uid_valid(uid) || !gid_valid(gid)) | 53 | if (!uid_valid(uid) || !gid_valid(gid)) |
53 | return -EINVAL; | 54 | return -EINVAL; |
54 | 55 | ||
55 | if ((creds->pid == task_tgid_vnr(current) || nsown_capable(CAP_SYS_ADMIN)) && | 56 | if ((creds->pid == task_tgid_vnr(current) || |
57 | ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) && | ||
56 | ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || | 58 | ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || |
57 | uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) && | 59 | uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) && |
58 | ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || | 60 | ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index e33fe0ab2568..2bab2aa59745 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -118,6 +118,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
118 | ipv6_addr_loopback(&hdr->daddr)) | 118 | ipv6_addr_loopback(&hdr->daddr)) |
119 | goto err; | 119 | goto err; |
120 | 120 | ||
121 | /* RFC4291 Errata ID: 3480 | ||
122 | * Interface-Local scope spans only a single interface on a | ||
123 | * node and is useful only for loopback transmission of | ||
124 | * multicast. Packets with interface-local scope received | ||
125 | * from another node must be discarded. | ||
126 | */ | ||
127 | if (!(skb->pkt_type == PACKET_LOOPBACK || | ||
128 | dev->flags & IFF_LOOPBACK) && | ||
129 | ipv6_addr_is_multicast(&hdr->daddr) && | ||
130 | IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) | ||
131 | goto err; | ||
132 | |||
121 | /* RFC4291 2.7 | 133 | /* RFC4291 2.7 |
122 | * Nodes must not originate a packet to a multicast address whose scope | 134 | * Nodes must not originate a packet to a multicast address whose scope |
123 | * field contains the reserved value 0; if such a packet is received, it | 135 | * field contains the reserved value 0; if such a packet is received, it |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 8555f331ea60..5b1e5af25713 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -2693,6 +2693,7 @@ static int key_notify_policy_flush(const struct km_event *c) | |||
2693 | hdr->sadb_msg_pid = c->portid; | 2693 | hdr->sadb_msg_pid = c->portid; |
2694 | hdr->sadb_msg_version = PF_KEY_V2; | 2694 | hdr->sadb_msg_version = PF_KEY_V2; |
2695 | hdr->sadb_msg_errno = (uint8_t) 0; | 2695 | hdr->sadb_msg_errno = (uint8_t) 0; |
2696 | hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; | ||
2696 | hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | 2697 | hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); |
2697 | pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); | 2698 | pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); |
2698 | return 0; | 2699 | return 0; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d85282f64405..7530c60fe502 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
349 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 349 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
350 | { | 350 | { |
351 | struct ieee80211_sub_if_data *sdata; | 351 | struct ieee80211_sub_if_data *sdata; |
352 | int ret = 0; | 352 | int ret; |
353 | 353 | ||
354 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 354 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
355 | return 0; | 355 | return 0; |
356 | 356 | ||
357 | mutex_lock(&local->iflist_mtx); | 357 | ASSERT_RTNL(); |
358 | 358 | ||
359 | if (local->monitor_sdata) | 359 | if (local->monitor_sdata) |
360 | goto out_unlock; | 360 | return 0; |
361 | 361 | ||
362 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); | 362 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); |
363 | if (!sdata) { | 363 | if (!sdata) |
364 | ret = -ENOMEM; | 364 | return -ENOMEM; |
365 | goto out_unlock; | ||
366 | } | ||
367 | 365 | ||
368 | /* set up data */ | 366 | /* set up data */ |
369 | sdata->local = local; | 367 | sdata->local = local; |
@@ -377,13 +375,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
377 | if (WARN_ON(ret)) { | 375 | if (WARN_ON(ret)) { |
378 | /* ok .. stupid driver, it asked for this! */ | 376 | /* ok .. stupid driver, it asked for this! */ |
379 | kfree(sdata); | 377 | kfree(sdata); |
380 | goto out_unlock; | 378 | return ret; |
381 | } | 379 | } |
382 | 380 | ||
383 | ret = ieee80211_check_queues(sdata); | 381 | ret = ieee80211_check_queues(sdata); |
384 | if (ret) { | 382 | if (ret) { |
385 | kfree(sdata); | 383 | kfree(sdata); |
386 | goto out_unlock; | 384 | return ret; |
387 | } | 385 | } |
388 | 386 | ||
389 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | 387 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
@@ -391,13 +389,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
391 | if (ret) { | 389 | if (ret) { |
392 | drv_remove_interface(local, sdata); | 390 | drv_remove_interface(local, sdata); |
393 | kfree(sdata); | 391 | kfree(sdata); |
394 | goto out_unlock; | 392 | return ret; |
395 | } | 393 | } |
396 | 394 | ||
395 | mutex_lock(&local->iflist_mtx); | ||
397 | rcu_assign_pointer(local->monitor_sdata, sdata); | 396 | rcu_assign_pointer(local->monitor_sdata, sdata); |
398 | out_unlock: | ||
399 | mutex_unlock(&local->iflist_mtx); | 397 | mutex_unlock(&local->iflist_mtx); |
400 | return ret; | 398 | |
399 | return 0; | ||
401 | } | 400 | } |
402 | 401 | ||
403 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 402 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
@@ -407,14 +406,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
407 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 406 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
408 | return; | 407 | return; |
409 | 408 | ||
409 | ASSERT_RTNL(); | ||
410 | |||
410 | mutex_lock(&local->iflist_mtx); | 411 | mutex_lock(&local->iflist_mtx); |
411 | 412 | ||
412 | sdata = rcu_dereference_protected(local->monitor_sdata, | 413 | sdata = rcu_dereference_protected(local->monitor_sdata, |
413 | lockdep_is_held(&local->iflist_mtx)); | 414 | lockdep_is_held(&local->iflist_mtx)); |
414 | if (!sdata) | 415 | if (!sdata) { |
415 | goto out_unlock; | 416 | mutex_unlock(&local->iflist_mtx); |
417 | return; | ||
418 | } | ||
416 | 419 | ||
417 | rcu_assign_pointer(local->monitor_sdata, NULL); | 420 | rcu_assign_pointer(local->monitor_sdata, NULL); |
421 | mutex_unlock(&local->iflist_mtx); | ||
422 | |||
418 | synchronize_net(); | 423 | synchronize_net(); |
419 | 424 | ||
420 | ieee80211_vif_release_channel(sdata); | 425 | ieee80211_vif_release_channel(sdata); |
@@ -422,8 +427,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
422 | drv_remove_interface(local, sdata); | 427 | drv_remove_interface(local, sdata); |
423 | 428 | ||
424 | kfree(sdata); | 429 | kfree(sdata); |
425 | out_unlock: | ||
426 | mutex_unlock(&local->iflist_mtx); | ||
427 | } | 430 | } |
428 | 431 | ||
429 | /* | 432 | /* |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 5ac017f3fcd2..77b5710db241 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -1007,7 +1007,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | |||
1007 | 1007 | ||
1008 | rcu_read_lock(); | 1008 | rcu_read_lock(); |
1009 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 1009 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
1010 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1010 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1011 | ieee80211_sdata_running(sdata)) | ||
1011 | ieee80211_queue_work(&local->hw, &sdata->work); | 1012 | ieee80211_queue_work(&local->hw, &sdata->work); |
1012 | rcu_read_unlock(); | 1013 | rcu_read_unlock(); |
1013 | } | 1014 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fdc06e381c10..167158646593 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3527,8 +3527,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
3527 | 3527 | ||
3528 | /* Restart STA timers */ | 3528 | /* Restart STA timers */ |
3529 | rcu_read_lock(); | 3529 | rcu_read_lock(); |
3530 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 3530 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
3531 | ieee80211_restart_sta_timer(sdata); | 3531 | if (ieee80211_sdata_running(sdata)) |
3532 | ieee80211_restart_sta_timer(sdata); | ||
3533 | } | ||
3532 | rcu_read_unlock(); | 3534 | rcu_read_unlock(); |
3533 | } | 3535 | } |
3534 | 3536 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5b4492af4e85..2528b5a4d6d4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2666,7 +2666,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | |||
2666 | 2666 | ||
2667 | memset(nskb->cb, 0, sizeof(nskb->cb)); | 2667 | memset(nskb->cb, 0, sizeof(nskb->cb)); |
2668 | 2668 | ||
2669 | ieee80211_tx_skb(rx->sdata, nskb); | 2669 | if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { |
2670 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb); | ||
2671 | |||
2672 | info->flags = IEEE80211_TX_CTL_TX_OFFCHAN | | ||
2673 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK | | ||
2674 | IEEE80211_TX_CTL_NO_CCK_RATE; | ||
2675 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||
2676 | info->hw_queue = | ||
2677 | local->hw.offchannel_tx_hw_queue; | ||
2678 | } | ||
2679 | |||
2680 | __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, | ||
2681 | status->band); | ||
2670 | } | 2682 | } |
2671 | dev_kfree_skb(rx->skb); | 2683 | dev_kfree_skb(rx->skb); |
2672 | return RX_QUEUED; | 2684 | return RX_QUEUED; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 3644ad79688a..85458a28ffa0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -771,6 +771,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
771 | struct ieee80211_local *local; | 771 | struct ieee80211_local *local; |
772 | struct ieee80211_sub_if_data *sdata; | 772 | struct ieee80211_sub_if_data *sdata; |
773 | int ret, i; | 773 | int ret, i; |
774 | bool have_key = false; | ||
774 | 775 | ||
775 | might_sleep(); | 776 | might_sleep(); |
776 | 777 | ||
@@ -798,14 +799,22 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
798 | list_del_rcu(&sta->list); | 799 | list_del_rcu(&sta->list); |
799 | 800 | ||
800 | mutex_lock(&local->key_mtx); | 801 | mutex_lock(&local->key_mtx); |
801 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) | 802 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { |
802 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]), | 803 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]), |
803 | true); | 804 | true); |
804 | if (sta->ptk) | 805 | have_key = true; |
806 | } | ||
807 | if (sta->ptk) { | ||
805 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk), | 808 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk), |
806 | true); | 809 | true); |
810 | have_key = true; | ||
811 | } | ||
812 | |||
807 | mutex_unlock(&local->key_mtx); | 813 | mutex_unlock(&local->key_mtx); |
808 | 814 | ||
815 | if (!have_key) | ||
816 | synchronize_net(); | ||
817 | |||
809 | sta->dead = true; | 818 | sta->dead = true; |
810 | 819 | ||
811 | local->num_sta--; | 820 | local->num_sta--; |
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 4e606fcb2534..55786283a3df 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
@@ -195,7 +195,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
195 | flow->deficit = q->quantum; | 195 | flow->deficit = q->quantum; |
196 | flow->dropped = 0; | 196 | flow->dropped = 0; |
197 | } | 197 | } |
198 | if (++sch->q.qlen < sch->limit) | 198 | if (++sch->q.qlen <= sch->limit) |
199 | return NET_XMIT_SUCCESS; | 199 | return NET_XMIT_SUCCESS; |
200 | 200 | ||
201 | q->drop_overlimit++; | 201 | q->drop_overlimit++; |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index ffad48109a22..eac7e0ee23c1 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -904,7 +904,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate) | |||
904 | u64 mult; | 904 | u64 mult; |
905 | int shift; | 905 | int shift; |
906 | 906 | ||
907 | r->rate_bps = rate << 3; | 907 | r->rate_bps = (u64)rate << 3; |
908 | r->shift = 0; | 908 | r->shift = 0; |
909 | r->mult = 1; | 909 | r->mult = 1; |
910 | /* | 910 | /* |
diff --git a/net/wireless/core.c b/net/wireless/core.c index f382cae983ba..00be55530a32 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | |||
212 | rdev_rfkill_poll(rdev); | 212 | rdev_rfkill_poll(rdev); |
213 | } | 213 | } |
214 | 214 | ||
215 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||
216 | struct wireless_dev *wdev) | ||
217 | { | ||
218 | lockdep_assert_held(&rdev->devlist_mtx); | ||
219 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
220 | |||
221 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) | ||
222 | return; | ||
223 | |||
224 | if (!wdev->p2p_started) | ||
225 | return; | ||
226 | |||
227 | rdev_stop_p2p_device(rdev, wdev); | ||
228 | wdev->p2p_started = false; | ||
229 | |||
230 | rdev->opencount--; | ||
231 | |||
232 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { | ||
233 | bool busy = work_busy(&rdev->scan_done_wk); | ||
234 | |||
235 | /* | ||
236 | * If the work isn't pending or running (in which case it would | ||
237 | * be waiting for the lock we hold) the driver didn't properly | ||
238 | * cancel the scan when the interface was removed. In this case | ||
239 | * warn and leak the scan request object to not crash later. | ||
240 | */ | ||
241 | WARN_ON(!busy); | ||
242 | |||
243 | rdev->scan_req->aborted = true; | ||
244 | ___cfg80211_scan_done(rdev, !busy); | ||
245 | } | ||
246 | } | ||
247 | |||
215 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 248 | static int cfg80211_rfkill_set_block(void *data, bool blocked) |
216 | { | 249 | { |
217 | struct cfg80211_registered_device *rdev = data; | 250 | struct cfg80211_registered_device *rdev = data; |
@@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
221 | return 0; | 254 | return 0; |
222 | 255 | ||
223 | rtnl_lock(); | 256 | rtnl_lock(); |
224 | mutex_lock(&rdev->devlist_mtx); | 257 | |
258 | /* read-only iteration need not hold the devlist_mtx */ | ||
225 | 259 | ||
226 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 260 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
227 | if (wdev->netdev) { | 261 | if (wdev->netdev) { |
@@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
231 | /* otherwise, check iftype */ | 265 | /* otherwise, check iftype */ |
232 | switch (wdev->iftype) { | 266 | switch (wdev->iftype) { |
233 | case NL80211_IFTYPE_P2P_DEVICE: | 267 | case NL80211_IFTYPE_P2P_DEVICE: |
234 | if (!wdev->p2p_started) | 268 | /* but this requires it */ |
235 | break; | 269 | mutex_lock(&rdev->devlist_mtx); |
236 | rdev_stop_p2p_device(rdev, wdev); | 270 | mutex_lock(&rdev->sched_scan_mtx); |
237 | wdev->p2p_started = false; | 271 | cfg80211_stop_p2p_device(rdev, wdev); |
238 | rdev->opencount--; | 272 | mutex_unlock(&rdev->sched_scan_mtx); |
273 | mutex_unlock(&rdev->devlist_mtx); | ||
239 | break; | 274 | break; |
240 | default: | 275 | default: |
241 | break; | 276 | break; |
242 | } | 277 | } |
243 | } | 278 | } |
244 | 279 | ||
245 | mutex_unlock(&rdev->devlist_mtx); | ||
246 | rtnl_unlock(); | 280 | rtnl_unlock(); |
247 | 281 | ||
248 | return 0; | 282 | return 0; |
@@ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work) | |||
745 | wdev = container_of(work, struct wireless_dev, cleanup_work); | 779 | wdev = container_of(work, struct wireless_dev, cleanup_work); |
746 | rdev = wiphy_to_dev(wdev->wiphy); | 780 | rdev = wiphy_to_dev(wdev->wiphy); |
747 | 781 | ||
748 | cfg80211_lock_rdev(rdev); | 782 | mutex_lock(&rdev->sched_scan_mtx); |
749 | 783 | ||
750 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | 784 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { |
751 | rdev->scan_req->aborted = true; | 785 | rdev->scan_req->aborted = true; |
752 | ___cfg80211_scan_done(rdev, true); | 786 | ___cfg80211_scan_done(rdev, true); |
753 | } | 787 | } |
754 | 788 | ||
755 | cfg80211_unlock_rdev(rdev); | ||
756 | |||
757 | mutex_lock(&rdev->sched_scan_mtx); | ||
758 | |||
759 | if (WARN_ON(rdev->sched_scan_req && | 789 | if (WARN_ON(rdev->sched_scan_req && |
760 | rdev->sched_scan_req->dev == wdev->netdev)) { | 790 | rdev->sched_scan_req->dev == wdev->netdev)) { |
761 | __cfg80211_stop_sched_scan(rdev, false); | 791 | __cfg80211_stop_sched_scan(rdev, false); |
@@ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | |||
781 | return; | 811 | return; |
782 | 812 | ||
783 | mutex_lock(&rdev->devlist_mtx); | 813 | mutex_lock(&rdev->devlist_mtx); |
814 | mutex_lock(&rdev->sched_scan_mtx); | ||
784 | list_del_rcu(&wdev->list); | 815 | list_del_rcu(&wdev->list); |
785 | rdev->devlist_generation++; | 816 | rdev->devlist_generation++; |
786 | 817 | ||
787 | switch (wdev->iftype) { | 818 | switch (wdev->iftype) { |
788 | case NL80211_IFTYPE_P2P_DEVICE: | 819 | case NL80211_IFTYPE_P2P_DEVICE: |
789 | if (!wdev->p2p_started) | 820 | cfg80211_stop_p2p_device(rdev, wdev); |
790 | break; | ||
791 | rdev_stop_p2p_device(rdev, wdev); | ||
792 | wdev->p2p_started = false; | ||
793 | rdev->opencount--; | ||
794 | break; | 821 | break; |
795 | default: | 822 | default: |
796 | WARN_ON_ONCE(1); | 823 | WARN_ON_ONCE(1); |
797 | break; | 824 | break; |
798 | } | 825 | } |
826 | mutex_unlock(&rdev->sched_scan_mtx); | ||
799 | mutex_unlock(&rdev->devlist_mtx); | 827 | mutex_unlock(&rdev->devlist_mtx); |
800 | } | 828 | } |
801 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 829 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
@@ -945,6 +973,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
945 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); | 973 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); |
946 | cfg80211_lock_rdev(rdev); | 974 | cfg80211_lock_rdev(rdev); |
947 | mutex_lock(&rdev->devlist_mtx); | 975 | mutex_lock(&rdev->devlist_mtx); |
976 | mutex_lock(&rdev->sched_scan_mtx); | ||
948 | wdev_lock(wdev); | 977 | wdev_lock(wdev); |
949 | switch (wdev->iftype) { | 978 | switch (wdev->iftype) { |
950 | #ifdef CONFIG_CFG80211_WEXT | 979 | #ifdef CONFIG_CFG80211_WEXT |
@@ -976,6 +1005,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
976 | break; | 1005 | break; |
977 | } | 1006 | } |
978 | wdev_unlock(wdev); | 1007 | wdev_unlock(wdev); |
1008 | mutex_unlock(&rdev->sched_scan_mtx); | ||
979 | rdev->opencount++; | 1009 | rdev->opencount++; |
980 | mutex_unlock(&rdev->devlist_mtx); | 1010 | mutex_unlock(&rdev->devlist_mtx); |
981 | cfg80211_unlock_rdev(rdev); | 1011 | cfg80211_unlock_rdev(rdev); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index d5d06fdea961..b5174f65cc9a 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -500,9 +500,14 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
500 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 500 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
501 | enum nl80211_iftype iftype, int num); | 501 | enum nl80211_iftype iftype, int num); |
502 | 502 | ||
503 | |||
503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 504 | void cfg80211_leave(struct cfg80211_registered_device *rdev, |
504 | struct wireless_dev *wdev); | 505 | struct wireless_dev *wdev); |
505 | 506 | ||
507 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||
508 | struct wireless_dev *wdev); | ||
509 | |||
510 | |||
506 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 511 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
507 | 512 | ||
508 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 513 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f924d45af1b8..671b69a3c136 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5048,14 +5048,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5048 | if (!rdev->ops->scan) | 5048 | if (!rdev->ops->scan) |
5049 | return -EOPNOTSUPP; | 5049 | return -EOPNOTSUPP; |
5050 | 5050 | ||
5051 | if (rdev->scan_req) | 5051 | mutex_lock(&rdev->sched_scan_mtx); |
5052 | return -EBUSY; | 5052 | if (rdev->scan_req) { |
5053 | err = -EBUSY; | ||
5054 | goto unlock; | ||
5055 | } | ||
5053 | 5056 | ||
5054 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 5057 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
5055 | n_channels = validate_scan_freqs( | 5058 | n_channels = validate_scan_freqs( |
5056 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | 5059 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); |
5057 | if (!n_channels) | 5060 | if (!n_channels) { |
5058 | return -EINVAL; | 5061 | err = -EINVAL; |
5062 | goto unlock; | ||
5063 | } | ||
5059 | } else { | 5064 | } else { |
5060 | enum ieee80211_band band; | 5065 | enum ieee80211_band band; |
5061 | n_channels = 0; | 5066 | n_channels = 0; |
@@ -5069,23 +5074,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5069 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) | 5074 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) |
5070 | n_ssids++; | 5075 | n_ssids++; |
5071 | 5076 | ||
5072 | if (n_ssids > wiphy->max_scan_ssids) | 5077 | if (n_ssids > wiphy->max_scan_ssids) { |
5073 | return -EINVAL; | 5078 | err = -EINVAL; |
5079 | goto unlock; | ||
5080 | } | ||
5074 | 5081 | ||
5075 | if (info->attrs[NL80211_ATTR_IE]) | 5082 | if (info->attrs[NL80211_ATTR_IE]) |
5076 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 5083 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5077 | else | 5084 | else |
5078 | ie_len = 0; | 5085 | ie_len = 0; |
5079 | 5086 | ||
5080 | if (ie_len > wiphy->max_scan_ie_len) | 5087 | if (ie_len > wiphy->max_scan_ie_len) { |
5081 | return -EINVAL; | 5088 | err = -EINVAL; |
5089 | goto unlock; | ||
5090 | } | ||
5082 | 5091 | ||
5083 | request = kzalloc(sizeof(*request) | 5092 | request = kzalloc(sizeof(*request) |
5084 | + sizeof(*request->ssids) * n_ssids | 5093 | + sizeof(*request->ssids) * n_ssids |
5085 | + sizeof(*request->channels) * n_channels | 5094 | + sizeof(*request->channels) * n_channels |
5086 | + ie_len, GFP_KERNEL); | 5095 | + ie_len, GFP_KERNEL); |
5087 | if (!request) | 5096 | if (!request) { |
5088 | return -ENOMEM; | 5097 | err = -ENOMEM; |
5098 | goto unlock; | ||
5099 | } | ||
5089 | 5100 | ||
5090 | if (n_ssids) | 5101 | if (n_ssids) |
5091 | request->ssids = (void *)&request->channels[n_channels]; | 5102 | request->ssids = (void *)&request->channels[n_channels]; |
@@ -5222,6 +5233,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5222 | kfree(request); | 5233 | kfree(request); |
5223 | } | 5234 | } |
5224 | 5235 | ||
5236 | unlock: | ||
5237 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5225 | return err; | 5238 | return err; |
5226 | } | 5239 | } |
5227 | 5240 | ||
@@ -8130,20 +8143,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8130 | if (!rdev->ops->stop_p2p_device) | 8143 | if (!rdev->ops->stop_p2p_device) |
8131 | return -EOPNOTSUPP; | 8144 | return -EOPNOTSUPP; |
8132 | 8145 | ||
8133 | if (!wdev->p2p_started) | 8146 | mutex_lock(&rdev->sched_scan_mtx); |
8134 | return 0; | 8147 | cfg80211_stop_p2p_device(rdev, wdev); |
8135 | 8148 | mutex_unlock(&rdev->sched_scan_mtx); | |
8136 | rdev_stop_p2p_device(rdev, wdev); | ||
8137 | wdev->p2p_started = false; | ||
8138 | |||
8139 | mutex_lock(&rdev->devlist_mtx); | ||
8140 | rdev->opencount--; | ||
8141 | mutex_unlock(&rdev->devlist_mtx); | ||
8142 | |||
8143 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||
8144 | rdev->scan_req->aborted = true; | ||
8145 | ___cfg80211_scan_done(rdev, true); | ||
8146 | } | ||
8147 | 8149 | ||
8148 | return 0; | 8150 | return 0; |
8149 | } | 8151 | } |
@@ -8929,7 +8931,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
8929 | struct nlattr *nest; | 8931 | struct nlattr *nest; |
8930 | int i; | 8932 | int i; |
8931 | 8933 | ||
8932 | ASSERT_RDEV_LOCK(rdev); | 8934 | lockdep_assert_held(&rdev->sched_scan_mtx); |
8933 | 8935 | ||
8934 | if (WARN_ON(!req)) | 8936 | if (WARN_ON(!req)) |
8935 | return 0; | 8937 | return 0; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 674aadca0079..fd99ea495b7e 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | |||
169 | union iwreq_data wrqu; | 169 | union iwreq_data wrqu; |
170 | #endif | 170 | #endif |
171 | 171 | ||
172 | ASSERT_RDEV_LOCK(rdev); | 172 | lockdep_assert_held(&rdev->sched_scan_mtx); |
173 | 173 | ||
174 | request = rdev->scan_req; | 174 | request = rdev->scan_req; |
175 | 175 | ||
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
230 | rdev = container_of(wk, struct cfg80211_registered_device, | 230 | rdev = container_of(wk, struct cfg80211_registered_device, |
231 | scan_done_wk); | 231 | scan_done_wk); |
232 | 232 | ||
233 | cfg80211_lock_rdev(rdev); | 233 | mutex_lock(&rdev->sched_scan_mtx); |
234 | ___cfg80211_scan_done(rdev, false); | 234 | ___cfg80211_scan_done(rdev, false); |
235 | cfg80211_unlock_rdev(rdev); | 235 | mutex_unlock(&rdev->sched_scan_mtx); |
236 | } | 236 | } |
237 | 237 | ||
238 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | 238 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) |
@@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
698 | found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); | 698 | found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); |
699 | 699 | ||
700 | if (found) { | 700 | if (found) { |
701 | found->pub.beacon_interval = tmp->pub.beacon_interval; | ||
702 | found->pub.signal = tmp->pub.signal; | ||
703 | found->pub.capability = tmp->pub.capability; | ||
704 | found->ts = tmp->ts; | ||
705 | |||
706 | /* Update IEs */ | 701 | /* Update IEs */ |
707 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { | 702 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { |
708 | const struct cfg80211_bss_ies *old; | 703 | const struct cfg80211_bss_ies *old; |
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
723 | 718 | ||
724 | if (found->pub.hidden_beacon_bss && | 719 | if (found->pub.hidden_beacon_bss && |
725 | !list_empty(&found->hidden_list)) { | 720 | !list_empty(&found->hidden_list)) { |
721 | const struct cfg80211_bss_ies *f; | ||
722 | |||
726 | /* | 723 | /* |
727 | * The found BSS struct is one of the probe | 724 | * The found BSS struct is one of the probe |
728 | * response members of a group, but we're | 725 | * response members of a group, but we're |
@@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
732 | * SSID to showing it, which is confusing so | 729 | * SSID to showing it, which is confusing so |
733 | * drop this information. | 730 | * drop this information. |
734 | */ | 731 | */ |
732 | |||
733 | f = rcu_access_pointer(tmp->pub.beacon_ies); | ||
734 | kfree_rcu((struct cfg80211_bss_ies *)f, | ||
735 | rcu_head); | ||
735 | goto drop; | 736 | goto drop; |
736 | } | 737 | } |
737 | 738 | ||
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
761 | kfree_rcu((struct cfg80211_bss_ies *)old, | 762 | kfree_rcu((struct cfg80211_bss_ies *)old, |
762 | rcu_head); | 763 | rcu_head); |
763 | } | 764 | } |
765 | |||
766 | found->pub.beacon_interval = tmp->pub.beacon_interval; | ||
767 | found->pub.signal = tmp->pub.signal; | ||
768 | found->pub.capability = tmp->pub.capability; | ||
769 | found->ts = tmp->ts; | ||
764 | } else { | 770 | } else { |
765 | struct cfg80211_internal_bss *new; | 771 | struct cfg80211_internal_bss *new; |
766 | struct cfg80211_internal_bss *hidden; | 772 | struct cfg80211_internal_bss *hidden; |
@@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1056 | if (IS_ERR(rdev)) | 1062 | if (IS_ERR(rdev)) |
1057 | return PTR_ERR(rdev); | 1063 | return PTR_ERR(rdev); |
1058 | 1064 | ||
1065 | mutex_lock(&rdev->sched_scan_mtx); | ||
1059 | if (rdev->scan_req) { | 1066 | if (rdev->scan_req) { |
1060 | err = -EBUSY; | 1067 | err = -EBUSY; |
1061 | goto out; | 1068 | goto out; |
@@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1162 | dev_hold(dev); | 1169 | dev_hold(dev); |
1163 | } | 1170 | } |
1164 | out: | 1171 | out: |
1172 | mutex_unlock(&rdev->sched_scan_mtx); | ||
1165 | kfree(creq); | 1173 | kfree(creq); |
1166 | cfg80211_unlock_rdev(rdev); | 1174 | cfg80211_unlock_rdev(rdev); |
1167 | return err; | 1175 | return err; |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index bad4c4b5e4eb..ff6f7ae35586 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
85 | ASSERT_RTNL(); | 85 | ASSERT_RTNL(); |
86 | ASSERT_RDEV_LOCK(rdev); | 86 | ASSERT_RDEV_LOCK(rdev); |
87 | ASSERT_WDEV_LOCK(wdev); | 87 | ASSERT_WDEV_LOCK(wdev); |
88 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
88 | 89 | ||
89 | if (rdev->scan_req) | 90 | if (rdev->scan_req) |
90 | return -EBUSY; | 91 | return -EBUSY; |
@@ -324,11 +325,9 @@ void cfg80211_sme_scan_done(struct net_device *dev) | |||
324 | { | 325 | { |
325 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 326 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
326 | 327 | ||
327 | mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
328 | wdev_lock(wdev); | 328 | wdev_lock(wdev); |
329 | __cfg80211_sme_scan_done(dev); | 329 | __cfg80211_sme_scan_done(dev); |
330 | wdev_unlock(wdev); | 330 | wdev_unlock(wdev); |
331 | mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
332 | } | 331 | } |
333 | 332 | ||
334 | void cfg80211_sme_rx_auth(struct net_device *dev, | 333 | void cfg80211_sme_rx_auth(struct net_device *dev, |
@@ -928,9 +927,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
928 | int err; | 927 | int err; |
929 | 928 | ||
930 | mutex_lock(&rdev->devlist_mtx); | 929 | mutex_lock(&rdev->devlist_mtx); |
930 | /* might request scan - scan_mtx -> wdev_mtx dependency */ | ||
931 | mutex_lock(&rdev->sched_scan_mtx); | ||
931 | wdev_lock(dev->ieee80211_ptr); | 932 | wdev_lock(dev->ieee80211_ptr); |
932 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); | 933 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); |
933 | wdev_unlock(dev->ieee80211_ptr); | 934 | wdev_unlock(dev->ieee80211_ptr); |
935 | mutex_unlock(&rdev->sched_scan_mtx); | ||
934 | mutex_unlock(&rdev->devlist_mtx); | 936 | mutex_unlock(&rdev->devlist_mtx); |
935 | 937 | ||
936 | return err; | 938 | return err; |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ccadef2106ac..3c2033b8f596 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -27,7 +27,8 @@ | |||
27 | #define WIPHY_PR_ARG __entry->wiphy_name | 27 | #define WIPHY_PR_ARG __entry->wiphy_name |
28 | 28 | ||
29 | #define WDEV_ENTRY __field(u32, id) | 29 | #define WDEV_ENTRY __field(u32, id) |
30 | #define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0) | 30 | #define WDEV_ASSIGN (__entry->id) = (!IS_ERR_OR_NULL(wdev) \ |
31 | ? wdev->identifier : 0) | ||
31 | #define WDEV_PR_FMT "wdev(%u)" | 32 | #define WDEV_PR_FMT "wdev(%u)" |
32 | #define WDEV_PR_ARG (__entry->id) | 33 | #define WDEV_PR_ARG (__entry->id) |
33 | 34 | ||
@@ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl, | |||
1778 | ), | 1779 | ), |
1779 | TP_fast_assign( | 1780 | TP_fast_assign( |
1780 | WIPHY_ASSIGN; | 1781 | WIPHY_ASSIGN; |
1781 | WIPHY_ASSIGN; | 1782 | NETDEV_ASSIGN; |
1782 | __entry->acl_policy = params->acl_policy; | 1783 | __entry->acl_policy = params->acl_policy; |
1783 | ), | 1784 | ), |
1784 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d", | 1785 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d", |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index fb9622f6d99c..e79cb5c0655a 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
89 | 89 | ||
90 | cfg80211_lock_rdev(rdev); | 90 | cfg80211_lock_rdev(rdev); |
91 | mutex_lock(&rdev->devlist_mtx); | 91 | mutex_lock(&rdev->devlist_mtx); |
92 | mutex_lock(&rdev->sched_scan_mtx); | ||
92 | wdev_lock(wdev); | 93 | wdev_lock(wdev); |
93 | 94 | ||
94 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 95 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
@@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
135 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 136 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
136 | out: | 137 | out: |
137 | wdev_unlock(wdev); | 138 | wdev_unlock(wdev); |
139 | mutex_unlock(&rdev->sched_scan_mtx); | ||
138 | mutex_unlock(&rdev->devlist_mtx); | 140 | mutex_unlock(&rdev->devlist_mtx); |
139 | cfg80211_unlock_rdev(rdev); | 141 | cfg80211_unlock_rdev(rdev); |
140 | return err; | 142 | return err; |
@@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
190 | 192 | ||
191 | cfg80211_lock_rdev(rdev); | 193 | cfg80211_lock_rdev(rdev); |
192 | mutex_lock(&rdev->devlist_mtx); | 194 | mutex_lock(&rdev->devlist_mtx); |
195 | mutex_lock(&rdev->sched_scan_mtx); | ||
193 | wdev_lock(wdev); | 196 | wdev_lock(wdev); |
194 | 197 | ||
195 | err = 0; | 198 | err = 0; |
@@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
223 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 226 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
224 | out: | 227 | out: |
225 | wdev_unlock(wdev); | 228 | wdev_unlock(wdev); |
229 | mutex_unlock(&rdev->sched_scan_mtx); | ||
226 | mutex_unlock(&rdev->devlist_mtx); | 230 | mutex_unlock(&rdev->devlist_mtx); |
227 | cfg80211_unlock_rdev(rdev); | 231 | cfg80211_unlock_rdev(rdev); |
228 | return err; | 232 | return err; |
@@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
285 | 289 | ||
286 | cfg80211_lock_rdev(rdev); | 290 | cfg80211_lock_rdev(rdev); |
287 | mutex_lock(&rdev->devlist_mtx); | 291 | mutex_lock(&rdev->devlist_mtx); |
292 | mutex_lock(&rdev->sched_scan_mtx); | ||
288 | wdev_lock(wdev); | 293 | wdev_lock(wdev); |
289 | 294 | ||
290 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 295 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
@@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
313 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 318 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
314 | out: | 319 | out: |
315 | wdev_unlock(wdev); | 320 | wdev_unlock(wdev); |
321 | mutex_unlock(&rdev->sched_scan_mtx); | ||
316 | mutex_unlock(&rdev->devlist_mtx); | 322 | mutex_unlock(&rdev->devlist_mtx); |
317 | cfg80211_unlock_rdev(rdev); | 323 | cfg80211_unlock_rdev(rdev); |
318 | return err; | 324 | return err; |
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 35754cc8a9e5..8dafe6d3c6e4 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
@@ -334,6 +334,70 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event) | |||
334 | x->xflags &= ~XFRM_TIME_DEFER; | 334 | x->xflags &= ~XFRM_TIME_DEFER; |
335 | } | 335 | } |
336 | 336 | ||
337 | static void xfrm_replay_notify_esn(struct xfrm_state *x, int event) | ||
338 | { | ||
339 | u32 seq_diff, oseq_diff; | ||
340 | struct km_event c; | ||
341 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | ||
342 | struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn; | ||
343 | |||
344 | /* we send notify messages in case | ||
345 | * 1. we updated on of the sequence numbers, and the seqno difference | ||
346 | * is at least x->replay_maxdiff, in this case we also update the | ||
347 | * timeout of our timer function | ||
348 | * 2. if x->replay_maxage has elapsed since last update, | ||
349 | * and there were changes | ||
350 | * | ||
351 | * The state structure must be locked! | ||
352 | */ | ||
353 | |||
354 | switch (event) { | ||
355 | case XFRM_REPLAY_UPDATE: | ||
356 | if (!x->replay_maxdiff) | ||
357 | break; | ||
358 | |||
359 | if (replay_esn->seq_hi == preplay_esn->seq_hi) | ||
360 | seq_diff = replay_esn->seq - preplay_esn->seq; | ||
361 | else | ||
362 | seq_diff = ~preplay_esn->seq + replay_esn->seq + 1; | ||
363 | |||
364 | if (replay_esn->oseq_hi == preplay_esn->oseq_hi) | ||
365 | oseq_diff = replay_esn->oseq - preplay_esn->oseq; | ||
366 | else | ||
367 | oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1; | ||
368 | |||
369 | if (seq_diff < x->replay_maxdiff && | ||
370 | oseq_diff < x->replay_maxdiff) { | ||
371 | |||
372 | if (x->xflags & XFRM_TIME_DEFER) | ||
373 | event = XFRM_REPLAY_TIMEOUT; | ||
374 | else | ||
375 | return; | ||
376 | } | ||
377 | |||
378 | break; | ||
379 | |||
380 | case XFRM_REPLAY_TIMEOUT: | ||
381 | if (memcmp(x->replay_esn, x->preplay_esn, | ||
382 | xfrm_replay_state_esn_len(replay_esn)) == 0) { | ||
383 | x->xflags |= XFRM_TIME_DEFER; | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | break; | ||
388 | } | ||
389 | |||
390 | memcpy(x->preplay_esn, x->replay_esn, | ||
391 | xfrm_replay_state_esn_len(replay_esn)); | ||
392 | c.event = XFRM_MSG_NEWAE; | ||
393 | c.data.aevent = event; | ||
394 | km_state_notify(x, &c); | ||
395 | |||
396 | if (x->replay_maxage && | ||
397 | !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) | ||
398 | x->xflags &= ~XFRM_TIME_DEFER; | ||
399 | } | ||
400 | |||
337 | static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb) | 401 | static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb) |
338 | { | 402 | { |
339 | int err = 0; | 403 | int err = 0; |
@@ -510,7 +574,7 @@ static struct xfrm_replay xfrm_replay_esn = { | |||
510 | .advance = xfrm_replay_advance_esn, | 574 | .advance = xfrm_replay_advance_esn, |
511 | .check = xfrm_replay_check_esn, | 575 | .check = xfrm_replay_check_esn, |
512 | .recheck = xfrm_replay_recheck_esn, | 576 | .recheck = xfrm_replay_recheck_esn, |
513 | .notify = xfrm_replay_notify_bmp, | 577 | .notify = xfrm_replay_notify_esn, |
514 | .overflow = xfrm_replay_overflow_esn, | 578 | .overflow = xfrm_replay_overflow_esn, |
515 | }; | 579 | }; |
516 | 580 | ||