123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- From: Hante Meuleman <[email protected]>
- Date: Wed, 18 Mar 2015 13:25:22 +0100
- Subject: [PATCH] brcmfmac: Add necessary memory barriers for SDIO.
- SDIO uses a thread to handle all communication with the device,
- for this data is exchanged between threads. This data needs proper
- memory barriers to make sure that data "exchange" is going correct.
- Reviewed-by: Arend Van Spriel <[email protected]>
- Reviewed-by: Franky (Zhenhui) Lin <[email protected]>
- Reviewed-by: Pieter-Paul Giesberts <[email protected]>
- Reviewed-by: Daniel (Deognyoun) Kim <[email protected]>
- Signed-off-by: Hante Meuleman <[email protected]>
- Signed-off-by: Arend van Spriel <[email protected]>
- Signed-off-by: Kalle Valo <[email protected]>
- ---
- --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
- +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
- @@ -507,8 +507,8 @@ struct brcmf_sdio {
-
- struct workqueue_struct *brcmf_wq;
- struct work_struct datawork;
- - atomic_t dpc_tskcnt;
- - atomic_t dpc_running;
- + bool dpc_triggered;
- + bool dpc_running;
-
- bool txoff; /* Transmit flow-controlled */
- struct brcmf_sdio_count sdcnt;
- @@ -2713,6 +2713,7 @@ static void brcmf_sdio_dpc(struct brcmf_
- err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
- bus->ctrl_frame_len);
- bus->ctrl_frame_err = err;
- + wmb();
- bus->ctrl_frame_stat = false;
- }
- sdio_release_host(bus->sdiodev->func[1]);
- @@ -2734,6 +2735,7 @@ static void brcmf_sdio_dpc(struct brcmf_
- sdio_claim_host(bus->sdiodev->func[1]);
- if (bus->ctrl_frame_stat) {
- bus->ctrl_frame_err = -ENODEV;
- + wmb();
- bus->ctrl_frame_stat = false;
- brcmf_sdio_wait_event_wakeup(bus);
- }
- @@ -2744,7 +2746,7 @@ static void brcmf_sdio_dpc(struct brcmf_
- (!atomic_read(&bus->fcstate) &&
- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
- data_ok(bus))) {
- - atomic_inc(&bus->dpc_tskcnt);
- + bus->dpc_triggered = true;
- }
- }
-
- @@ -2940,6 +2942,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
- /* Send from dpc */
- bus->ctrl_frame_buf = msg;
- bus->ctrl_frame_len = msglen;
- + wmb();
- bus->ctrl_frame_stat = true;
-
- brcmf_sdio_trigger_dpc(bus);
- @@ -2958,6 +2961,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
- if (!ret) {
- brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
- bus->ctrl_frame_err);
- + rmb();
- ret = bus->ctrl_frame_err;
- }
-
- @@ -3526,8 +3530,8 @@ done:
-
- void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
- {
- - if (atomic_read(&bus->dpc_tskcnt) == 0) {
- - atomic_inc(&bus->dpc_tskcnt);
- + if (!bus->dpc_triggered) {
- + bus->dpc_triggered = true;
- queue_work(bus->brcmf_wq, &bus->datawork);
- }
- }
- @@ -3558,7 +3562,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
- if (!bus->intr)
- brcmf_err("isr w/o interrupt configured!\n");
-
- - atomic_inc(&bus->dpc_tskcnt);
- + bus->dpc_triggered = true;
- queue_work(bus->brcmf_wq, &bus->datawork);
- }
-
- @@ -3578,7 +3582,7 @@ static void brcmf_sdio_bus_watchdog(stru
- if (!bus->intr ||
- (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
-
- - if (atomic_read(&bus->dpc_tskcnt) == 0) {
- + if (!bus->dpc_triggered) {
- u8 devpend;
-
- sdio_claim_host(bus->sdiodev->func[1]);
- @@ -3596,7 +3600,7 @@ static void brcmf_sdio_bus_watchdog(stru
- bus->sdcnt.pollcnt++;
- atomic_set(&bus->ipend, 1);
-
- - atomic_inc(&bus->dpc_tskcnt);
- + bus->dpc_triggered = true;
- queue_work(bus->brcmf_wq, &bus->datawork);
- }
- }
- @@ -3623,17 +3627,21 @@ static void brcmf_sdio_bus_watchdog(stru
- #endif /* DEBUG */
-
- /* On idle timeout clear activity flag and/or turn off clock */
- - 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);
- + if (!bus->dpc_triggered) {
- + rmb();
- + if ((!bus->dpc_running) && (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;
- + brcmf_sdio_bus_sleep(bus, true, false);
- + sdio_release_host(bus->sdiodev->func[1]);
- + }
- + } else {
- bus->idlecount = 0;
- - brcmf_sdio_bus_sleep(bus, true, false);
- - sdio_release_host(bus->sdiodev->func[1]);
- }
- } else {
- bus->idlecount = 0;
- @@ -3645,13 +3653,14 @@ static void brcmf_sdio_dataworker(struct
- struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
- datawork);
-
- - while (atomic_read(&bus->dpc_tskcnt)) {
- - atomic_set(&bus->dpc_running, 1);
- - atomic_set(&bus->dpc_tskcnt, 0);
- + bus->dpc_running = true;
- + wmb();
- + while (ACCESS_ONCE(bus->dpc_triggered)) {
- + bus->dpc_triggered = false;
- brcmf_sdio_dpc(bus);
- bus->idlecount = 0;
- - atomic_set(&bus->dpc_running, 0);
- }
- + bus->dpc_running = false;
- if (brcmf_sdiod_freezing(bus->sdiodev)) {
- brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
- brcmf_sdiod_try_freeze(bus->sdiodev);
- @@ -4144,8 +4153,8 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- bus->watchdog_tsk = NULL;
- }
- /* Initialize DPC thread */
- - atomic_set(&bus->dpc_tskcnt, 0);
- - atomic_set(&bus->dpc_running, 0);
- + bus->dpc_triggered = false;
- + bus->dpc_running = false;
-
- /* Assign bus interface call back */
- bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
|