patch-2.4.22 linux-2.4.22/arch/ia64/kernel/iosapic.c

Next file: linux-2.4.22/arch/ia64/kernel/irq.c
Previous file: linux-2.4.22/arch/ia64/kernel/ia64_ksyms.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/arch/ia64/kernel/iosapic.c linux-2.4.22/arch/ia64/kernel/iosapic.c
@@ -4,7 +4,7 @@
  * Copyright (C) 1999 Intel Corp.
  * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
  * Copyright (C) 2000-2002 J.I. Lee <jung-ik.lee@intel.com>
- * Copyright (C) 1999-2000, 2002 Hewlett-Packard Co.
+ * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co.
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
@@ -28,6 +28,9 @@
  * 02/07/29	T. Kochi	Allocate interrupt vectors dynamically
  * 02/08/04	T. Kochi	Cleaned up terminology (irq, global system interrupt, vector, etc.)
  * 02/08/13	B. Helgaas	Support PCI segments
+ * 03/02/19	B. Helgaas	Make pcat_compat system-wide, not per-IOSAPIC.
+ *				Remove iosapic_address & gsi_base from external interfaces.
+ *				Rationalize __init/__devinit attributes.
  */
 /*
  * Here is what the interrupt logic between a PCI device and the CPU looks like:
@@ -63,14 +66,14 @@
  */
 #include <linux/config.h>
 
-#include <linux/kernel.h>
+#include <linux/acpi.h>
 #include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
-#include <linux/irq.h>
-#include <linux/acpi.h>
 
 #include <asm/delay.h>
 #include <asm/hw_irq.h>
@@ -83,7 +86,6 @@
 
 
 #undef DEBUG_INTERRUPT_ROUTING
-#undef OVERRIDE_DEBUG
 
 #ifdef DEBUG_INTERRUPT_ROUTING
 #define DBG(fmt...)	printk(fmt)
@@ -115,23 +117,26 @@
 	char		*addr;		/* base address of IOSAPIC */
 	unsigned int 	gsi_base;	/* first GSI assigned to this IOSAPIC */
 	unsigned short 	num_rte;	/* number of RTE in this IOSAPIC */
-	unsigned char	pcat_compat;	/* 8259 compatibility flag */
-} iosapic_lists[256] __devinitdata;
+} iosapic_lists[256];
 
-static int __devinitdata num_iosapic = 0;
+static int num_iosapic;
+
+static unsigned char pcat_compat __initdata;	/* 8259 compatibility flag */
 
 
 /*
  * Find an IOSAPIC associated with a GSI
  */
-static inline int __devinit
+static inline int
 find_iosapic (unsigned int gsi)
 {
 	int i;
 
-	for (i = 0; i < num_iosapic; i++)
+	for (i = 0; i < num_iosapic; i++) {
 		if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)
 			return i;
+	}
+
 	return -1;
 }
 
@@ -159,6 +164,8 @@
 	int rte_index;
 	char redir;
 
