add chaos_calmer branch
[15.05/openwrt.git] / package / kernel / mac80211 / patches / 336-brcmfmac-Simplify-watchdog-sleep.patch
1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Fri, 6 Mar 2015 18:40:39 +0100
3 Subject: [PATCH] brcmfmac: Simplify watchdog sleep.
4
5 The watchdog thread is used to put the SDIO bus to sleep when the
6 system is idling. This patch simplifies the way it is determined
7 when sleep can be entered.
8
9 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
10 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
11 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
12 Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
13 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
14 Signed-off-by: Arend van Spriel <arend@broadcom.com>
15 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
16 ---
17
18 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
19 +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
20 @@ -485,10 +485,9 @@ struct brcmf_sdio {
21  #endif                         /* DEBUG */
22  
23         uint clkstate;          /* State of sd and backplane clock(s) */
24 -       bool activity;          /* Activity flag for clock down */
25         s32 idletime;           /* Control for activity timeout */
26 -       s32 idlecount;  /* Activity timeout counter */
27 -       s32 idleclock;  /* How to set bus driver when idle */
28 +       s32 idlecount;          /* Activity timeout counter */
29 +       s32 idleclock;          /* How to set bus driver when idle */
30         bool rxflow_mode;       /* Rx flow control mode */
31         bool rxflow;            /* Is rx flow control on */
32         bool alp_only;          /* Don't use HT clock (ALP only) */
33 @@ -511,6 +510,7 @@ struct brcmf_sdio {
34         struct workqueue_struct *brcmf_wq;
35         struct work_struct datawork;
36         atomic_t dpc_tskcnt;
37 +       atomic_t dpc_running;
38  
39         bool txoff;             /* Transmit flow-controlled */
40         struct brcmf_sdio_count sdcnt;
41 @@ -959,13 +959,8 @@ static int brcmf_sdio_clkctl(struct brcm
42         brcmf_dbg(SDIO, "Enter\n");
43  
44         /* Early exit if we're already there */
45 -       if (bus->clkstate == target) {
46 -               if (target == CLK_AVAIL) {
47 -                       brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
48 -                       bus->activity = true;
49 -               }
50 +       if (bus->clkstate == target)
51                 return 0;
52 -       }
53  
54         switch (target) {
55         case CLK_AVAIL:
56 @@ -975,7 +970,6 @@ static int brcmf_sdio_clkctl(struct brcm
57                 /* Now request HT Avail on the backplane */
58                 brcmf_sdio_htclk(bus, true, pendok);
59                 brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
60 -               bus->activity = true;
61                 break;
62  
63         case CLK_SDONLY:
64 @@ -1024,17 +1018,6 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
65  
66                 /* Going to sleep */
67                 if (sleep) {
68 -                       /* Don't sleep if something is pending */
69 -                       if (atomic_read(&bus->intstatus) ||
70 -                           atomic_read(&bus->ipend) > 0 ||
71 -                           bus->ctrl_frame_stat ||
72 -                           (!atomic_read(&bus->fcstate) &&
73 -                           brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
74 -                           data_ok(bus))) {
75 -                                err = -EBUSY;
76 -                                goto done;
77 -                       }
78 -
79                         clkcsr = brcmf_sdiod_regrb(bus->sdiodev,
80                                                    SBSDIO_FUNC1_CHIPCLKCSR,
81                                                    &err);
82 @@ -1045,11 +1028,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
83                                                   SBSDIO_ALP_AVAIL_REQ, &err);
84                         }
85                         err = brcmf_sdio_kso_control(bus, false);
86 -                       /* disable watchdog */
87 -                       if (!err)
88 -                               brcmf_sdio_wd_timer(bus, 0);
89                 } else {
90 -                       bus->idlecount = 0;
91                         err = brcmf_sdio_kso_control(bus, true);
92                 }
93                 if (err) {
94 @@ -3566,7 +3545,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
95         queue_work(bus->brcmf_wq, &bus->datawork);
96  }
97  
98 -static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
99 +static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
100  {
101         brcmf_dbg(TIMER, "Enter\n");
102  
103 @@ -3627,22 +3606,21 @@ static bool brcmf_sdio_bus_watchdog(stru
104  #endif                         /* DEBUG */
105  
106         /* On idle timeout clear activity flag and/or turn off clock */
107 -       if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
108 -               if (++bus->idlecount >= bus->idletime) {
109 +       if ((atomic_read(&bus->dpc_tskcnt) == 0) &&
110 +           (atomic_read(&bus->dpc_running) == 0) &&
111 +           (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
112 +               bus->idlecount++;
113 +               if (bus->idlecount > bus->idletime) {
114 +                       brcmf_dbg(SDIO, "idle\n");
115 +                       sdio_claim_host(bus->sdiodev->func[1]);
116 +                       brcmf_sdio_wd_timer(bus, 0);
117                         bus->idlecount = 0;
118 -                       if (bus->activity) {
119 -                               bus->activity = false;
120 -                               brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
121 -                       } else {
122 -                               brcmf_dbg(SDIO, "idle\n");
123 -                               sdio_claim_host(bus->sdiodev->func[1]);
124 -                               brcmf_sdio_bus_sleep(bus, true, false);
125 -                               sdio_release_host(bus->sdiodev->func[1]);
126 -                       }
127 +                       brcmf_sdio_bus_sleep(bus, true, false);
128 +                       sdio_release_host(bus->sdiodev->func[1]);
129                 }
130 +       } else {
131 +               bus->idlecount = 0;
132         }
133 -
134 -       return (atomic_read(&bus->ipend) > 0);
135  }
136  
137  static void brcmf_sdio_dataworker(struct work_struct *work)
138 @@ -3651,8 +3629,11 @@ static void brcmf_sdio_dataworker(struct
139                                               datawork);
140  
141         while (atomic_read(&bus->dpc_tskcnt)) {
142 +               atomic_set(&bus->dpc_running, 1);
143                 atomic_set(&bus->dpc_tskcnt, 0);
144                 brcmf_sdio_dpc(bus);
145 +               bus->idlecount = 0;
146 +               atomic_set(&bus->dpc_running, 0);
147         }
148         if (brcmf_sdiod_freezing(bus->sdiodev)) {
149                 brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
150 @@ -4154,6 +4135,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
151         }
152         /* Initialize DPC thread */
153         atomic_set(&bus->dpc_tskcnt, 0);
154 +       atomic_set(&bus->dpc_running, 0);
155  
156         /* Assign bus interface call back */
157         bus->sdiodev->bus_if->dev = bus->sdiodev->dev;