Message ID | 20211026041636.5008-1-bqiang@codeaurora.org (mailing list archive) |
---|---|
State | Accepted |
Commit | 87b4072d7ef818e368b0f4162a1af2fb4727f51c |
Delegated to: | Kalle Valo |
Headers | show |
Series | ath11k: support one MSI vector | expand |
Baochen Qiang <bqiang@codeaurora.org> wrote: > The reservation mode of interrupts in kernel assigns a dummy vector > when the interrupt is allocated and assigns a real vector when the > request_irq is called. The reservation mode helps to ease vector > pressure when devices with a large amount of queues/interrupts > are initialized, but only a minimal subset of those queues/interrupts > is actually used. > > So on reservation mode, the msi_data may change after request_irq > is called, so ath11k reads msi_data again after request_irq is called, > and then the correct msi_data is programmed into QCA6390 hardware > components. Without this change, spurious interrupt occurs in case of > one MSI vector. When VT-d in BIOS is enabled and ath11k can get 32 MSI > vectors, ath11k always get the same msi_data before and after request_irq, > that's why this change is only required when one MSI vector is to be > supported. > > Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 > > Signed-off-by: Carl Huang <cjhuang@codeaurora.org> > Signed-off-by: Kalle Valo <kvalo@codeaurora.org> 7 patches applied to ath-next branch of ath.git, thanks. 87b4072d7ef8 ath11k: get msi_data again after request_irq is called 01279bcd01d9 ath11k: add CE and ext IRQ flag to indicate irq_handler 4ab4693f327a ath11k: use ATH11K_PCI_IRQ_DP_OFFSET for DP IRQ c41a6700b276 ath11k: refactor multiple MSI vector implementation ac6e73483f7b ath11k: add support one MSI vector 915a081ff307 ath11k: do not restore ASPM in case of single MSI vector e94b07493da3 ath11k: Set IRQ affinity to CPU0 in case of one MSI vector
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 3d353e7c9d5c..8691e1649d6c 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -929,6 +929,25 @@ static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci) pci_free_irq_vectors(ab_pci->pdev); } +static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci) +{ + struct msi_desc *msi_desc; + + msi_desc = irq_get_msi_desc(ab_pci->pdev->irq); + if (!msi_desc) { + ath11k_err(ab_pci->ab, "msi_desc is NULL!\n"); + pci_free_irq_vectors(ab_pci->pdev); + return -EINVAL; + } + + ab_pci->msi_ep_base_data = msi_desc->msg.data; + + ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n", + ab_pci->msi_ep_base_data); + + return 0; +} + static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev) { struct ath11k_base *ab = ab_pci->ab; @@ -1328,6 +1347,17 @@ static int ath11k_pci_probe(struct pci_dev *pdev, goto err_ce_free; } + /* kernel may allocate a dummy vector before request_irq and + * then allocate a real vector when request_irq is called. + * So get msi_data here again to avoid spurious interrupt + * as msi_data will configured to srngs. + */ + ret = ath11k_pci_config_msi_data(ab_pci); + if (ret) { + ath11k_err(ab, "failed to config msi_data: %d\n", ret); + goto err_free_irq; + } + ret = ath11k_core_init(ab); if (ret) { ath11k_err(ab, "failed to init core: %d\n", ret);