PCI/MSI: Allow an msi_controller to be associated to an irq domain
authorMarc Zyngier <marc.zyngier@arm.com>
Sat, 15 Nov 2014 10:49:12 +0000 (10:49 +0000)
committerThomas Gleixner <tglx@linutronix.de>
Sun, 23 Nov 2014 16:14:43 +0000 (17:14 +0100)
With the new stacked irq domains, it becomes pretty tempting to
allocate an MSI domain per PCI bus, which would remove the requirement
of either relying on arch-specific code, or a default PCI MSI domain.

By allowing the msi_controller structure to carry a pointer to an
irq_domain, we can easily use this in pci_msi_setup_msi_irqs.  The
existing code can still be used as a fallback if the MSI driver does
not populate the domain field.

Tested on arm64 with the GICv3 ITS driver.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Yingjoe Chen <yingjoe.chen@mediatek.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Link: http://lkml.kernel.org/r/1416048553-29289-2-git-send-email-marc.zyngier@arm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
drivers/pci/msi.c
include/linux/msi.h

index 4befe09053c1968810c104ed7a5234ec4ec8ccf9..476f4b1a2727ee875323d2f616d1cfb3ca25611b 100644 (file)
@@ -37,11 +37,23 @@ struct irq_domain * __weak arch_get_pci_msi_domain(struct pci_dev *dev)
        return pci_msi_default_domain;
 }
 
+static struct irq_domain *pci_msi_get_domain(struct pci_dev *dev)
+{
+       struct irq_domain *domain = NULL;
+
+       if (dev->bus->msi)
+               domain = dev->bus->msi->domain;
+       if (!domain)
+               domain = arch_get_pci_msi_domain(dev);
+
+       return domain;
+}
+
 static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
        struct irq_domain *domain;
 
-       domain = arch_get_pci_msi_domain(dev);
+       domain = pci_msi_get_domain(dev);
        if (domain)
                return pci_msi_domain_alloc_irqs(domain, dev, nvec, type);
 
@@ -52,7 +64,7 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
 {
        struct irq_domain *domain;
 
-       domain = arch_get_pci_msi_domain(dev);
+       domain = pci_msi_get_domain(dev);
        if (domain)
                pci_msi_domain_free_irqs(domain, dev);
        else
index 692f217ae8135fe78f22f039084fc8d85746009a..8ac4a68ffae2d928f677e0a9535402eb8978636a 100644 (file)
@@ -108,6 +108,9 @@ struct msi_controller {
        struct device *dev;
        struct device_node *of_node;
        struct list_head list;
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+       struct irq_domain *domain;
+#endif
 
        int (*setup_irq)(struct msi_controller *chip, struct pci_dev *dev,
                         struct msi_desc *desc);