wlcore: use sta_state-based ROCs for AP mode
authorEliad Peller <eliad@wizery.com>
Mon, 26 Nov 2012 16:05:45 +0000 (18:05 +0200)
committerLuciano Coelho <coelho@ti.com>
Tue, 4 Dec 2012 14:36:07 +0000 (16:36 +0200)
Try an opportunistic ROC when a STA is first added and stop the ROC when
the STA is removed or successfully authenticated. This would ensure we
don't miss auth/assoc/EAPOL packets during connection

Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/wlcore_i.h

index 4bdf3d7..99ac6c5 100644 (file)
@@ -4486,6 +4486,45 @@ static int wl12xx_sta_remove(struct wl1271 *wl,
        return ret;
 }
 
+static void wlcore_roc_if_possible(struct wl1271 *wl,
+                                  struct wl12xx_vif *wlvif)
+{
+       if (find_first_bit(wl->roc_map,
+                          WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES)
+               return;
+
+       if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID))
+               return;
+
+       wl12xx_roc(wl, wlvif, wlvif->role_id, wlvif->band, wlvif->channel);
+}
+
+static void wlcore_update_inconn_sta(struct wl1271 *wl,
+                                    struct wl12xx_vif *wlvif,
+                                    struct wl1271_station *wl_sta,
+                                    bool in_connection)
+{
+       if (in_connection) {
+               if (WARN_ON(wl_sta->in_connection))
+                       return;
+               wl_sta->in_connection = true;
+               if (!wlvif->inconn_count++)
+                       wlcore_roc_if_possible(wl, wlvif);
+       } else {
+               if (!wl_sta->in_connection)
+                       return;
+
+               wl_sta->in_connection = false;
+               wlvif->inconn_count--;
+               if (WARN_ON(wlvif->inconn_count < 0))
+                       return;
+
+               if (!wlvif->inconn_count)
+                       if (test_bit(wlvif->role_id, wl->roc_map))
+                               wl12xx_croc(wl, wlvif->role_id);
+       }
+}
+
 static int wl12xx_update_sta_state(struct wl1271 *wl,
                                   struct wl12xx_vif *wlvif,
                                   struct ieee80211_sta *sta,
@@ -4508,6 +4547,8 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
                ret = wl12xx_sta_add(wl, wlvif, sta);
                if (ret)
                        return ret;
+
+               wlcore_update_inconn_sta(wl, wlvif, wl_sta, true);
        }
 
        /* Remove station (AP mode) */
@@ -4516,6 +4557,8 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
            new_state == IEEE80211_STA_NOTEXIST) {
                /* must not fail */
                wl12xx_sta_remove(wl, wlvif, sta);
+
+               wlcore_update_inconn_sta(wl, wlvif, wl_sta, false);
        }
 
        /* Authorize station (AP mode) */
@@ -4529,6 +4572,8 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
                                                     hlid);
                if (ret)
                        return ret;
+
+               wlcore_update_inconn_sta(wl, wlvif, wl_sta, false);
        }
 
        /* Authorize station */
index e3a77aa..5a92cb2 100644 (file)
@@ -315,6 +315,7 @@ struct wl12xx_rx_filter {
 
 struct wl1271_station {
        u8 hlid;
+       bool in_connection;
 };
 
 struct wl12xx_vif {
@@ -425,6 +426,9 @@ struct wl12xx_vif {
        struct delayed_work channel_switch_work;
        struct delayed_work connection_loss_work;
 
+       /* number of in connection stations */
+       int inconn_count;
+
        /*
         * This struct must be last!
         * data that has to be saved acrossed reconfigs (e.g. recovery)