From 5f561f686b90f51d97a1a6985175860200e55a2d Mon Sep 17 00:00:00 2001 From: "Bartosz.Markowski@tieto.com" Date: Thu, 26 Apr 2012 10:35:07 +0300 Subject: [PATCH] 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 Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/boot.c | 1 + drivers/net/wireless/ti/wlcore/event.c | 29 +++++++++----------- drivers/net/wireless/ti/wlcore/main.c | 35 +++++++++++++++++++++++++ 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 eb204ba9793..9b98230f84c 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) /* unmask required mbox events */ wl->event_mask = BSS_LOSE_EVENT_ID | + REGAINED_BSS_EVENT_ID | SCAN_COMPLETE_EVENT_ID | ROLE_STOP_COMPLETE_EVENT_ID | 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 292632ddf89..28e2a633c3b 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) struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; u32 vector; - bool beacon_loss = false; bool disconnect_sta = false; unsigned long sta_bitmap = 0; @@ -141,20 +140,23 @@ static int wl1271_event_process(struct wl1271 *wl) mbox->soft_gemini_sense_info); /* - * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon - * filtering) is enabled. Without PSM, the stack will receive all - * beacons and can detect beacon loss by itself. - * - * As there's possibility that the driver disables PSM before receiving - * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. - * + * We are HW_MONITOR device. On beacon loss - queue + * connection loss work. Cancel it on REGAINED event. */ if (vector & BSS_LOSE_EVENT_ID) { /* TODO: check for multi-role */ + int delay = wl->conf.conn.synch_fail_thold * + wl->conf.conn.bss_lose_timeout; wl1271_info("Beacon loss detected."); + cancel_delayed_work_sync(&wl->connection_loss_work); + ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, + msecs_to_jiffies(delay)); + } - /* indicate to the stack, that beacons have been lost */ - beacon_loss = true; + if (vector & REGAINED_BSS_EVENT_ID) { + /* TODO: check for multi-role */ + wl1271_info("Beacon regained."); + cancel_delayed_work_sync(&wl->connection_loss_work); } if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { @@ -257,13 +259,6 @@ static int wl1271_event_process(struct wl1271 *wl) rcu_read_unlock(); } } - - if (beacon_loss) - wl12xx_for_each_wlvif_sta(wl, wlvif) { - vif = wl12xx_wlvif_to_vif(wlvif); - ieee80211_connection_loss(vif); - } - return 0; } diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 6cd09646d6e..45fe911a650 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) cancel_work_sync(&wl->recovery_work); cancel_delayed_work_sync(&wl->elp_work); cancel_delayed_work_sync(&wl->tx_watchdog_work); + cancel_delayed_work_sync(&wl->connection_loss_work); mutex_lock(&wl->mutex); wl1271_power_off(wl); @@ -1753,6 +1754,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) cancel_work_sync(&wl->tx_work); cancel_delayed_work_sync(&wl->elp_work); cancel_delayed_work_sync(&wl->tx_watchdog_work); + cancel_delayed_work_sync(&wl->connection_loss_work); /* let's notify MAC80211 about the remaining pending TX frames */ wl12xx_tx_reset(wl, true); @@ -3705,6 +3707,9 @@ sta_not_found: do_join = true; set_assoc = true; + /* Cancel connection_loss_work */ + cancel_delayed_work_sync(&wl->connection_loss_work); + /* * use basic rates from AP, and determine lowest rate * to use with control frames. @@ -4815,6 +4820,34 @@ static struct bin_attribute fwlog_attr = { .read = wl1271_sysfs_read_fwlog, }; +void wl1271_connection_loss_work(struct work_struct *work) +{ + struct delayed_work *dwork; + struct wl1271 *wl; + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; + + dwork = container_of(work, struct delayed_work, work); + wl = container_of(dwork, struct wl1271, connection_loss_work); + + wl1271_info("Connection loss work."); + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + + /* Call mac80211 connection loss */ + wl12xx_for_each_wlvif_sta(wl, wlvif) { + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + goto out; + vif = wl12xx_wlvif_to_vif(wlvif); + ieee80211_connection_loss(vif); + } +out: + mutex_unlock(&wl->mutex); +} + static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic, int n) { @@ -5070,6 +5103,8 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) INIT_WORK(&wl->recovery_work, wl1271_recovery_work); INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); + INIT_DELAYED_WORK(&wl->connection_loss_work, + wl1271_connection_loss_work); wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); if (!wl->freezable_wq) { diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index e4f7aa345b4..0b3f0b586f4 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -243,6 +243,9 @@ struct wl1271 { struct wl1271_scan scan; struct delayed_work scan_complete_work; + /* Connection loss work */ + struct delayed_work connection_loss_work; + bool sched_scanning; /* The current band */