public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH][RFC] Vector sharing
@ 2004-04-19  9:31 Kenji Kaneshige
  2004-04-20 12:25 ` Jean-Francois Neyroud
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Kenji Kaneshige @ 2004-04-19  9:31 UTC (permalink / raw)
  To: linux-ia64

[-- Attachment #1: Type: text/plain, Size: 21581 bytes --]

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;

[-- Attachment #2: share_vector.patch --]
[-- Type: application/octet-stream, Size: 20070 bytes --]

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;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][RFC] Vector sharing
  2004-04-19  9:31 [PATCH][RFC] Vector sharing Kenji Kaneshige
@ 2004-04-20 12:25 ` Jean-Francois Neyroud
  2004-04-20 14:46 ` Bjorn Helgaas
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jean-Francois Neyroud @ 2004-04-20 12:25 UTC (permalink / raw)
  To: linux-ia64

[-- Attachment #1: Type: text/plain, Size: 641 bytes --]



Kenji Kaneshige wrote:

>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
>
Hi Kenji,

An other or complementary way is to attach a vector only for interrupt
lines witch are used, PCI slots have 4 interrupt lines but only 1 or
sometime 2 are used by adapters.

Find hereafter a patch tested on IA64 platform.

Jean-Francois.

-- 
Jean-Francois Neyroud 
Bull SA                                               http://www-frec.bull.com 



[-- Attachment #2: Bull_irq_dynamic.patch --]
[-- Type: text/plain, Size: 1098 bytes --]

--- linux-2.6.3_ref/drivers/acpi/pci_irq.c	Wed Feb 18 04:57:46 2004
+++ linux-2.6.3/drivers/acpi/pci_irq.c	Fri Feb 27 14:06:37 2004
@@ -264,8 +264,15 @@
 		}
 	}
 	else if (!entry->irq) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static routing entry (IRQ 0)\n"));
-		return_VALUE(0);
+		int irq;
+	    
+		irq = iosapic_register_intr(entry->link.index, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
+		if (irq < 0) {
+
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static routing entry (IRQ 0)\n"));
+			return_VALUE(0);
+		}
+		entry->irq = irq;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", entry->irq));
--- linux-2.6.3_ref/arch/ia64/kernel/iosapic.c	Fri Feb 27 13:57:06 2004
+++ linux-2.6.3/arch/ia64/kernel/iosapic.c	Fri Feb 27 14:03:20 2004
@@ -706,8 +706,8 @@
 			if (pcat_compat && (gsi < 16))
 				vector = isa_irq_to_vector(gsi);
 			else
-				/* new GSI; allocate a vector for it */
-				vector = ia64_alloc_vector();
+				/* new GSI; don't allocate a vector for it */
+				continue;
 
 			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
 				      IOSAPIC_LEVEL);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][RFC] Vector sharing
  2004-04-19  9:31 [PATCH][RFC] Vector sharing Kenji Kaneshige
  2004-04-20 12:25 ` Jean-Francois Neyroud
@ 2004-04-20 14:46 ` Bjorn Helgaas
  2004-04-21  1:15 ` Kenji Kaneshige
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Bjorn Helgaas @ 2004-04-20 14:46 UTC (permalink / raw)
  To: linux-ia64

On Tuesday 20 April 2004 6:25 am, Jean-Francois Neyroud wrote:
> Kenji Kaneshige wrote:
> >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).
> 
> An other or complementary way is to attach a vector only for interrupt
> lines witch are used, PCI slots have 4 interrupt lines but only 1 or
> sometime 2 are used by adapters.

I have a patch in the works that will clean up ACPI _PRT handling
(it removes the boot-time _PRT parsing and does the IOSAPIC setup
at pci_enable_device()-time).  One side effect is that we only set
up vectors for interrupt lines actually used.

The attached patch is the current status.  It's been tested on
a few ia64 configs, but I think there are some x86 wrinkles that
I still need to work out, so this is just FYI, in case anybody
wants to give it a whirl.

Bjorn

