diff options
author | Luciano Coelho <coelho@ti.com> | 2011-05-10 07:46:02 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-05-12 17:06:33 -0400 |
commit | 33c2c06cd2d766387cf919d0afd432cc5796c369 (patch) | |
tree | 6a3dd1f574fba9841bb9feeb3067b6fab5b819bb /drivers/net | |
parent | 95feadca6dca909ae0f6e65665b782c7ca9d5122 (diff) |
wl12xx: implement scheduled scan driver operations and reporting
This patch adds the mac80211 operations for scheduled scan and the
scheduled scan results reporting.
Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/wl12xx/event.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 70 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/scan.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 2 |
4 files changed, 83 insertions, 1 deletions
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index dc110e8a618..1e4bd6a2c39 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -191,11 +191,17 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
191 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { | 191 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { |
192 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " | 192 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " |
193 | "(status 0x%0x)", mbox->scheduled_scan_status); | 193 | "(status 0x%0x)", mbox->scheduled_scan_status); |
194 | |||
195 | wl1271_scan_sched_scan_results(wl); | ||
194 | } | 196 | } |
195 | 197 | ||
196 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { | 198 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { |
197 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " | 199 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " |
198 | "(status 0x%0x)", mbox->scheduled_scan_status); | 200 | "(status 0x%0x)", mbox->scheduled_scan_status); |
201 | if (wl->sched_scanning) { | ||
202 | wl1271_scan_sched_scan_stop(wl); | ||
203 | ieee80211_sched_scan_stopped(wl->hw); | ||
204 | } | ||
199 | } | 205 | } |
200 | 206 | ||
201 | /* disable dynamic PS when requested by the firmware */ | 207 | /* disable dynamic PS when requested by the firmware */ |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 88d2e9052a0..a14a035aa44 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -988,6 +988,11 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
988 | /* Prevent spurious TX during FW restart */ | 988 | /* Prevent spurious TX during FW restart */ |
989 | ieee80211_stop_queues(wl->hw); | 989 | ieee80211_stop_queues(wl->hw); |
990 | 990 | ||
991 | if (wl->sched_scanning) { | ||
992 | ieee80211_sched_scan_stopped(wl->hw); | ||
993 | wl->sched_scanning = false; | ||
994 | } | ||
995 | |||
991 | /* reboot the chipset */ | 996 | /* reboot the chipset */ |
992 | __wl1271_op_remove_interface(wl, false); | 997 | __wl1271_op_remove_interface(wl, false); |
993 | ieee80211_restart_hw(wl->hw); | 998 | ieee80211_restart_hw(wl->hw); |
@@ -1576,6 +1581,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
1576 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | 1581 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); |
1577 | wl->ap_fw_ps_map = 0; | 1582 | wl->ap_fw_ps_map = 0; |
1578 | wl->ap_ps_map = 0; | 1583 | wl->ap_ps_map = 0; |
1584 | wl->sched_scanning = false; | ||
1579 | 1585 | ||
1580 | /* | 1586 | /* |
1581 | * this is performed after the cancel_work calls and the associated | 1587 | * this is performed after the cancel_work calls and the associated |
@@ -1778,6 +1784,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) | |||
1778 | wl->session_counter++; | 1784 | wl->session_counter++; |
1779 | if (wl->session_counter >= SESSION_COUNTER_MAX) | 1785 | if (wl->session_counter >= SESSION_COUNTER_MAX) |
1780 | wl->session_counter = 0; | 1786 | wl->session_counter = 0; |
1787 | |||
1788 | /* The current firmware only supports sched_scan in idle */ | ||
1789 | if (wl->sched_scanning) { | ||
1790 | wl1271_scan_sched_scan_stop(wl); | ||
1791 | ieee80211_sched_scan_stopped(wl->hw); | ||
1792 | } | ||
1793 | |||
1781 | ret = wl1271_dummy_join(wl); | 1794 | ret = wl1271_dummy_join(wl); |
1782 | if (ret < 0) | 1795 | if (ret < 0) |
1783 | goto out; | 1796 | goto out; |
@@ -2330,6 +2343,60 @@ out: | |||
2330 | return ret; | 2343 | return ret; |
2331 | } | 2344 | } |
2332 | 2345 | ||
2346 | static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | ||
2347 | struct ieee80211_vif *vif, | ||
2348 | struct cfg80211_sched_scan_request *req, | ||
2349 | struct ieee80211_sched_scan_ies *ies) | ||
2350 | { | ||
2351 | struct wl1271 *wl = hw->priv; | ||
2352 | int ret; | ||
2353 | |||
2354 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); | ||
2355 | |||
2356 | mutex_lock(&wl->mutex); | ||
2357 | |||
2358 | ret = wl1271_ps_elp_wakeup(wl); | ||
2359 | if (ret < 0) | ||
2360 | goto out; | ||
2361 | |||
2362 | ret = wl1271_scan_sched_scan_config(wl, req, ies); | ||
2363 | if (ret < 0) | ||
2364 | goto out_sleep; | ||
2365 | |||
2366 | ret = wl1271_scan_sched_scan_start(wl); | ||
2367 | if (ret < 0) | ||
2368 | goto out_sleep; | ||
2369 | |||
2370 | wl->sched_scanning = true; | ||
2371 | |||
2372 | out_sleep: | ||
2373 | wl1271_ps_elp_sleep(wl); | ||
2374 | out: | ||
2375 | mutex_unlock(&wl->mutex); | ||
2376 | return ret; | ||
2377 | } | ||
2378 | |||
2379 | static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | ||
2380 | struct ieee80211_vif *vif) | ||
2381 | { | ||
2382 | struct wl1271 *wl = hw->priv; | ||
2383 | int ret; | ||
2384 | |||
2385 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); | ||
2386 | |||
2387 | mutex_lock(&wl->mutex); | ||
2388 | |||
2389 | ret = wl1271_ps_elp_wakeup(wl); | ||
2390 | if (ret < 0) | ||
2391 | goto out; | ||
2392 | |||
2393 | wl1271_scan_sched_scan_stop(wl); | ||
2394 | |||
2395 | wl1271_ps_elp_sleep(wl); | ||
2396 | out: | ||
2397 | mutex_unlock(&wl->mutex); | ||
2398 | } | ||
2399 | |||
2333 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | 2400 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) |
2334 | { | 2401 | { |
2335 | struct wl1271 *wl = hw->priv; | 2402 | struct wl1271 *wl = hw->priv; |
@@ -3445,6 +3512,8 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3445 | .tx = wl1271_op_tx, | 3512 | .tx = wl1271_op_tx, |
3446 | .set_key = wl1271_op_set_key, | 3513 | .set_key = wl1271_op_set_key, |
3447 | .hw_scan = wl1271_op_hw_scan, | 3514 | .hw_scan = wl1271_op_hw_scan, |
3515 | .sched_scan_start = wl1271_op_sched_scan_start, | ||
3516 | .sched_scan_stop = wl1271_op_sched_scan_stop, | ||
3448 | .bss_info_changed = wl1271_op_bss_info_changed, | 3517 | .bss_info_changed = wl1271_op_bss_info_changed, |
3449 | .set_frag_threshold = wl1271_op_set_frag_threshold, | 3518 | .set_frag_threshold = wl1271_op_set_frag_threshold, |
3450 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 3519 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
@@ -3765,6 +3834,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3765 | wl->ap_fw_ps_map = 0; | 3834 | wl->ap_fw_ps_map = 0; |
3766 | wl->quirks = 0; | 3835 | wl->quirks = 0; |
3767 | wl->platform_quirks = 0; | 3836 | wl->platform_quirks = 0; |
3837 | wl->sched_scanning = false; | ||
3768 | 3838 | ||
3769 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3839 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
3770 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3840 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index d78044f0081..668ff46a682 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c | |||
@@ -548,8 +548,12 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl) | |||
548 | 548 | ||
549 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, | 549 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, |
550 | sizeof(*stop), 0); | 550 | sizeof(*stop), 0); |
551 | if (ret < 0) | 551 | if (ret < 0) { |
552 | wl1271_error("failed to send sched scan stop command"); | 552 | wl1271_error("failed to send sched scan stop command"); |
553 | goto out_free; | ||
554 | } | ||
555 | wl->sched_scanning = false; | ||
553 | 556 | ||
557 | out_free: | ||
554 | kfree(stop); | 558 | kfree(stop); |
555 | } | 559 | } |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b7601438eca..10f076770fe 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -480,6 +480,8 @@ struct wl1271 { | |||
480 | struct wl1271_scan scan; | 480 | struct wl1271_scan scan; |
481 | struct delayed_work scan_complete_work; | 481 | struct delayed_work scan_complete_work; |
482 | 482 | ||
483 | bool sched_scanning; | ||
484 | |||
483 | /* probe-req template for the current AP */ | 485 | /* probe-req template for the current AP */ |
484 | struct sk_buff *probereq; | 486 | struct sk_buff *probereq; |
485 | 487 | ||