PCI/MSI: Make arch_restore_msi_irqs() less horrible.
authorThomas Gleixner <tglx@linutronix.de>
Mon, 6 Dec 2021 22:27:42 +0000 (23:27 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 9 Dec 2021 10:52:21 +0000 (11:52 +0100)
Make arch_restore_msi_irqs() return a boolean which indicates whether the
core code should restore the MSI message or not. Get rid of the indirection
in x86.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com> # PCI
Link: https://lore.kernel.org/r/20211206210224.485668098@linutronix.de
arch/s390/pci/pci_irq.c
arch/x86/include/asm/x86_init.h
arch/x86/include/asm/xen/hypervisor.h
arch/x86/kernel/apic/msi.c
arch/x86/kernel/x86_init.c
arch/x86/pci/xen.c
drivers/pci/msi.c
include/linux/msi.h

index 954bb7a831241394f637fc3fc8423f5d9ef266ea..2beb8a082e6fa45efeaf502754497bc65858c7a5 100644 (file)
@@ -387,13 +387,13 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
                airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, zdev->msi_nr_irqs);
 }
 
-void arch_restore_msi_irqs(struct pci_dev *pdev)
+bool arch_restore_msi_irqs(struct pci_dev *pdev)
 {
        struct zpci_dev *zdev = to_zpci(pdev);
 
        if (!zdev->irqs_registered)
                zpci_set_irq(zdev);
-       default_restore_msi_irqs(pdev);
+       return true;
 }
 
 static struct airq_struct zpci_airq = {
index 5c69f7eb5d47e81e9b4d4f14a30041fe0465d9ab..22b7412c08f63413c3f963827ed56e2297c6168f 100644 (file)
@@ -289,12 +289,6 @@ struct x86_platform_ops {
        struct x86_hyper_runtime hyper;
 };
 
-struct pci_dev;
-
-struct x86_msi_ops {
-       void (*restore_msi_irqs)(struct pci_dev *dev);
-};
-
 struct x86_apic_ops {
        unsigned int    (*io_apic_read)   (unsigned int apic, unsigned int reg);
        void            (*restore)(void);
index 5adab895127e190a8fd9259c839604f943c4de18..677f84d0039fd67541ee72ada5b76bc9b6a414d6 100644 (file)
@@ -57,6 +57,14 @@ static inline bool __init xen_x2apic_para_available(void)
 }
 #endif
 
+struct pci_dev;
+
+#ifdef CONFIG_XEN_DOM0
+bool xen_initdom_restore_msi(struct pci_dev *dev);
+#else
+static inline bool xen_initdom_restore_msi(struct pci_dev *dev) { return true; }
+#endif
+
 #ifdef CONFIG_HOTPLUG_CPU
 void xen_arch_register_cpu(int num);
 void xen_arch_unregister_cpu(int num);
index 1656477e4169aade14557fffb1e244fae76b6a4d..b270b70f41c622c10046a12cc3651c3c113fea3e 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/hw_irq.h>
 #include <asm/apic.h>
 #include <asm/irq_remapping.h>
+#include <asm/xen/hypervisor.h>
 
 struct irq_domain *x86_pci_msi_default_domain __ro_after_init;
 
@@ -345,3 +346,8 @@ void dmar_free_hwirq(int irq)
        irq_domain_free_irqs(irq, 1);
 }
 #endif
+
+bool arch_restore_msi_irqs(struct pci_dev *dev)
+{
+       return xen_initdom_restore_msi(dev);
+}
index 8b395821cb8d022ba7a532f43dfcf01361fe12bf..7d20c1d34a3cdf1bcc9fe143bf540b4e201d1239 100644 (file)
@@ -145,18 +145,6 @@ struct x86_platform_ops x86_platform __ro_after_init = {
 
 EXPORT_SYMBOL_GPL(x86_platform);
 
-#if defined(CONFIG_PCI_MSI)
-struct x86_msi_ops x86_msi __ro_after_init = {
-       .restore_msi_irqs       = default_restore_msi_irqs,
-};
-
-/* MSI arch specific hooks */
-void arch_restore_msi_irqs(struct pci_dev *dev)
-{
-       x86_msi.restore_msi_irqs(dev);
-}
-#endif
-
 struct x86_apic_ops x86_apic_ops __ro_after_init = {
        .io_apic_read   = native_io_apic_read,
        .restore        = native_restore_boot_irq_mode,
index 2dace884d6f7caa25923f483ac24de502f78c3ff..a63d30a52879e9e185e08785b4bb7e56c2491e75 100644 (file)
@@ -351,10 +351,13 @@ out:
        return ret;
 }
 
-static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
+bool xen_initdom_restore_msi(struct pci_dev *dev)
 {
        int ret = 0;
 
+       if (!xen_initial_domain())
+               return true;
+
        if (pci_seg_supported) {
                struct physdev_pci_device restore_ext;
 
@@ -375,10 +378,10 @@ static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
                ret = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore);
                WARN(ret && ret != -ENOSYS, "restore_msi -> %d\n", ret);
        }
+       return false;
 }
 #else /* CONFIG_XEN_PV_DOM0 */
 #define xen_initdom_setup_msi_irqs     NULL