=== arch/i386/kernel/mpparse.c 1.69 vs edited ==--- 1.69/arch/i386/kernel/mpparse.c	Mon Mar 22 14:00:03 2004
+++ edited/arch/i386/kernel/mpparse.c	Tue Apr 13 11:10:37 2004
@@ -1036,93 +1036,58 @@
 
 extern FADT_DESCRIPTOR acpi_fadt;
 
-#ifdef CONFIG_ACPI_PCI
+#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
+
+#ifdef CONFIG_X86_IO_APIC
 
-void __init mp_parse_prt (void)
+void mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
 {
-	struct list_head	*node = NULL;
-	struct acpi_prt_entry	*entry = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
-	int			gsi = 0;
 	int			idx, bit = 0;
-	int			edge_level = 0;
-	int			active_high_low = 0;
 
-	/*
-	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
-	 * routing for all entries.
-	 */
-	list_for_each(node, &acpi_prt.entries) {
-		entry = list_entry(node, struct acpi_prt_entry, node);
+	/* Don't set up the ACPI SCI because it's already set up */
+	if (acpi_fadt.sci_int = gsi)
+		return;
+
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic < 0) {
+		printk(KERN_WARNING "No IOAPIC for GSI 0x%x\n", gsi);
+		return;
+	}
+
+	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
 
-		/* Need to get gsi for dynamic entry */
-		if (entry->link.handle) {
-			gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
-			if (!gsi)
-				continue;
-		}
-		else {
-			/* Hardwired GSI. Assume PCI standard settings */
-			gsi = entry->link.index;
-			edge_level = 1;
-			active_high_low = 1;
-		}
-
-		/* Don't set up the ACPI SCI because it's already set up */
-                if (acpi_fadt.sci_int = gsi) {
-			/* we still need to set entry's irq */
-			acpi_gsi_to_irq(gsi, &entry->irq);
-			continue;
-                }
-	
-		ioapic = mp_find_ioapic(gsi);
-		if (ioapic < 0)
-			continue;
-		ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
-
-		if (es7000_plat) {
-			if (!ioapic && (gsi < 16))
-				gsi += 16;
-		}
-
-		/* 
-		 * Avoid pin reprogramming.  PRTs typically include entries  
-		 * with redundant pin->gsi mappings (but unique PCI devices);
-		 * we only only program the IOAPIC on the first.
-		 */
-		bit = ioapic_pin % 32;
-		idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
-		if (idx > 3) {
-			printk(KERN_ERR "Invalid reference to IOAPIC pin "
-				"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
-				ioapic_pin);
-			continue;
-		}
-		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
-				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-			acpi_gsi_to_irq(gsi, &entry->irq);
-			continue;
-		}
-
-		mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
-
-		if (!io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, edge_level, active_high_low)) {
-			acpi_gsi_to_irq(gsi, &entry->irq);
-		}
-		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
-			entry->id.segment, entry->id.bus,
-			entry->id.device, ('A' + entry->pin),
-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
-			entry->irq);
+	if (es7000_plat) {
+		if (!ioapic && (gsi < 16))
+			gsi += 16;
 	}
 
-	print_IO_APIC();
+	/* 
+	 * Avoid pin reprogramming.  PRTs typically include entries  
+	 * with redundant pin->gsi mappings (but unique PCI devices);
+	 * we only only program the IOAPIC on the first.
+	 */
+	bit = ioapic_pin % 32;
+	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+	if (idx > 3) {
+		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+			ioapic_pin);
+		return;
+	}
+	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+		return;
+	}
 
-	return;
+	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+
+	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+		    edge_level = ACPI_EDGE_SENSITIVE ? 0 : 1,
+		    active_high_low = ACPI_ACTIVE_HIGH ? 0 : 1);
 }
 
-#endif /*CONFIG_ACPI_PCI*/
-#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
+#endif /*CONFIG_X86_IO_APIC*/
 #endif /*CONFIG_ACPI_BOOT*/
=== arch/i386/kernel/acpi/boot.c 1.57 vs edited ==--- 1.57/arch/i386/kernel/acpi/boot.c	Tue Mar 30 15:05:19 2004
+++ edited/arch/i386/kernel/acpi/boot.c	Tue Apr 13 16:09:50 2004
@@ -425,6 +425,28 @@
 	return 0;
 }
 
+unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
+{
+	static u16 irq_mask;
+	unsigned int irq;
+	extern void eisa_set_level_irq(unsigned int irq);
+
+	/*
+	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
+	 */
+	if ((gsi < 16) && !((1 << gsi) & irq_mask)) {
+		printk(KERN_DEBUG PREFIX "Setting GSI 0x%x as level-triggered\n", gsi);
+		irq_mask |= (1 << gsi);
+		eisa_set_level_irq(gsi);
+	}
+
+#ifdef CONFIG_X86_IO_APIC
+	mp_register_gsi(gsi, edge_level, active_high_low);
+#endif
+	acpi_gsi_to_irq(gsi, &irq);
+	return irq;
+}
+
 static unsigned long __init
 acpi_scan_rsdp (
 	unsigned long		start,
=== arch/i386/pci/acpi.c 1.12 vs edited ==--- 1.12/arch/i386/pci/acpi.c	Thu Dec 11 19:19:07 2003
+++ edited/arch/i386/pci/acpi.c	Tue Apr 13 17:42:01 2004
@@ -18,16 +18,16 @@
 	if (pcibios_scanned)
 		return 0;
 
-	if (!acpi_noirq) {
-		if (!acpi_pci_irq_init()) {
-			printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-			printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or even 'acpi=off'\n");
-			pcibios_scanned++;
-			pcibios_enable_irq = acpi_pci_irq_enable;
-		} else
-			printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
+	if (acpi_noirq)
+		return 0;
 
-	}
+	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
+	printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or even 'acpi=off'\n");
+	if (!acpi_pci_irq_init()) {
+		pcibios_scanned++;
+		pcibios_enable_irq = acpi_pci_irq_enable;
+	} else
+		printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
 
 	return 0;
 }
=== arch/ia64/kernel/acpi.c 1.68 vs edited ==--- 1.68/arch/ia64/kernel/acpi.c	Thu Apr  8 19:30:12 2004
+++ edited/arch/ia64/kernel/acpi.c	Tue Apr 13 10:50:16 2004
@@ -508,9 +508,14 @@
 #endif /* CONFIG_ACPI_NUMA */
 
 unsigned int
-acpi_register_gsi (u32 gsi, int polarity, int trigger)
+acpi_register_gsi (u32 gsi, int edge_level, int active_high_low)
 {
-	return acpi_register_irq(gsi, polarity, trigger);
+	if (has_8259 && gsi < 16)
+		return isa_irq_to_vector(gsi);
+
+	return iosapic_register_intr(gsi,
+			(active_high_low = ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+			(edge_level = ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 }
 EXPORT_SYMBOL(acpi_register_gsi);
 
@@ -535,7 +540,7 @@
 	if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES)
 		acpi_legacy_devices = 1;
 
-	acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
+	acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
 	return 0;
 }
 
@@ -658,17 +663,5 @@
 	}
 	return 0;
 }
