From patchwork Sun Jan 25 19:31:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arend van Spriel X-Patchwork-Id: 5705141 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CE1B39F302 for ; Sun, 25 Jan 2015 19:32:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DA3BA20172 for ; Sun, 25 Jan 2015 19:32:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B18CB20115 for ; Sun, 25 Jan 2015 19:31:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759952AbbAYTbv (ORCPT ); Sun, 25 Jan 2015 14:31:51 -0500 Received: from mail-gw2-out.broadcom.com ([216.31.210.63]:63700 "EHLO mail-gw2-out.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759943AbbAYTbs (ORCPT ); Sun, 25 Jan 2015 14:31:48 -0500 X-IronPort-AV: E=Sophos;i="5.09,464,1418112000"; d="scan'208";a="55513306" Received: from irvexchcas08.broadcom.com (HELO IRVEXCHCAS08.corp.ad.broadcom.com) ([10.9.208.57]) by mail-gw2-out.broadcom.com with ESMTP; 25 Jan 2015 12:09:03 -0800 Received: from IRVEXCHSMTP2.corp.ad.broadcom.com (10.9.207.52) by IRVEXCHCAS08.corp.ad.broadcom.com (10.9.208.57) with Microsoft SMTP Server (TLS) id 14.3.174.1; Sun, 25 Jan 2015 11:31:45 -0800 Received: from mail-sj1-12.sj.broadcom.com (10.10.10.20) by IRVEXCHSMTP2.corp.ad.broadcom.com (10.9.207.52) with Microsoft SMTP Server id 14.3.174.1; Sun, 25 Jan 2015 11:32:03 -0800 Received: from lb-bun-235.bun.broadcom.com (lb-bun-235.bun.broadcom.com [10.176.8.235]) by mail-sj1-12.sj.broadcom.com (Postfix) with ESMTP id B1B7D27A86; Sun, 25 Jan 2015 11:31:46 -0800 (PST) Received: from arend by lb-bun-235.bun.broadcom.com with local (Exim 4.82) (envelope-from ) id 1YFSuP-00023I-Ts; Sun, 25 Jan 2015 20:31:45 +0100 From: Arend van Spriel To: Kalle Valo CC: linux-wireless , Arend van Spriel Subject: [PATCH 05/14] brcmfmac: wait for driver to go idle during suspend Date: Sun, 25 Jan 2015 20:31:34 +0100 Message-ID: <1422214303-7816-6-git-send-email-arend@broadcom.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1422214303-7816-1-git-send-email-arend@broadcom.com> References: <1422214303-7816-1-git-send-email-arend@broadcom.com> MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Before going in suspend state the watchdog thread needs to put the device in bus sleep state, which assures it can go in deep-sleep state during D3 state. Reviewed-by: Hante Meuleman Reviewed-by: Daniel (Deognyoun) Kim Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel --- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 20 +++++++++++++++----- drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 18 ++++++++---------- drivers/net/wireless/brcm80211/brcmfmac/sdio.h | 2 ++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 8ba60f6..9afaeb6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -1045,7 +1045,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, bus_if->wowl_supported = true; #endif + sdiodev->sleeping = false; atomic_set(&sdiodev->suspend, false); + init_waitqueue_head(&sdiodev->idle_wait); brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); err = brcmf_sdiod_probe(sdiodev); @@ -1107,12 +1109,23 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled) #ifdef CONFIG_PM_SLEEP static int brcmf_ops_sdio_suspend(struct device *dev) { - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_bus *bus_if; + struct brcmf_sdio_dev *sdiodev; mmc_pm_flag_t sdio_flags; brcmf_dbg(SDIO, "Enter\n"); + bus_if = dev_get_drvdata(dev); + sdiodev = bus_if->bus_priv.sdio; + + /* wait for watchdog to go idle */ + if (wait_event_timeout(sdiodev->idle_wait, sdiodev->sleeping, + msecs_to_jiffies(3 * BRCMF_WD_POLL_MS)) == 0) { + brcmf_err("bus still active\n"); + return -EBUSY; + } + /* disable watchdog */ + brcmf_sdio_wd_timer(sdiodev->bus, 0); atomic_set(&sdiodev->suspend, true); if (sdiodev->wowl_enabled) { @@ -1124,9 +1137,6 @@ static int brcmf_ops_sdio_suspend(struct device *dev) if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) brcmf_err("Failed to set pm_flags %x\n", sdio_flags); } - - brcmf_sdio_wd_timer(sdiodev->bus, 0); - return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index b4f5fe5..488a0f6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c @@ -515,7 +515,6 @@ struct brcmf_sdio { bool txoff; /* Transmit flow-controlled */ struct brcmf_sdio_count sdcnt; bool sr_enabled; /* SaveRestore enabled */ - bool sleeping; /* SDIO bus sleeping */ u8 tx_hdrlen; /* sdio bus header length for tx packet */ bool txglom; /* host tx glomming enable flag */ @@ -1014,12 +1013,12 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) brcmf_dbg(SDIO, "Enter: request %s currently %s\n", (sleep ? "SLEEP" : "WAKE"), - (bus->sleeping ? "SLEEP" : "WAKE")); + (bus->sdiodev->sleeping ? "SLEEP" : "WAKE")); /* If SR is enabled control bus state with KSO */ if (bus->sr_enabled) { /* Done if we're already in the requested state */ - if (sleep == bus->sleeping) + if (sleep == bus->sdiodev->sleeping) goto end; /* Going to sleep */ @@ -1051,12 +1050,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) bus->idlecount = 0; err = brcmf_sdio_kso_control(bus, true); } - if (!err) { - /* Change state */ - bus->sleeping = sleep; - brcmf_dbg(SDIO, "new state %s\n", - (sleep ? "SLEEP" : "WAKE")); - } else { + if (err) { brcmf_err("error while changing bus sleep state %d\n", err); goto done; @@ -1071,6 +1065,11 @@ end: } else { brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); } + bus->sdiodev->sleeping = sleep; + if (sleep) + wake_up(&bus->sdiodev->idle_wait); + brcmf_dbg(SDIO, "new state %s\n", + (sleep ? "SLEEP" : "WAKE")); done: brcmf_dbg(SDIO, "Exit: err=%d\n", err); return err; @@ -4215,7 +4214,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) bus->idleclock = BRCMF_IDLE_ACTIVE; /* SR state */ - bus->sleeping = false; bus->sr_enabled = false; brcmf_sdio_debugfs_create(bus); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h index 82494df..9c5d42d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h @@ -169,6 +169,8 @@ struct brcmf_sdio_dev { u32 sbwad; /* Save backplane window address */ struct brcmf_sdio *bus; atomic_t suspend; /* suspend flag */ + bool sleeping; + wait_queue_head_t idle_wait; struct device *dev; struct brcmf_bus *bus_if; struct brcmfmac_sdio_platform_data *pdata;