aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartosz.Markowski@tieto.com <Bartosz.Markowski@tieto.com>2012-04-26 03:35:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-05-15 17:53:25 -0400
commit5f561f686b90f51d97a1a6985175860200e55a2d (patch)
tree2455e3bb86f422ffd83d7d2289306d41e3340c0b
parent161f17b5307ecf56484c1d0e0ae433506394651c (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.c1
-rw-r--r--drivers/net/wireless/ti/wlcore/event.c29
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c35
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h3
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
4823void 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 }
4847out:
4848 mutex_unlock(&wl->mutex);
4849}
4850
4818static void wl12xx_derive_mac_addresses(struct wl1271 *wl, 4851static 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 */