summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChi-Hsien Lin <chi-hsien.lin@cypress.com>2020-06-22 09:48:51 -0500
committerKalle Valo <kvalo@codeaurora.org>2020-07-14 12:48:34 +0300
commit7836102a750a92ddec19b7cd997a76f05c0a16ea (patch)
tree5af7acecea395fc3dbc5048b57ff0143ab456b7b /drivers
parent0d9de08da52a6cbda290d125d96a0015e172186f (diff)
downloadlinux-7836102a750a92ddec19b7cd997a76f05c0a16ea.tar.bz2
brcmfmac: reset SDIO bus on a firmware crash
commit 4684997d9eea ("brcmfmac: reset PCIe bus on a firmware crash") adds a reset function to recover firmware trap for PCIe bus. This commit adds an implementation for SDIO bus. Upon SDIO firmware trap, do below: - Remove the device - Reset hardware - Probe the device again Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/20200622144851.165248-1-chi-hsien.lin@cypress.com
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c34
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h3
3 files changed, 38 insertions, 3 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 46346cb3bc84..1a7ab49295aa 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -863,7 +863,7 @@ static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev)
}
#endif /* CONFIG_PM_SLEEP */
-static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
+int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
{
sdiodev->state = BRCMF_SDIOD_DOWN;
if (sdiodev->bus) {
@@ -898,7 +898,7 @@ static void brcmf_sdiod_host_fixup(struct mmc_host *host)
host->caps |= MMC_CAP_NONREMOVABLE;
}
-static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
+int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
{
int ret = 0;
unsigned int f2_blksz = SDIO_FUNC2_BLOCKSIZE;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 1e66535e23f5..e8712ad3ac45 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -16,6 +16,7 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/core.h>
#include <linux/semaphore.h>
#include <linux/firmware.h>
#include <linux/module.h>
@@ -4126,6 +4127,36 @@ int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
return 0;
}
+static int brcmf_sdio_bus_reset(struct device *dev)
+{
+ int ret = 0;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+
+ brcmf_dbg(SDIO, "Enter\n");
+
+ /* start by unregistering irqs */
+ brcmf_sdiod_intr_unregister(sdiodev);
+
+ brcmf_sdiod_remove(sdiodev);
+
+ /* reset the adapter */
+ sdio_claim_host(sdiodev->func1);
+ mmc_hw_reset(sdiodev->func1->card->host);
+ sdio_release_host(sdiodev->func1);
+
+ brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
+
+ ret = brcmf_sdiod_probe(sdiodev);
+ if (ret) {
+ brcmf_err("Failed to probe after sdio device reset: ret %d\n",
+ ret);
+ brcmf_sdiod_remove(sdiodev);
+ }
+
+ return ret;
+}
+
static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.stop = brcmf_sdio_bus_stop,
.preinit = brcmf_sdio_bus_preinit,
@@ -4137,7 +4168,8 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.get_ramsize = brcmf_sdio_bus_get_ramsize,
.get_memdump = brcmf_sdio_bus_get_memdump,
.get_fwname = brcmf_sdio_get_fwname,
- .debugfs_create = brcmf_sdio_debugfs_create
+ .debugfs_create = brcmf_sdio_debugfs_create,
+ .reset = brcmf_sdio_bus_reset
};
#define BRCMF_SDIO_FW_CODE 0
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 163fd664780a..12108927fb50 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -367,6 +367,9 @@ static inline void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev)
}
#endif /* CONFIG_PM_SLEEP */
+int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev);
+
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdio_remove(struct brcmf_sdio *bus);
void brcmf_sdio_isr(struct brcmf_sdio *bus);