msi_setup_msi_descs and msix_setup_msi_descs are the two callers of genirq helper msi_domain_insert_msi_desc that is now ready for a preset msi_iova. So, do the same in these two callers. Note MSIx supports multiple entries, so use struct msix_entry to pass msi_iova in. Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx> --- include/linux/pci.h | 1 + drivers/pci/msi/msi.c | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index 573b4c4c2be6..68ebb9d42f7f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1652,6 +1652,7 @@ int pci_set_vga_state(struct pci_dev *pdev, bool decode, struct msix_entry { u32 vector; /* Kernel uses to write allocated vector */ u16 entry; /* Driver uses to specify entry, OS writes */ + u64 iova; /* Kernel uses to override doorbell address */ }; #ifdef CONFIG_PCI_MSI diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c index 3a45879d85db..95caa81d3421 100644 --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -282,7 +282,7 @@ static void pci_msi_set_enable(struct pci_dev *dev, int enable) pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); } -static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, +static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, dma_addr_t iova, struct irq_affinity_desc *masks) { struct msi_desc desc; @@ -312,6 +312,10 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, else desc.pci.mask_pos = dev->msi_cap + PCI_MSI_MASK_32; +#ifdef CONFIG_IRQ_MSI_IOMMU + desc.msi_iova = iova; +#endif + /* Save the initial mask status */ if (desc.pci.msi_attrib.can_mask) pci_read_config_dword(dev, desc.pci.mask_pos, &desc.pci.msi_mask); @@ -349,7 +353,7 @@ static int msi_verify_entries(struct pci_dev *dev) * which could have been allocated. */ static int msi_capability_init(struct pci_dev *dev, int nvec, - struct irq_affinity *affd) + struct irq_affinity *affd, dma_addr_t iova) { struct irq_affinity_desc *masks = NULL; struct msi_desc *entry, desc; @@ -370,7 +374,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, masks = irq_create_affinity_masks(nvec, affd); msi_lock_descs(&dev->dev); - ret = msi_setup_msi_desc(dev, nvec, masks); + ret = msi_setup_msi_desc(dev, nvec, iova, masks); if (ret) goto fail; @@ -456,7 +460,7 @@ int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, return -ENOSPC; } - rc = msi_capability_init(dev, nvec, affd); + rc = msi_capability_init(dev, nvec, affd, PHYS_ADDR_MAX); if (rc == 0) return nvec; @@ -625,6 +629,12 @@ static int msix_setup_msi_descs(struct pci_dev *dev, struct msix_entry *entries, memset(&desc, 0, sizeof(desc)); for (i = 0, curmsk = masks; i < nvec; i++, curmsk++) { +#ifdef CONFIG_IRQ_MSI_IOMMU + if (entries && entries[i].iova) + desc.msi_iova = (dma_addr_t)entries[i].iova; + else + desc.msi_iova = PHYS_ADDR_MAX; +#endif desc.msi_index = entries ? entries[i].entry : i; desc.affinity = masks ? curmsk : NULL; desc.pci.msi_attrib.is_virtual = desc.msi_index >= vec_count; -- 2.43.0