IOSAPIC cleanup and bugfixes patch
David,
Here's a patch for iosapic.c name cleanup and bugfixes.
During the cleanup, I found another bug in iosapic.c.
If you echo "r xx" > /proc/irq/yy/smp_affinity, the redirection is encoded in bit31 of `irq' in iosapic_set_affinity(). But the old code didn't care the bit31 and would call set_irq_affinity_info() with bit31 on. This may
lead to memory corruption.
This patch is generated against ia64 020722 patch and includes:
1) cleanup irq/vector/pin terminology in iosapic.c
2) 20_iosapic_gsi.diff from Bjorn (Jul.22)
the old gsi_to_vector is obviously wrong and we have to remove it.
3) 30_sci.diff from Bjorn (Jul.22) with slight changes ACPI assumed irq = vector, but this patch resolves this.
4) dynamic vector allocation patch from me (Jul.29) allocates ia64 interrupt vector only for existing pci_dev's.
5) legacy irq override patch from me (Aug.2)
fix incorrect programming of IOSAPIC when ACPI MADT interrupt source override record points to other IOSAPIC than default one.
6) fix for smp_affinity redirection bit
7) Bjorn's cleanups for printk's
I'm sorry that a patch grew this big.
The fixes 2-7 are relatively independent, but (1) cleanup depends on especially 2 and 3 and touches places for 4,5,6,7.
So I couldn't divide:)
arch/ia64/kernel/acpi.c +98 -45
@@ -47,9 +47,9 @@#define PREFIX "ACPI: " -asm (".weak iosapic_register_irq" ); -asm (".weak iosapic_register_legacy_irq" ); -asm (".weak iosapic_register_platform_irq" ); +asm (".weak iosapic_register_intr" ); +asm (".weak iosapic_override_isa_irq" ); +asm (".weak iosapic_register_platform_intr" ); asm (".weak iosapic_init" ); asm (".weak iosapic_version" );
@@ -173,10 +173,10 @@#ifdef CONFIG_ACPI_BOOT -#define ACPI_MAX_PLATFORM_IRQS 256 +#define ACPI_MAX_PLATFORM_INTERRUPTS 256/* Array to record platform interrupt vectors for generic interrupt routing. */ -int platform_irq_list[ACPI_MAX_PLATFORM_IRQS ]; +int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS ];enum acpi_irq_model_id acpi_irq_model =ACPI_IRQ_MODEL_IOSAPIC ;
@@ -189,9 +189,9 @@ {int vector =-1 ; -if (int_type <ACPI_MAX_PLATFORM_IRQS ) { +if (int_type <ACPI_MAX_PLATFORM_INTERRUPTS ) {/* correctable platform error interrupt */ - vector = platform_irq_list[int_type]; + vector = platform_intr_list[int_type]; }else printk ("acpi_request_vector(): invalid interrupt type\n" );
@@ -213,6 +213,7 @@static int total_cpus__initdata ;static int available_cpus__initdata ;struct acpi_table_madt * acpi_madt__initdata ; +static u8 has_8259; static int __init
@@ -289,7 +290,7 @@static int __init -acpi_find_iosapic (int global_vector,u32 *irq_base,char **iosapic_address) +acpi_find_iosapic (unsigned int gsi,u32 *gsi_base,char **iosapic_address) {struct acpi_table_iosapic *iosapic =NULL ;int ver =0 ;
@@ -297,7 +298,7 @@char *p =0 ;char *end =0 ; -if (!irq_base || !iosapic_address) +if (!gsi_base || !iosapic_address)return -ENODEV ; p = (char *) (acpi_madt +1 );
@@ -307,13 +308,13 @@if (*p =ACPI_MADT_IOSAPIC ) { iosapic = (struct acpi_table_iosapic *) p; - *irq_base = iosapic->global_irq_base; + *gsi_base = iosapic->global_irq_base; *iosapic_address =ioremap (iosapic->address,0 ); ver =iosapic_version (*iosapic_address); max_pin = (ver >>16 ) &0xff ; -if ((global_vector - *irq_base) <= max_pin) +if ((gsi - *gsi_base) <= max_pin)return 0 ;/* Found it! */ } p += p[1 ];
@@ -352,7 +353,7 @@ {struct acpi_table_plat_int_src *plintsrc =NULL ;int vector =0 ; -u32 irq_base =0 ; +u32 gsi_base =0 ;char *iosapic_address =NULL ; plintsrc = (struct acpi_table_plat_int_src *) header;
@@ -361,31 +362,31 @@acpi_table_print_madt_entry (header); -if (!iosapic_register_platform_irq) { - printk(KERN_WARNING PREFIX "No ACPI platform IRQ support\n"); +if (!iosapic_register_platform_intr) { + printk(KERN_WARNING PREFIX "No ACPI platform interrupt support\n");return -ENODEV ; } -if (0 !=acpi_find_iosapic (plintsrc->global_irq, &irq_base, &iosapic_address)) { +if (0 !=acpi_find_iosapic (plintsrc->global_irq, &gsi_base, &iosapic_address)) { printk(KERN_WARNING PREFIX "IOSAPIC not found\n");return -ENODEV ; }/* -* Get vector assignment for this IRQ, set attributes, and program the -* IOSAPIC routing table. +* Get vector assignment for this interrupt, set attributes, +* and program the IOSAPIC routing table. */ - vector =iosapic_register_platform_irq (plintsrc->type, - plintsrc->global_irq, - plintsrc->iosapic_vector, - plintsrc->eid, - plintsrc->id, - (plintsrc->flags.polarity =1 ) ?1 :0 , - (plintsrc->flags.trigger =1 ) ?1 :0 , - irq_base, - iosapic_address); + vector =iosapic_register_platform_intr (plintsrc->type, + plintsrc->global_irq, + plintsrc->iosapic_vector, + plintsrc->eid, + plintsrc->id, + (plintsrc->flags.polarity =1 ) ?1 :0 , + (plintsrc->flags.trigger =1 ) ?1 :0 , + gsi_base, + iosapic_address); - platform_irq_list[plintsrc->type] = vector; + platform_intr_list[plintsrc->type] = vector;return 0 ; }
@@ -402,10 +403,10 @@acpi_table_print_madt_entry (header);/* Ignore if the platform doesn't support overrides */ -if (!iosapic_register_legacy_irq) +if (!iosapic_override_isa_irq)return 0 ; -iosapic_register_legacy_irq (p->bus_irq, p->global_irq, +iosapic_override_isa_irq (p->bus_irq, p->global_irq, (p->flags.polarity =1 ) ?1 :0 , (p->flags.trigger =1 ) ?1 :0 );
@@ -444,10 +445,13 @@return -ENODEV ; } +/* remember the value for reference after free_initmem() */ + has_8259 = acpi_madt->flags.pcat_compat; +/* Initialize platform interrupt vector array */ -for (i =0 ; i <ACPI_MAX_PLATFORM_IRQS ; i++) - platform_irq_list[i] =-1 ; +for (i =0 ; i <ACPI_MAX_PLATFORM_INTERRUPTS ; i++) + platform_intr_list[i] =-1 ;/* Get base address of IPI Message Block */
@@ -461,6 +465,39 @@ } +static int __init +acpi_parse_facp (unsigned long phys_addr,unsigned long size) +{ +struct acpi_table_header *facp_header; +fadt_descriptor_rev2 *facp; +u32 sci_irq, gsi_base =0 ; +char *iosapic_address =NULL ; + +if (!phys_addr || !size) +return -EINVAL ; + +if (!iosapic_register_intr) +return -ENODEV ; + + facp_header = (struct acpi_table_header *)__va (phys_addr); + +/* Only deal with ACPI 2.0 FACP */ +if (facp_header->revision !=3 ) +return -ENODEV ; + + facp = (fadt_descriptor_rev2 *)facp_header; + sci_irq = facp->sci_int; + +if (has_8259 && sci_irq <16 ) +return 0 ;/* legacy, no setup required */ + +if (!acpi_find_iosapic (sci_irq, &gsi_base, &iosapic_address)) +iosapic_register_intr (sci_irq,0 ,0 , gsi_base, iosapic_address); + +return 0 ; +} + +unsigned long __init acpi_find_rsdp (void ) {
@@ -485,12 +522,12 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size) {acpi_ser_t *spcr =NULL ; -unsigned long global_int =0 ; +unsigned int gsi =0 ;if (!phys_addr || !size)return -EINVAL ; -if (!iosapic_register_irq) +if (!iosapic_register_intr)return -ENODEV ;/*
@@ -517,22 +554,22 @@if ((spcr->base_addr.space_id !=ACPI_SERIAL_PCICONF_SPACE ) && (spcr->int_type =ACPI_SERIAL_INT_SAPIC )) { -u32 irq_base =0 ; +u32 gsi_base =0 ;char *iosapic_address =NULL ;int vector =0 ;/* We have a UART in memory space with an SAPIC interrupt */ - global_int = ( (spcr->global_int[3 ] <<24 ) | - (spcr->global_int[2 ] <<16 ) | - (spcr->global_int[1 ] <<8 ) | - (spcr->global_int[0 ]) ); - -/* Which iosapic does this IRQ belong to? */ - - if (0 = acpi_find_iosapic(global_int, &irq_base, &iosapic_address)) { - vector =iosapic_register_irq (global_int,1 ,1 , - irq_base, iosapic_address); + gsi = ( (spcr->global_int[3 ] <<24 ) | + (spcr->global_int[2 ] <<16 ) | + (spcr->global_int[1 ] <<8 ) | + (spcr->global_int[0 ]) ); + +/* Which iosapic does this interrupt belong to? */ + + if (0 = acpi_find_iosapic(gsi, &gsi_base, &iosapic_address)) { + vector =iosapic_register_intr (gsi,1 ,1 , + gsi_base, iosapic_address); } }return 0 ;
@@ -611,6 +648,13 @@return result; } +/* +* The FADT table contains an SCI_INT line, by which the system +* gets interrupts such as power and sleep buttons. If it's not +* on a Legacy interrupt, it needs to be setup. +*/ +acpi_table_parse (ACPI_FACP , acpi_parse_facp); +#ifdef CONFIG_SERIAL_ACPI /* * TBD: Need phased approach to table parsing (only do those absolutely
@@ -654,7 +698,7 @@ *count =0 ;if (acpi_prt.count <0 ) { - printk(KERN_ERR PREFIX "No PCI IRQ routing entries\n"); + printk(KERN_ERR PREFIX "No PCI interrupt routing entries\n");return -ENODEV ; }
@@ -693,4 +737,13 @@ return 0; } +int +acpi_irq_to_vector (u32 irq) +{ +if (has_8259 && irq <16 ) +return isa_irq_to_vector (irq); + +return gsi_to_vector (irq); +} +#endif /* CONFIG_ACPI_BOOT */
arch/ia64/kernel/ia64_ksyms.c +0 -1
@@ -28,7 +28,6 @@#include <linux/irq.h> EXPORT_SYMBOL (isa_irq_to_vector_map); -EXPORT_SYMBOL (gsi_to_vector_map);EXPORT_SYMBOL (enable_irq);EXPORT_SYMBOL (disable_irq);EXPORT_SYMBOL (disable_irq_nosync);
arch/ia64/kernel/iosapic.c +359 -294
941 lines not on this page · raw message
arch/ia64/kernel/irq.c +1 -1
@@ -1165,7 +1165,7 @@if (!(new_value & cpu_online_map))return -EINVAL ; -irq_desc (irq)->handler->set_affinity (irq | (redir?(1 <<31 ):0 ), new_value); +irq_desc (irq)->handler->set_affinity (irq | (redir?IA64_IRQ_REDIRECTED :0 ), new_value);return full_count; }
arch/ia64/kernel/irq_ia64.c +5 -10
@@ -54,20 +54,15 @@ 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21 }; -/* -* GSI to IA-64 vector translation table. -*/ -__u8 gsi_to_vector_map[255 ]; -int -ia64_alloc_irq (void ) +ia64_alloc_vector (void ) { -static int next_irq =IA64_FIRST_DEVICE_VECTOR ; +static int next_vector =IA64_FIRST_DEVICE_VECTOR ; -if (next_irq >IA64_LAST_DEVICE_VECTOR ) +if (next_vector >IA64_LAST_DEVICE_VECTOR )/* XXX could look for sharable vectors instead of panic'ing... */ -panic ("ia64_alloc_irq: out of interrupt vectors!" ); -return next_irq++; +panic ("ia64_alloc_vector: out of interrupt vectors!" ); +return next_vector++; }extern unsigned int do_IRQ (unsigned long irq,struct pt_regs *regs);
drivers/acpi/osl.c +9 -7
@@ -41,11 +41,6 @@u64 efi_mem_attributes (u64 phys_addr);#endif -#ifdef CONFIG_IA64 -#include <asm/hw_irq.h> -#include <asm/delay.h> -#endif -#define _COMPONENT ACPI_OS_SERVICESACPI_MODULE_NAME ("osl" )
@@ -235,7 +230,14 @@ acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) { #ifdef CONFIG_IA64 - irq =gsi_to_vector (irq); + int vector; + + vector =acpi_irq_to_vector (irq); +if (vector <0 ) { + printk(KERN_ERR PREFIX "SCI (IRQ%d) not registerd\n", irq); +return AE_OK ; + } + irq = vector;#endif /* CONFIG_IA64 */ acpi_irq_irq = irq; acpi_irq_handler = handler;
@@ -253,7 +255,7 @@ {if (acpi_irq_handler) {#ifdef CONFIG_IA64 - irq =gsi_to_vector (irq); + irq =acpi_irq_to_vector (irq);#endif /* CONFIG_IA64 */ free_irq (irq, acpi_irq); acpi_irq_handler =NULL ;
include/asm-ia64/acpi.h +1 -0
@@ -101,6 +101,7 @@int acpi_request_vector (u32 int_type);int acpi_get_prt (struct pci_vector_struct **vectors,int *count);int acpi_get_interrupt_model (int *type); +int acpi_irq_to_vector (u32 irq);#ifdef CONFIG_DISCONTIGMEM #define NODE_ARRAY_INDEX (x) ((x) / 8)/* 8 bits/char */
include/asm-ia64/hw_irq.h +5 -3
@@ -52,6 +52,10 @@#define IA64_IPI_RESCHEDULE 0xfd/* SMP reschedule */ #define IA64_IPI_VECTOR 0xfe/* inter-processor interrupt vector */ +/* Used for encoding redirected irqs */ + +#define IA64_IRQ_REDIRECTED (1 << 31) +/* IA64 inter-cpu interrupt related definitions */ #define IA64_IPI_DEFAULT_BASE_ADDR 0xfee00000
@@ -67,14 +71,12 @@extern __u8 isa_irq_to_vector_map[16 ];#define isa_irq_to_vector (x) isa_irq_to_vector_map[(x)] -extern __u8 gsi_to_vector_map[255 ]; -#define gsi_to_vector (x) gsi_to_vector_map[(x)]extern unsigned long ipi_base_addr;extern struct hw_interrupt_type irq_type_ia64_lsapic;/* CPU-internal interrupt controller */ -extern int ia64_alloc_irq (void );/* allocate a free irq */ +extern int ia64_alloc_vector (void );/* allocate a free vector */ extern void ia64_send_ipi (int cpu,int vector,int delivery_mode,int redirect);extern void register_percpu_irq (ia64_vector vec,struct irqaction *action);
include/asm-ia64/iosapic.h +18 -11
@@ -51,17 +51,24 @@#ifndef __ASSEMBLY__ -extern void __init iosapic_init (unsigned long address,unsigned int base_irq, -int pcat_compat); -extern int iosapic_register_irq (u32 global_vector,unsigned long polarity, -unsigned long edge_triggered,u32 base_irq, -char *iosapic_address); -extern void iosapic_register_legacy_irq (unsigned long irq,unsigned long pin, -unsigned long polarity,unsigned long trigger); -extern int iosapic_register_platform_irq (u32 int_type,u32 global_vector,u32 iosapic_vector, -u16 eid,u16 id,unsigned long polarity, -unsigned long edge_triggered,u32 base_irq, -char *iosapic_address); +extern void __devinit iosapic_init (unsigned long address, +unsigned int gsi_base, +int pcat_compat); +extern int gsi_to_vector (unsigned int gsi); +extern int iosapic_register_intr (unsigned int gsi,unsigned long polarity, +unsigned long edge_triggered, +u32 gsi_base,char *iosapic_address); +extern void iosapic_override_isa_irq (unsigned int isa_irq,unsigned int gsi, +unsigned long polarity, +unsigned long edge_triggered); +extern int iosapic_register_platform_intr (u32 int_type, +unsigned int gsi, +int pmi_vector, +u16 eid,u16 id, +unsigned long polarity, +unsigned long edge_triggered, +unsigned int gsi_base, +char *iosapic_address);extern unsigned int iosapic_version (char *addr);extern void iosapic_pci_fixup (int );
Thanks,
Signature · 1 line
KOCHI, Takayoshi <[email protected]/[email protected]>