[PATCH][RFC] Vector sharing

From: Kenji Kaneshige <kaneshige.kenji_at_jp.fujitsu.com>
Date: 2004-04-19 19:31:31
Hi,

I'm trying to make a patch that allows device vectors to be shared by
multiple interrupt sources. This patch enables ia64 linux to boot on
the machine that has single vector number space and many device
interrupt sources (more than 184).

I am changing IA64_LAST_DEVICE_VECTOR to 0x30 in order to test my
patch. My patch seems to work fine on my test environment.

The information of /proc/interrupts on my test environment is shown
below. It says multiple devices are sharing the vector (==IRQ)
0x30. Of course, these devices are not sharing the same interrupt
lines.

           CPU0       CPU1       CPU2       CPU3
 29:          0          0          0          0          LSAPIC  cmc_poll
 30:          0          0          0          0  IO-SAPIC-level  cpe_hndlr
 31:          0          0          0          0          LSAPIC  cmc_hndlr
 34:          2          0          6          0   IO-SAPIC-edge  ide0
 39:          0          0          0          0  IO-SAPIC-level  acpi
 45:          0         50        189          2   IO-SAPIC-edge  serial
 48:          0        280      56383         16  IO-SAPIC-level  ioc0,
ioc1, ehci_hcd, uhci_hcd, uhci_hcd, eth0, eth1
232:          0          0          0          0          LSAPIC  mca_rdzv
238:          0          0          0          0          LSAPIC  perfmon
239:    6732150    6729399    6729272    6729140          LSAPIC  timer
240:          0          0          0          0          LSAPIC  mca_wkup
254:          7         85         85         81          LSAPIC  IPI
NMI:          0          0          0          0
ERR:          0


