summaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/irq_ia64.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /arch/ia64/kernel/irq_ia64.c
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'arch/ia64/kernel/irq_ia64.c')
-rw-r--r--arch/ia64/kernel/irq_ia64.c93
1 files changed, 50 insertions, 43 deletions
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index a2c493ba5..1a8398f85 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -25,10 +25,6 @@
#include <linux/smp_lock.h>
#include <linux/threads.h>
-#ifdef CONFIG_KDB
-# include <linux/kdb.h>
-#endif
-
#include <asm/bitops.h>
#include <asm/delay.h>
#include <asm/io.h>
@@ -41,13 +37,15 @@
spinlock_t ivr_read_lock;
#endif
+unsigned long ipi_base_addr = IPI_DEFAULT_BASE_ADDR; /* default base addr of IPI table */
+
/*
* Legacy IRQ to IA-64 vector translation table. Any vector not in
* this table maps to itself (ie: irq 0x30 => IA64 vector 0x30)
*/
-__u8 isa_irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = {
+__u8 isa_irq_to_vector_map[16] = {
/* 8259 IRQ translation, first 16 entries */
- 0x60, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54,
+ 0x60, 0x50, 0x10, 0x51, 0x52, 0x53, 0x43, 0x54,
0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41
};
@@ -80,8 +78,8 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
# ifndef CONFIG_SMP
static unsigned int max_prio = 0;
-# endif
unsigned int prev_prio;
+# endif
unsigned long eoi_ptr;
# ifdef CONFIG_USB
@@ -95,21 +93,25 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
* Stop IPIs by getting the ivr_read_lock
*/
spin_lock(&ivr_read_lock);
+ {
+ unsigned int tmp;
- /*
- * Disable PCI writes
- */
- outl(0x80ff81c0, 0xcf8);
- outl(0x73002188, 0xcfc);
- eoi_ptr = inl(0xcfc);
+ /*
+ * Disable PCI writes
+ */
+ outl(0x80ff81c0, 0xcf8);
+ tmp = inl(0xcfc);
+ outl(tmp | 0x400, 0xcfc);
- vector = ia64_get_ivr();
+ eoi_ptr = inl(0xcfc);
- /*
- * Enable PCI writes
- */
- outl(0x73182188, 0xcfc);
+ vector = ia64_get_ivr();
+ /*
+ * Enable PCI writes
+ */
+ outl(tmp, 0xcfc);
+ }
spin_unlock(&ivr_read_lock);
# ifdef CONFIG_USB
@@ -152,9 +154,6 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n"
"(bsp=0x%lx, sp=%lx)\n", bsp, sp);
}
-#ifdef CONFIG_KDB
- kdb(KDB_REASON_PANIC, 0, regs);
-#endif
}
/*
@@ -175,9 +174,6 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
if (!pEOI) {
printk("Yikes: ia64_handle_irq() without pEOI!!\n");
asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI));
-# ifdef CONFIG_KDB
- kdb(KDB_REASON_PANIC, 0, regs);
-# endif
}
}
@@ -195,13 +191,13 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
#ifdef CONFIG_SMP
-void __init
-init_IRQ_SMP (void)
-{
- if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL))
- panic("Could not allocate IPI Interrupt Handler!");
-}
+extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
+static struct irqaction ipi_irqaction = {
+ handler: handle_IPI,
+ flags: SA_INTERRUPT,
+ name: "IPI"
+};
#endif
void __init
@@ -214,13 +210,14 @@ init_IRQ (void)
ia64_set_lrr0(0, 1);
ia64_set_lrr1(0, 1);
- irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal;
+ irq_desc[TIMER_IRQ].handler = &irq_type_ia64_sapic;
+ irq_desc[IA64_SPURIOUS_INT].handler = &irq_type_ia64_sapic;
#ifdef CONFIG_SMP
/*
* Configure the IPI vector and handler
*/
- irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal;
- init_IRQ_SMP();
+ irq_desc[IPI_IRQ].handler = &irq_type_ia64_sapic;
+ setup_irq(IPI_IRQ, &ipi_irqaction);
#endif
ia64_set_pmv(1 << 16);
@@ -232,16 +229,26 @@ init_IRQ (void)
ia64_set_tpr(0);
}
-/* TBD:
- * Certain IA64 platforms can have inter-processor interrupt support.
- * This interface is supposed to default to the IA64 IPI block-based
- * mechanism if the platform doesn't provide a separate mechanism
- * for IPIs.
- * Choices : (1) Extend hw_interrupt_type interfaces
- * (2) Use machine vector mechanism
- * For now defining the following interface as a place holder.
- */
void
-ipi_send (int cpu, int vector, int delivery_mode)
+ipi_send (int cpu, int vector, int delivery_mode, int redirect)
{
+ unsigned long ipi_addr;
+ unsigned long ipi_data;
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+ unsigned long flags;
+#endif
+# define EID 0
+
+ ipi_data = (delivery_mode << 8) | (vector & 0xff);
+ ipi_addr = ipi_base_addr | ((cpu << 8 | EID) << 4) | ((redirect & 1) << 3);
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+ spin_lock_irqsave(&ivr_read_lock, flags);
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+ writeq(ipi_data, ipi_addr);
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+ spin_unlock_irqrestore(&ivr_read_lock, flags);
+#endif
}