mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-07-01 16:27:08 +08:00
90 lines
2.9 KiB
Diff
90 lines
2.9 KiB
Diff
From e94b07493da31705c3fdd0b2854f0cffe1dacb3c Mon Sep 17 00:00:00 2001
|
|
From: Baochen Qiang <bqiang@codeaurora.org>
|
|
Date: Fri, 19 Nov 2021 15:36:26 +0200
|
|
Subject: [PATCH] ath11k: Set IRQ affinity to CPU0 in case of one MSI vector
|
|
|
|
With VT-d disabled on Intel platform, ath11k gets only one MSI
|
|
vector. In that case, ath11k does not free IRQ when doing suspend,
|
|
hence the kernel has to migrate it to CPU0 (if it was affine to
|
|
other CPUs) and allocates a new MSI vector. However, ath11k has
|
|
no chance to reconfig it to HW srngs during this phase, thus
|
|
ath11k fails to resume.
|
|
|
|
This issue can be fixed by setting IRQ affinity to CPU0 before
|
|
request_irq is called. With such affinity, migration will not
|
|
happen and thus the vector keeps unchanged during suspend/resume.
|
|
|
|
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
|
|
|
|
Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
|
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
|
Link: https://lore.kernel.org/r/20211026041732.5323-1-bqiang@codeaurora.org
|
|
---
|
|
drivers/net/wireless/ath/ath11k/pci.c | 25 +++++++++++++++++++++++--
|
|
1 file changed, 23 insertions(+), 2 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/pci.c
|
|
@@ -849,6 +849,15 @@ static int ath11k_pci_ext_irq_config(str
|
|
return 0;
|
|
}
|
|
|
|
+static int ath11k_pci_set_irq_affinity_hint(struct ath11k_pci *ab_pci,
|
|
+ const struct cpumask *m)
|
|
+{
|
|
+ if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
|
+ return 0;
|
|
+
|
|
+ return irq_set_affinity_hint(ab_pci->pdev->irq, m);
|
|
+}
|
|
+
|
|
static int ath11k_pci_config_irq(struct ath11k_base *ab)
|
|
{
|
|
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
|
@@ -865,6 +874,12 @@ static int ath11k_pci_config_irq(struct
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0));
|
|
+ if (ret) {
|
|
+ ath11k_err(ab, "failed to set irq affinity %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
/* Configure CE irqs */
|
|
for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
|
|
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
|
@@ -884,7 +899,7 @@ static int ath11k_pci_config_irq(struct
|
|
if (ret) {
|
|
ath11k_err(ab, "failed to request irq %d: %d\n",
|
|
irq_idx, ret);
|
|
- return ret;
|
|
+ goto err_irq_affinity_cleanup;
|
|
}
|
|
|
|
ab->irq_num[irq_idx] = irq;
|
|
@@ -895,9 +910,13 @@ static int ath11k_pci_config_irq(struct
|
|
|
|
ret = ath11k_pci_ext_irq_config(ab);
|
|
if (ret)
|
|
- return ret;
|
|
+ goto err_irq_affinity_cleanup;
|
|
|
|
return 0;
|
|
+
|
|
+err_irq_affinity_cleanup:
|
|
+ ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
|
+ return ret;
|
|
}
|
|
|
|
static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
|
|
@@ -1494,6 +1513,8 @@ static void ath11k_pci_remove(struct pci
|
|
struct ath11k_base *ab = pci_get_drvdata(pdev);
|
|
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
|
|
|
+ ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
|
+
|
|
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
|
ath11k_pci_power_down(ab);
|
|
ath11k_debugfs_soc_destroy(ab);
|