Commit 6b8bf5bc authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Luciano Coelho

wlcore: fixes for connection_loss_work

We can't use cancel_delayed_work_sync() from functions that take the
wl->mutex, since connection_loss_work also takes the mutex. This might
result in a deadlock. Restructure the code so the work is synchronously
canceled before taking the mutex.
Avoid a bug where we would indefinitely delay the connection loss
indication by re-queuing the connection loss work on consecutive beacon
loss events.

Cc: bartosz.markowski <bartosz.markowski@tieto.com>
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 6e066921
...@@ -148,15 +148,24 @@ static int wl1271_event_process(struct wl1271 *wl) ...@@ -148,15 +148,24 @@ static int wl1271_event_process(struct wl1271 *wl)
int delay = wl->conf.conn.synch_fail_thold * int delay = wl->conf.conn.synch_fail_thold *
wl->conf.conn.bss_lose_timeout; wl->conf.conn.bss_lose_timeout;
wl1271_info("Beacon loss detected."); wl1271_info("Beacon loss detected.");
cancel_delayed_work_sync(&wl->connection_loss_work);
/*
* if the work is already queued, it should take place. We
* don't want to delay the connection loss indication
* any more.
*/
ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work,
msecs_to_jiffies(delay)); msecs_to_jiffies(delay));
} }
if (vector & REGAINED_BSS_EVENT_ID) { if (vector & REGAINED_BSS_EVENT_ID) {
/* TODO: check for multi-role */ /* TODO: check for multi-role */
wl1271_info("Beacon regained."); wl1271_info("Beacon regained.");
cancel_delayed_work_sync(&wl->connection_loss_work); cancel_delayed_work(&wl->connection_loss_work);
/* sanity check - we can't lose and gain the beacon together */
WARN(vector & BSS_LOSE_EVENT_ID,
"Concurrent beacon loss and gain from FW");
} }
if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
......
...@@ -3712,9 +3712,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ...@@ -3712,9 +3712,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
do_join = true; do_join = true;
set_assoc = 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 * use basic rates from AP, and determine lowest rate
* to use with control frames. * to use with control frames.
...@@ -3964,6 +3961,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -3964,6 +3961,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x",
(int)changed); (int)changed);
/*
* make sure to cancel pending disconnections if our association
* state changed
*/
if (!is_ap && (changed & BSS_CHANGED_ASSOC))
cancel_delayed_work_sync(&wl->connection_loss_work);
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (unlikely(wl->state == WL1271_STATE_OFF)) if (unlikely(wl->state == WL1271_STATE_OFF))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment