diff options
author | Luciano Coelho <coelho@ti.com> | 2011-05-12 09:28:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-05-12 14:10:55 -0400 |
commit | 85a9994a0a6cba1a6cc6af4bd3ebd85f778be0fe (patch) | |
tree | e9dd8fff75d9c0ee2f5aec129bb6132499c72461 /net/wireless | |
parent | a3836e02ba4c50db958d32d710b226f2408623dc (diff) |
cfg80211/mac80211: avoid bounce back mac->cfg->mac on sched_scan_stopped
When sched_scan_stopped was called by the driver, mac80211 calls
cfg80211, which in turn was calling mac80211 back with a flag
"driver_initiated". This flag was used so that mac80211 would do the
necessary cleanup but would not call the driver. This was enough to
prevent the bounce back between the driver and mac80211, but not
between mac80211 and cfg80211.
To fix this, we now do the cleanup in mac80211 before calling
cfg80211. To help with locking issues, the workqueue was moved from
cfg80211 to mac80211.
Reported-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 1 | ||||
-rw-r--r-- | net/wireless/core.h | 2 | ||||
-rw-r--r-- | net/wireless/scan.c | 21 |
3 files changed, 7 insertions, 17 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index e2ab65d7c86d..18b002f16860 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -371,7 +371,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
371 | INIT_LIST_HEAD(&rdev->bss_list); | 371 | INIT_LIST_HEAD(&rdev->bss_list); |
372 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); | 372 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); |
373 | INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); | 373 | INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); |
374 | INIT_WORK(&rdev->sched_scan_stopped_wk, __cfg80211_sched_scan_stopped); | ||
375 | #ifdef CONFIG_CFG80211_WEXT | 374 | #ifdef CONFIG_CFG80211_WEXT |
376 | rdev->wiphy.wext = &cfg80211_wext_handler; | 375 | rdev->wiphy.wext = &cfg80211_wext_handler; |
377 | #endif | 376 | #endif |
diff --git a/net/wireless/core.h b/net/wireless/core.h index fd9135f9b5be..d4b8f4c0bbbb 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -64,7 +64,6 @@ struct cfg80211_registered_device { | |||
64 | unsigned long suspend_at; | 64 | unsigned long suspend_at; |
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 | struct work_struct sched_scan_stopped_wk; | ||
68 | 67 | ||
69 | #ifdef CONFIG_NL80211_TESTMODE | 68 | #ifdef CONFIG_NL80211_TESTMODE |
70 | struct genl_info *testmode_info; | 69 | struct genl_info *testmode_info; |
@@ -417,7 +416,6 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); | |||
417 | void __cfg80211_sched_scan_results(struct work_struct *wk); | 416 | void __cfg80211_sched_scan_results(struct work_struct *wk); |
418 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 417 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, |
419 | bool driver_initiated); | 418 | bool driver_initiated); |
420 | void __cfg80211_sched_scan_stopped(struct work_struct *wk); | ||
421 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); | 419 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); |
422 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | 420 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, |
423 | struct net_device *dev, enum nl80211_iftype ntype, | 421 | struct net_device *dev, enum nl80211_iftype ntype, |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 65dfae3b9d41..73a441d237b5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -119,22 +119,14 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy) | |||
119 | } | 119 | } |
120 | EXPORT_SYMBOL(cfg80211_sched_scan_results); | 120 | EXPORT_SYMBOL(cfg80211_sched_scan_results); |
121 | 121 | ||
122 | void __cfg80211_sched_scan_stopped(struct work_struct *wk) | 122 | void cfg80211_sched_scan_stopped(struct wiphy *wiphy) |
123 | { | 123 | { |
124 | struct cfg80211_registered_device *rdev; | 124 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
125 | |||
126 | rdev = container_of(wk, struct cfg80211_registered_device, | ||
127 | sched_scan_stopped_wk); | ||
128 | 125 | ||
129 | cfg80211_lock_rdev(rdev); | 126 | cfg80211_lock_rdev(rdev); |
130 | __cfg80211_stop_sched_scan(rdev, true); | 127 | __cfg80211_stop_sched_scan(rdev, true); |
131 | cfg80211_unlock_rdev(rdev); | 128 | cfg80211_unlock_rdev(rdev); |
132 | } | 129 | } |
133 | |||
134 | void cfg80211_sched_scan_stopped(struct wiphy *wiphy) | ||
135 | { | ||
136 | queue_work(cfg80211_wq, &wiphy_to_dev(wiphy)->sched_scan_stopped_wk); | ||
137 | } | ||
138 | EXPORT_SYMBOL(cfg80211_sched_scan_stopped); | 130 | EXPORT_SYMBOL(cfg80211_sched_scan_stopped); |
139 | 131 | ||
140 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 132 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, |
@@ -150,10 +142,11 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | |||
150 | 142 | ||
151 | dev = rdev->sched_scan_req->dev; | 143 | dev = rdev->sched_scan_req->dev; |
152 | 144 | ||
153 | err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev, | 145 | if (!driver_initiated) { |
154 | driver_initiated); | 146 | err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev); |
155 | if (err) | 147 | if (err) |
156 | return err; | 148 | return err; |
149 | } | ||
157 | 150 | ||
158 | nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); | 151 | nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); |
159 | 152 | ||