diff --git a/cnss2/pci.c b/cnss2/pci.c index f6761cd076..bf01dab70b 100644 --- a/cnss2/pci.c +++ b/cnss2/pci.c @@ -2121,11 +2121,48 @@ out: return ret; } +static int cnss_pci_config_msi_addr(struct cnss_pci_data *pci_priv) +{ + int ret = 0; + struct pci_dev *pci_dev = pci_priv->pci_dev; + struct cnss_plat_data *plat_priv; + + if (!pci_dev) + return -ENODEV; + + if (!pci_dev->msix_enabled) + return ret; + + plat_priv = pci_priv->plat_priv; + if (!plat_priv) { + cnss_pr_err("plat_priv is NULL\n"); + return -ENODEV; + } + + ret = of_property_read_u32(plat_priv->plat_dev->dev.of_node, + "msix-match-addr", + &pci_priv->msix_addr); + cnss_pr_dbg("MSI-X Match address is 0x%X\n", + pci_priv->msix_addr); + + return ret; +} + static int cnss_pci_config_msi_data(struct cnss_pci_data *pci_priv) { struct msi_desc *msi_desc; + struct cnss_msi_config *msi_config; struct pci_dev *pci_dev = pci_priv->pci_dev; + msi_config = pci_priv->msi_config; + + if (pci_dev->msix_enabled) { + pci_priv->msi_ep_base_data = msi_config->users[0].base_vector; + cnss_pr_dbg("MSI-X base data is %d\n", + pci_priv->msi_ep_base_data); + return 0; + } + msi_desc = irq_get_msi_desc(pci_dev->irq); if (!msi_desc) { cnss_pr_err("msi_desc is NULL!\n"); @@ -5077,7 +5114,7 @@ static int cnss_pci_enable_msi(struct cnss_pci_data *pci_priv) num_vectors = pci_alloc_irq_vectors(pci_dev, msi_config->total_vectors, msi_config->total_vectors, - PCI_IRQ_MSI); + PCI_IRQ_MSI | PCI_IRQ_MSIX); if ((num_vectors != msi_config->total_vectors) && !cnss_pci_fallback_one_msi(pci_priv, &num_vectors)) { cnss_pr_err("Failed to get enough MSI vectors (%d), available vectors = %d", @@ -5087,6 +5124,11 @@ static int cnss_pci_enable_msi(struct cnss_pci_data *pci_priv) goto reset_msi_config; } + if (cnss_pci_config_msi_addr(pci_priv)) { + ret = -EINVAL; + goto free_msi_vector; + } + if (cnss_pci_config_msi_data(pci_priv)) { ret = -EINVAL; goto free_msi_vector; @@ -5178,8 +5220,25 @@ void cnss_get_msi_address(struct device *dev, u32 *msi_addr_low, u32 *msi_addr_high) { struct pci_dev *pci_dev = to_pci_dev(dev); + struct cnss_pci_data *pci_priv; u16 control; + if (!pci_dev) + return; + + pci_priv = cnss_get_pci_priv(pci_dev); + if (!pci_priv) + return; + + if (pci_dev->msix_enabled) { + *msi_addr_low = pci_priv->msix_addr; + *msi_addr_high = 0; + if (!print_optimize.msi_addr_chk++) + cnss_pr_dbg("Get MSI low addr = 0x%x, high addr = 0x%x\n", + *msi_addr_low, *msi_addr_high); + return; + } + pci_read_config_word(pci_dev, pci_dev->msi_cap + PCI_MSI_FLAGS, &control); pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, diff --git a/cnss2/pci.h b/cnss2/pci.h index 7ea38898bf..c2d86beda4 100644 --- a/cnss2/pci.h +++ b/cnss2/pci.h @@ -160,6 +160,7 @@ struct cnss_pci_data { void __iomem *bar; struct cnss_msi_config *msi_config; u32 msi_ep_base_data; + u32 msix_addr; struct mhi_controller *mhi_ctrl; unsigned long mhi_state; u32 remap_window;