x86, msi: Use IRQ remapping specific setup_msi_irqs routine
authorJoerg Roedel <joro@8bytes.org>
Wed, 26 Sep 2012 10:44:38 +0000 (12:44 +0200)
committerJoerg Roedel <joro@8bytes.org>
Mon, 28 Jan 2013 11:17:25 +0000 (12:17 +0100)
Use seperate routines to setup MSI IRQs for both
irq_remapping_enabled cases.

Signed-off-by: Joerg Roedel <joro@8bytes.org>
Acked-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
arch/x86/include/asm/irq_remapping.h
arch/x86/include/asm/pci.h
arch/x86/kernel/apic/io_apic.c
drivers/iommu/irq_remapping.c
include/linux/irq.h

index 5fb9bbb..0ee1e88 100644 (file)
@@ -47,9 +47,6 @@ extern void free_remapped_irq(int irq);
 extern void compose_remapped_msi_msg(struct pci_dev *pdev,
                                     unsigned int irq, unsigned int dest,
                                     struct msi_msg *msg, u8 hpet_id);
-extern int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
-extern int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
-                                 int index, int sub_handle);
 extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id);
 
 #else  /* CONFIG_IRQ_REMAP */
@@ -83,15 +80,6 @@ static inline void compose_remapped_msi_msg(struct pci_dev *pdev,
                                            struct msi_msg *msg, u8 hpet_id)
 {
 }
-static inline int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
-{
-       return -ENODEV;
-}
-static inline int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
-                                        int index, int sub_handle)
-{
-       return -ENODEV;
-}
 static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
 {
        return -ENODEV;
index dba7805..c28fd02 100644 (file)
@@ -121,9 +121,12 @@ static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
 #define arch_teardown_msi_irq x86_teardown_msi_irq
 #define arch_restore_msi_irqs x86_restore_msi_irqs
 /* implemented in arch/x86/kernel/apic/io_apic. */
+struct msi_desc;
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev, int irq);
+int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
+                 unsigned int irq_base, unsigned int irq_offset);
 /* default to the implementation in drivers/lib/msi.c */
 #define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
 #define HAVE_DEFAULT_MSI_RESTORE_IRQS
index e7b8763..d4b045e 100644 (file)
@@ -3066,7 +3066,7 @@ void destroy_irq(unsigned int irq)
        free_irq_at(irq, cfg);
 }
 
-static inline void destroy_irqs(unsigned int irq, unsigned int count)
+void destroy_irqs(unsigned int irq, unsigned int count)
 {
        unsigned int i;
 
@@ -3165,8 +3165,8 @@ static struct irq_chip msi_chip = {
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
-static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-                        unsigned int irq_base, unsigned int irq_offset)
+int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
+                 unsigned int irq_base, unsigned int irq_offset)
 {
        struct irq_chip *chip = &msi_chip;
        struct msi_msg msg;
@@ -3198,44 +3198,28 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
        return 0;
 }
 
-int setup_msix_irqs(struct pci_dev *dev, int nvec)
+int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-       int node, ret, sub_handle, index = 0;
        unsigned int irq, irq_want;
        struct msi_desc *msidesc;
+       int node, ret;
+
+       /* Multiple MSI vectors only supported with interrupt remapping */
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
 
        node = dev_to_node(&dev->dev);
        irq_want = nr_irqs_gsi;
-       sub_handle = 0;
        list_for_each_entry(msidesc, &dev->msi_list, list) {
                irq = create_irq_nr(irq_want, node);
                if (irq == 0)
                        return -ENOSPC;
+
                irq_want = irq + 1;
-               if (!irq_remapping_enabled)
-                       goto no_ir;
 
-               if (!sub_handle) {
-                       /*
-                        * allocate the consecutive block of IRTE's
-                        * for 'nvec'
-                        */
-                       index = msi_alloc_remapped_irq(dev, irq, nvec);
-                       if (index < 0) {
-                               ret = index;
-                               goto error;
-                       }
-               } else {
-                       ret = msi_setup_remapped_irq(dev, irq, index,
-                                                    sub_handle);
-                       if (ret < 0)
-                               goto error;
-               }
-no_ir:
                ret = setup_msi_irq(dev, msidesc, irq, 0);
                if (ret < 0)
                        goto error;
-               sub_handle++;
        }
        return 0;
 