I am concerned about following point of the design:

    o My patch supports to find the sharable vectors not only for
      level triggered interrupt sources but also for edge triggered
      interrupt sources (Please see
      iosapic_find_sharable_vector()). But I am wondering if it is
      needed for edge triggered interrupt sources.  (As a matter of
      fact, my patch doesn't mark the vectors for edge triggered
      interrupts as sharable (e.g. iosapic_register_intr()).


Any comments are welcomed.

Thanks,
Kenji Kaneshige


diff -Naur linux-2.6.6-rc1/arch/ia64/kernel/iosapic.c
linux-2.6.6-rc1-changed/arch/ia64/kernel/iosapic.c
--- linux-2.6.6-rc1/arch/ia64/kernel/iosapic.c	2004-04-19
16:10:25.970346988 +0900
+++ linux-2.6.6-rc1-changed/arch/ia64/kernel/iosapic.c	2004-04-19
16:25:23.251036926 +0900
@@ -101,15 +101,23 @@

 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this
vector. */

-static struct iosapic_intr_info {
+struct iosapic_pin {
+	struct list_head pin_list;	/* IOSAPIC pins which share the same vector
*/
 	char		*addr;		/* base address of IOSAPIC */
 	u32		low32;		/* current value of low word of Redirection table entry
*/
 	unsigned int	gsi_base;	/* first GSI assigned to this IOSAPIC */
-	char		rte_index;	/* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt)
*/
-	unsigned char	dmode	: 3;	/* delivery mode (see iosapic.h) */
+	char		rte_index;	/* IOSAPIC RTE index */
 	unsigned char 	polarity: 1;	/* interrupt polarity (see iosapic.h) */
+};
+
+static struct iosapic_intr_info {
+	struct list_head pin_head;	/* List head of IOSAPIC pins */
+	struct iosapic_pin pin;		/* First entry of IOSAPIC pins list */
+	int		count;		/* # of pins (0 => not an IOSAPIC interrupt) */
+	unsigned char	dmode	: 3;	/* delivery mode (see iosapic.h) */
 	unsigned char	trigger	: 1;	/* trigger mode (see iosapic.h) */
-} iosapic_intr_info[IA64_NUM_VECTORS];
+	unsigned char	type	: 1;	/* Vector type */
+} iosapic_intr_info[IA64_NUM_VECTORS] __cacheline_aligned;

 static struct iosapic {
 	char		*addr;		/* base address of IOSAPIC */
@@ -142,10 +150,14 @@
 _gsi_to_vector (unsigned int gsi)
 {
 	struct iosapic_intr_info *info;
+	struct iosapic_pin *pin;

-	for (info = iosapic_intr_info; info < iosapic_intr_info +
IA64_NUM_VECTORS; ++info)
-		if (info->gsi_base + info->rte_index == gsi)
-			return info - iosapic_intr_info;
+	for (info = iosapic_intr_info; info < iosapic_intr_info +
IA64_NUM_VECTORS; ++info) {
+		list_for_each_entry(pin, &info->pin_head, pin_list) {
+			if (pin->gsi_base + pin->rte_index == gsi)
+				return info - iosapic_intr_info;
+		}
+	}
 	return -1;
 }

@@ -177,15 +189,13 @@
 	char *addr;
 	int rte_index;
 	char redir;
+	struct iosapic_pin *pin;

 	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)
+	if (!iosapic_intr_info[vector].count)
 		return;		/* not an IOSAPIC interrupt */

-	addr    = iosapic_intr_info[vector].addr;
-	pol     = iosapic_intr_info[vector].polarity;
 	trigger = iosapic_intr_info[vector].trigger;
 	dmode   = iosapic_intr_info[vector].dmode;

@@ -193,31 +203,47 @@
 #ifdef CONFIG_SMP
 	{
 		unsigned int irq;
+		cpumask_t cpumask;

 		for (irq = 0; irq < NR_IRQS; ++irq)
 			if (irq_to_vector(irq) == vector) {
-				set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
+				/* All pins should use the same destination CPU */
+				cpumask = get_irq_affinity_info(irq);
+				if (cpumask != CPU_MASK_ALL)
+					dest = cpu_physical_id(first_cpu(mask));
+				else
+					set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
 				break;
 			}
 	}
 #endif

-	low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
-		 (trigger << IOSAPIC_TRIGGER_SHIFT) |
-		 (dmode << IOSAPIC_DELIVERY_SHIFT) |
-		 ((mask ? 1 : 0) << IOSAPIC_MASK_SHIFT) |
-		 vector);
-
 	/* dest contains both id and eid */
 	high32 = (dest << IOSAPIC_DEST_SHIFT);

 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
-		writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
-		writel(high32, addr + IOSAPIC_WINDOW);
-		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
-		writel(low32, addr + IOSAPIC_WINDOW);
-		iosapic_intr_info[vector].low32 = low32;
+		list_for_each_entry(pin, &iosapic_intr_info[vector].pin_head, pin_list)
{
+			/* Don't change RTE which is already unmasked */
+			if (!(pin->low32 & IOSAPIC_MASK))
+				continue;
+
+			rte_index = pin->rte_index;
+			addr    = pin->addr;
+			pol     = pin->polarity;
+
+			low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
+				 (trigger << IOSAPIC_TRIGGER_SHIFT) |
+				 (dmode << IOSAPIC_DELIVERY_SHIFT) |
+				 ((mask ? 1 : 0) << IOSAPIC_MASK_SHIFT) |
+				 vector);
+
+			writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
+			writel(high32, addr + IOSAPIC_WINDOW);
+			writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
+			writel(low32, addr + IOSAPIC_WINDOW);
+			pin->low32 = low32;
+		}
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
@@ -236,21 +262,24 @@
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
+	struct iosapic_pin *pin;

-	addr = iosapic_intr_info[vec].addr;
-	rte_index = iosapic_intr_info[vec].rte_index;
-
-	if (rte_index < 0)
+	if (!iosapic_intr_info[vec].count)
 		return;			/* not an IOSAPIC interrupt! */

 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
-		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
+		list_for_each_entry(pin, &iosapic_intr_info[vec].pin_head, pin_list) {
+			addr = pin->addr;
+			rte_index = pin->rte_index;
+
+			writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);

