summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c')
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index d24b80e492e0..869c4872d399 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -911,6 +911,7 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
return ret;
}
switch (sdiodev->func2->device) {
+ case SDIO_DEVICE_ID_BROADCOM_43752:
case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE;
break;
@@ -1069,6 +1070,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
bus_if = kzalloc_obj(*bus_if);
if (!bus_if)
return -ENOMEM;
+ mutex_init(&bus_if->bus_reset_lock);
sdiodev = kzalloc_obj(*sdiodev);
if (!sdiodev) {
kfree(bus_if);
@@ -1130,6 +1132,14 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
if (func->num != 1)
return;
+ /* Drain bus_reset before the shared brcmf_sdiod_remove()
+ * teardown, which the SDIO reset callback also reaches. The
+ * data worker can arm bus_reset via brcmf_fw_crashed(); cancel
+ * it first.
+ */
+ brcmf_sdio_cancel_datawork(sdiodev->bus);
+ brcmf_bus_cancel_reset_work(bus_if);
+
/* only proceed with rest of cleanup if func 1 */
brcmf_sdiod_remove(sdiodev);
@@ -1204,6 +1214,8 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
} else {
/* power will be cut so remove device, probe again in resume */
brcmf_sdiod_intr_unregister(sdiodev);
+ brcmf_sdio_cancel_datawork(sdiodev->bus);
+ brcmf_bus_cancel_reset_work(bus_if);
ret = brcmf_sdiod_remove(sdiodev);
if (ret)
brcmf_err("Failed to remove device on suspend\n");
@@ -1229,6 +1241,8 @@ static int brcmf_ops_sdio_resume(struct device *dev)
ret = brcmf_sdiod_probe(sdiodev);
if (ret)
brcmf_err("Failed to probe device on resume\n");
+ else
+ brcmf_bus_allow_reset_work(bus_if);
} else {
if (sdiodev->wowl_enabled && sdiodev->settings->bus.sdio.oob_irq_supported)
disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);