+	DBG(KERN_DEBUG "IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
+
 	rte_index = iosapic_intr_info[vector].rte_index;
 	if (rte_index < 0)
 		return;		/* not an IOSAPIC interrupt */
@@ -171,7 +178,7 @@
 	redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
 #ifdef CONFIG_SMP
 	{
-		int irq;
+		unsigned int irq;
 
 		for (irq = 0; irq < NR_IRQS; ++irq)
 			if (irq_to_vector(irq) == vector) {
@@ -333,14 +340,14 @@
 #define iosapic_ack_level_irq		nop
 
 struct hw_interrupt_type irq_type_iosapic_level = {
-	typename:	"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,
-	set_affinity:	iosapic_set_affinity
+	.typename =	"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,
+	.set_affinity =	iosapic_set_affinity
 };
 
 /*
@@ -377,14 +384,14 @@
 #define iosapic_end_edge_irq		nop
 
 struct hw_interrupt_type irq_type_iosapic_edge = {
-	typename:	"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,
-	set_affinity:	iosapic_set_affinity
+	.typename =	"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,
+	.set_affinity =	iosapic_set_affinity
 };
 
 unsigned int
@@ -407,7 +414,7 @@
  * if the given vector is already owned by other,
  *  assign a new vector for the other and make the vector available
  */
-static void
+static void __init
 iosapic_reassign_vector (int vector)
 {
 	int new_vector;
@@ -417,67 +424,52 @@
 	    || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger)
 	{
 		new_vector = ia64_alloc_vector();
-		printk("Reassigning Vector %d to %d\n", vector, new_vector);
-		memcpy (&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
-			sizeof(struct iosapic_intr_info));
-		memset (&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
+		printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);
+		memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
+		       sizeof(struct iosapic_intr_info));
+		memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
 		iosapic_intr_info[vector].rte_index = -1;
 	}
 }
 
 static void
 register_intr (unsigned int gsi, int vector, unsigned char delivery,
-	       unsigned long polarity, unsigned long edge_triggered,
-	       unsigned int gsi_base, char *iosapic_address)
+	       unsigned long polarity, unsigned long trigger)
 {
 	irq_desc_t *idesc;
 	struct hw_interrupt_type *irq_type;
 	int rte_index;
+	int index;
+	unsigned long gsi_base;
+	char *iosapic_address;
+
+	index = find_iosapic(gsi);
+	if (index < 0) {
+		printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi);
+		return;
+	}
+
+	iosapic_address = iosapic_lists[index].addr;
+	gsi_base = iosapic_lists[index].gsi_base;
 
 	rte_index = gsi - gsi_base;
 	iosapic_intr_info[vector].rte_index = rte_index;
-	iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+	iosapic_intr_info[vector].polarity = polarity;
 	iosapic_intr_info[vector].dmode    = delivery;
+	iosapic_intr_info[vector].addr     = iosapic_address;
+	iosapic_intr_info[vector].gsi_base = gsi_base;
+	iosapic_intr_info[vector].trigger  = trigger;
 
-	/*
-	 * In override, it may not provide addr/gsi_base.  GSI is enough to
-	 * locate iosapic addr, gsi_base and rte_index by examining
-	 * gsi_base and num_rte of registered iosapics (tbd)
-	 */
-#ifndef	OVERRIDE_DEBUG
-	if (iosapic_address) {
-		iosapic_intr_info[vector].addr = iosapic_address;
-		iosapic_intr_info[vector].gsi_base = gsi_base;
-	}
-#else
-	if (iosapic_address) {
-		if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address))
-			printk("WARN: %s: diff IOSAPIC ADDRESS for GSI 0x%x, vector %d\n",
-			       __FUNCTION__, gsi, vector);
-		iosapic_intr_info[vector].addr = iosapic_address;
-		if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) {
-			printk("WARN: %s: diff GSI base 0x%x for GSI 0x%x, vector %d\n",
-			       __FUNCTION__, gsi_base, gsi, vector);
-		}
-		iosapic_intr_info[vector].gsi_base = gsi_base;
-	} else if (!iosapic_intr_info[vector].addr)
-		printk("WARN: %s: invalid override for GSI 0x%x, vector %d\n",
-		       __FUNCTION__, gsi, vector);
-#endif
-	if (edge_triggered) {
-		iosapic_intr_info[vector].trigger = IOSAPIC_EDGE;
+	if (trigger == IOSAPIC_EDGE)
 		irq_type = &irq_type_iosapic_edge;
-	} else {
-		iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL;
+	else
 		irq_type = &irq_type_iosapic_level;
-	}
 
 	idesc = irq_desc(vector);
 	if (idesc->handler != irq_type) {
 		if (idesc->handler != &no_irq_type)
-			printk("%s: changing vector %d from %s to %s\n",
-			       __FUNCTION__, vector, idesc->handler->typename,
-			       irq_type->typename);
+			printk(KERN_WARNING "%s: changing vector %d from %s to %s\n",
+			       __FUNCTION__, vector, idesc->handler->typename, irq_type->typename);
 		idesc->handler = irq_type;
 	}
 }