-		/* set only the mask bit */
-		low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
+			/* set only the mask bit */
+			low32 = pin->low32 |= IOSAPIC_MASK;

-		writel(low32, addr + IOSAPIC_WINDOW);
+			writel(low32, addr + IOSAPIC_WINDOW);
+		}
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
@@ -263,17 +292,21 @@
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
+	struct iosapic_pin *pin;

-	addr = iosapic_intr_info[vec].addr;
-	rte_index = iosapic_intr_info[vec].rte_index;
-	if (rte_index < 0)
+	if (!iosapic_intr_info[vec].count)
 		return;			/* not an IOSAPIC interrupt! */

 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
-		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
-		low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
-		writel(low32, addr + IOSAPIC_WINDOW);
+		list_for_each_entry(pin, &iosapic_intr_info[vec].pin_head, pin_list) {
+			addr = pin->addr;
+			rte_index = pin->rte_index;
+
+			writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
+			low32 = pin->low32 &= ~IOSAPIC_MASK;
+			writel(low32, addr + IOSAPIC_WINDOW);
+		}
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
@@ -289,6 +322,7 @@
 	char *addr;
 	int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
 	ia64_vector vec;
+	struct iosapic_pin *pin;

 	irq &= (~IA64_IRQ_REDIRECTED);
 	vec = irq_to_vector(irq);
@@ -298,10 +332,7 @@

 	dest = cpu_physical_id(first_cpu(mask));

-	rte_index = iosapic_intr_info[vec].rte_index;
-	addr = iosapic_intr_info[vec].addr;
-
-	if (rte_index < 0)
+	if (!iosapic_intr_info[vec].count)
 		return;			/* not an IOSAPIC interrupt */

 	set_irq_affinity_info(irq, dest, redir);
@@ -311,21 +342,26 @@

 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
-		/* get current delivery mode by reading the low32 */
-		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
-		low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
-		if (redir)
-		        /* change delivery mode to lowest priority */
-			low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
-		else
-		        /* change delivery mode to fixed */
-			low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
-
-		iosapic_intr_info[vec].low32 = low32;
-		writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
-		writel(high32, addr + IOSAPIC_WINDOW);
-		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
-		writel(low32, addr + IOSAPIC_WINDOW);
+		list_for_each_entry(pin, &iosapic_intr_info[vec].pin_head, pin_list) {
+			rte_index = pin->rte_index;
+			addr = pin->addr;
+
+			/* get current delivery mode by reading the low32 */
+			writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
+			low32 = pin->low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
+			if (redir)
+				/* change delivery mode to lowest priority */
+				low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
+			else
+				/* change delivery mode to fixed */
+				low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
+
+			pin->low32 = low32;
+			writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
+			writel(high32, addr + IOSAPIC_WINDOW);
+			writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
+			writel(low32, addr + IOSAPIC_WINDOW);
+		}
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 #endif
@@ -346,8 +382,11 @@
 iosapic_end_level_irq (unsigned int irq)
 {
 	ia64_vector vec = irq_to_vector(irq);
+	struct iosapic_pin *pin;

-	writel(vec, iosapic_intr_info[vec].addr + IOSAPIC_EOI);
+	list_for_each_entry(pin, &iosapic_intr_info[vec].pin_head, pin_list) {
+		writel(vec, pin->addr + IOSAPIC_EOI);
+	}
 }

 #define iosapic_shutdown_level_irq	mask_irq
@@ -427,6 +466,30 @@
 }

 /*
+ * Find a sharable vector.
+ *
+ * NOTE: This function assumes that platform interrupt doesn't share
+ * the vector.
+ */
+static int
+iosapic_find_sharable_vector (unsigned long trigger)
+{
+	int i;
+	static int next_vector = IA64_FIRST_DEVICE_VECTOR;
+
+	for (i = 0; i < IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1;
i++) {
+		if (next_vector > IA64_LAST_DEVICE_VECTOR)
+			next_vector = IA64_FIRST_DEVICE_VECTOR;
+
+		if (iosapic_intr_info[next_vector].type == IOSAPIC_VECTOR_SHARABLE &&
+		    iosapic_intr_info[next_vector].trigger == trigger)
+			return next_vector++;
+	}
+
+	return -1;
+}
+
+/*
  * if the given vector is already owned by other,
  *  assign a new vector for the other and make the vector available
  */
