All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.