Commit e75db4e3 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: re-enable interrupts properly in hw recovery

Recent changes done to start/restart sequences
broke hw recovery in some hw configurations. The
pci transport was stopped twice however due to a
workaround in the pci disabling code the
disable/enable for first msi interrupt was not
balanced. This ended up with irqs not being
properly re-enabled and the following print out
during recovery:

 ath10k: failed to receive control response completion, polling..
 ath10k: Service connect timeout: -110
 ath10k: Could not init core: -110

Legacy interrupt mode was unaffected while msi
ranged mode would be partially crippled (it would
miss fw indication interrupts but otherwise it
worked fine).

This fixes completely broken fw recovery for a
single msi interrupt mode and fixes subsequent fw
crash reports for msi range interrupt mode.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 6a5d088a
......@@ -1172,16 +1172,8 @@ static void ath10k_pci_irq_disable(struct ath10k *ar)
int i;
ath10k_ce_disable_interrupts(ar);
/* Regardless how many interrupts were assigned for MSI the first one
* is always used for firmware indications (crashes). There's no way to
* mask the irq in the device so call disable_irq(). Legacy (shared)
* interrupts can be masked on the device though.
*/
if (ar_pci->num_msi_intrs > 0)
disable_irq(ar_pci->pdev->irq);
else
ath10k_pci_disable_and_clear_legacy_irq(ar);
ath10k_pci_disable_and_clear_legacy_irq(ar);
/* FIXME: How to mask all MSI interrupts? */
for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
synchronize_irq(ar_pci->pdev->irq + i);
......@@ -1189,15 +1181,9 @@ static void ath10k_pci_irq_disable(struct ath10k *ar)
static void ath10k_pci_irq_enable(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
ath10k_ce_enable_interrupts(ar);
/* See comment in ath10k_pci_irq_disable() */
if (ar_pci->num_msi_intrs > 0)
enable_irq(ar_pci->pdev->irq);
else
ath10k_pci_enable_legacy_irq(ar);
ath10k_pci_enable_legacy_irq(ar);
/* FIXME: How to unmask all MSI interrupts? */
}
static int ath10k_pci_hif_start(struct ath10k *ar)
......@@ -1311,14 +1297,21 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
{
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
ath10k_pci_irq_disable(ar);
ath10k_pci_flush(ar);
/* Most likely the device has HTT Rx ring configured. The only way to
* prevent the device from accessing (and possible corrupting) host
* memory is to reset the chip now.
*
* There's also no known way of masking MSI interrupts on the device.
* For ranged MSI the CE-related interrupts can be masked. However
* regardless how many MSI interrupts are assigned the first one
* is always used for firmware indications (crashes) and cannot be
* masked. To prevent the device from asserting the interrupt reset it
* before proceeding with cleanup.
*/
ath10k_pci_warm_reset(ar);
ath10k_pci_irq_disable(ar);
ath10k_pci_flush(ar);
}
static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment