[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20200214161147.15842-219-sashal@kernel.org>
Date: Fri, 14 Feb 2020 11:11:14 -0500
From: Sasha Levin <sashal@...nel.org>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
Cc: Bryan O'Donoghue <bryan.odonoghue@...aro.org>,
Kalle Valo <kvalo@...eaurora.org>,
Sasha Levin <sashal@...nel.org>, ath10k@...ts.infradead.org,
linux-wireless@...r.kernel.org, netdev@...r.kernel.org
Subject: [PATCH AUTOSEL 4.19 219/252] ath10k: pci: Only dump ATH10K_MEM_REGION_TYPE_IOREG when safe
From: Bryan O'Donoghue <bryan.odonoghue@...aro.org>
[ Upstream commit d239380196c4e27a26fa4bea73d2bf994c14ec2d ]
ath10k_pci_dump_memory_reg() will try to access memory of type
ATH10K_MEM_REGION_TYPE_IOREG however, if a hardware restart is in progress
this can crash a system.
Individual ioread32() time has been observed to jump from 15-20 ticks to >
80k ticks followed by a secure-watchdog bite and a system reset.
Work around this corner case by only issuing the read transaction when the
driver state is ATH10K_STATE_ON.
Tested-on: QCA9988 PCI 10.4-3.9.0.2-00044
Fixes: 219cc084c6706 ("ath10k: add memory dump support QCA9984")
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@...aro.org>
Signed-off-by: Kalle Valo <kvalo@...eaurora.org>
Signed-off-by: Sasha Levin <sashal@...nel.org>
---
drivers/net/wireless/ath/ath10k/pci.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 2a503aacf0c64..caece8339a50a 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1613,11 +1613,22 @@ static int ath10k_pci_dump_memory_reg(struct ath10k *ar,
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
u32 i;
+ int ret;
+
+ mutex_lock(&ar->conf_mutex);
+ if (ar->state != ATH10K_STATE_ON) {
+ ath10k_warn(ar, "Skipping pci_dump_memory_reg invalid state\n");
+ ret = -EIO;
+ goto done;
+ }
for (i = 0; i < region->len; i += 4)
*(u32 *)(buf + i) = ioread32(ar_pci->mem + region->start + i);
- return region->len;
+ ret = region->len;
+done:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
}
/* if an error happened returns < 0, otherwise the length */
@@ -1713,7 +1724,11 @@ static void ath10k_pci_dump_memory(struct ath10k *ar,
count = ath10k_pci_dump_memory_sram(ar, current_region, buf);
break;
case ATH10K_MEM_REGION_TYPE_IOREG:
- count = ath10k_pci_dump_memory_reg(ar, current_region, buf);
+ ret = ath10k_pci_dump_memory_reg(ar, current_region, buf);
+ if (ret < 0)
+ break;
+
+ count = ret;
break;
default:
ret = ath10k_pci_dump_memory_generic(ar, current_region, buf);
--
2.20.1
Powered by blists - more mailing lists