From a2f6dc90cefd3eb25414444da810975941eaf117 Mon Sep 17 00:00:00 2001
From: Ishan Deshpande <IshanShirish.Deshpande@infineon.com>
Date: Fri, 22 Sep 2023 09:11:52 -0500
Subject: [PATCH 249/296] brcmfmac: Check bus sleep state in isr

Check if the bus is in sleep state in interrupt service routine before
reading the interrupt status register. Wake up the bus if it is in sleep
state as accessing the backplane when bus in sleep may lead to a crash


Signed-off-by: Ishan Deshpande <IshanShirish.Deshpande@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/bcmsdh.c      | 25 +++++++++++++++++++
 .../broadcom/brcm80211/brcmfmac/sdio.c        | 10 ++++++++
 .../broadcom/brcm80211/brcmfmac/sdio.h        |  1 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index a9e8c1891c19..739e351ff478 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -233,6 +233,10 @@ static int brcmf_sdiod_set_backplane_window(struct brcmf_sdio_dev *sdiodev,
 	u32 v, bar0 = addr & SBSDIO_SBWINDOW_MASK;
 	int err = 0, i;
 
+	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
+		brcmf_err("WARN: Write operation when bus is in sleep state\n");
+	}
+
 	if (bar0 == sdiodev->sbwad)
 		return 0;
 
@@ -253,6 +257,10 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 	u32 data = 0;
 	int retval;
 
+	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
+		brcmf_err("WARN: Read operation when bus is in sleep state\n");
+	}
+
 	retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
 	if (retval)
 		goto out;
@@ -277,6 +285,10 @@ void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr,
 {
 	int retval;
 
+	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
+		brcmf_err("WARN: Write operation when bus is in sleep state\n");
+	}
+
 	retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
 	if (retval)
 		goto out;
@@ -300,6 +312,10 @@ static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev,
 	unsigned int req_sz;
 	int err;
 
+	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
+		brcmf_err("WARN: Read operation when bus is in sleep state\n");
+	}
+
 	/* Single skb use the standard mmc interface */
 	req_sz = skb->len + 3;
 	req_sz &= (uint)~3;
@@ -332,6 +348,10 @@ static int brcmf_sdiod_skbuff_write(struct brcmf_sdio_dev *sdiodev,
 	unsigned int req_sz;
 	int err;
 
+	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
+		brcmf_err("WARN: Write operation when bus is in sleep state\n");
+	}
+
 	/* Single skb use the standard mmc interface */
 	req_sz = skb->len + 3;
 	req_sz &= (uint)~3;
@@ -357,6 +377,11 @@ static int mmc_submit_one(struct mmc_data *md, struct mmc_request *mr,
 {
 	int ret;
 
+	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
+		brcmf_err("WARN: %s operation when bus is in sleep state\n",
+			write ? "Write" : "Read");
+	}
+
 	md->sg_len = sg_cnt;
 	md->blocks = req_sz / func_blk_sz;
 	mc->arg |= (*addr & 0x1FFFF) << 9;	/* address */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index acc546f5554c..ad442535415f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -1236,6 +1236,11 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
 
 }
 
+bool brcmf_sdio_bus_sleep_state(struct brcmf_sdio *bus)
+{
+	return bus->sleeping;
+}
+
 #ifdef DEBUG
 static inline bool brcmf_sdio_valid_shared_address(u32 addr)
 {
@@ -4419,6 +4424,11 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr)
 		return;
 	}
 
+	/* Wake up the bus if in sleep */
+	if (brcmf_sdio_bus_sleep_state(bus)) {
+		brcmf_sdio_bus_sleep(bus, false, false);
+	}
+
 	/* Count the interrupt call */
 	bus->sdcnt.intrcount++;
 	if (in_isr)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index d9e0d156365b..e4d884e958e2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -453,6 +453,7 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
 int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep);
 int brcmf_sdio_set_sdbus_clk_width(struct brcmf_sdio *bus, unsigned int flags);
 int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok);
+bool brcmf_sdio_bus_sleep_state(struct brcmf_sdio *bus);
 void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus);
 u32 brcmf_sdio_get_enum_addr(struct brcmf_sdio *bus);
 
-- 
2.25.1

