brcmfmac: Fix oops when SDIO device is removed.
authorHante Meuleman <meuleman@broadcom.com>
Fri, 6 Mar 2015 17:40:38 +0000 (18:40 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Fri, 13 Mar 2015 13:16:30 +0000 (15:16 +0200)
On removal of SDIO card both functions of card will be getting
a remove call. When the first is hanging in ctrl frame xmit then
the second will cause oops. This patch fixes the xmit ctrl
handling in case of serious errors and also limits the handling
for remove to function 1 only.

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>
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/sdio.c

index c438ccdb6ed8215ef0c1470adde8522c1e355944..ffb0e2d382ea8b191770e913ec23407cf0f59f62 100644 (file)
@@ -1194,7 +1194,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
        brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
        brcmf_dbg(SDIO, "Function: %d\n", func->num);
 
-       if (func->num != 1 && func->num != 2)
+       if (func->num != 1)
                return;
 
        bus_if = dev_get_drvdata(&func->dev);
index 257ee70feb5b143d8e9b5acbf59115f917bc072f..c54ba4f8b489eac290e560a1251c3d14a84f2a0b 100644 (file)
@@ -2740,6 +2740,11 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
        if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) {
                brcmf_err("failed backplane access over SDIO, halting operation\n");
                atomic_set(&bus->intstatus, 0);
+               if (bus->ctrl_frame_stat) {
+                       bus->ctrl_frame_err = -ENODEV;
+                       bus->ctrl_frame_stat = false;
+                       brcmf_sdio_wait_event_wakeup(bus);
+               }
        } else if (atomic_read(&bus->intstatus) ||
                   atomic_read(&bus->ipend) > 0 ||
                   (!atomic_read(&bus->fcstate) &&