aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch')
-rw-r--r--package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch157
1 files changed, 157 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch b/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch
new file mode 100644
index 0000000000..201da75bfc
--- /dev/null
+++ b/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch
@@ -0,0 +1,157 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 6 Mar 2015 18:40:39 +0100
+Subject: [PATCH] brcmfmac: Simplify watchdog sleep.
+
+The watchdog thread is used to put the SDIO bus to sleep when the
+system is idling. This patch simplifies the way it is determined
+when sleep can be entered.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+@@ -485,10 +485,9 @@ struct brcmf_sdio {
+ #endif /* DEBUG */
+
+ uint clkstate; /* State of sd and backplane clock(s) */
+- bool activity; /* Activity flag for clock down */
+ s32 idletime; /* Control for activity timeout */
+- s32 idlecount; /* Activity timeout counter */
+- s32 idleclock; /* How to set bus driver when idle */
++ s32 idlecount; /* Activity timeout counter */
++ s32 idleclock; /* How to set bus driver when idle */
+ bool rxflow_mode; /* Rx flow control mode */
+ bool rxflow; /* Is rx flow control on */
+ bool alp_only; /* Don't use HT clock (ALP only) */
+@@ -511,6 +510,7 @@ struct brcmf_sdio {
+ struct workqueue_struct *brcmf_wq;
+ struct work_struct datawork;
+ atomic_t dpc_tskcnt;
++ atomic_t dpc_running;
+
+ bool txoff; /* Transmit flow-controlled */
+ struct brcmf_sdio_count sdcnt;
+@@ -959,13 +959,8 @@ static int brcmf_sdio_clkctl(struct brcm
+ brcmf_dbg(SDIO, "Enter\n");
+
+ /* Early exit if we're already there */
+- if (bus->clkstate == target) {
+- if (target == CLK_AVAIL) {
+- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+- bus->activity = true;
+- }
++ if (bus->clkstate == target)
+ return 0;
+- }
+
+ switch (target) {
+ case CLK_AVAIL:
+@@ -975,7 +970,6 @@ static int brcmf_sdio_clkctl(struct brcm
+ /* Now request HT Avail on the backplane */
+ brcmf_sdio_htclk(bus, true, pendok);
+ brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+- bus->activity = true;
+ break;
+
+ case CLK_SDONLY:
+@@ -1024,17 +1018,6 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
+
+ /* Going to sleep */
+ if (sleep) {
+- /* Don't sleep if something is pending */
+- if (atomic_read(&bus->intstatus) ||
+- atomic_read(&bus->ipend) > 0 ||
+- bus->ctrl_frame_stat ||
+- (!atomic_read(&bus->fcstate) &&
+- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+- data_ok(bus))) {
+- err = -EBUSY;
+- goto done;
+- }
+-
+ clkcsr = brcmf_sdiod_regrb(bus->sdiodev,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ &err);
+@@ -1045,11 +1028,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
+ SBSDIO_ALP_AVAIL_REQ, &err);
+ }
+ err = brcmf_sdio_kso_control(bus, false);
+- /* disable watchdog */
+- if (!err)
+- brcmf_sdio_wd_timer(bus, 0);
+ } else {
+- bus->idlecount = 0;
+ err = brcmf_sdio_kso_control(bus, true);
+ }
+ if (err) {
+@@ -3566,7 +3545,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
+ queue_work(bus->brcmf_wq, &bus->datawork);
+ }
+
+-static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
++static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
+ {
+ brcmf_dbg(TIMER, "Enter\n");
+
+@@ -3627,22 +3606,21 @@ static bool brcmf_sdio_bus_watchdog(stru
+ #endif /* DEBUG */
+
+ /* On idle timeout clear activity flag and/or turn off clock */
+- if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+- if (++bus->idlecount >= bus->idletime) {
++ if ((atomic_read(&bus->dpc_tskcnt) == 0) &&
++ (atomic_read(&bus->dpc_running) == 0) &&
++ (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
++ bus->idlecount++;
++ if (bus->idlecount > bus->idletime) {
++ brcmf_dbg(SDIO, "idle\n");
++ sdio_claim_host(bus->sdiodev->func[1]);
++ brcmf_sdio_wd_timer(bus, 0);
+ bus->idlecount = 0;
+- if (bus->activity) {
+- bus->activity = false;
+- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+- } else {
+- brcmf_dbg(SDIO, "idle\n");
+- sdio_claim_host(bus->sdiodev->func[1]);
+- brcmf_sdio_bus_sleep(bus, true, false);
+- sdio_release_host(bus->sdiodev->func[1]);
+- }
++ brcmf_sdio_bus_sleep(bus, true, false);
++ sdio_release_host(bus->sdiodev->func[1]);
+ }
++ } else {
++ bus->idlecount = 0;
+ }
+-
+- return (atomic_read(&bus->ipend) > 0);
+ }
+
+ static void brcmf_sdio_dataworker(struct work_struct *work)
+@@ -3651,8 +3629,11 @@ static void brcmf_sdio_dataworker(struct
+ datawork);
+
+ while (atomic_read(&bus->dpc_tskcnt)) {
++ atomic_set(&bus->dpc_running, 1);
+ atomic_set(&bus->dpc_tskcnt, 0);
+ brcmf_sdio_dpc(bus);
++ bus->idlecount = 0;
++ atomic_set(&bus->dpc_running, 0);
+ }
+ if (brcmf_sdiod_freezing(bus->sdiodev)) {
+ brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
+@@ -4154,6 +4135,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+ }
+ /* Initialize DPC thread */
+ atomic_set(&bus->dpc_tskcnt, 0);
++ atomic_set(&bus->dpc_running, 0);
+
+ /* Assign bus interface call back */
+ bus->sdiodev->bus_if->dev = bus->sdiodev->dev;