diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 3a5611bba9d9..161f39761844 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -407,6 +407,63 @@ static void xen_teardown_msi_irq(unsigned int irq) WARN_ON_ONCE(1); } +static int xen_msi_domain_alloc_irqs(struct irq_domain *domain, + struct device *dev, int nvec) +{ + int type; + + if (WARN_ON_ONCE(!dev_is_pci(dev))) + return -EINVAL; + + if (first_msi_entry(dev)->msi_attrib.is_msix) + type = PCI_CAP_ID_MSIX; + else + type = PCI_CAP_ID_MSI; + + return x86_msi.setup_msi_irqs(to_pci_dev(dev), nvec, type); +} + +static void xen_msi_domain_free_irqs(struct irq_domain *domain, + struct device *dev) +{ + if (WARN_ON_ONCE(!dev_is_pci(dev))) + return; + + x86_msi.teardown_msi_irqs(to_pci_dev(dev)); +} + +static struct msi_domain_ops xen_pci_msi_domain_ops = { + .domain_alloc_irqs = xen_msi_domain_alloc_irqs, + .domain_free_irqs = xen_msi_domain_free_irqs, +}; + +static struct msi_domain_info xen_pci_msi_domain_info = { + .ops = &xen_pci_msi_domain_ops, +}; + +/* + * This irq domain is a blatant violation of the irq domain design, but + * distangling XEN into real irq domains is not a job for mere mortals with + * limited XENology. But it's the least dangerous way for a mere mortal to + * get rid of the arch_*_msi_irqs() hackery in order to store the irq + * domain pointer in struct device. This irq domain wrappery allows to do + * that without breaking XEN terminally. + */ +static __init struct irq_domain *xen_create_pci_msi_domain(void) +{ + struct irq_domain *d = NULL; + struct fwnode_handle *fn; + + fn = irq_domain_alloc_named_fwnode("XEN-MSI"); + if (fn) + d = msi_create_irq_domain(fn, &xen_pci_msi_domain_info, NULL); + + /* FIXME: No idea how to survive if this fails */ + BUG_ON(!d); + + return d; +} + static __init void xen_setup_pci_msi(void) { if (xen_pv_domain()) { @@ -427,6 +484,12 @@ static __init void xen_setup_pci_msi(void) } x86_msi.teardown_msi_irq = xen_teardown_msi_irq; + + /* + * Override the PCI/MSI irq domain init function. No point + * in allocating the native domain and never use it. + */ + x86_init.irqs.create_pci_msi_domain = xen_create_pci_msi_domain; } #else /* CONFIG_PCI_MSI */