@@ -3244,74 +3228,6 @@ error:
        return ret;
 }
 
-int setup_msi_irqs(struct pci_dev *dev, int nvec)
-{
-       int node, ret, sub_handle, index = 0;
-       unsigned int irq;
-       struct msi_desc *msidesc;
-
-       if (nvec > 1 && !irq_remapping_enabled)
-               return 1;
-
-       nvec = __roundup_pow_of_two(nvec);
-
-       WARN_ON(!list_is_singular(&dev->msi_list));
-       msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
-       WARN_ON(msidesc->irq);
-       WARN_ON(msidesc->msi_attrib.multiple);
-
-       node = dev_to_node(&dev->dev);
-       irq = __create_irqs(nr_irqs_gsi, nvec, node);
-       if (irq == 0)
-               return -ENOSPC;
-
-       if (!irq_remapping_enabled) {
-               ret = setup_msi_irq(dev, msidesc, irq, 0);
-               if (ret < 0)
-                       goto error;
-               return 0;
-       }
-
-       msidesc->msi_attrib.multiple = ilog2(nvec);
-       for (sub_handle = 0; sub_handle < nvec; sub_handle++) {
-               if (!sub_handle) {
-                       index = msi_alloc_remapped_irq(dev, irq, nvec);
-                       if (index < 0) {
-                               ret = index;
-                               goto error;
-                       }
-               } else {
-                       ret = msi_setup_remapped_irq(dev, irq + sub_handle,
-                                                    index, sub_handle);
-                       if (ret < 0)
-                               goto error;
-               }
-               ret = setup_msi_irq(dev, msidesc, irq, sub_handle);
-               if (ret < 0)
-                       goto error;
-       }
-       return 0;
-
-error:
-       destroy_irqs(irq, nvec);
-
-       /*
-        * Restore altered MSI descriptor fields and prevent just destroyed
-        * IRQs from tearing down again in default_teardown_msi_irqs()
-        */
-       msidesc->irq = 0;
-       msidesc->msi_attrib.multiple = 0;
-
-       return ret;
-}
-
-int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-       if (type == PCI_CAP_ID_MSI)
-               return setup_msi_irqs(dev, nvec);
-       return setup_msix_irqs(dev, nvec);
-}
-
 void native_teardown_msi_irq(unsigned int irq)
 {
        destroy_irq(irq);
index 0baad3b..20f04b6 100644 (file)
@@ -4,6 +4,8 @@
 #include <linux/cpumask.h>
 #include <linux/errno.h>
 #include <linux/msi.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
 
 #include <asm/hw_irq.h>
 #include <asm/irq_remapping.h>
@@ -21,6 +23,10 @@ int no_x2apic_optout;
 
 static struct irq_remap_ops *remap_ops;
 
+static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
+static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
+                                 int index, int sub_handle);
+
 static void irq_remapping_disable_io_apic(void)
 {
        /*
@@ -34,9 +40,109 @@ static void irq_remapping_disable_io_apic(void)
                disconnect_bsp_APIC(0);
 }
 
+static int do_setup_msi_irqs(struct pci_dev *dev, int nvec)
+{
+       int node, ret, sub_handle, index = 0;
+       unsigned int irq;
+       struct msi_desc *msidesc;
+
+       nvec = __roundup_pow_of_two(nvec);
+
+       WARN_ON(!list_is_singular(&dev->msi_list));
+       msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
+       WARN_ON(msidesc->irq);
+       WARN_ON(msidesc->msi_attrib.multiple);
+
+       node = dev_to_node(&dev->dev);
+       irq = __create_irqs(get_nr_irqs_gsi(), nvec, node);
+       if (irq == 0)
+               return -ENOSPC;
+
+       msidesc->msi_attrib.multiple = ilog2(nvec);
+       for (sub_handle = 0; sub_handle < nvec; sub_handle++) {
+               if (!sub_handle) {
+                       index = msi_alloc_remapped_irq(dev, irq, nvec);
+                       if (index < 0) {
+                               ret = index;
+                               goto error;
+                       }
+               } else {
+                       ret = msi_setup_remapped_irq(dev, irq + sub_handle,
+                                                    index, sub_handle);
+                       if (ret < 0)
+                               goto error;
+               }
+               ret = setup_msi_irq(dev, msidesc, irq, sub_handle);
+               if (ret < 0)
+                       goto error;
+       }
+       return 0;
+
+error:
+       destroy_irqs(irq, nvec);
+
+       /*
+        * Restore altered MSI descriptor fields and prevent just destroyed
+        * IRQs from tearing down again in default_teardown_msi_irqs()
+        */
+       msidesc->irq = 0;
+       msidesc->msi_attrib.multiple = 0;
+
+       return ret;
+}
+
+static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
+{
+       int node, ret, sub_handle, index = 0;
+       struct msi_desc *msidesc;
+       unsigned int irq;
+
+       node            = dev_to_node(&dev->dev);
+       irq             = get_nr_irqs_gsi();
+       sub_handle      = 0;
+
+       list_for_each_entry(msidesc, &dev->msi_list, list) {
+
+               irq = create_irq_nr(irq, node);
+               if (irq == 0)
+                       return -1;
+
+               if (sub_handle == 0)
+                       ret = index = msi_alloc_remapped_irq(dev, irq, nvec);
+               else
+                       ret = msi_setup_remapped_irq(dev, irq, index, sub_handle);
+
+               if (ret < 0)
+                       goto error;
+
+               ret = setup_msi_irq(dev, msidesc, irq, 0);
+               if (ret < 0)
+                       goto error;
+
+               sub_handle += 1;
+               irq        += 1;
+       }
+
+       return 0;
+
+error:
+       destroy_irq(irq);
+       return ret;
+}
+
+static int irq_remapping_setup_msi_irqs(struct pci_dev *dev,
+                                       int nvec, int type)
+{
+       if (type == PCI_CAP_ID_MSI)
+               return do_setup_msi_irqs(dev, nvec);
+       else
+               return do_setup_msix_irqs(dev, nvec);
+}
+
 static void __init irq_remapping_modify_x86_ops(void)
 {
        x86_io_apic_ops.disable         = irq_remapping_disable_io_apic;
+       x86_msi.setup_msi_irqs          = irq_remapping_setup_msi_irqs;
        x86_msi.setup_hpet_msi          = setup_hpet_msi_remapped;
 }
 
@@ -186,7 +292,7 @@ void compose_remapped_msi_msg(struct pci_dev *pdev,
        remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
 }
 
-int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
+static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
 {
        if (!remap_ops || !remap_ops->msi_alloc_irq)
                return -ENODEV;
@@ -194,8 +300,8 @@ int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
        return remap_ops->msi_alloc_irq(pdev, irq, nvec);
 }
 
-int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
-                          int index, int sub_handle)
+static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
+                                 int index, int sub_handle)
 {
        if (!remap_ops || !remap_ops->msi_setup_irq)
                return -ENODEV;
index 1eab991..bc4e066 100644 (file)
@@ -509,8 +509,11 @@ static inline void irq_set_percpu_devid_flags(unsigned int irq)
 
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
+extern unsigned int __create_irqs(unsigned int from, unsigned int count,
+                                 int node);
 extern int create_irq(void);
 extern void destroy_irq(unsigned int irq);
+extern void destroy_irqs(unsigned int irq, unsigned int count);
 
 /*
  * Dynamic irq helper functions. Obsolete. Use irq_alloc_desc* and