-
-int
-acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
-{
-	if (has_8259 && gsi < 16)
-		return isa_irq_to_vector(gsi);
-
-	return iosapic_register_intr(gsi,
-			(polarity = ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
-			(trigger = ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
-}
-EXPORT_SYMBOL(acpi_register_irq);
 
 #endif /* CONFIG_ACPI_BOOT */
=== arch/ia64/pci/pci.c 1.47 vs edited ==--- 1.47/arch/ia64/pci/pci.c	Mon Apr 12 19:50:46 2004
+++ edited/arch/ia64/pci/pci.c	Tue Apr 13 10:58:44 2004
@@ -158,18 +158,6 @@
 	.write = pci_write,
 };
 
-static int __init
-pci_acpi_init (void)
-{
-	if (!acpi_pci_irq_init())
-		printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-	else
-		printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
-	return 0;
-}
-
-subsys_initcall(pci_acpi_init);
-
 /* Called by ACPI when it finds a new root bus.  */
 
 static struct pci_controller * __devinit
=== arch/x86_64/kernel/mpparse.c 1.25 vs edited ==--- 1.25/arch/x86_64/kernel/mpparse.c	Mon Apr 12 11:53:56 2004
+++ edited/arch/x86_64/kernel/mpparse.c	Tue Apr 13 11:11:01 2004
@@ -894,84 +894,48 @@
 
 extern FADT_DESCRIPTOR acpi_fadt;
 
-#ifdef CONFIG_ACPI_PCI
-
-void __init mp_parse_prt (void)
+void mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
 {
-	struct list_head	*node = NULL;
-	struct acpi_prt_entry	*entry = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
-	int			gsi = 0;
 	int			idx, bit = 0;
-	int			edge_level = 0;
-	int			active_high_low = 0;
-
-	/*
-	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
-	 * routing for all static (IOAPIC-direct) entries.
-	 */
-	list_for_each(node, &acpi_prt.entries) {
-		entry = list_entry(node, struct acpi_prt_entry, node);
-
-		/* Need to get gsi for dynamic entry */
-		if (entry->link.handle) {
-			gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
-			if (!gsi)
-				continue;
-		} else {
-			/* Hardwired GSI. Assume PCI standard settings */
-			gsi = entry->link.index;
-			edge_level = 1;
-			active_high_low = 1;
-		}
-
-		/* Don't set up the ACPI SCI because it's already set up */
-		if (acpi_fadt.sci_int = gsi)
-			continue;
 
-		ioapic = mp_find_ioapic(gsi);
-		if (ioapic < 0)
-			continue;
-		ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
+	/* Don't set up the ACPI SCI because it's already set up */
+	if (acpi_fadt.sci_int = gsi)
+		return;
+
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic < 0) {
+		printk(KERN_WARNING "No IOAPIC for GSI 0x%x\n", gsi);
+		return;
+	}
 
-		/* 
-		 * Avoid pin reprogramming.  PRTs typically include entries  
-		 * with redundant pin->gsi mappings (but unique PCI devices);
-		 * we only only program the IOAPIC on the first.
-		 */
-		bit = ioapic_pin % 32;
-		idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
-		if (idx > 3) {
-			printk(KERN_ERR "Invalid reference to IOAPIC pin "
-				"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
-				ioapic_pin);
-			continue;
-		}
-		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
-				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-			acpi_gsi_to_irq(gsi, &entry->irq);
-			continue;
-		}
+	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
 
-		mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
-		if (!io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, edge_level, active_high_low)) {
-			acpi_gsi_to_irq(gsi, &entry->irq);
- 		}
-		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
-			entry->id.segment, entry->id.bus,
-			entry->id.device, ('A' + entry->pin), 
-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
-			entry->irq);
+	/* 
+	 * Avoid pin reprogramming.  PRTs typically include entries  
+	 * with redundant pin->gsi mappings (but unique PCI devices);
+	 * we only only program the IOAPIC on the first.
+	 */
+	bit = ioapic_pin % 32;
+	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+	if (idx > 3) {
+		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+			ioapic_pin);
+		return;
+	}
+	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+		return;
 	}
-	
-	print_IO_APIC();
 
-	return;
+	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+		edge_level = ACPI_EDGE_SENSITIVE ? 0 : 1,
+		active_high_low = ACPI_ACTIVE_HIGH ? 0 : 1);
 }
-
-#endif /*CONFIG_ACPI_PCI*/
 
 #endif /*CONFIG_X86_IO_APIC*/
 
=== drivers/acpi/pci_irq.c 1.26 vs edited ==--- 1.26/drivers/acpi/pci_irq.c	Thu Apr  1 02:03:21 2004
+++ edited/drivers/acpi/pci_irq.c	Tue Apr 13 16:16:08 2004
@@ -35,12 +35,6 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
-#ifdef CONFIG_X86_IO_APIC
-#include <asm/mpspec.h>
-#endif
-#ifdef CONFIG_IOSAPIC
-# include <asm/iosapic.h>
-#endif
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -50,10 +44,6 @@
 
 struct acpi_prt_list		acpi_prt;
 