@@ -435,22 +498,20 @@
 {
 	int new_vector;

-	if (iosapic_intr_info[vector].rte_index >= 0 ||
iosapic_intr_info[vector].addr
-	    || iosapic_intr_info[vector].gsi_base ||
iosapic_intr_info[vector].dmode
-	    || iosapic_intr_info[vector].polarity ||
iosapic_intr_info[vector].trigger)
+	if (!iosapic_intr_info[vector].count)
 	{
 		new_vector = assign_irq_vector(AUTO_ASSIGN);
 		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;
+		INIT_LIST_HEAD(&iosapic_intr_info[vector].pin_head);
 	}
 }

 static void
 register_intr (unsigned int gsi, int vector, unsigned char delivery,
-	       unsigned long polarity, unsigned long trigger)
+	       unsigned long polarity, unsigned long trigger, unsigned long type)
 {
 	irq_desc_t *idesc;
 	struct hw_interrupt_type *irq_type;
@@ -458,6 +519,7 @@
 	int index;
 	unsigned long gsi_base;
 	char *iosapic_address;
+	struct iosapic_pin *pin, *tmp;

 	index = find_iosapic(gsi);
 	if (index < 0) {
@@ -468,13 +530,86 @@
 	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_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;
+	/*
+	 * Only interrupt sources whose delivery mode is IOSAPIC_LOWEST_PRIORITY
or
+	 * IOSAPIC_FIXED can share the vector in the current implementation.
+	 */
+	if (delivery != IOSAPIC_LOWEST_PRIORITY &&
+	    delivery != IOSAPIC_FIXED &&
+	    type != IOSAPIC_VECTOR_EXCLUSIVE)
+	{
+		type = IOSAPIC_VECTOR_EXCLUSIVE;
+	}
+
+	pin = NULL;
+	list_for_each_entry(tmp, &iosapic_intr_info[vector].pin_head, pin_list) {
+		if (tmp->gsi_base + tmp->rte_index == gsi) {
+			pin = tmp;
+			break;
+		}
+	}
+
+	if (!pin) {
+		/*
+		 * Register a new interrupt
+		 */
+		if (!iosapic_intr_info[vector].count) {
+			pin = &iosapic_intr_info[vector].pin;
+			iosapic_intr_info[vector].dmode   = delivery;
+			iosapic_intr_info[vector].trigger = trigger;
+			iosapic_intr_info[vector].type    = type;
+		}
+		else if (type == IOSAPIC_VECTOR_EXCLUSIVE) {
+			printk (KERN_WARNING "%s: vector %d is in use\n", __FUNCTION__,
vector);
+			return;
+		}
+		else if (iosapic_intr_info[vector].type == IOSAPIC_VECTOR_EXCLUSIVE) {
+			printk (KERN_WARNING "%s: cannot share the vector %d\n",
__FUNCTION__, vector);
+			return;
+		}
+		else {
+			pin = kmalloc(sizeof(struct iosapic_pin), GFP_KERNEL);
+			if (!pin) {
+				printk (KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__);
+				return;
+			}
+		}
+
+		rte_index = gsi - gsi_base;
+		pin->rte_index = rte_index;
+		pin->polarity = polarity;
+		pin->addr     = iosapic_address;
+		pin->gsi_base = gsi_base;
+		pin->low32    = IOSAPIC_MASK;
+
+		list_add_tail(&pin->pin_list, &iosapic_intr_info[vector].pin_head);
+		iosapic_intr_info[vector].count++;
+	}
+	else {
+		/*
+		 * Override a existing interupt
+		 */
+		if (iosapic_intr_info[vector].count > 1) {
+			if (iosapic_intr_info[vector].trigger != trigger) {
+				printk (KERN_WARNING "%s: cannot change trigger mode\n",
__FUNCTION__);
+				return;
+			}
+			if (type == IOSAPIC_VECTOR_EXCLUSIVE) {
+				printk (KERN_WARNING "%s: vector %d is already shared\n",
__FUNCTION__, vector);
+				return;
+			}
+		}
+
+		rte_index = gsi - gsi_base;
+		pin->rte_index = rte_index;
+		pin->polarity = polarity;
+		pin->addr     = iosapic_address;
+		pin->gsi_base = gsi_base;
+		pin->low32    = IOSAPIC_MASK;
+		iosapic_intr_info[vector].dmode   = delivery;
+		iosapic_intr_info[vector].trigger = trigger;
+		iosapic_intr_info[vector].type    = type;
+	}

 	if (trigger == IOSAPIC_EDGE)
 		irq_type = &irq_type_iosapic_edge;
@@ -504,10 +639,17 @@

 	vector = gsi_to_vector(gsi);
 	if (vector < 0)
-		vector = assign_irq_vector(AUTO_ASSIGN);
+		vector = assign_irq_vector_nopanic(AUTO_ASSIGN);
+
+	if (vector < 0)
+		vector = iosapic_find_sharable_vector(trigger);
+
+	if (vector < 0)
+		panic ("%s: out of interrupt vectors!", __FUNCTION__);

 	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-		      polarity, trigger);
+		      polarity, trigger,
+		      (trigger == IOSAPIC_EDGE ? IOSAPIC_VECTOR_EXCLUSIVE :
IOSAPIC_VECTOR_SHARABLE));

 	printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
 	       gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
