wl1271: workaround to send a disconnect before rejoining
authorLuciano Coelho <luciano.coelho@nokia.com>
Mon, 12 Oct 2009 12:08:43 +0000 (15:08 +0300)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 27 Oct 2009 20:48:02 +0000 (16:48 -0400)
We don't get any indication from the stack when we have disassociated.  In
wl1271, it is important to send a CMD_DISCONNECT before joining again,
because the firmware cleans some things up.  So we check if we're already
joined and disconnect if that's the case.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/wl12xx/wl1271.h
drivers/net/wireless/wl12xx/wl1271_cmd.c
drivers/net/wireless/wl12xx/wl1271_main.c

index 96a58131694105a0a1c3d9cfd3621aca441b4e31..858bf6b160a18642389b31e31e642805642f2d0b 100644 (file)
@@ -422,6 +422,9 @@ struct wl1271 {
        struct wl1271_tx_hw_res_if *tx_res_if;
 
        struct ieee80211_vif *vif;
+
+       /* Used for a workaround to send disconnect before rejoining */
+       bool joined;
 };
 
 int wl1271_plt_start(struct wl1271 *wl);
index d09ad12119770c2ade2703a87c993cd60081836a..ef92834e0e8f795f312ad218feed3b5e1af7afe8 100644 (file)
@@ -191,6 +191,19 @@ int wl1271_cmd_join(struct wl1271 *wl)
                        do_cal = false;
        }
 
+       /* FIXME: This is a workaround, because with the current stack, we
+        * cannot know when we have disassociated.  So, if we have already
+        * joined, we disconnect before joining again. */
+       if (wl->joined) {
+               ret = wl1271_cmd_disconnect(wl);
+               if (ret < 0) {
+                       wl1271_error("failed to disconnect before rejoining");
+                       goto out;
+               }
+
+               wl->joined = false;
+       }
+
        join = kzalloc(sizeof(*join), GFP_KERNEL);
        if (!join) {
                ret = -ENOMEM;
@@ -245,6 +258,8 @@ int wl1271_cmd_join(struct wl1271 *wl)
                goto out_free;
        }
 
+       wl->joined = true;
+
        /*
         * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
         * simplify locking we just sleep instead, for now
index 3662715c0313aa7ce309c2a21cae8de7b488485d..b9f20918a25d32545f4d0129920d644e1e25bc21 100644 (file)
@@ -648,6 +648,8 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
        wl->tx_security_seq_32 = 0;
        wl->time_offset = 0;
        wl->session_counter = 0;
+       wl->joined = false;
+
        for (i = 0; i < NUM_TX_QUEUES; i++)
                wl->tx_blocks_freed[i] = 0;
 
@@ -1395,6 +1397,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
        wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
        wl->band = IEEE80211_BAND_2GHZ;
        wl->vif = NULL;
+       wl->joined = false;
 
        for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
                wl->tx_frames[i] = NULL;