-#ifdef CONFIG_X86
-extern void eisa_set_level_irq(unsigned int irq);
-#endif
-
 
 /* --------------------------------------------------------------------------
                          PCI IRQ Routing Table (PRT) Support
@@ -237,12 +227,18 @@
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
 
-int
-acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
+static int
+acpi_pci_irq_lookup (
+	struct pci_bus		*bus,
+	int			device,
+	int			pin,
+	int			*edge_level,
+	int			*active_high_low)
 {
 	struct acpi_prt_entry	*entry = NULL;
 	int segment = pci_domain_nr(bus);
 	int bus_nr = bus->number;
+	int irq;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
 
@@ -255,28 +251,30 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
 		return_VALUE(0);
 	}
-
-	if (!entry->irq && entry->link.handle) {
-		entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, NULL, NULL);
-		if (!entry->irq) {
+	
+	if (entry->link.handle) {
+		irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low);
+		if (!irq) {
 			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
 			return_VALUE(0);
 		}
-	}
-	else if (!entry->irq) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static routing entry (IRQ 0)\n"));
-		return_VALUE(0);
+	} else {
+		irq = entry->link.index;
+		*edge_level = ACPI_LEVEL_SENSITIVE;
+		*active_high_low = ACPI_ACTIVE_LOW;
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", entry->irq));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
 
-	return_VALUE(entry->irq);
+	return_VALUE(irq);
 }
 
 static int
 acpi_pci_irq_derive (
 	struct pci_dev		*dev,
-	int			pin)
+	int			pin,
+	int			*edge_level,
+	int			*active_high_low)
 {
 	struct pci_dev		*bridge = dev;
 	int			irq = 0;
@@ -308,8 +306,8 @@
 			pin = bridge_pin;
 		}
 
-		irq = acpi_pci_irq_lookup(bridge->bus,
-				PCI_SLOT(bridge->devfn), pin);
+		irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
+			pin, edge_level, active_high_low);
 	}
 
 	if (!irq) {
@@ -330,6 +328,8 @@
 {
 	int			irq = 0;
 	u8			pin = 0;
+	int			edge_level = ACPI_LEVEL_SENSITIVE;
+	int			active_high_low = ACPI_ACTIVE_LOW;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
 
@@ -352,21 +352,22 @@
 	 * First we check the PCI IRQ routing table (PRT) for an IRQ.  PRT
 	 * values override any BIOS-assigned IRQs set during boot.
 	 */
- 	irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin);
+ 	irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low);
 
 	/*
 	 * If no PRT entry was found, we'll try to derive an IRQ from the
 	 * device's parent bridge.
 	 */
 	if (!irq)
- 		irq = acpi_pci_irq_derive(dev, pin);
+ 		irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low);
  
 	/*
 	 * No IRQ known to the ACPI subsystem - maybe the BIOS / 
 	 * driver reported one, then use it. Exit in any case.
 	 */
 	if (!irq) {
-		printk(KERN_WARNING PREFIX "No IRQ known for interrupt pin %c of device %s", ('A' + pin), pci_name(dev));
+		printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI",
+			pci_name(dev), ('A' + pin));
 		/* Interrupt Line values above 0xF are forbidden */
 		if (dev->irq && dev->irq >= 0xF) {
 			printk(" - using IRQ %d\n", dev->irq);
@@ -378,27 +379,10 @@
 		}
  	}
 
-	dev->irq = irq;
+	dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", pci_name(dev), dev->irq));
-
-	/* 
-	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
-	 */
-#ifdef CONFIG_X86
-	{
-		static u16 irq_mask;
-		if ((dev->irq < 16) &&  !((1 << dev->irq) & irq_mask)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Setting IRQ %d as level-triggered\n", dev->irq));
-			irq_mask |= (1 << dev->irq);
-			eisa_set_level_irq(dev->irq);
-		}
-	}
-#endif
-#ifdef CONFIG_IOSAPIC
-	if (acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_enable_intr(dev->irq);
-#endif
+	printk(KERN_DEBUG PREFIX "PCI interrupt %s[%c] -> GSI 0x%x -> IRQ %d\n",
+		pci_name(dev), 'A' + pin, irq, dev->irq);
 
 	return_VALUE(dev->irq);
 }
@@ -421,16 +405,6 @@
 	if (acpi_pci_link_check()) {
 		return_VALUE(-ENODEV);
 	}
