Interrupt source override (Re: ACPI power button events)
On BigSur, there's an interrupt source override record for IRQ9 (SCI) in ACPI table and the kernel should set it correct.
But the current code doesn't reprogram IO-SAPIC correctly and set interrupt handler type, so the SCI interrupts were never delivered to running CPUs.
This patch fixes this problem. This is against 2.4.17 + 011226 ia64 patch (only affects arch/ia64/kernel/iosapic.c and acpi.c).
And with this patch, I can cat /proc/acpi/event and see "button power 00000080 00000000" now!
Quoted 6 lines · Takayoshi
Oh well, our BigSur says
39: 0 0 IO-SAPIC-edge acpi
But ACPI specification says the SCI (ACPI interrupt) should be active low, level and shareable. I'll look into it...
The spec says active low, but the trigger mode is actually platform-dependent. BigSur and AzusA defines IRQ9 override as active-high.
Anyway we should obey what the interrupt override record says...
Thanks,
Signature · 1 line
KOCHI Takayoshi <[email protected]/[email protected]>
Index: acpi.c
===================================================================
RCS file: /data/cvsroot/linux/arch/ia64/kernel/acpi.c,v retrieving revision 1.1.1.9
acpi.c +5 -12
@@ -101,7 +101,7 @@ acpi_legacy_irq (char *p) {acpi_entry_int_override_t *legacy = (acpi_entry_int_override_t *) p; -unsigned long polarity =0 , edge_triggered =0 ; +unsigned long polarity =0 , trigger =0 ;/* * If the platform we're running doesn't define
@@ -110,17 +110,10 @@if (!iosapic_register_legacy_irq)return ; -switch (legacy->flags) { -case 0x5 : polarity =1 ; edge_triggered =1 ;break ; -case 0x7 : polarity =0 ; edge_triggered =1 ;break ; -case 0xd : polarity =1 ; edge_triggered =0 ;break ; -case 0xf : polarity =0 ; edge_triggered =0 ;break ; -default : -printk (" ACPI Legacy IRQ 0x%02x: Unknown flags 0x%x\n" , legacy->isa_irq, - legacy->flags); -break ; - } -iosapic_register_legacy_irq (legacy->isa_irq, legacy->pin, polarity, edge_triggered); + polarity = legacy->flags &0x03 ; + trigger = (legacy->flags >>2 ) &0x03 ; + +iosapic_register_legacy_irq (legacy->isa_irq, legacy->pin, polarity, trigger); }/*
Index: iosapic.c
===================================================================
RCS file: /data/cvsroot/linux/arch/ia64/kernel/iosapic.c,v retrieving revision 1.1.1.10
iosapic.c +23 -4
@@ -453,24 +453,43 @@* ACPI calls this when it finds an entry for a legacy ISA interrupt. Note that the * irq_base and IOSAPIC address must be set in iosapic_init(). */ + +#define POLARITY_ACTIVE_HIGH (0x01) +#define POLARITY_ACTIVE_LOW (0x03) +#define TRIGGER_EDGE (0x01) +#define TRIGGER_LEVEL (0x03) +void iosapic_register_legacy_irq (unsigned long irq,unsigned long pin,unsigned long polarity, -unsigned long edge_triggered) +unsigned long trigger) {unsigned int vector =isa_irq_to_vector (irq); +irq_desc_t *idesc =irq_desc (vector); +struct hw_interrupt_type *irq_type;#ifdef DEBUG_IRQ_ROUTING printk ("ISA: IRQ %u -> IOSAPIC irq 0x%02x (%s, %s) -> vector %02x\n" , (unsigned ) irq, (unsigned ) pin, - polarity ?"high" :"low" , edge_triggered ?"edge" :"level" , + (polarity ==POLARITY_ACTIVE_HIGH ) ?"high" :"low" , + (trigger ==TRIGGER_EDGE ) ?"edge" :"level" , vector);#endif iosapic_irq[vector].pin = pin; iosapic_irq[vector].dmode =IOSAPIC_LOWEST_PRIORITY ; - iosapic_irq[vector].polarity = polarity ?IOSAPIC_POL_HIGH :IOSAPIC_POL_LOW ; - iosapic_irq[vector].trigger = edge_triggered ?IOSAPIC_EDGE :IOSAPIC_LEVEL ; + iosapic_irq[vector].polarity = (polarity ==POLARITY_ACTIVE_HIGH ) + ?IOSAPIC_POL_HIGH :IOSAPIC_POL_LOW ; +if (trigger ==TRIGGER_EDGE ) { + iosapic_irq[vector].trigger =IOSAPIC_EDGE ; + idesc->handler = &irq_type_iosapic_edge; + }else { + iosapic_irq[vector].trigger =IOSAPIC_LEVEL ; + idesc->handler = &irq_type_iosapic_level; + } + +/* reprogram IOSAPIC */ +set_rte (vector, (ia64_get_lid () >>16 ) &0xffff ); }void __init
RE: [Linux-ia64] [BUG] Interrupt source override (Re: ACPI power
We have similar problems with the IRQ overrides on our CMP and NUMA systems. Our system does not have integrated legacy hardware. Instead we insert a legacy IO card into a modified PCI slot. THE PCI bus uses IRQ0 - IRQ11 for the PCI slots and if the legacy card is present then IRQ12 - IRQ20 are used for the legacy devices and IRQ overrides are used to redirect the IRQs.
One problem we have is that the existing code gives the legacy vectors away to the PCI interrupts and then when the overrides are processed the legacy IRQs reclaim their vectors, resulting in conflicts between PCI and ISA.
The fix we put in is similar to yours with the addition of the change below.
If the legacy card is present (pcat_compat is set) and the PCI interrupt is in the range of the legacy interrupts then we mark the irq as unused. This will prevent the vector from being found by iosapic_irq_to_vector(). This forces a new vector to be assigned to the PCI irq and leaves the vector free to be reclaimed when the IRQ override is processed.
Chuck Sluder
Unisys Corp.
-- linux-2.4.16/arch/ia64/kernel/iosapic.c Fri Nov 9 15:26:17 2001
+++ linux/arch/ia64/kernel/iosapic.c Sun Jan 13 15:45:28 2002
@@ -544,15 +547,16 @@
/* the interrupt route is for another controller...
*/
continue;- if (pcat_compat && (irq < 16))
+ if (pcat_compat && (irq < 16)){
vector = isa_irq_to_vector(irq);- else {
- vector = iosapic_irq_to_vector(irq);
- if (vector < 0)
- /* new iosapic irq: allocate a vector for it
*/
- vector = ia64_alloc_irq();
+ iosapic_irq[vector].pin = -1; /* mark as unused */
}
+ vector = iosapic_irq_to_vector(irq);
+ if (vector < 0)
+ /* new iosapic irq: allocate a vector for it */
+ vector = ia64_alloc_irq();
+
iosapic_irq[vector].addr = addr;
iosapic_irq[vector].base_irq = base_irq;
iosapic_irq[vector].pin = (irq - base_irq);-----Original Message-----
From: KOCHI, Takayoshi [mailto:[email protected]]
Sent: Tuesday, January 15, 2002 8:03 PM
To: [email protected]
Subject: [Linux-ia64] [BUG] Interrupt source override (Re: ACPI power button events)
On BigSur, there's an interrupt source override record for IRQ9 (SCI) in ACPI table and the kernel should set it correct.
But the current code doesn't reprogram IO-SAPIC correctly and set interrupt handler type, so the SCI interrupts were never delivered to running CPUs.
This patch fixes this problem. This is against 2.4.17 + 011226 ia64 patch (only affects arch/ia64/kernel/iosapic.c and acpi.c).
And with this patch, I can cat /proc/acpi/event and see "button power 00000080 00000000" now!
Quoted 6 lines · Takayoshi
Oh well, our BigSur says
39: 0 0 IO-SAPIC-edge acpi
But ACPI specification says the SCI (ACPI interrupt) should be active low, level and shareable. I'll look into it...
The spec says active low, but the trigger mode is actually platform-dependent. BigSur and AzusA defines IRQ9 override as active-high.
Anyway we should obey what the interrupt override record says...
Thanks,
Signature · 1 line
KOCHI Takayoshi <[email protected]/[email protected]>