ath10k: pci: Only dump ATH10K_MEM_REGION_TYPE_IOREG when safe

commit d239380196 upstream.

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: 219cc084c6 ("ath10k: add memory dump support QCA9984")
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Bryan O'Donoghue 2019-12-19 13:15:38 +00:00 committed by Greg Kroah-Hartman
parent 4f0e6425a2
commit 15818c08ca
1 changed files with 17 additions and 2 deletions

View File

@ -1604,11 +1604,22 @@ static int ath10k_pci_dump_memory_reg(struct ath10k *ar,
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
u32 i; 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) for (i = 0; i < region->len; i += 4)
*(u32 *)(buf + i) = ioread32(ar_pci->mem + region->start + i); *(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 */ /* if an error happened returns < 0, otherwise the length */
@ -1704,7 +1715,11 @@ static void ath10k_pci_dump_memory(struct ath10k *ar,
count = ath10k_pci_dump_memory_sram(ar, current_region, buf); count = ath10k_pci_dump_memory_sram(ar, current_region, buf);
break; break;
case ATH10K_MEM_REGION_TYPE_IOREG: 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; break;
default: default:
ret = ath10k_pci_dump_memory_generic(ar, current_region, buf); ret = ath10k_pci_dump_memory_generic(ar, current_region, buf);