Skip to contentSkip to conversation

IOSAPIC cleanup and bugfixes patch

Linux-ia64 KOCHI, Takayoshi 1 participant 1 message Aug 6, 2002 ACPI

lore
Share & tools
lore
#0 lore raw

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
diff -Nura david-020722/arch/ia64/kernel/acpi.c david-020722-iosapic/arch/ia64/kernel/acpi.c
@@ -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
diff -Nura david-020722/arch/ia64/kernel/ia64_ksyms.c david-020722-iosapic/arch/ia64/kernel/ia64_ksyms.c
@@ -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
diff -Nura david-020722/arch/ia64/kernel/irq.c david-020722-iosapic/arch/ia64/kernel/irq.c
@@ -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
diff -Nura david-020722/arch/ia64/kernel/irq_ia64.c david-020722-iosapic/arch/ia64/kernel/irq_ia64.c
@@ -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
diff -Nura david-020722/drivers/acpi/osl.c david-020722-iosapic/drivers/acpi/osl.c
@@ -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_SERVICES
 ACPI_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
diff -Nura david-020722/include/asm-ia64/acpi.h david-020722-iosapic/include/asm-ia64/acpi.h
@@ -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
diff -Nura david-020722/include/asm-ia64/hw_irq.h david-020722-iosapic/include/asm-ia64/hw_irq.h
@@ -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
diff -Nura david-020722/include/asm-ia64/iosapic.h david-020722-iosapic/include/asm-ia64/iosapic.h
@@ -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]>