@@ -489,8 +481,7 @@
  */
 int
 iosapic_register_intr (unsigned int gsi,
-		       unsigned long polarity, unsigned long edge_triggered,
-		       unsigned int gsi_base, char *iosapic_address)
+		       unsigned long polarity, unsigned long trigger)
 {
 	int vector;
 	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
@@ -500,11 +491,11 @@
 		vector = ia64_alloc_vector();
 
 	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-		      polarity, edge_triggered, gsi_base, iosapic_address);
+		      polarity, trigger);
 
-	printk("GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       gsi, (polarity ? "high" : "low"),
-	       (edge_triggered ? "edge" : "level"), dest, vector);
+	printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
+	       gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
@@ -515,11 +506,10 @@
  * ACPI calls this when it finds an entry for a platform interrupt.
  * Note that the irq_base and IOSAPIC address must be set in iosapic_init().
  */
-int
+int __init
 iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
 				int iosapic_vector, u16 eid, u16 id,
-				unsigned long polarity, unsigned long edge_triggered,
-				unsigned int gsi_base, char *iosapic_address)
+				unsigned long polarity, unsigned long trigger)
 {
 	unsigned char delivery;
 	int vector;
@@ -544,17 +534,16 @@
 		delivery = IOSAPIC_LOWEST_PRIORITY;
 		break;
 	      default:
-		printk("%s: invalid interrupt type (%d)\n", __FUNCTION__,
+		printk(KERN_ERR "%s: invalid interrupt type (%d)\n", __FUNCTION__,
 			int_type);
 		return -1;
 	}
 
-	register_intr(gsi, vector, delivery, polarity,
-		      edge_triggered, gsi_base, iosapic_address);
+	register_intr(gsi, vector, delivery, polarity, trigger);
 
-	printk("PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       int_type, gsi, (polarity ? "high" : "low"),
-	       (edge_triggered ? "edge" : "level"), dest, vector);
+	printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
+	       int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
@@ -566,32 +555,20 @@
  * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
  * Note that the gsi_base and IOSAPIC address must be set in iosapic_init().
  */
-void
+void __init
 iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
-			  unsigned long polarity, unsigned long edge_triggered)
+			  unsigned long polarity, unsigned long trigger)
 {
-	int index, vector;
-	unsigned int gsi_base;
-	char *addr;
+	int vector;
 	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
 
-	index = find_iosapic(gsi);
-
-	if (index < 0) {
-		printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", isa_irq, gsi);
-		return;
-	}
-
 	vector = isa_irq_to_vector(isa_irq);
-	addr = iosapic_lists[index].addr;
-	gsi_base = iosapic_lists[index].gsi_base;
 
-	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered,
-		      gsi_base, addr);
+	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
 
-	DBG("ISA: IRQ %u -> GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
+	DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
 	    isa_irq, gsi,
-	    polarity ? "high" : "low", edge_triggered ? "edge" : "level",
+	    polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level",
 	    dest, vector);
 
 	/* program the IOSAPIC routing table */
