[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 4/4] x86: split MSI IRQ chip



With the .end() accessor having become optional and noting that
several of the accessors' behavior really depends on the result of
msi_maskable_irq(), the splits the MSI IRQ chip type into two - one
for the maskable ones, and the other for the (MSI only) non-maskable
ones.

At once the implementation of those methods gets moved from io_apic.c
to msi.c.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -312,7 +312,7 @@ static void __hpet_setup_msi_irq(struct 
 {
     struct msi_msg msg;
 
-    msi_compose_msg(desc->irq, &msg);
+    msi_compose_msg(desc, &msg);
     hpet_msi_write(desc->action->dev_id, &msg);
 }
 
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -382,7 +382,7 @@ int msixtbl_pt_register(struct domain *d
         return r;
     }
 
-    if ( irq_desc->handler != &pci_msi_type )
+    if ( !irq_desc->msi_desc )
         goto out;
 
     msi_desc = irq_desc->msi_desc;
@@ -426,7 +426,7 @@ void msixtbl_pt_unregister(struct domain
     if ( !irq_desc )
         return;
 
-    if ( irq_desc->handler != &pci_msi_type )
+    if ( !irq_desc->msi_desc )
         goto out;
 
     msi_desc = irq_desc->msi_desc;
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -1882,44 +1882,6 @@ static hw_irq_controller ioapic_level_ty
     .set_affinity      = set_ioapic_affinity_irq,
 };
 
-static unsigned int startup_msi_irq(struct irq_desc *desc)
-{
-    unmask_msi_irq(desc);
-    return 0;
-}
-
-static void ack_msi_irq(struct irq_desc *desc)
-{
-    irq_complete_move(desc);
-    move_native_irq(desc);
-
-    if ( msi_maskable_irq(desc->msi_desc) )
-        ack_APIC_irq(); /* ACKTYPE_NONE */
-}
-
-static void end_msi_irq(struct irq_desc *desc, u8 vector)
-{
-    if ( !msi_maskable_irq(desc->msi_desc) )
-        ack_APIC_irq(); /* ACKTYPE_EOI */
-}
-
-#define shutdown_msi_irq mask_msi_irq
-
-/*
- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI or MSI-X Capability Structure.
- */
-hw_irq_controller pci_msi_type = {
-    .typename   = "PCI-MSI",
-    .startup    = startup_msi_irq,
-    .shutdown   = shutdown_msi_irq,
-    .enable        = unmask_msi_irq,
-    .disable    = mask_msi_irq,
-    .ack        = ack_msi_irq,
-    .end        = end_msi_irq,
-    .set_affinity   = set_msi_affinity,
-};
-
 static inline void init_IO_APIC_traps(void)
 {
     int irq;
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1303,7 +1303,7 @@ static int pirq_acktype(struct domain *d
      * MSIs are treated as edge-triggered interrupts, except
      * when there is no proper way to mask them.
      */
-    if ( desc->handler == &pci_msi_type )
+    if ( desc->msi_desc )
         return msi_maskable_irq(desc->msi_desc) ? ACKTYPE_NONE : ACKTYPE_EOI;
 
     /*
@@ -1722,7 +1722,7 @@ int map_domain_pirq(
         if ( desc->handler != &no_irq_type )
             dprintk(XENLOG_G_ERR, "dom%d: irq %d in use\n",
                     d->domain_id, irq);
-        desc->handler = &pci_msi_type;
+        setup_msi_handler(desc, msi_desc);
 
         if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV
              && !desc->chip_data->used_vectors )
@@ -1738,7 +1738,7 @@ int map_domain_pirq(
         }
 
         set_domain_irq_pirq(d, irq, info);
-        setup_msi_irq(msi_desc, irq);
+        setup_msi_irq(desc);
         spin_unlock_irqrestore(&desc->lock, flags);
     }
     else
@@ -1806,6 +1806,12 @@ int unmap_domain_pirq(struct domain *d, 
             radix_tree_int_to_ptr(-pirq));
     }
 
+    if ( msi_desc )
+    {
+        desc->handler = &no_irq_type;
+        desc->msi_desc = NULL;
+    }
+
     spin_unlock_irqrestore(&desc->lock, flags);
     if (msi_desc)
         msi_free_irq(msi_desc);
@@ -1818,9 +1824,6 @@ int unmap_domain_pirq(struct domain *d, 
         dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n",
                 d->domain_id, pirq);
 
-    if ( desc->handler == &pci_msi_type )
-        desc->handler = &no_irq_type;
-
  done:
     return ret;
 }
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -120,11 +120,11 @@ static void msix_put_fixmap(struct pci_d
 /*
  * MSI message composition
  */
-void msi_compose_msg(int irq, struct msi_msg *msg)
+void msi_compose_msg(struct irq_desc *desc, struct msi_msg *msg)
 {
     unsigned dest;
     cpumask_t domain;
-    struct irq_cfg *cfg = irq_cfg(irq);
+    struct irq_cfg *cfg = desc->chip_data;
     int vector = cfg->vector;
     domain = cfg->cpu_mask;
 
@@ -205,19 +205,6 @@ static void read_msi_msg(struct msi_desc
         iommu_read_msi_from_ire(entry, msg);
 }
 
-static int set_irq_msi(struct msi_desc *entry)
-{
-    if ( entry->irq >= nr_irqs )
-    {
-        dprintk(XENLOG_ERR, "Trying to install msi data for irq %d\n",
-                entry->irq);
-        return -EINVAL;
-    }
-
-    irq_desc[entry->irq].msi_desc = entry;
-    return 0;
-}
-
 static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
     entry->msg = *msg;
@@ -266,7 +253,7 @@ static void write_msi_msg(struct msi_des
     }
 }
 
-void set_msi_affinity(struct irq_desc *desc, const cpumask_t *mask)
+static void set_msi_affinity(struct irq_desc *desc, const cpumask_t *mask)
 {
     struct msi_msg msg;
     unsigned int dest;
@@ -387,16 +374,65 @@ static int msi_get_mask_bit(const struct
     return -1;
 }
 
-void mask_msi_irq(struct irq_desc *desc)
+static void mask_msi_irq(struct irq_desc *desc)
 {
     msi_set_mask_bit(desc, 1);
 }
 
-void unmask_msi_irq(struct irq_desc *desc)
+static void unmask_msi_irq(struct irq_desc *desc)
 {
     msi_set_mask_bit(desc, 0);
 }
 
+static unsigned int startup_msi_irq(struct irq_desc *desc)
+{
+    unmask_msi_irq(desc);
+    return 0;
+}
+
+static void ack_nonmaskable_msi_irq(struct irq_desc *desc)
+{
+    irq_complete_move(desc);
+    move_native_irq(desc);
+}
+
+static void ack_maskable_msi_irq(struct irq_desc *desc)
+{
+    ack_nonmaskable_msi_irq(desc);
+    ack_APIC_irq(); /* ACKTYPE_NONE */
+}
+
+static void end_nonmaskable_msi_irq(struct irq_desc *desc, u8 vector)
+{
+    ack_APIC_irq(); /* ACKTYPE_EOI */
+}
+
+/*
+ * IRQ chip for MSI PCI/PCI-X/PCI-Express devices,
+ * which implement the MSI or MSI-X capability structure.
+ */
+static hw_irq_controller pci_msi_maskable = {
+    .typename     = "PCI-MSI/-X",
+    .startup      = startup_msi_irq,
+    .shutdown     = mask_msi_irq,
+    .enable       = unmask_msi_irq,
+    .disable      = mask_msi_irq,
+    .ack          = ack_maskable_msi_irq,
+    .set_affinity = set_msi_affinity
+};
+
+/* As above, but without having masking capability. */
+static hw_irq_controller pci_msi_nonmaskable = {
+    .typename     = "PCI-MSI",
+    .startup      = irq_startup_none,
+    .shutdown     = irq_shutdown_none,
+    .enable       = irq_enable_none,
+    .disable      = irq_disable_none,
+    .ack          = ack_nonmaskable_msi_irq,
+    .end          = end_nonmaskable_msi_irq,
+    .set_affinity = set_msi_affinity
+};
+
 static struct msi_desc* alloc_msi_entry(void)
 {
     struct msi_desc *entry;
@@ -412,15 +448,19 @@ static struct msi_desc* alloc_msi_entry(
     return entry;
 }
 
-int setup_msi_irq(struct msi_desc *msidesc, int irq)
+void setup_msi_handler(struct irq_desc *desc, struct msi_desc *msidesc)
 {
-    struct msi_msg msg;
+    desc->msi_desc = msidesc;
+    desc->handler = msi_maskable_irq(msidesc) ? &pci_msi_maskable
+                                              : &pci_msi_nonmaskable;
+}
 
-    msi_compose_msg(irq, &msg);
-    set_irq_msi(msidesc);
-    write_msi_msg(irq_desc[irq].msi_desc, &msg);
+void setup_msi_irq(struct irq_desc *desc)
+{
+    struct msi_msg msg;
 
-    return 0;
+    msi_compose_msg(desc, &msg);
+    write_msi_msg(desc->msi_desc, &msg);
 }
 
 int msi_free_irq(struct msi_desc *entry)
@@ -1018,19 +1058,20 @@ static void dump_msi(unsigned char key)
     {
         struct irq_desc *desc = irq_to_desc(irq);
         const struct msi_desc *entry;
-        u32 addr, data;
+        u32 addr, data, dest32;
+        int mask;
+        struct msi_attrib attr;
         unsigned long flags;
         char type;
 
         spin_lock_irqsave(&desc->lock, flags);
 
         entry = desc->msi_desc;
-        type = desc->handler == &pci_msi_type && entry;
-
-        spin_unlock_irqrestore(&desc->lock, flags);
-
-        if ( !type )
+        if ( !entry )
+        {
+            spin_unlock_irqrestore(&desc->lock, flags);
             continue;
+        }
 
         switch ( entry->msi_attrib.type )
         {
@@ -1041,6 +1082,11 @@ static void dump_msi(unsigned char key)
 
         data = entry->msg.data;
         addr = entry->msg.address_lo;
+        dest32 = entry->msg.dest32;
+        attr = entry->msi_attrib;
+        mask = msi_get_mask_bit(entry);
+
+        spin_unlock_irqrestore(&desc->lock, flags);
 
         printk(" MSI%c %4u vec=%02x%7s%6s%3sassert%5s%7s"
                " dest=%08x mask=%d/%d/%d\n",
@@ -1051,9 +1097,7 @@ static void dump_msi(unsigned char key)
                data & MSI_DATA_LEVEL_ASSERT ? "" : "de",
                addr & MSI_ADDR_DESTMODE_LOGIC ? "log" : "phys",
                addr & MSI_ADDR_REDIRECTION_LOWPRI ? "lowest" : "cpu",
-               entry->msg.dest32,
-               entry->msi_attrib.maskbit, entry->msi_attrib.masked,
-               msi_get_mask_bit(entry));
+               dest32, attr.maskbit, attr.masked, mask);
     }
 }
 
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -73,15 +73,14 @@ struct msi_msg {
        u32     dest32;         /* used when Interrupt Remapping with EIM is 
enabled */
 };
 
+struct irq_desc;
 struct msi_desc;
 /* Helper functions */
-extern void mask_msi_irq(struct irq_desc *);
-extern void unmask_msi_irq(struct irq_desc *);
-extern void set_msi_affinity(struct irq_desc *, const cpumask_t *);
 extern int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc);
 extern void pci_disable_msi(struct msi_desc *desc);
 extern void pci_cleanup_msi(struct pci_dev *pdev);
-extern int setup_msi_irq(struct msi_desc *desc, int irq);
+extern void setup_msi_handler(struct irq_desc *, struct msi_desc *);
+extern void setup_msi_irq(struct irq_desc *);
 extern void teardown_msi_irq(int irq);
 extern int msi_free_vector(struct msi_desc *entry);
 extern int pci_restore_msi_state(struct pci_dev *pdev);
@@ -89,14 +88,14 @@ extern int pci_restore_msi_state(struct 
 extern unsigned int pci_msix_get_table_len(struct pci_dev *pdev);
 
 struct msi_desc {
-       struct {
+       struct msi_attrib {
                __u8    type    : 5;    /* {0: unused, 5h:MSI, 11h:MSI-X} */
                __u8    maskbit : 1;    /* mask-pending bit supported ?   */
                __u8    masked  : 1;
                __u8    is_64   : 1;    /* Address size: 0=32bit 1=64bit  */
                __u8    pos;            /* Location of the msi capability */
                __u16   entry_nr;       /* specific enabled entry         */
-       }msi_attrib;
+       } msi_attrib;
 
        struct list_head list;
 
@@ -122,8 +121,6 @@ int msi_free_irq(struct msi_desc *entry)
  */
 #define NR_HP_RESERVED_VECTORS         20
 
-extern const struct hw_interrupt_type pci_msi_type;
-
 #define PCI_MSIX_ENTRY_SIZE                    16
 #define  PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET      0
 #define  PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET      4
@@ -221,5 +218,6 @@ struct msg_address {
        __u32   hi_address;
 } __attribute__ ((packed));
 
-void msi_compose_msg(int irq, struct msi_msg *);
+void msi_compose_msg(struct irq_desc *, struct msi_msg *);
+
 #endif /* __ASM_MSI_H */


Attachment: x86-msi-type-split.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.