-#define xen_initdom_restore_msi_irqs   NULL
 #endif /* !CONFIG_XEN_PV_DOM0 */
 
 static void xen_teardown_msi_irqs(struct pci_dev *dev)
@@ -466,12 +469,10 @@ static __init struct irq_domain *xen_create_pci_msi_domain(void)
 static __init void xen_setup_pci_msi(void)
 {
        if (xen_pv_domain()) {
-               if (xen_initial_domain()) {
+               if (xen_initial_domain())
                        xen_msi_ops.setup_msi_irqs = xen_initdom_setup_msi_irqs;
-                       x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs;
-               } else {
+               else
                        xen_msi_ops.setup_msi_irqs = xen_setup_msi_irqs;
-               }
                xen_msi_ops.teardown_msi_irqs = xen_pv_teardown_msi_irqs;
                pci_msi_ignore_mask = 1;
        } else if (xen_hvm_domain()) {
index b6cd8b337210df5c68434831cc5fb672210126f3..8260b06ab5837105b75bc4a2777e86b1002b86f8 100644 (file)
@@ -106,29 +106,6 @@ void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
 }
 #endif /* CONFIG_PCI_MSI_ARCH_FALLBACKS */
 
-static void default_restore_msi_irq(struct pci_dev *dev, int irq)
-{
-       struct msi_desc *entry;
-
-       entry = NULL;
-       if (dev->msix_enabled) {
-               for_each_pci_msi_entry(entry, dev) {
-                       if (irq == entry->irq)
-                               break;
-               }
-       } else if (dev->msi_enabled)  {
-               entry = irq_get_msi_desc(irq);
-       }
-
-       if (entry)
-               __pci_write_msi_msg(entry, &entry->msg);
-}
-
-void __weak arch_restore_msi_irqs(struct pci_dev *dev)
-{
-       return default_restore_msi_irqs(dev);
-}
-
 /*
  * PCI 2.3 does not specify mask bits for each MSI interrupt.  Attempting to
  * mask all MSI interrupts by clearing the MSI enable bit does not work
@@ -242,14 +219,6 @@ void pci_msi_unmask_irq(struct irq_data *data)
 }
 EXPORT_SYMBOL_GPL(pci_msi_unmask_irq);
 
-void default_restore_msi_irqs(struct pci_dev *dev)
-{
-       struct msi_desc *entry;
-
-       for_each_pci_msi_entry(entry, dev)
-               default_restore_msi_irq(dev, entry->irq);
-}
-
 void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
        struct pci_dev *dev = msi_desc_to_pci_dev(entry);
@@ -403,10 +372,19 @@ static void pci_msi_set_enable(struct pci_dev *dev, int enable)
        pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
 }
 
+/*
+ * Architecture override returns true when the PCI MSI message should be
+ * written by the generic restore function.
+ */
+bool __weak arch_restore_msi_irqs(struct pci_dev *dev)
+{
+       return true;
+}
+
 static void __pci_restore_msi_state(struct pci_dev *dev)
 {
-       u16 control;
        struct msi_desc *entry;
+       u16 control;
 
        if (!dev->msi_enabled)
                return;
@@ -415,7 +393,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
 
        pci_intx_for_msi(dev, 0);
        pci_msi_set_enable(dev, 0);
-       arch_restore_msi_irqs(dev);
+       if (arch_restore_msi_irqs(dev))
+               __pci_write_msi_msg(entry, &entry->msg);
 
        pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
        pci_msi_update_mask(entry, 0, 0);
@@ -437,6 +416,7 @@ static void pci_msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set)
 static void __pci_restore_msix_state(struct pci_dev *dev)
 {
        struct msi_desc *entry;
+       bool write_msg;
 
        if (!dev->msix_enabled)
                return;
@@ -447,9 +427,13 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
        pci_msix_clear_and_set_ctrl(dev, 0,
                                PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
 
-       arch_restore_msi_irqs(dev);
-       for_each_pci_msi_entry(entry, dev)
+       write_msg = arch_restore_msi_irqs(dev);
+
+       for_each_pci_msi_entry(entry, dev) {
+               if (write_msg)
+                       __pci_write_msi_msg(entry, &entry->msg);
                pci_msix_write_vector_ctrl(entry, entry->pci.msix_ctrl);
+       }
 
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
 }
index 7e5c13f4e41b094b50cb793f4b11b73f6081cef7..673899fc24f6faf89f12c9b40b48468b4cc633b7 100644 (file)
@@ -273,11 +273,10 @@ static inline void arch_teardown_msi_irqs(struct pci_dev *dev)
 #endif
 
 /*
- * The restore hooks are still available as they are useful even
- * for fully irq domain based setups. Courtesy to XEN/X86.
+ * The restore hook is still available even for fully irq domain based
+ * setups. Courtesy to XEN/X86.
  */
-void arch_restore_msi_irqs(struct pci_dev *dev);
-void default_restore_msi_irqs(struct pci_dev *dev);
+bool arch_restore_msi_irqs(struct pci_dev *dev);
 
 #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN