aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2015-03-18 08:25:22 -0400
committerKalle Valo <kvalo@codeaurora.org>2015-03-20 03:03:36 -0400
commit2c64e16d1ff1228df837508ab32e8a060cb06907 (patch)
treed5fd39ba02e8edb551091ba08be783a1d01c4805 /drivers/net/wireless/brcm80211/brcmfmac
parent063d51776bd60ebf2587682eb394851c792e58d9 (diff)
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 <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>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index 17a7212cfd70..38fa0e8f859d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -507,8 +507,8 @@ struct brcmf_sdio {
507 507
508 struct workqueue_struct *brcmf_wq; 508 struct workqueue_struct *brcmf_wq;
509 struct work_struct datawork; 509 struct work_struct datawork;
510 atomic_t dpc_tskcnt; 510 bool dpc_triggered;
511 atomic_t dpc_running; 511 bool dpc_running;
512 512
513 bool txoff; /* Transmit flow-controlled */ 513 bool txoff; /* Transmit flow-controlled */
514 struct brcmf_sdio_count sdcnt; 514 struct brcmf_sdio_count sdcnt;
@@ -2713,6 +2713,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
2713 err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, 2713 err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
2714 bus->ctrl_frame_len); 2714 bus->ctrl_frame_len);
2715 bus->ctrl_frame_err = err; 2715 bus->ctrl_frame_err = err;
2716 wmb();
2716 bus->ctrl_frame_stat = false; 2717 bus->ctrl_frame_stat = false;
2717 } 2718 }
2718 sdio_release_host(bus->sdiodev->func[1]); 2719 sdio_release_host(bus->sdiodev->func[1]);
@@ -2734,6 +2735,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
2734 sdio_claim_host(bus->sdiodev->func[1]); 2735 sdio_claim_host(bus->sdiodev->func[1]);
2735 if (bus->ctrl_frame_stat) { 2736 if (bus->ctrl_frame_stat) {
2736 bus->ctrl_frame_err = -ENODEV; 2737 bus->ctrl_frame_err = -ENODEV;
2738 wmb();
2737 bus->ctrl_frame_stat = false; 2739 bus->ctrl_frame_stat = false;
2738 brcmf_sdio_wait_event_wakeup(bus); 2740 brcmf_sdio_wait_event_wakeup(bus);
2739 } 2741 }
@@ -2744,7 +2746,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
2744 (!atomic_read(&bus->fcstate) && 2746 (!atomic_read(&bus->fcstate) &&
2745 brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && 2747 brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
2746 data_ok(bus))) { 2748 data_ok(bus))) {
2747 atomic_inc(&bus->dpc_tskcnt); 2749 bus->dpc_triggered = true;
2748 } 2750 }
2749} 2751}
2750 2752
@@ -2940,6 +2942,7 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
2940 /* Send from dpc */ 2942 /* Send from dpc */
2941 bus->ctrl_frame_buf = msg; 2943 bus->ctrl_frame_buf = msg;
2942 bus->ctrl_frame_len = msglen; 2944 bus->ctrl_frame_len = msglen;
2945 wmb();
2943 bus->ctrl_frame_stat = true; 2946 bus->ctrl_frame_stat = true;
2944 2947
2945 brcmf_sdio_trigger_dpc(bus); 2948 brcmf_sdio_trigger_dpc(bus);
@@ -2958,6 +2961,7 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
2958 if (!ret) { 2961 if (!ret) {
2959 brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", 2962 brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
2960 bus->ctrl_frame_err); 2963 bus->ctrl_frame_err);
2964 rmb();
2961 ret = bus->ctrl_frame_err; 2965 ret = bus->ctrl_frame_err;
2962 } 2966 }
2963 2967
@@ -3526,8 +3530,8 @@ done:
3526 3530
3527void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) 3531void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
3528{ 3532{
3529 if (atomic_read(&bus->dpc_tskcnt) == 0) { 3533 if (!bus->dpc_triggered) {
3530 atomic_inc(&bus->dpc_tskcnt); 3534 bus->dpc_triggered = true;
3531 queue_work(bus->brcmf_wq, &bus->datawork); 3535 queue_work(bus->brcmf_wq, &bus->datawork);
3532 } 3536 }
3533} 3537}
@@ -3558,7 +3562,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
3558 if (!bus->intr) 3562 if (!bus->intr)
3559 brcmf_err("isr w/o interrupt configured!\n"); 3563 brcmf_err("isr w/o interrupt configured!\n");
3560 3564
3561 atomic_inc(&bus->dpc_tskcnt); 3565 bus->dpc_triggered = true;
3562 queue_work(bus->brcmf_wq, &bus->datawork); 3566 queue_work(bus->brcmf_wq, &bus->datawork);
3563} 3567}
3564 3568
@@ -3578,7 +3582,7 @@ static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
3578 if (!bus->intr || 3582 if (!bus->intr ||
3579 (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { 3583 (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
3580 3584
3581 if (atomic_read(&bus->dpc_tskcnt) == 0) { 3585 if (!bus->dpc_triggered) {
3582 u8 devpend; 3586 u8 devpend;
3583 3587
3584 sdio_claim_host(bus->sdiodev->func[1]); 3588 sdio_claim_host(bus->sdiodev->func[1]);
@@ -3596,7 +3600,7 @@ static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
3596 bus->sdcnt.pollcnt++; 3600 bus->sdcnt.pollcnt++;
3597 atomic_set(&bus->ipend, 1); 3601 atomic_set(&bus->ipend, 1);
3598 3602
3599 atomic_inc(&bus->dpc_tskcnt); 3603 bus->dpc_triggered = true;
3600 queue_work(bus->brcmf_wq, &bus->datawork); 3604 queue_work(bus->brcmf_wq, &bus->datawork);
3601 } 3605 }
3602 } 3606 }
@@ -3623,17 +3627,21 @@ static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
3623#endif /* DEBUG */ 3627#endif /* DEBUG */
3624 3628
3625 /* On idle timeout clear activity flag and/or turn off clock */ 3629 /* On idle timeout clear activity flag and/or turn off clock */
3626 if ((atomic_read(&bus->dpc_tskcnt) == 0) && 3630 if (!bus->dpc_triggered) {
3627 (atomic_read(&bus->dpc_running) == 0) && 3631 rmb();
3628 (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { 3632 if ((!bus->dpc_running) && (bus->idletime > 0) &&
3629 bus->idlecount++; 3633 (bus->clkstate == CLK_AVAIL)) {
3630 if (bus->idlecount > bus->idletime) { 3634 bus->idlecount++;
3631 brcmf_dbg(SDIO, "idle\n"); 3635 if (bus->idlecount > bus->idletime) {
3632 sdio_claim_host(bus->sdiodev->func[1]); 3636 brcmf_dbg(SDIO, "idle\n");
3633 brcmf_sdio_wd_timer(bus, 0); 3637 sdio_claim_host(bus->sdiodev->func[1]);
3638 brcmf_sdio_wd_timer(bus, 0);
3639 bus->idlecount = 0;
3640 brcmf_sdio_bus_sleep(bus, true, false);
3641 sdio_release_host(bus->sdiodev->func[1]);
3642 }
3643 } else {
3634 bus->idlecount = 0; 3644 bus->idlecount = 0;
3635 brcmf_sdio_bus_sleep(bus, true, false);
3636 sdio_release_host(bus->sdiodev->func[1]);
3637 } 3645 }
3638 } else { 3646 } else {
3639 bus->idlecount = 0; 3647 bus->idlecount = 0;
@@ -3645,13 +3653,14 @@ static void brcmf_sdio_dataworker(struct work_struct *work)
3645 struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, 3653 struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
3646 datawork); 3654 datawork);
3647 3655
3648 while (atomic_read(&bus->dpc_tskcnt)) { 3656 bus->dpc_running = true;
3649 atomic_set(&bus->dpc_running, 1); 3657 wmb();
3650 atomic_set(&bus->dpc_tskcnt, 0); 3658 while (ACCESS_ONCE(bus->dpc_triggered)) {
3659 bus->dpc_triggered = false;
3651 brcmf_sdio_dpc(bus); 3660 brcmf_sdio_dpc(bus);
3652 bus->idlecount = 0; 3661 bus->idlecount = 0;
3653 atomic_set(&bus->dpc_running, 0);
3654 } 3662 }
3663 bus->dpc_running = false;
3655 if (brcmf_sdiod_freezing(bus->sdiodev)) { 3664 if (brcmf_sdiod_freezing(bus->sdiodev)) {
3656 brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); 3665 brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
3657 brcmf_sdiod_try_freeze(bus->sdiodev); 3666 brcmf_sdiod_try_freeze(bus->sdiodev);
@@ -4144,8 +4153,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
4144 bus->watchdog_tsk = NULL; 4153 bus->watchdog_tsk = NULL;
4145 } 4154 }
4146 /* Initialize DPC thread */ 4155 /* Initialize DPC thread */
4147 atomic_set(&bus->dpc_tskcnt, 0); 4156 bus->dpc_triggered = false;
4148 atomic_set(&bus->dpc_running, 0); 4157 bus->dpc_running = false;
4149 4158
4150 /* Assign bus interface call back */ 4159 /* Assign bus interface call back */
4151 bus->sdiodev->bus_if->dev = bus->sdiodev->dev; 4160 bus->sdiodev->bus_if->dev = bus->sdiodev->dev;