@@ -555,7 +697,7 @@
 	}

 	register_intr(gsi, vector, delivery, polarity,
-		      trigger);
+		      trigger, IOSAPIC_VECTOR_EXCLUSIVE);

 	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"),
@@ -581,7 +723,7 @@

 	vector = isa_irq_to_vector(isa_irq);

-	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
+	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger,
IOSAPIC_VECTOR_EXCLUSIVE);

 	DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
 	    isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low",
@@ -596,8 +738,10 @@
 {
 	int vector;

-	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].count = 0;	/* mark as unused */
+		INIT_LIST_HEAD(&iosapic_intr_info[vector].pin_head);
+	}

 	pcat_compat = system_pcat_compat;
 	if (pcat_compat) {
@@ -710,12 +854,17 @@
 			/* allocate a vector for this interrupt line */
 			if (pcat_compat && (gsi < 16))
 				vector = isa_irq_to_vector(gsi);
-			else
+			else {
 				/* new GSI; allocate a vector for it */
-				vector = assign_irq_vector(AUTO_ASSIGN);
+				vector = assign_irq_vector_nopanic(AUTO_ASSIGN);
+				if (vector < 0)
+					vector = iosapic_find_sharable_vector(IOSAPIC_LEVEL);
+				if (vector < 0)
+					panic ("%s: out of interrupt vectors!", __FUNCTION__);
+			}

 			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
-				      IOSAPIC_LEVEL);
+				      IOSAPIC_LEVEL, IOSAPIC_VECTOR_SHARABLE);
 		}
 		entry->irq = vector;
 		snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
@@ -728,7 +877,7 @@
 		idesc = irq_descp(vector);
 		if (idesc->handler != irq_type)
 			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
-				      IOSAPIC_LEVEL);
+				      IOSAPIC_LEVEL, IOSAPIC_VECTOR_SHARABLE);

 	}
 }
diff -Naur linux-2.6.6-rc1/arch/ia64/kernel/irq.c
linux-2.6.6-rc1-changed/arch/ia64/kernel/irq.c
--- linux-2.6.6-rc1/arch/ia64/kernel/irq.c	2004-04-04 12:38:13.000000000
+0900
+++ linux-2.6.6-rc1-changed/arch/ia64/kernel/irq.c	2004-04-19
16:10:53.513448673 +0900
@@ -935,6 +935,11 @@
 	}
 }