@@ -624,13 +601,11 @@
 static int
 pci_pin_to_vector (int segment, int bus, int slot, int pci_pin)
 {
-	int index, vector;
-	int gsi_base, pcat_compat;
-	char *addr;
+	int vector;
 	unsigned int gsi;
 
 	if (pci_pin_to_gsi(segment, bus, slot, pci_pin, &gsi) < 0) {
-		printk("PCI: no interrupt route for %02x:%02x:%02x pin %c\n",
+		printk(KERN_ERR "PCI: no interrupt route for %02x:%02x:%02x pin %c\n",
 			segment, bus, slot, 'A' + pci_pin);
 		return -1;
 	}
@@ -638,19 +613,7 @@
 	vector = gsi_to_vector(gsi);
 
 	if (vector < 0) {
-		/* we should allocate a vector for this interrupt line */
-
-		index = find_iosapic(gsi);
-
-		if (index < 0) {
-			printk("PCI: GSI 0x%x has no IOSAPIC mapping\n", gsi);
-			return -1;
-		}
-
-		addr = iosapic_lists[index].addr;
-		gsi_base = iosapic_lists[index].gsi_base;
-		pcat_compat = iosapic_lists[index].pcat_compat;
-
+		/* allocate a vector for this interrupt line */
 		if (pcat_compat && (gsi < 16))
 			vector = isa_irq_to_vector(gsi);
 		else {
@@ -658,8 +621,7 @@
 			vector = ia64_alloc_vector();
 		}
 
-		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-			      0, 0, gsi_base, addr);
+		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
 
 		DBG("PCI: (%02x:%02x:%02x INT%c) -> GSI 0x%x -> vector %d\n",
 		    segment, bus, slot, 'A' + pci_pin, gsi, vector);
@@ -668,29 +630,32 @@
 	return vector;
 }
 
-void __devinit
-iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat)
+void __init
+iosapic_system_init (int system_pcat_compat)
 {
-	int num_rte, vector;
-	unsigned int isa_irq, ver;
-	char *addr;
-	static int first_time = 1;
+	int vector;
 
-	if (first_time) {
-		first_time = 0;
-		for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
-			iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
-	}
+	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
+		iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
 
+	pcat_compat = system_pcat_compat;
 	if (pcat_compat) {
 		/*
 		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
 		 * enabled.
 		 */
-		printk("%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);
+		printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);
 		outb(0xff, 0xA1);
 		outb(0xff, 0x21);
 	}
+}
+
+void __init
+iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
+{
+	int num_rte;
+	unsigned int isa_irq, ver;
+	char *addr;
 
 	addr = ioremap(phys_addr, 0);
 	ver = iosapic_version(addr);
@@ -703,35 +668,22 @@
 	num_rte = ((ver >> 16) & 0xff) + 1;
 
 	iosapic_lists[num_iosapic].addr = addr;
-	iosapic_lists[num_iosapic].pcat_compat = pcat_compat;
 	iosapic_lists[num_iosapic].gsi_base = gsi_base;
 	iosapic_lists[num_iosapic].num_rte = num_rte;
 	num_iosapic++;
 
-	printk("IOSAPIC: version %x.%x, address 0x%lx, GSIs 0x%x-0x%x\n",
+	printk(KERN_INFO "  IOSAPIC v%x.%x, address 0x%lx, GSIs 0x%x-0x%x\n",
 	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
 
 	if ((gsi_base == 0) && pcat_compat) {
-		unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
 
 		/*
 		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may
 		 * get reprogrammed later on with data from the ACPI Interrupt Source
 		 * Override table.
 		 */
-		for (isa_irq = 0; isa_irq < 16; ++isa_irq) {
-			vector = isa_irq_to_vector(isa_irq);
-
-			register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY,
-				     /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */
-				     1, 1, gsi_base, addr);
-
-			DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n",
-			    isa_irq, isa_irq, dest, vector);
-
-			/* program the IOSAPIC routing table: */
-			set_rte(vector, dest);
-		}
+		for (isa_irq = 0; isa_irq < 16; ++isa_irq)
+			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 }
 
@@ -790,7 +742,7 @@
 			idesc = irq_desc(vector);
 			if (idesc->handler != irq_type) {
 				if (idesc->handler != &no_irq_type)
-					printk("%s: changing vector %d from %s to %s\n",
+					printk(KERN_INFO "%s: changing vector %d from %s to %s\n",
 					       __FUNCTION__, vector,
 					       idesc->handler->typename,
 					       irq_type->typename);
@@ -822,7 +774,7 @@
 			dest = (ia64_get_lid() >> 16) & 0xffff;
 #endif
 
-			printk("PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n",
+			printk(KERN_INFO "PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n",
 			       dev->slot_name, 'A' + pci_pin, dest, vector);
 			set_rte(vector, dest);
 		}
@@ -837,7 +789,7 @@
 
 	if (phase == 0) {
 		if (0 != acpi_get_prt(&pci_irq.route, &pci_irq.num_routes)) {
-			printk("%s: acpi_get_prt failed\n", __FUNCTION__);
+			printk(KERN_ERR "%s: acpi_get_prt failed\n", __FUNCTION__);
 		}
 		return;
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)