brcmfmac: Use atomic functions for intstatus update.
authorHante Meuleman <meuleman@broadcom.com>
Wed, 26 Feb 2014 12:32:32 +0000 (13:32 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 28 Feb 2014 19:33:26 +0000 (14:33 -0500)
The intstatus in sdio code can be updated from different
threads. To protect intstatus access, atomic functions are
used. The loop was replaced using atomic_set_mask().

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: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c

index ac61419..0ccb7af 100644 (file)
@@ -2449,7 +2449,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
        struct brcmf_core *buscore;
        u32 addr;
        unsigned long val;
-       int n, ret;
+       int ret;
 
        buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
        addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus);
@@ -2457,7 +2457,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
        val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret);
        bus->sdcnt.f1regdata++;
        if (ret != 0)
-               val = 0;
+               return ret;
 
        val &= bus->hostintmask;
        atomic_set(&bus->fcstate, !!(val & I_HMB_FC_STATE));
@@ -2466,13 +2466,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
        if (val) {
                brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
                bus->sdcnt.f1regdata++;
-       }
-
-       if (ret) {
-               atomic_set(&bus->intstatus, 0);
-       } else if (val) {
-               for_each_set_bit(n, &val, 32)
-                       set_bit(n, (unsigned long *)&bus->intstatus.counter);
+               atomic_set_mask(val, &bus->intstatus);
        }
 
        return ret;
@@ -2484,7 +2478,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
        unsigned long intstatus;
        uint txlimit = bus->txbound;    /* Tx frames to send before resched */
        uint framecnt;                  /* Temporary counter of tx/rx frames */
-       int err = 0, n;
+       int err = 0;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -2588,10 +2582,8 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
        }
 
        /* Keep still-pending events for next scheduling */
-       if (intstatus) {
-               for_each_set_bit(n, &intstatus, 32)
-                       set_bit(n, (unsigned long *)&bus->intstatus.counter);
-       }
+       if (intstatus)
+               atomic_set_mask(intstatus, &bus->intstatus);
 
        brcmf_sdio_clrintr(bus);