From: "Arend van Spriel" <arend@broadcom.com>
To: gregkh@suse.de
Cc: "Sukesh Srikakula" <sukeshs@broadcom.com>,
devel@linuxdriverproject.org, linux-wireless@vger.kernel.org,
"Grant Grundler" <grundler@chromium.org>,
"Arend van Spriel" <arend@broadcom.com>
Subject: [PATCH 19/32] staging: brcm80211: Fix for suspend issue in brcmfmac driver
Date: Fri, 13 May 2011 11:59:39 +0200 [thread overview]
Message-ID: <1305280792-9475-19-git-send-email-arend@broadcom.com> (raw)
In-Reply-To: <1305280792-9475-1-git-send-email-arend@broadcom.com>
From: Sukesh Srikakula <sukeshs@broadcom.com>
Currently, there are 2 callbacks registered with OS for getting
notifications when system goes to suspend/resume. Racing between
these 2 callbacks results in random suspend failures. With this fix,
we avoid registering dhd callback for suspend/resume notification
when cfg80211 is used. Relevent functionality in dhd suspend/resume
callback function is moved to cfg80211 suspend/resume functions.
Cc: devel@linuxdriverproject.org
Cc: linux-wireless@vger.kernel.org
Cc: Grant Grundler <grundler@chromium.org>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Brett Rudley <brudley@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 5 +-
drivers/staging/brcm80211/brcmfmac/dhd.h | 22 ++++---
drivers/staging/brcm80211/brcmfmac/dhd_linux.c | 20 ++++--
drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c | 77 ++++++++++++++++++---
drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h | 1 +
5 files changed, 97 insertions(+), 28 deletions(-)
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 43aebfd..c0ffbd3 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -26,14 +26,11 @@
#include <linux/mmc/core.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
+#include <linux/suspend.h>
#include <dngl_stats.h>
#include <dhd.h>
-#if defined(CONFIG_PM_SLEEP)
-#include <linux/suspend.h>
-extern volatile bool dhd_mmc_suspend;
-#endif
#include "bcmsdh_sdmmc.h"
extern int sdio_function_init(void);
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/staging/brcm80211/brcmfmac/dhd.h
index 99c38dd..a726b49 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd.h
@@ -31,6 +31,7 @@
#include <linux/random.h>
#include <linux/spinlock.h>
#include <linux/ethtool.h>
+#include <linux/suspend.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
/* The kernel threading is sdio-specific */
@@ -122,19 +123,22 @@ typedef struct dhd_pub {
} dhd_pub_t;
#if defined(CONFIG_PM_SLEEP)
-
+extern atomic_t dhd_mmc_suspend;
#define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define _DHD_PM_RESUME_WAIT(a, b) do {\
- int retry = 0; \
- while (dhd_mmc_suspend && retry++ != b) { \
- wait_event_timeout(a, false, HZ/100); \
- } \
- } while (0)
+#define _DHD_PM_RESUME_WAIT(a, b) do { \
+ int retry = 0; \
+ while (atomic_read(&dhd_mmc_suspend) && retry++ != b) { \
+ wait_event_timeout(a, false, HZ/100); \
+ } \
+ } while (0)
#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30)
#define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
#define DHD_PM_RESUME_RETURN_ERROR(a) \
- do { if (dhd_mmc_suspend) return a; } while (0)
-#define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0)
+ do { if (atomic_read(&dhd_mmc_suspend)) return a; } while (0)
+#define DHD_PM_RESUME_RETURN do { \
+ if (atomic_read(&dhd_mmc_suspend)) \
+ return; \
+ } while (0)
#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
#define SPINWAIT_SLEEP(a, exp, us) do { \
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
index ba73ce0..31a5ca0 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -166,7 +166,7 @@ void wifi_del_dev(void)
#if defined(CONFIG_PM_SLEEP)
#include <linux/suspend.h>
-volatile bool dhd_mmc_suspend = false;
+atomic_t dhd_mmc_suspend;
DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
#endif /* defined(CONFIG_PM_SLEEP) */
@@ -407,11 +407,11 @@ static int dhd_sleep_pm_callback(struct notifier_block *nfb,
switch (action) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
- dhd_mmc_suspend = true;
+ atomic_set(&dhd_mmc_suspend, true);
return NOTIFY_OK;
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
- dhd_mmc_suspend = false;
+ atomic_set(&dhd_mmc_suspend, false);
return NOTIFY_OK;
}
return 0;
@@ -2011,7 +2011,9 @@ dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
g_bus = bus;
#endif
#if defined(CONFIG_PM_SLEEP)
- register_pm_notifier(&dhd_sleep_pm_notifier);
+ atomic_set(&dhd_mmc_suspend, false);
+ if (!IS_CFG80211_FAVORITE())
+ register_pm_notifier(&dhd_sleep_pm_notifier);
#endif /* defined(CONFIG_PM_SLEEP) */
/* && defined(DHD_GPL) */
/* Init lock suspend to prevent kernel going to suspend */
@@ -2305,7 +2307,8 @@ void dhd_detach(dhd_pub_t *dhdp)
wl_cfg80211_detach();
#if defined(CONFIG_PM_SLEEP)
- unregister_pm_notifier(&dhd_sleep_pm_notifier);
+ if (!IS_CFG80211_FAVORITE())
+ unregister_pm_notifier(&dhd_sleep_pm_notifier);
#endif /* defined(CONFIG_PM_SLEEP) */
/* && defined(DHD_GPL) */
free_netdev(ifp->net);
@@ -2816,6 +2819,13 @@ int dhd_wait_pend8021x(struct net_device *dev)
return pend;
}
+void wl_os_wd_timer(struct net_device *ndev, uint wdtick)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(ndev);
+
+ dhd_os_wd_timer(&dhd->pub, wdtick);
+}
+
#ifdef DHD_DEBUG
int write_to_file(dhd_pub_t *dhd, u8 *buf, int size)
{
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index c60fc7c..2d67048 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -1969,34 +1969,91 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
static s32 wl_cfg80211_resume(struct wiphy *wiphy)
{
- s32 err = 0;
+ struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
- CHECK_SYS_UP();
- wl_invoke_iscan(wiphy_to_wl(wiphy));
+ /*
+ * Check for WL_STATUS_READY before any function call which
+ * could result is bus access. Don't block the resume for
+ * any driver error conditions
+ */
- return err;
+#if defined(CONFIG_PM_SLEEP)
+ atomic_set(&dhd_mmc_suspend, false);
+#endif /* defined(CONFIG_PM_SLEEP) */
+
+ if (test_bit(WL_STATUS_READY, &wl->status)) {
+ /* Turn on Watchdog timer */
+ wl_os_wd_timer(ndev, dhd_watchdog_ms);
+ wl_invoke_iscan(wiphy_to_wl(wiphy));
+ }
+
+ return 0;
}
static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
{
struct wl_priv *wl = wiphy_to_wl(wiphy);
struct net_device *ndev = wl_to_ndev(wl);
- s32 err = 0;
+
+
+ /*
+ * Check for WL_STATUS_READY before any function call which
+ * could result is bus access. Don't block the suspend for
+ * any driver error conditions
+ */
+
+ /*
+ * 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)) {
+ WL_INFO("Disassociating from AP"
+ " while entering suspend state\n");
+ 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 (test_bit(WL_STATUS_READY, &wl->status))
+ wl_term_iscan(wl);
+
if (wl->scan_request) {
- cfg80211_scan_done(wl->scan_request, true); /* true means
- abort */
- wl_set_mpc(ndev, 1);
+ /* Indidate scan abort to cfg80211 layer */
+ WL_INFO("Terminating scan in progress\n");
+ cfg80211_scan_done(wl->scan_request, true);
wl->scan_request = NULL;
}
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);
- return err;
+ /* Turn off watchdog timer */
+ if (test_bit(WL_STATUS_READY, &wl->status)) {
+ WL_INFO("Terminate watchdog timer and enable MPC\n");
+ wl_set_mpc(ndev, 1);
+ wl_os_wd_timer(ndev, 0);
+ }
+
+#if defined(CONFIG_PM_SLEEP)
+ atomic_set(&dhd_mmc_suspend, true);
+#endif /* defined(CONFIG_PM_SLEEP) */
+
+
+ return 0;
}
static __used s32
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
index 5112160..3c8b902 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
@@ -375,5 +375,6 @@ extern s8 *wl_cfg80211_get_fwname(void); /* get firmware name for
the dongle */
extern s8 *wl_cfg80211_get_nvramname(void); /* get nvram name for
the dongle */
+extern void wl_os_wd_timer(struct net_device *ndev, uint wdtick);
#endif /* _wl_cfg80211_h_ */
--
1.7.4.1
next prev parent reply other threads:[~2011-05-13 10:00 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-13 9:59 [PATCH 01/32] staging: brcm80211: replaced IL_BIGENDIAN by __BIG_ENDIAN Arend van Spriel
2011-05-13 9:59 ` [PATCH 02/32] staging: brcm80211: new Kconfig item to enable IO reordering fix Arend van Spriel
2011-05-14 10:23 ` Christoph Hellwig
2011-05-14 15:46 ` Greg KH
2011-05-15 12:53 ` Arend van Spriel
2011-05-17 19:19 ` Greg KH
2011-05-13 9:59 ` [PATCH 03/32] staging: brcm80211: replaced #ifdef __mips__ sections by W_REG_FLUSH Arend van Spriel
2011-05-13 9:59 ` [PATCH 04/32] staging: brcm80211: got rid of #ifdef __mips__ sections in hnddma.c Arend van Spriel
2011-05-14 10:16 ` Jonas Gorski
2011-05-17 19:10 ` Greg KH
2011-05-13 9:59 ` [PATCH 05/32] staging: brcm80211: got rid of #ifdef __mips__ by new dma_spin_for_len() Arend van Spriel
2011-05-13 9:59 ` [PATCH 06/32] staging: brcm80211: remove unnecessary functions from wlc_main.c Arend van Spriel
2011-05-13 9:59 ` [PATCH 07/32] staging: brcm80211: remove unused functions and prototypes Arend van Spriel
2011-05-13 9:59 ` [PATCH 08/32] staging: brcm80211: make function definitions and prototype consistent Arend van Spriel
2011-05-13 9:59 ` [PATCH 09/32] staging: brcm80211: cleanup functions in nvram.c Arend van Spriel
2011-05-13 9:59 ` [PATCH 10/32] staging: brcm80211: fix makefiles for building drivers in kernel Arend van Spriel
2011-05-13 9:59 ` [PATCH 11/32] staging: brcm80211: Kconfig fix for 'Broadcom I/O order fix' Arend van Spriel
2011-05-13 9:59 ` [PATCH 12/32] staging: brcm80211: removed unused struct net_device_stats related code Arend van Spriel
2011-05-13 9:59 ` [PATCH 13/32] staging: brcm80211: removed counter related macros that expanded to NOP Arend van Spriel
2011-05-13 9:59 ` [PATCH 14/32] staging: brcm80211: removed stats WEXT support from fullmac Arend van Spriel
2011-05-13 9:59 ` [PATCH 15/32] staging: brcm80211: removed support for proprietary ioctl WLC_GET_PKTCNTS Arend van Spriel
2011-05-13 9:59 ` [PATCH 16/32] staging: brcm80211: removed counter related struct wl_cnt Arend van Spriel
2011-05-13 9:59 ` [PATCH 17/32] staging: brcm80211: removed more unused counter related structures Arend van Spriel
2011-05-13 9:59 ` [PATCH 18/32] staging: brcm80211: Fix for WPA GTK install issue in brcmfmac driver Arend van Spriel
2011-05-13 15:22 ` Grant Grundler
2011-05-13 9:59 ` Arend van Spriel [this message]
2011-05-13 15:30 ` [PATCH 19/32] staging: brcm80211: Fix for suspend " Grant Grundler
2011-05-13 9:59 ` [PATCH 20/32] staging: brcm80211: brcmfmac driver's interface name changed to "wlan" Arend van Spriel
2011-05-13 9:59 ` [PATCH 21/32] staging: brcm80211: Fixed wl_assoc_params structure miss match in brcmfmac driver Arend van Spriel
2011-05-13 9:59 ` [PATCH 22/32] staging: brcm80211: Optimized wl_inform_single_bss function " Arend van Spriel
2011-05-13 9:59 ` [PATCH 23/32] staging: brcm80211: Fixed bss (re)connect/disconnect issues " Arend van Spriel
2011-05-13 9:59 ` [PATCH 24/32] staging: brcm80211: Fixed ibss join/leave functionality " Arend van Spriel
2011-05-13 9:59 ` [PATCH 25/32] staging: brcm80211: Added support to change roaming parameters from " Arend van Spriel
2011-05-13 9:59 ` [PATCH 26/32] staging: brcm80211: Added support to change scan times " Arend van Spriel
2011-05-13 9:59 ` [PATCH 27/32] staging: brcm80211: Fixed scan notification functionality in " Arend van Spriel
2011-05-13 9:59 ` [PATCH 28/32] staging: brcm80211: Removed unused variable from " Arend van Spriel
2011-05-13 9:59 ` [PATCH 29/32] staging: brcm80211: cfg80211 up/down routines in brcmfmac driver are fixed Arend van Spriel
2011-05-13 9:59 ` [PATCH 30/32] staging: brcm80211: Better debug support added to brcmfmac driver Arend van Spriel
2011-05-13 9:59 ` [PATCH 31/32] staging: brcm80211: Corrected sdpcm_shared_t structure definition Arend van Spriel
2011-05-13 9:59 ` [PATCH 32/32] staging: brcm80211: fix checkpatch issue in wlc_channel.c Arend van Spriel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1305280792-9475-19-git-send-email-arend@broadcom.com \
--to=arend@broadcom.com \
--cc=devel@linuxdriverproject.org \
--cc=gregkh@suse.de \
--cc=grundler@chromium.org \
--cc=linux-wireless@vger.kernel.org \
--cc=sukeshs@broadcom.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).