From 38ac13d668f237941c8b77f16375f8f0e4de966a Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 25 Mar 2019 13:50:19 +0100 Subject: [PATCH 4.19] ath10k: restore QCA9880-AR1A (v1) detection To: linux-wireless@vger.kernel.org, ath10k@lists.infradead.org Cc: Kalle Valo This patch restores the old behavior that read the chip_id on the QCA988x before resetting the chip. This needs to be done in this order since the unsupported QCA988x AR1A chips fall off the bus when resetted. Otherwise the next MMIO Op after the reset causes a BUS ERROR and panic. Cc: stable@vger.kernel.org # 4.19 Fixes: 1a7fecb766c8 ("ath10k: reset chip before reading chip_id in probe") Signed-off-by: Christian Lamparter --- drivers/net/wireless/ath/ath10k/pci.c | 36 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c --- a/drivers/net/wireless/ath/ath10k/pci.c 2019-09-08 00:07:21.374565470 +0200 +++ b/drivers/net/wireless/ath/ath10k/pci.c 2019-09-08 00:17:15.365912133 +0200 @@ -3483,7 +3483,7 @@ static int ath10k_pci_probe(struct pci_d struct ath10k_pci *ar_pci; enum ath10k_hw_rev hw_rev; u32 chip_id; - bool pci_ps; + bool pci_ps, is_qca988x = false; int (*pci_soft_reset)(struct ath10k *ar); int (*pci_hard_reset)(struct ath10k *ar); u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr); @@ -3493,6 +3493,7 @@ static int ath10k_pci_probe(struct pci_d case QCA988X_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA988X; pci_ps = false; + is_qca988x = true; pci_soft_reset = ath10k_pci_warm_reset; pci_hard_reset = ath10k_pci_qca988x_chip_reset; targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr; @@ -3612,6 +3613,19 @@ static int ath10k_pci_probe(struct pci_d goto err_deinit_irq; } + /* Read CHIP_ID before reset to catch QCA9880-AR1A v1 devices that + * fall off the bus during chip_reset. These chips have the same pci + * device id as the QCA9880 BR4A or 2R4E. So that's why the check. + */ + if (is_qca988x) { + chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); + if (chip_id != 0xffffffff) { + if (!ath10k_pci_chip_is_supported(pdev->device, + chip_id)) + goto err_unsupported; + } + } + ret = ath10k_pci_chip_reset(ar); if (ret) { ath10k_err(ar, "failed to reset chip: %d\n", ret); @@ -3624,11 +3638,8 @@ static int ath10k_pci_probe(struct pci_d goto err_free_irq; } - if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) { - ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", - pdev->device, chip_id); - goto err_free_irq; - } + if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) + goto err_unsupported; ret = ath10k_core_register(ar, chip_id); if (ret) { @@ -3638,6 +3649,10 @@ static int ath10k_pci_probe(struct pci_d return 0; +err_unsupported: + ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", + pdev->device, bus_params.chip_id); + err_free_irq: ath10k_pci_free_irq(ar); ath10k_pci_rx_retry_sync(ar);