diff options
-rw-r--r-- | xen/arch/x86/hpet.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmsi.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/io_apic.c | 38 | ||||
-rw-r--r-- | xen/arch/x86/irq.c | 15 | ||||
-rw-r--r-- | xen/arch/x86/msi.c | 110 | ||||
-rw-r--r-- | xen/include/asm-x86/msi.h | 16 |
6 files changed, 96 insertions, 89 deletions
diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c index 262ed0e439..508bb4ae51 100644 --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -312,7 +312,7 @@ static void __hpet_setup_msi_irq(struct irq_desc *desc) { struct msi_msg msg; - msi_compose_msg(desc->irq, &msg); + msi_compose_msg(desc, &msg); hpet_msi_write(desc->action->dev_id, &msg); } diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c index 9db092befd..9ea861fca6 100644 --- 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, struct pirq *pirq, uint64_t gtable) 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 *d, struct pirq *pirq) if ( !irq_desc ) return; - if ( irq_desc->handler != &pci_msi_type ) + if ( !irq_desc->msi_desc ) goto out; msi_desc = irq_desc->msi_desc; diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index b337024653..a7081570ca 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -1882,44 +1882,6 @@ static hw_irq_controller ioapic_level_type = { .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; diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 71ea764868..9606ae2c1e 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -1304,7 +1304,7 @@ static int pirq_acktype(struct domain *d, int pirq) * 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; /* @@ -1723,7 +1723,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 ) @@ -1739,7 +1739,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 @@ -1807,6 +1807,12 @@ int unmap_domain_pirq(struct domain *d, int pirq) 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); @@ -1819,9 +1825,6 @@ int unmap_domain_pirq(struct domain *d, int pirq) 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; } diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c index 5ff4e3d098..c6f938503e 100644 --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -120,11 +120,11 @@ static void msix_put_fixmap(struct pci_dev *dev, int idx) /* * 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 *entry, struct msi_msg *msg) 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_desc *entry, struct msi_msg *msg) } } -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 msi_desc *entry) 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(void) 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) @@ -1022,19 +1062,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 ) { @@ -1045,6 +1086,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", @@ -1055,9 +1101,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); } } diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h index 5917746a39..09d4231ece 100644 --- a/xen/include/asm-x86/msi.h +++ b/xen/include/asm-x86/msi.h @@ -74,15 +74,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); @@ -90,14 +89,14 @@ extern int pci_restore_msi_state(struct pci_dev *pdev); 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; @@ -123,8 +122,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 @@ -222,5 +219,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 */ |