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 --- 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 */