-
-#ifdef CONFIG_X86_IO_APIC
-	/* Program IOAPICs using data from PRT entries. */
-	if (acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC)
-		mp_parse_prt();
-#endif
-#ifdef CONFIG_IOSAPIC
-	if (acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_parse_prt();
-#endif
 
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
 		acpi_pci_irq_enable(dev);
=== drivers/serial/8250_acpi.c 1.8 vs edited ==--- 1.8/drivers/serial/8250_acpi.c	Mon Mar 15 15:53:32 2004
+++ edited/drivers/serial/8250_acpi.c	Tue Apr 13 10:45:59 2004
@@ -58,28 +58,18 @@
 static acpi_status acpi_serial_ext_irq(struct serial_struct *req,
 				       struct acpi_resource_ext_irq *ext_irq)
 {
-	if (ext_irq->number_of_interrupts > 0) {
-#ifdef CONFIG_IA64
-		req->irq = acpi_register_irq(ext_irq->interrupts[0],
-	                  ext_irq->active_high_low, ext_irq->edge_level);
-#else
-		req->irq = ext_irq->interrupts[0];
-#endif
-	}
+	if (ext_irq->number_of_interrupts > 0)
+		req->irq = acpi_register_gsi(ext_irq->interrupts[0],
+	                  ext_irq->edge_level, ext_irq->active_high_low);
 	return AE_OK;
 }
 
 static acpi_status acpi_serial_irq(struct serial_struct *req,
 				   struct acpi_resource_irq *irq)
 {
-	if (irq->number_of_interrupts > 0) {
-#ifdef CONFIG_IA64
-		req->irq = acpi_register_irq(irq->interrupts[0],
-	                  irq->active_high_low, irq->edge_level);
-#else
-		req->irq = irq->interrupts[0];
-#endif
-	}
+	if (irq->number_of_interrupts > 0)
+		req->irq = acpi_register_gsi(irq->interrupts[0],
+	                  irq->edge_level, irq->active_high_low);
 	return AE_OK;
 }
 
=== drivers/serial/8250_hcdp.c 1.4 vs edited ==--- 1.4/drivers/serial/8250_hcdp.c	Sat Apr 10 03:26:14 2004
+++ edited/drivers/serial/8250_hcdp.c	Tue Apr 13 10:46:00 2004
@@ -179,12 +179,8 @@
 			printk(KERN_WARNING"warning: No support for PCI serial console\n");
 			return;
 		}
-#ifdef CONFIG_IA64
-		port.irq = acpi_register_irq(gsi, ACPI_ACTIVE_HIGH,
-				ACPI_EDGE_SENSITIVE);
-#else
-		port.irq = gsi;
-#endif
+		port.irq = acpi_register_gsi(gsi,
+			ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH);
 		port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_RESOURCES;
 		if (gsi)
 			port.flags |= UPF_AUTO_IRQ;
=== include/asm-i386/mpspec.h 1.20 vs edited ==--- 1.20/include/asm-i386/mpspec.h	Mon Apr 12 11:55:30 2004
+++ edited/include/asm-i386/mpspec.h	Tue Apr 13 11:11:13 2004
@@ -33,7 +33,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern void mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
 #endif /*CONFIG_ACPI_BOOT*/
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
=== include/asm-x86_64/mpspec.h 1.11 vs edited ==--- 1.11/include/asm-x86_64/mpspec.h	Mon Apr 12 11:55:30 2004
+++ edited/include/asm-x86_64/mpspec.h	Tue Apr 13 11:11:26 2004
@@ -189,7 +189,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern void mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
 #endif /*CONFIG_X86_IO_APIC*/
 #endif
 
=== include/linux/acpi.h 1.32 vs edited ==--- 1.32/include/linux/acpi.h	Mon Mar  1 01:26:35 2004
+++ edited/include/linux/acpi.h	Tue Apr 13 11:09:08 2004
@@ -438,6 +438,7 @@
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
 int acpi_pci_irq_init (void);
+unsigned int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
 
 struct acpi_pci_driver {
 	struct acpi_pci_driver *next;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH][RFC] Vector sharing
  2004-04-19  9:31 [PATCH][RFC] Vector sharing Kenji Kaneshige
  2004-04-20 12:25 ` Jean-Francois Neyroud
  2004-04-20 14:46 ` Bjorn Helgaas
