aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorLuciano Coelho <coelho@ti.com>2011-05-11 10:09:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-11 15:12:26 -0400
commit807f8a8c300435d5483e8d78df9dcdbc27333166 (patch)
tree1537d40e149d7a8712fe63d17ea3b51093bf03a1 /net/wireless/scan.c
parent6bdbdbf4a151a3a1333818cd17a7d7795e936041 (diff)
cfg80211/nl80211: add support for scheduled scans
Implement new functionality for scheduled scan offload. With this feature we can scan automatically at certain intervals. The idea is that the hardware can perform scan automatically and filter on desired results without waking up the host unnecessarily. Add NL80211_CMD_START_SCHED_SCAN and NL80211_CMD_STOP_SCHED_SCAN commands to the nl80211 interface. When results are available they are reported by NL80211_CMD_SCHED_SCAN_RESULTS events. The userspace is informed when the scheduled scan has stopped with a NL80211_CMD_SCHED_SCAN_STOPPED event, which can be triggered either by the driver or by a call to NL80211_CMD_STOP_SCHED_SCAN. Signed-off-by: Luciano Coelho <coelho@ti.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 62e542a2b192..65dfae3b9d41 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -93,6 +93,76 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
93} 93}
94EXPORT_SYMBOL(cfg80211_scan_done); 94EXPORT_SYMBOL(cfg80211_scan_done);
95 95
96void __cfg80211_sched_scan_results(struct work_struct *wk)
97{
98 struct cfg80211_registered_device *rdev;
99
100 rdev = container_of(wk, struct cfg80211_registered_device,
101 sched_scan_results_wk);
102
103 cfg80211_lock_rdev(rdev);
104
105 /* we don't have sched_scan_req anymore if the scan is stopping */
106 if (rdev->sched_scan_req)
107 nl80211_send_sched_scan_results(rdev,
108 rdev->sched_scan_req->dev);
109
110 cfg80211_unlock_rdev(rdev);
111}
112
113void cfg80211_sched_scan_results(struct wiphy *wiphy)
114{
115 /* ignore if we're not scanning */
116 if (wiphy_to_dev(wiphy)->sched_scan_req)
117 queue_work(cfg80211_wq,
118 &wiphy_to_dev(wiphy)->sched_scan_results_wk);
119}
120EXPORT_SYMBOL(cfg80211_sched_scan_results);
121
122void __cfg80211_sched_scan_stopped(struct work_struct *wk)
123{
124 struct cfg80211_registered_device *rdev;
125
126 rdev = container_of(wk, struct cfg80211_registered_device,
127 sched_scan_stopped_wk);
128
129 cfg80211_lock_rdev(rdev);
130 __cfg80211_stop_sched_scan(rdev, true);
131 cfg80211_unlock_rdev(rdev);
132}
133
134void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
135{
136 queue_work(cfg80211_wq, &wiphy_to_dev(wiphy)->sched_scan_stopped_wk);
137}
138EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
139
140int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
141 bool driver_initiated)
142{
143 int err;
144 struct net_device *dev;
145
146 ASSERT_RDEV_LOCK(rdev);
147
148 if (!rdev->sched_scan_req)
149 return 0;
150
151 dev = rdev->sched_scan_req->dev;
152
153 err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev,
154 driver_initiated);
155 if (err)
156 return err;
157
158 nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);
159
160 kfree(rdev->sched_scan_req);
161 rdev->sched_scan_req = NULL;
162
163 return err;
164}
165
96static void bss_release(struct kref *ref) 166static void bss_release(struct kref *ref)
97{ 167{
98 struct cfg80211_internal_bss *bss; 168 struct cfg80211_internal_bss *bss;