X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fkernel%2Fiosapic.c;h=60ff56dddcf3a4243df79751886055b85b5127b0;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=d58c1c5c903a9cfdae0981411ae53604fce020f1;hpb=43bc926fffd92024b46cafaf7350d669ba9ca884;p=linux-2.6.git diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index d58c1c5c9..60ff56ddd 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -79,7 +79,6 @@ * describeinterrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ * (isa_irq) is the only exception in this source code. */ -#include #include #include @@ -160,6 +159,65 @@ static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ static int iosapic_kmalloc_ok; static LIST_HEAD(free_rte_list); +#ifdef CONFIG_XEN +#include +#include +#include +static inline unsigned int xen_iosapic_read(char __iomem *iosapic, unsigned int reg) +{ + struct physdev_apic apic_op; + int ret; + + apic_op.apic_physbase = (unsigned long)iosapic - + __IA64_UNCACHED_OFFSET; + apic_op.reg = reg; + ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op); + if (ret) + return ret; + return apic_op.value; +} + +static inline void xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +{ + struct physdev_apic apic_op; + + apic_op.apic_physbase = (unsigned long)iosapic - + __IA64_UNCACHED_OFFSET; + apic_op.reg = reg; + apic_op.value = val; + HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op); +} + +static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int reg) +{ + if (!is_running_on_xen()) { + writel(reg, iosapic + IOSAPIC_REG_SELECT); + return readl(iosapic + IOSAPIC_WINDOW); + } else + return xen_iosapic_read(iosapic, reg); +} + +static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +{ + if (!is_running_on_xen()) { + writel(reg, iosapic + IOSAPIC_REG_SELECT); + writel(val, iosapic + IOSAPIC_WINDOW); + } else + xen_iosapic_write(iosapic, reg, val); +} + +int xen_assign_irq_vector(int irq) +{ + struct physdev_irq irq_op; + + irq_op.irq = irq; + if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) + return -ENOSPC; + + return irq_op.vector; +} +#endif /* XEN */ + /* * Find an IOSAPIC associated with a GSI */ @@ -289,6 +347,27 @@ nop (unsigned int irq) /* do nothing... */ } + +#ifdef CONFIG_KEXEC +void +kexec_disable_iosapic(void) +{ + struct iosapic_intr_info *info; + struct iosapic_rte_info *rte; + u8 vec = 0; + for (info = iosapic_intr_info; info < + iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { + list_for_each_entry(rte, &info->rtes, + rte_list) { + iosapic_write(rte->addr, + IOSAPIC_RTE_LOW(rte->rte_index), + IOSAPIC_MASK|vec); + iosapic_eoi(rte->addr, vec); + } + } +} +#endif + static void mask_irq (unsigned int irq) { @@ -426,14 +505,16 @@ iosapic_end_level_irq (unsigned int irq) #define iosapic_disable_level_irq mask_irq #define iosapic_ack_level_irq nop -struct hw_interrupt_type irq_type_iosapic_level = { - .typename = "IO-SAPIC-level", +struct irq_chip irq_type_iosapic_level = { + .name = "IO-SAPIC-level", .startup = iosapic_startup_level_irq, .shutdown = iosapic_shutdown_level_irq, .enable = iosapic_enable_level_irq, .disable = iosapic_disable_level_irq, .ack = iosapic_ack_level_irq, .end = iosapic_end_level_irq, + .mask = mask_irq, + .unmask = unmask_irq, .set_affinity = iosapic_set_affinity }; @@ -456,7 +537,7 @@ iosapic_startup_edge_irq (unsigned int irq) static void iosapic_ack_edge_irq (unsigned int irq) { - irq_desc_t *idesc = irq_descp(irq); + irq_desc_t *idesc = irq_desc + irq; move_native_irq(irq); /* @@ -473,14 +554,16 @@ iosapic_ack_edge_irq (unsigned int irq) #define iosapic_disable_edge_irq nop #define iosapic_end_edge_irq nop -struct hw_interrupt_type irq_type_iosapic_edge = { - .typename = "IO-SAPIC-edge", +struct irq_chip irq_type_iosapic_edge = { + .name = "IO-SAPIC-edge", .startup = iosapic_startup_edge_irq, .shutdown = iosapic_disable_edge_irq, .enable = iosapic_enable_edge_irq, .disable = iosapic_disable_edge_irq, .ack = iosapic_ack_edge_irq, .end = iosapic_end_edge_irq, + .mask = mask_irq, + .unmask = unmask_irq, .set_affinity = iosapic_set_affinity }; @@ -654,19 +737,22 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, iosapic_intr_info[vector].dmode = delivery; iosapic_intr_info[vector].trigger = trigger; + if (is_running_on_xen()) + return 0; + if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; else irq_type = &irq_type_iosapic_level; - idesc = irq_descp(vector); - if (idesc->handler != irq_type) { - if (idesc->handler != &no_irq_type) + idesc = irq_desc + vector; + if (idesc->chip != irq_type) { + if (idesc->chip != &no_irq_type) printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", __FUNCTION__, vector, - idesc->handler->typename, irq_type->typename); - idesc->handler = irq_type; + idesc->chip->name, irq_type->name); + idesc->chip = irq_type; } return 0; } @@ -793,14 +879,14 @@ again: return -ENOSPC; } - spin_lock_irqsave(&irq_descp(vector)->lock, flags); + spin_lock_irqsave(&irq_desc[vector].lock, flags); spin_lock(&iosapic_lock); { if (gsi_to_vector(gsi) > 0) { if (list_empty(&iosapic_intr_info[vector].rtes)) free_irq_vector(vector); spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_descp(vector)->lock, + spin_unlock_irqrestore(&irq_desc[vector].lock, flags); goto again; } @@ -810,7 +896,7 @@ again: polarity, trigger); if (err < 0) { spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_descp(vector)->lock, + spin_unlock_irqrestore(&irq_desc[vector].lock, flags); return err; } @@ -825,7 +911,7 @@ again: set_rte(gsi, vector, dest, mask); } spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_descp(vector)->lock, flags); + spin_unlock_irqrestore(&irq_desc[vector].lock, flags); printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), @@ -860,7 +946,7 @@ iosapic_unregister_intr (unsigned int gsi) } vector = irq_to_vector(irq); - idesc = irq_descp(irq); + idesc = irq_desc + irq; spin_lock_irqsave(&idesc->lock, flags); spin_lock(&iosapic_lock); { @@ -903,7 +989,7 @@ iosapic_unregister_intr (unsigned int gsi) BUG_ON(iosapic_intr_info[vector].count); /* Clear the interrupt controller descriptor */ - idesc->handler = &no_irq_type; + idesc->chip = &no_irq_type; /* Clear the interrupt information */ memset(&iosapic_intr_info[vector], 0, @@ -1016,6 +1102,9 @@ iosapic_system_init (int system_pcat_compat) } pcat_compat = system_pcat_compat; + if (is_running_on_xen()) + return; + if (pcat_compat) { /* * Disable the compatibility mode interrupts (8259 style),