Commit 1b66601d authored by Kang Yang's avatar Kang Yang Committed by Kalle Valo

wifi: ath12k: get msi_data again after request_irq is called

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, then it will lead to spurious interrupt. But when VT-d in
BIOS is enabled and ath12k can get 32 MSI vectors, ath12k always get
the same msi_data before and after request_irq.

So in case of one MSI vector, ath12k need read msi_data again after
request_irq is called, and then the correct msi_data is programmed
into WCN7850 hardware components.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
Signed-off-by: default avatarKang Yang <quic_kangyang@quicinc.com>
Acked-by: default avatarJeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20231121021304.12966-2-quic_kangyang@quicinc.com
parent 8cc18a70
...@@ -708,6 +708,25 @@ static void ath12k_pci_msi_free(struct ath12k_pci *ab_pci) ...@@ -708,6 +708,25 @@ static void ath12k_pci_msi_free(struct ath12k_pci *ab_pci)
pci_free_irq_vectors(ab_pci->pdev); pci_free_irq_vectors(ab_pci->pdev);
} }
static int ath12k_pci_config_msi_data(struct ath12k_pci *ab_pci)
{
struct msi_desc *msi_desc;
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
if (!msi_desc) {
ath12k_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;
ath12k_dbg(ab_pci->ab, ATH12K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n",
ab_pci->msi_ep_base_data);
return 0;
}
static int ath12k_pci_claim(struct ath12k_pci *ab_pci, struct pci_dev *pdev) static int ath12k_pci_claim(struct ath12k_pci *ab_pci, struct pci_dev *pdev)
{ {
struct ath12k_base *ab = ab_pci->ab; struct ath12k_base *ab = ab_pci->ab;
...@@ -1286,6 +1305,17 @@ static int ath12k_pci_probe(struct pci_dev *pdev, ...@@ -1286,6 +1305,17 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
goto err_ce_free; 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 = ath12k_pci_config_msi_data(ab_pci);
if (ret) {
ath12k_err(ab, "failed to config msi_data: %d\n", ret);
goto err_free_irq;
}
ret = ath12k_core_init(ab); ret = ath12k_core_init(ab);
if (ret) { if (ret) {
ath12k_err(ab, "failed to init core: %d\n", ret); ath12k_err(ab, "failed to init core: %d\n", ret);
......
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