aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-14 10:56:40 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-14 10:56:40 -0400
commit6a7ebdf2fd15417e87b4fd02ff411aeaca34da5f (patch)
tree86b15d8cd3e25c97b348b5a61bdb16c02726a480 /net/wireless
parentf6b72b6217f8c24f2a54988e58af858b4e66024d (diff)
parent51414d41084496aaefd06d7f19eb8206e8bfac2d (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: net/bluetooth/l2cap_core.c
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c12
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/nl80211.c24
-rw-r--r--net/wireless/scan.c10
4 files changed, 34 insertions, 14 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c22ef3492ee6..880dbe2e6f94 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -366,6 +366,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
366 366
367 mutex_init(&rdev->mtx); 367 mutex_init(&rdev->mtx);
368 mutex_init(&rdev->devlist_mtx); 368 mutex_init(&rdev->devlist_mtx);
369 mutex_init(&rdev->sched_scan_mtx);
369 INIT_LIST_HEAD(&rdev->netdev_list); 370 INIT_LIST_HEAD(&rdev->netdev_list);
370 spin_lock_init(&rdev->bss_lock); 371 spin_lock_init(&rdev->bss_lock);
371 INIT_LIST_HEAD(&rdev->bss_list); 372 INIT_LIST_HEAD(&rdev->bss_list);
@@ -701,6 +702,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
701 rfkill_destroy(rdev->rfkill); 702 rfkill_destroy(rdev->rfkill);
702 mutex_destroy(&rdev->mtx); 703 mutex_destroy(&rdev->mtx);
703 mutex_destroy(&rdev->devlist_mtx); 704 mutex_destroy(&rdev->devlist_mtx);
705 mutex_destroy(&rdev->sched_scan_mtx);
704 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) 706 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
705 cfg80211_put_bss(&scan->pub); 707 cfg80211_put_bss(&scan->pub);
706 cfg80211_rdev_free_wowlan(rdev); 708 cfg80211_rdev_free_wowlan(rdev);
@@ -737,12 +739,16 @@ static void wdev_cleanup_work(struct work_struct *work)
737 ___cfg80211_scan_done(rdev, true); 739 ___cfg80211_scan_done(rdev, true);
738 } 740 }
739 741
742 cfg80211_unlock_rdev(rdev);
743
744 mutex_lock(&rdev->sched_scan_mtx);
745
740 if (WARN_ON(rdev->sched_scan_req && 746 if (WARN_ON(rdev->sched_scan_req &&
741 rdev->sched_scan_req->dev == wdev->netdev)) { 747 rdev->sched_scan_req->dev == wdev->netdev)) {
742 __cfg80211_stop_sched_scan(rdev, false); 748 __cfg80211_stop_sched_scan(rdev, false);
743 } 749 }
744 750
745 cfg80211_unlock_rdev(rdev); 751 mutex_unlock(&rdev->sched_scan_mtx);
746 752
747 mutex_lock(&rdev->devlist_mtx); 753 mutex_lock(&rdev->devlist_mtx);
748 rdev->opencount--; 754 rdev->opencount--;
@@ -830,9 +836,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
830 break; 836 break;
831 case NL80211_IFTYPE_P2P_CLIENT: 837 case NL80211_IFTYPE_P2P_CLIENT:
832 case NL80211_IFTYPE_STATION: 838 case NL80211_IFTYPE_STATION:
833 cfg80211_lock_rdev(rdev); 839 mutex_lock(&rdev->sched_scan_mtx);
834 __cfg80211_stop_sched_scan(rdev, false); 840 __cfg80211_stop_sched_scan(rdev, false);
835 cfg80211_unlock_rdev(rdev); 841 mutex_unlock(&rdev->sched_scan_mtx);
836 842
837 wdev_lock(wdev); 843 wdev_lock(wdev);
838#ifdef CONFIG_CFG80211_WEXT 844#ifdef CONFIG_CFG80211_WEXT
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3dce1f167eba..a570ff9214ec 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -65,6 +65,8 @@ struct cfg80211_registered_device {
65 struct work_struct scan_done_wk; 65 struct work_struct scan_done_wk;
66 struct work_struct sched_scan_results_wk; 66 struct work_struct sched_scan_results_wk;
67 67
68 struct mutex sched_scan_mtx;
69
68#ifdef CONFIG_NL80211_TESTMODE 70#ifdef CONFIG_NL80211_TESTMODE
69 struct genl_info *testmode_info; 71 struct genl_info *testmode_info;
70#endif 72#endif
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 491b0ba40c43..6a82c898f831 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3470,9 +3470,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3470 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3470 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3471 return -EINVAL; 3471 return -EINVAL;
3472 3472
3473 if (rdev->sched_scan_req)
3474 return -EINPROGRESS;
3475
3476 if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) 3473 if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
3477 return -EINVAL; 3474 return -EINVAL;
3478 3475
@@ -3511,12 +3508,21 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3511 if (ie_len > wiphy->max_scan_ie_len) 3508 if (ie_len > wiphy->max_scan_ie_len)
3512 return -EINVAL; 3509 return -EINVAL;
3513 3510
3511 mutex_lock(&rdev->sched_scan_mtx);
3512
3513 if (rdev->sched_scan_req) {
3514 err = -EINPROGRESS;
3515 goto out;
3516 }
3517
3514 request = kzalloc(sizeof(*request) 3518 request = kzalloc(sizeof(*request)
3515 + sizeof(*request->ssids) * n_ssids 3519 + sizeof(*request->ssids) * n_ssids
3516 + sizeof(*request->channels) * n_channels 3520 + sizeof(*request->channels) * n_channels
3517 + ie_len, GFP_KERNEL); 3521 + ie_len, GFP_KERNEL);
3518 if (!request) 3522 if (!request) {
3519 return -ENOMEM; 3523 err = -ENOMEM;
3524 goto out;
3525 }
3520 3526
3521 if (n_ssids) 3527 if (n_ssids)
3522 request->ssids = (void *)&request->channels[n_channels]; 3528 request->ssids = (void *)&request->channels[n_channels];
@@ -3614,6 +3620,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3614out_free: 3620out_free:
3615 kfree(request); 3621 kfree(request);
3616out: 3622out:
3623 mutex_unlock(&rdev->sched_scan_mtx);
3617 return err; 3624 return err;
3618} 3625}
3619 3626
@@ -3621,12 +3628,17 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
3621 struct genl_info *info) 3628 struct genl_info *info)
3622{ 3629{
3623 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 3630 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3631 int err;
3624 3632
3625 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || 3633 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
3626 !rdev->ops->sched_scan_stop) 3634 !rdev->ops->sched_scan_stop)
3627 return -EOPNOTSUPP; 3635 return -EOPNOTSUPP;
3628 3636
3629 return __cfg80211_stop_sched_scan(rdev, false); 3637 mutex_lock(&rdev->sched_scan_mtx);
3638 err = __cfg80211_stop_sched_scan(rdev, false);
3639 mutex_unlock(&rdev->sched_scan_mtx);
3640
3641 return err;
3630} 3642}
3631 3643
3632static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, 3644static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 5d23503dd5e0..2cc9d4ab5578 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -100,14 +100,14 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
100 rdev = container_of(wk, struct cfg80211_registered_device, 100 rdev = container_of(wk, struct cfg80211_registered_device,
101 sched_scan_results_wk); 101 sched_scan_results_wk);
102 102
103 cfg80211_lock_rdev(rdev); 103 mutex_lock(&rdev->sched_scan_mtx);
104 104
105 /* we don't have sched_scan_req anymore if the scan is stopping */ 105 /* we don't have sched_scan_req anymore if the scan is stopping */
106 if (rdev->sched_scan_req) 106 if (rdev->sched_scan_req)
107 nl80211_send_sched_scan_results(rdev, 107 nl80211_send_sched_scan_results(rdev,
108 rdev->sched_scan_req->dev); 108 rdev->sched_scan_req->dev);
109 109
110 cfg80211_unlock_rdev(rdev); 110 mutex_unlock(&rdev->sched_scan_mtx);
111} 111}
112 112
113void cfg80211_sched_scan_results(struct wiphy *wiphy) 113void cfg80211_sched_scan_results(struct wiphy *wiphy)
@@ -123,9 +123,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
123{ 123{
124 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 124 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
125 125
126 cfg80211_lock_rdev(rdev); 126 mutex_lock(&rdev->sched_scan_mtx);
127 __cfg80211_stop_sched_scan(rdev, true); 127 __cfg80211_stop_sched_scan(rdev, true);
128 cfg80211_unlock_rdev(rdev); 128 mutex_unlock(&rdev->sched_scan_mtx);
129} 129}
130EXPORT_SYMBOL(cfg80211_sched_scan_stopped); 130EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
131 131
@@ -134,7 +134,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
134{ 134{
135 struct net_device *dev; 135 struct net_device *dev;
136 136
137 ASSERT_RDEV_LOCK(rdev); 137 lockdep_assert_held(&rdev->sched_scan_mtx);
138 138
139 if (!rdev->sched_scan_req) 139 if (!rdev->sched_scan_req)
140 return 0; 140 return 0;