brcmfmac: raise SDIO host lock to higher level
authorFranky Lin <frankyl@broadcom.com>
Thu, 13 Sep 2012 19:12:02 +0000 (21:12 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 24 Sep 2012 18:59:09 +0000 (14:59 -0400)
Use SDIO host lock to protect the entire communication process
of register access or data read/write rather than function calls
to MMC/SDIO stack only. This can help to avoid unintentional
memory access and unexpected interruption.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@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/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c

index 8e7e6928c93699bf9b7df35f9efc4c9b26928481..0c1d08ae726b3e2e40aa2aa6e1caf3ac57a51ed0 100644 (file)
@@ -249,7 +249,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+       sdio_release_host(sdiodev->func[1]);
        brcmf_dbg(INFO, "data:0x%02x\n", data);
 
        if (ret)
@@ -264,7 +266,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+       sdio_release_host(sdiodev->func[1]);
        brcmf_dbg(INFO, "data:0x%08x\n", data);
 
        if (ret)
@@ -279,7 +283,9 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
+       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
+       sdio_release_host(sdiodev->func[1]);
 
        if (ret)
                *ret = retval;
@@ -291,7 +297,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
+       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
+       sdio_release_host(sdiodev->func[1]);
 
        if (ret)
                *ret = retval;
@@ -356,15 +364,20 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
        brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
                  fn, addr, pkt->len);
 
+       sdio_claim_host(sdiodev->func[1]);
+
        width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
        err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
        if (err)
-               return err;
+               goto done;
 
        incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
        err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
                                         fn, addr, pkt);
 
+done:
+       sdio_release_host(sdiodev->func[1]);
+
        return err;
 }
 
@@ -378,15 +391,20 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
        brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
                  fn, addr, pktq->qlen);
 
+       sdio_claim_host(sdiodev->func[1]);
+
        width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
        err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
        if (err)
-               return err;
+               goto done;
 
        incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
        err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
                                        pktq);
 
+done:
+       sdio_release_host(sdiodev->func[1]);
+
        return err;
 }
 
@@ -428,10 +446,12 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
        if (flags & SDIO_REQ_ASYNC)
                return -ENOTSUPP;
 
+       sdio_claim_host(sdiodev->func[1]);
+
        if (bar0 != sdiodev->sbwad) {
                err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
                if (err)
-                       return err;
+                       goto done;
 
                sdiodev->sbwad = bar0;
        }
@@ -443,8 +463,13 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
        if (width == 4)
                addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
 
-       return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
-                                         addr, pkt);
+       err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
+                                        addr, pkt);
+
+done:
+       sdio_release_host(sdiodev->func[1]);
+
+       return err;
 }
 
 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
@@ -485,8 +510,10 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
        brcmf_dbg(TRACE, "Enter\n");
 
        /* issue abort cmd52 command through F0 */
+       sdio_claim_host(sdiodev->func[1]);
        brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
                                 SDIO_CCCR_ABORT, &t_func);
+       sdio_release_host(sdiodev->func[1]);
 
        brcmf_dbg(TRACE, "Exit\n");
        return 0;
index e0b313c7f5ce48ced1512cc7a3c6c2fc85260515..70f21a4355329b9526b2fe45e3969d9b37d5b7b3 100644 (file)
@@ -103,7 +103,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
        if (regaddr == SDIO_CCCR_IOEx) {
                sdfunc = sdiodev->func[2];
                if (sdfunc) {
-                       sdio_claim_host(sdfunc);
                        if (*byte & SDIO_FUNC_ENABLE_2) {
                                /* Enable Function 2 */
                                err_ret = sdio_enable_func(sdfunc);
@@ -119,7 +118,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
                                                  "Disable F2 failed:%d\n",
                                                  err_ret);
                        }
-                       sdio_release_host(sdfunc);
                }
        } else if ((regaddr == SDIO_CCCR_ABORT) ||
                   (regaddr == SDIO_CCCR_IENx)) {
@@ -128,17 +126,13 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
                if (!sdfunc)
                        return -ENOMEM;
                sdfunc->num = 0;
-               sdio_claim_host(sdfunc);
                sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
-               sdio_release_host(sdfunc);
                kfree(sdfunc);
        } else if (regaddr < 0xF0) {
                brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
                err_ret = -EPERM;
        } else {
-               sdio_claim_host(sdfunc);
                sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
-               sdio_release_host(sdfunc);
        }
 
        return err_ret;
@@ -159,7 +153,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
                /* handle F0 separately */
                err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
        } else {
-               sdio_claim_host(sdiodev->func[func]);
                if (rw) /* CMD52 Write */
                        sdio_writeb(sdiodev->func[func], *byte, regaddr,
                                    &err_ret);
@@ -170,7 +163,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
                        *byte = sdio_readb(sdiodev->func[func], regaddr,
                                           &err_ret);
                }
-               sdio_release_host(sdiodev->func[func]);
        }
 
        if (err_ret)
@@ -197,8 +189,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
        brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
        if (brcmf_pm_resume_error(sdiodev))
                return -EIO;
-       /* Claim host controller */
-       sdio_claim_host(sdiodev->func[func]);
 
        if (rw) {               /* CMD52 Write */
                if (nbytes == 4)
@@ -219,9 +209,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
                        brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
        }
 
-       /* Release host controller */
-       sdio_release_host(sdiodev->func[func]);
-
        if (err_ret)
                brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
                          rw ? "write" : "read", err_ret);
@@ -275,9 +262,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
        if (brcmf_pm_resume_error(sdiodev))
                return -EIO;
 
-       /* Claim host controller */
-       sdio_claim_host(sdiodev->func[func]);
-
        skb_queue_walk(pktq, pkt) {
                uint pkt_len = pkt->len;
                pkt_len += 3;
@@ -300,9 +284,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
                SGCount++;
        }
 
-       /* Release host controller */
-       sdio_release_host(sdiodev->func[func]);
-
        brcmf_dbg(TRACE, "Exit\n");
        return err_ret;
 }
@@ -328,9 +309,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
        if (brcmf_pm_resume_error(sdiodev))
                return -EIO;
 
-       /* Claim host controller */
-       sdio_claim_host(sdiodev->func[func]);
-
        pkt_len += 3;
        pkt_len &= (uint)~3;
 
@@ -344,9 +322,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
                          write ? "TX" : "RX", pkt, addr, pkt_len);
        }
 
-       /* Release host controller */
-       sdio_release_host(sdiodev->func[func]);
-
        return status;
 }
 
index 90a3849b41fecdce8f37456b2094e2fb3490d9fe..619f3cdcb8e2b3bc96f67ae0cd20ee9a93038ea3 100644 (file)
@@ -2564,6 +2564,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
        else
                dsize = size;
 
+       sdio_claim_host(bus->sdiodev->func[1]);
+
        /* Set the backplane window to include the start address */
        bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
        if (bcmerror) {
@@ -2605,6 +2607,8 @@ xfer_done:
                brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n",
                          bus->sdiodev->sbwad);
 
+       sdio_release_host(bus->sdiodev->func[1]);
+
        return bcmerror;
 }