From f212595d5e41f8790560353e35a8143ba1de022e Mon Sep 17 00:00:00 2001 From: Sukesh Srikakula Date: Thu, 9 Jun 2011 16:44:51 +0200 Subject: [PATCH] staging: brcm80211: Fix for suspend issue in brcmfmac driver Issue with disconnect at the time of suspend is fixed by properly setting connection status bits maintained by brcmfmac driver. Signed-off-by: Sukesh Srikakula Reviewed-by: Roland Vossen Reviewed-by: Arend van Spriel Reviewed-by: Franky Lin Signed-off-by: Greg Kroah-Hartman --- .../staging/brcm80211/brcmfmac/wl_cfg80211.c | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c index e9d19c5acd71..399d7a8efa46 100644 --- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c @@ -2110,8 +2110,9 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) * While going to suspend if associated with AP disassociate * from AP to save power while system is in suspended state */ - if (test_bit(WL_STATUS_CONNECTED, &wl->status) && - test_bit(WL_STATUS_READY, &wl->status)) { + if ((test_bit(WL_STATUS_CONNECTED, &wl->status) || + test_bit(WL_STATUS_CONNECTING, &wl->status)) && + test_bit(WL_STATUS_READY, &wl->status)) { WL_INFO("Disassociating from AP" " while entering suspend state\n"); wl_link_down(wl); @@ -2138,8 +2139,6 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) } clear_bit(WL_STATUS_SCANNING, &wl->status); clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status); - clear_bit(WL_STATUS_CONNECTING, &wl->status); - clear_bit(WL_STATUS_CONNECTED, &wl->status); /* Inform SDIO stack not to switch off power to the chip */ sdioh_sdio_set_host_pm_flags(MMC_PM_KEEP_POWER); @@ -2620,10 +2619,12 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, } else if (wl_is_linkdown(wl, e)) { WL_CONN("Linkdown\n"); if (wl_is_ibssmode(wl)) { + clear_bit(WL_STATUS_CONNECTING, &wl->status); if (test_and_clear_bit(WL_STATUS_CONNECTED, &wl->status)) wl_link_down(wl); } else { + wl_bss_connect_done(wl, ndev, e, data, false); if (test_and_clear_bit(WL_STATUS_CONNECTED, &wl->status)) { cfg80211_disconnected(ndev, 0, NULL, 0, @@ -4099,6 +4100,25 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) static s32 __wl_cfg80211_down(struct wl_priv *wl) { + /* + * While going down, if associated with AP disassociate + * from AP to save power + */ + if ((test_bit(WL_STATUS_CONNECTED, &wl->status) || + test_bit(WL_STATUS_CONNECTING, &wl->status)) && + test_bit(WL_STATUS_READY, &wl->status)) { + WL_INFO("Disassociating from AP"); + wl_link_down(wl); + + /* Make sure WPA_Supplicant receives all the event + generated due to DISASSOC call to the fw to keep + the state fw and WPA_Supplicant state consistent + */ + rtnl_unlock(); + wl_delay(500); + rtnl_lock(); + } + set_bit(WL_STATUS_SCAN_ABORTING, &wl->status); wl_term_iscan(wl); if (wl->scan_request) { @@ -4110,8 +4130,6 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) clear_bit(WL_STATUS_READY, &wl->status); clear_bit(WL_STATUS_SCANNING, &wl->status); clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status); - clear_bit(WL_STATUS_CONNECTING, &wl->status); - clear_bit(WL_STATUS_CONNECTED, &wl->status); wl_debugfs_remove_netdev(wl); @@ -4230,14 +4248,12 @@ static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v) return err; } - static void wl_link_down(struct wl_priv *wl) { struct net_device *dev = NULL; s32 err = 0; WL_TRACE("Enter\n"); - clear_bit(WL_STATUS_CONNECTED, &wl->status); if (wl->link_up) { dev = wl_to_ndev(wl); -- 2.39.5