diff options
author | Eliad Peller <eliad@wizery.com> | 2012-11-26 18:05:45 +0200 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2012-12-04 16:36:07 +0200 |
commit | 426001a6aaffce040226a19ad2795ac26c10f942 (patch) | |
tree | 73d9dc25a5b7070c9af86faf6e2dc3c9c5eccc79 | |
parent | de40750f4b10aa236ae44a9a3f10f50998e1c345 (diff) |
wlcore: use sta_state-based ROCs for AP mode
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>
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore_i.h | 4 |
2 files changed, 49 insertions, 0 deletions
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 4bdf3d7b947..99ac6c518de 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -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 */ diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index e3a77aa932d..5a92cb211f2 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -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) |