wlcore: fixes for connection_loss_work
authorArik Nemtsov <arik@wizery.com>
Tue, 15 May 2012 14:08:54 +0000 (17:08 +0300)
committerLuciano Coelho <coelho@ti.com>
Tue, 5 Jun 2012 14:16:08 +0000 (17:16 +0300)
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: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
drivers/net/wireless/ti/wlcore/event.c
drivers/net/wireless/ti/wlcore/main.c

index 28e2a633c3be0eb96689f1414520c03c10de8060..4ed8357991782ec1dc55c8751de24ef8565937e2 100644 (file)
@@ -148,15 +148,24 @@ static int wl1271_event_process(struct wl1271 *wl)
                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);
+
+               /*
+                * 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,
-                     msecs_to_jiffies(delay));
+                                            msecs_to_jiffies(delay));
        }
 
        if (vector & REGAINED_BSS_EVENT_ID) {
                /* TODO: check for multi-role */
                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) {
index af00dabf96b7bf8deae6796b2d82c80f4b040f7c..4be62c93808bfba47862220c01a10376ec2fad32 100644 (file)
@@ -3712,9 +3712,6 @@ 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.
@@ -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",
                     (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);
 
        if (unlikely(wl->state == WL1271_STATE_OFF))