@ 2004-04-21  1:15 ` Kenji Kaneshige
  2004-04-21  1:37 ` Kenji Kaneshige
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Kenji Kaneshige @ 2004-04-21  1:15 UTC (permalink / raw)
  To: linux-ia64

Hi,

Thank you for your comments.

> An other or complementary way is to attach a vector only for interrupt
> lines witch are used, PCI slots have 4 interrupt lines but only 1 or
> sometime 2 are used by adapters.

I agree with attaching a vector only for interrupt lines which are used.
Your patch stops the waste of the vector resource, and it becomes difficult
for the lack of vectors to happen. I think we can also do this by using
Bjorn's
ACPI IRQ cleanup patch. To tell the truth, I also had a same idea before.

However, this idea doesn't solve the problem completely. The problem will
happen in the following case:

	o many PCI adapters have 2 or more functions
	o machine has more than 184 PCI slots in the same domain

So, I think vector sharing is necessary to solve this problem.

Thanks,
Kenji Kaneshige


> -----Original Message-----
> From: linux-ia64-owner@vger.kernel.org
> [mailto:linux-ia64-owner@vger.kernel.org]On Behalf Of
> Jean-Francois Neyroud
> Sent: Tuesday, April 20, 2004 9:25 PM
> To: Kenji Kaneshige
> Cc: linux-ia64@vger.kernel.org
> Subject: Re: [PATCH][RFC] Vector sharing
>
>
>
>
> Kenji Kaneshige wrote:
>
> >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
> >
> Hi Kenji,
>
> An other or complementary way is to attach a vector only for interrupt
> lines witch are used, PCI slots have 4 interrupt lines but only 1 or
> sometime 2 are used by adapters.
>
> Find hereafter a patch tested on IA64 platform.
>
> Jean-Francois.
>
> --
> Jean-Francois Neyroud
> Bull SA
http://www-frec.bull.com




^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH][RFC] Vector sharing
  2004-04-19  9:31 [PATCH][RFC] Vector sharing Kenji Kaneshige
                   ` (2 preceding siblings ...)
  2004-04-21  1:15 ` Kenji Kaneshige
@ 2004-04-21  1:37 ` Kenji Kaneshige
  2004-04-22  2:37 ` Kenji Kaneshige
  2004-04-23  7:09 ` Kenji Kaneshige
  5 siblings, 0 replies; 7+ messages in thread
From: Kenji Kaneshige @ 2004-04-21  1:37 UTC (permalink / raw)
  To: linux-ia64

Hi,

> I have a patch in the works that will clean up ACPI _PRT handling
> (it removes the boot-time _PRT parsing and does the IOSAPIC setup
> at pci_enable_device()-time).  One side effect is that we only set
> up vectors for interrupt lines actually used.

I know your patch setting up vectors for interrupt lines actually used :)
But as I said in the previous mail, I think vector sharing is necessary
to solve the problem (lack of vectors).

Thanks,
Kenji Kaneshige


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH][RFC] Vector sharing
  2004-04-19  9:31 [PATCH][RFC] Vector sharing Kenji Kaneshige
                   ` (3 preceding siblings ...)
  2004-04-21  1:37 ` Kenji Kaneshige
@ 2004-04-22  2:37 ` Kenji Kaneshige
  2004-04-23  7:09 ` Kenji Kaneshige
  5 siblings, 0 replies; 7+ messages in thread
From: Kenji Kaneshige @ 2004-04-22  2:37 UTC (permalink / raw)
  To: linux-ia64

Hi Jean-Francois,

> I agree with you ACPI IRQ cleanup patch or my patch only stops the
> waste of the vector resource for line not used but doesn't solve  the
> problem completely.

Thank you :)

> In addition with on of theses patch our patch set_rte() should get
> iosapic_lock is mandatory.

I think both of your patch needs to get iosapic_lock in
iosapic_register_intr()
also. Please see following message:

http://www.gelato.unsw.edu.au/linux-ia64/0404/9352.html

Thanks,
Kenji Kaneshige

-----Original Message-----
From: Jean-Francois Neyroud [mailto:Jean-Francois.Neyroud@bull.net]
Sent: Wednesday, April 21, 2004 3:26 PM
To: Kenji Kaneshige
Cc: linux-ia64@vger.kernel.org; Bjorn Helgaas
Subject: Re: [PATCH][RFC] Vector sharing




Kenji Kaneshige wrote:

Hi,

Thank you for your comments.


An other or complementary way is to attach a vector only for interrupt
lines witch are used, PCI slots have 4 interrupt lines but only 1 or
sometime 2 are used by adapters.


I agree with attaching a vector only for interrupt lines which are used.
Your patch stops the waste of the vector resource, and it becomes difficult
for the lack of vectors to happen. I think we can also do this by using
Bjorn's
ACPI IRQ cleanup patch. To tell the truth, I also had a same idea before.

However, this idea doesn't solve the problem completely. The problem will
happen in the following case:

	o many PCI adapters have 2 or more functions
	o machine has more than 184 PCI slots in the same domain

So, I think vector sharing is necessary to solve this problem.


I agree with you ACPI IRQ cleanup patch or my patch only stops the waste of
the vector resource for line not used but doesn't solve  the problem
completely.
In addition with on of theses patch our patch set_rte() should get
iosapic_lock is mandatory.

Jean-Francois


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH][RFC] Vector sharing
  2004-04-19  9:31 [PATCH][RFC] Vector sharing Kenji Kaneshige
                   ` (4 preceding siblings ...)
  2004-04-22  2:37 ` Kenji Kaneshige
@ 2004-04-23  7:09 ` Kenji Kaneshige
  5 siblings, 0 replies; 7+ messages in thread