+cpumask_t get_irq_affinity_info (unsigned int irq)
+{
+	return irq_affinity[irq];
+}
+
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
diff -Naur linux-2.6.6-rc1/arch/ia64/kernel/irq_ia64.c
linux-2.6.6-rc1-changed/arch/ia64/kernel/irq_ia64.c
--- linux-2.6.6-rc1/arch/ia64/kernel/irq_ia64.c	2004-04-19
16:10:25.971323555 +0900
+++ linux-2.6.6-rc1-changed/arch/ia64/kernel/irq_ia64.c	2004-04-19
16:10:53.513448673 +0900
@@ -72,17 +72,25 @@
 	preempt_enable_no_resched();
 }

+static int next_vector = IA64_FIRST_DEVICE_VECTOR;
+
 int
 assign_irq_vector (int irq)
 {
-	static int next_vector = IA64_FIRST_DEVICE_VECTOR;
-
 	if (next_vector > IA64_LAST_DEVICE_VECTOR)
 		/* XXX could look for sharable vectors instead of panic'ing... */
 		panic("assign_irq_vector: out of interrupt vectors!");
 	return next_vector++;
 }

+int
+assign_irq_vector_nopanic (int irq)
+{
+	if (next_vector > IA64_LAST_DEVICE_VECTOR)
+		return -1;
+	return next_vector++;
+}
+
 extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs);

 /*
diff -Naur linux-2.6.6-rc1/include/asm-ia64/hw_irq.h
linux-2.6.6-rc1-changed/include/asm-ia64/hw_irq.h
--- linux-2.6.6-rc1/include/asm-ia64/hw_irq.h	2004-04-19 16:10:27.139297942
+0900
+++ linux-2.6.6-rc1-changed/include/asm-ia64/hw_irq.h	2004-04-19
16:10:53.514425240 +0900
@@ -83,6 +83,7 @@
 extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal
interrupt controller */

 extern int assign_irq_vector (int irq);	/* allocate a free vector */
+extern int assign_irq_vector_nopanic (int irq);
 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);

diff -Naur linux-2.6.6-rc1/include/asm-ia64/iosapic.h
linux-2.6.6-rc1-changed/include/asm-ia64/iosapic.h
--- linux-2.6.6-rc1/include/asm-ia64/iosapic.h	2004-04-04
12:37:23.000000000 +0900
+++ linux-2.6.6-rc1-changed/include/asm-ia64/iosapic.h	2004-04-19
16:10:53.514425240 +0900
@@ -49,6 +49,12 @@
 #define	IOSAPIC_MASK_SHIFT		16
 #define	IOSAPIC_MASK			(1<<IOSAPIC_MASK_SHIFT)

+/*
+ * Vector type
+ */
+#define IOSAPIC_VECTOR_EXCLUSIVE	(0)
+#define IOSAPIC_VECTOR_SHARABLE		(1)
+
 #ifndef __ASSEMBLY__

 #ifdef CONFIG_IOSAPIC
diff -Naur linux-2.6.6-rc1/include/asm-ia64/irq.h
linux-2.6.6-rc1-changed/include/asm-ia64/irq.h
--- linux-2.6.6-rc1/include/asm-ia64/irq.h	2004-04-19 16:10:27.140274509
+0900
+++ linux-2.6.6-rc1-changed/include/asm-ia64/irq.h	2004-04-19
16:10:53.514425240 +0900
@@ -29,6 +29,10 @@
 extern void disable_irq_nosync (unsigned int);
 extern void enable_irq (unsigned int);
 extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
+#ifdef CONFIG_SMP
+#include <asm/cpumask.h>
+extern cpumask_t get_irq_affinity_info (unsigned int irq);
+#endif /* CONFIG_SMP */

 struct irqaction;
 struct pt_regs;


-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Received on Mon Apr 19 05:29:51 2004

This archive was generated by hypermail 2.1.8 : 2005-08-02 09:20:25 EST