linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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



  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).