From: Kenji Kaneshige @ 2004-04-23  7:09 UTC (permalink / raw)
  To: linux-ia64

Hi Bjorn,

> Yes, I think you're right.  Thanks for posting your patch.  I'll
> integrate that when I get some time to work on that again.
> (I apologize that it is taking me so long to get the patch
> straightened out.  I haven't had much time to work on it
> lately.)

I'm glad to contribute to your patch. I'll send comments or
patches again when I find something about your patch.


> I also agree that while my patch should reduce the usage of
> vectors, we will also need another mechanism to avoid running
> out.  I don't know whether the right answer is sharing,
> doing per-CPU vector allocation, some combination, or what.

Though the performance of per-CPU vector allocation is certainly
good, but I don't think it is good approach because the lack of
vector will happen in the following case:

	o if system has few CPUs
	o if CPUs are hot-removed by operator

The combination of sharing and per-CPU sounds good, though
I have not investigated it much yet. I think it is good for us to
implement vector sharing first, and implement per-CPU allocation
afterwards.

Thanks,
Kenji Kaneshige


> -----Original Message-----
> From: Bjorn Helgaas [mailto:bjorn.helgaas@hp.com]
> Sent: Thursday, April 22, 2004 1:45 PM
> To: Kenji Kaneshige
> Subject: Re: [PATCH][RFC] Vector sharing
> 
> 
> On Wednesday 21 April 2004 8:37 pm, you wrote:
> > I think both of your patch needs to get iosapic_lock in
> > iosapic_register_intr()
> > also. Please see following message:
> > 
> > http://www.gelato.unsw.edu.au/linux-ia64/0404/9352.html
> 
> Yes, I think you're right.  Thanks for posting your patch.  I'll
> integrate that when I get some time to work on that again.
> (I apologize that it is taking me so long to get the patch
> straightened out.  I haven't had much time to work on it
> lately.)
> 
> I also agree that while my patch should reduce the usage of
> vectors, we will also need another mechanism to avoid running
> out.  I don't know whether the right answer is sharing,
> doing per-CPU vector allocation, some combination, or what.
> 
> Bjorn

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-04-23  7:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-19  9:31 [PATCH][RFC] Vector sharing Kenji Kaneshige
2004-04-20 12:25 ` Jean-Francois Neyroud
2004-04-20 14:46 ` Bjorn Helgaas
2004-04-21  1:15 ` Kenji Kaneshige
2004-04-21  1:37 ` Kenji Kaneshige
2004-04-22  2:37 ` Kenji Kaneshige
2004-04-23  7:09 ` Kenji Kaneshige

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox