diff options
author | Bartosz.Markowski@tieto.com <Bartosz.Markowski@tieto.com> | 2012-04-26 03:35:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-15 17:53:25 -0400 |
commit | 5f561f686b90f51d97a1a6985175860200e55a2d (patch) | |
tree | 2455e3bb86f422ffd83d7d2289306d41e3340c0b | |
parent | 161f17b5307ecf56484c1d0e0ae433506394651c (diff) |
wlcore/wl12xx: implement better beacon loss handling
Make use of REGAINED_BSS_EVENT and instead of reporting connection
loss immediately on each BEACON_LOSE event, try if not regained
in reasonable period of time.
Signed-off-by: bartosz.markowski <bartosz.markowski@tieto.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r-- | drivers/net/wireless/ti/wlcore/boot.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/event.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore.h | 3 |
4 files changed, 51 insertions, 17 deletions
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index eb204ba97935..9b98230f84ce 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
@@ -413,6 +413,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
413 | 413 | ||
414 | /* unmask required mbox events */ | 414 | /* unmask required mbox events */ |
415 | wl->event_mask = BSS_LOSE_EVENT_ID | | 415 | wl->event_mask = BSS_LOSE_EVENT_ID | |
416 | REGAINED_BSS_EVENT_ID | | ||
416 | SCAN_COMPLETE_EVENT_ID | | 417 | SCAN_COMPLETE_EVENT_ID | |
417 | ROLE_STOP_COMPLETE_EVENT_ID | | 418 | ROLE_STOP_COMPLETE_EVENT_ID | |
418 | RSSI_SNR_TRIGGER_0_EVENT_ID | | 419 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 292632ddf890..28e2a633c3be 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -103,7 +103,6 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
103 | struct ieee80211_vif *vif; | 103 | struct ieee80211_vif *vif; |
104 | struct wl12xx_vif *wlvif; | 104 | struct wl12xx_vif *wlvif; |
105 | u32 vector; | 105 | u32 vector; |
106 | bool beacon_loss = false; | ||
107 | bool disconnect_sta = false; | 106 | bool disconnect_sta = false; |
108 | unsigned long sta_bitmap = 0; | 107 | unsigned long sta_bitmap = 0; |
109 | 108 | ||
@@ -141,20 +140,23 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
141 | mbox->soft_gemini_sense_info); | 140 | mbox->soft_gemini_sense_info); |
142 | 141 | ||
143 | /* | 142 | /* |
144 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | 143 | * We are HW_MONITOR device. On beacon loss - queue |
145 | * filtering) is enabled. Without PSM, the stack will receive all | 144 | * connection loss work. Cancel it on REGAINED event. |
146 | * beacons and can detect beacon loss by itself. | ||
147 | * | ||
148 | * As there's possibility that the driver disables PSM before receiving | ||
149 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | ||
150 | * | ||
151 | */ | 145 | */ |
152 | if (vector & BSS_LOSE_EVENT_ID) { | 146 | if (vector & BSS_LOSE_EVENT_ID) { |
153 | /* TODO: check for multi-role */ | 147 | /* TODO: check for multi-role */ |
148 | int delay = wl->conf.conn.synch_fail_thold * | ||
149 | wl->conf.conn.bss_lose_timeout; | ||
154 | wl1271_info("Beacon loss detected."); | 150 | wl1271_info("Beacon loss detected."); |
151 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
152 | ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, | ||
153 | msecs_to_jiffies(delay)); | ||
154 | } | ||
155 | 155 | ||
156 | /* indicate to the stack, that beacons have been lost */ | 156 | if (vector & REGAINED_BSS_EVENT_ID) { |
157 | beacon_loss = true; | 157 | /* TODO: check for multi-role */ |
158 | wl1271_info("Beacon regained."); | ||
159 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
158 | } | 160 | } |
159 | 161 | ||
160 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 162 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
@@ -257,13 +259,6 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
257 | rcu_read_unlock(); | 259 | rcu_read_unlock(); |
258 | } | 260 | } |
259 | } | 261 | } |
260 | |||
261 | if (beacon_loss) | ||
262 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
263 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
264 | ieee80211_connection_loss(vif); | ||
265 | } | ||
266 | |||
267 | return 0; | 262 | return 0; |
268 | } | 263 | } |
269 | 264 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 6cd09646d6ed..45fe911a6504 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -1120,6 +1120,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1120 | cancel_work_sync(&wl->recovery_work); | 1120 | cancel_work_sync(&wl->recovery_work); |
1121 | cancel_delayed_work_sync(&wl->elp_work); | 1121 | cancel_delayed_work_sync(&wl->elp_work); |
1122 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1122 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
1123 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
1123 | 1124 | ||
1124 | mutex_lock(&wl->mutex); | 1125 | mutex_lock(&wl->mutex); |
1125 | wl1271_power_off(wl); | 1126 | wl1271_power_off(wl); |
@@ -1753,6 +1754,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1753 | cancel_work_sync(&wl->tx_work); | 1754 | cancel_work_sync(&wl->tx_work); |
1754 | cancel_delayed_work_sync(&wl->elp_work); | 1755 | cancel_delayed_work_sync(&wl->elp_work); |
1755 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1756 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
1757 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
1756 | 1758 | ||
1757 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1759 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1758 | wl12xx_tx_reset(wl, true); | 1760 | wl12xx_tx_reset(wl, true); |
@@ -3705,6 +3707,9 @@ sta_not_found: | |||
3705 | do_join = true; | 3707 | do_join = true; |
3706 | set_assoc = true; | 3708 | set_assoc = true; |
3707 | 3709 | ||
3710 | /* Cancel connection_loss_work */ | ||
3711 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
3712 | |||
3708 | /* | 3713 | /* |
3709 | * use basic rates from AP, and determine lowest rate | 3714 | * use basic rates from AP, and determine lowest rate |
3710 | * to use with control frames. | 3715 | * to use with control frames. |
@@ -4815,6 +4820,34 @@ static struct bin_attribute fwlog_attr = { | |||
4815 | .read = wl1271_sysfs_read_fwlog, | 4820 | .read = wl1271_sysfs_read_fwlog, |
4816 | }; | 4821 | }; |
4817 | 4822 | ||
4823 | void wl1271_connection_loss_work(struct work_struct *work) | ||
4824 | { | ||
4825 | struct delayed_work *dwork; | ||
4826 | struct wl1271 *wl; | ||
4827 | struct ieee80211_vif *vif; | ||
4828 | struct wl12xx_vif *wlvif; | ||
4829 | |||
4830 | dwork = container_of(work, struct delayed_work, work); | ||
4831 | wl = container_of(dwork, struct wl1271, connection_loss_work); | ||
4832 | |||
4833 | wl1271_info("Connection loss work."); | ||
4834 | |||
4835 | mutex_lock(&wl->mutex); | ||
4836 | |||
4837 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
4838 | goto out; | ||
4839 | |||
4840 | /* Call mac80211 connection loss */ | ||
4841 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
4842 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
4843 | goto out; | ||
4844 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
4845 | ieee80211_connection_loss(vif); | ||
4846 | } | ||
4847 | out: | ||
4848 | mutex_unlock(&wl->mutex); | ||
4849 | } | ||
4850 | |||
4818 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, | 4851 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, |
4819 | u32 oui, u32 nic, int n) | 4852 | u32 oui, u32 nic, int n) |
4820 | { | 4853 | { |
@@ -5070,6 +5103,8 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
5070 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | 5103 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); |
5071 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | 5104 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); |
5072 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); | 5105 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); |
5106 | INIT_DELAYED_WORK(&wl->connection_loss_work, | ||
5107 | wl1271_connection_loss_work); | ||
5073 | 5108 | ||
5074 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); | 5109 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); |
5075 | if (!wl->freezable_wq) { | 5110 | if (!wl->freezable_wq) { |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index e4f7aa345b45..0b3f0b586f4b 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -243,6 +243,9 @@ struct wl1271 { | |||
243 | struct wl1271_scan scan; | 243 | struct wl1271_scan scan; |
244 | struct delayed_work scan_complete_work; | 244 | struct delayed_work scan_complete_work; |
245 | 245 | ||
246 | /* Connection loss work */ | ||
247 | struct delayed_work connection_loss_work; | ||
248 | |||
246 | bool sched_scanning; | 249 | bool sched_scanning; |
247 | 250 | ||
248 | /* The current band */ | 251 | /* The current band */ |