Re: [PATCH 11/25] i386 irq: Dynamic irq support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jun 20, 2006 at 08:21:00PM -0600, Eric W. Biederman wrote:
> Rajesh Shah <[email protected]> writes:
> 
> > It would be really good to decouple MSI implementation from IO
> > APICs, since there's really no real hardware dependence here.
> > This code can actually go to arch/xxx/pci/msi-apic.c
> 
> I agree in theory.  In practice however msi interrupts look like io_apics.
> with a different register set and the use all of the same support facilities.
> So until that part of the architecture is refactored it doesn't make much
> sense.  There is a slightly better case for moving the code into a separate
> file.  Namely I think I know of a second common implementation for x86_64.
> At which point the files will probably be named msi-intel.c and msi-amd.c
> Or something like that.  
> 
Actually, I meant just the vector tracking code could be in a
separate file and the ioapic and msi code could both assign
vectors from a common routine. I had the patch below in my
patchkit, plus another patch for x86_64 to do the same thing
in io_apic.c and share the same intrvec.c file between the 
two archs. Once you have this, the MSI callbacks in arch
code can be moved out of io_apic.c


 arch/i386/kernel/Makefile                   |    2 
 arch/i386/kernel/intrvec.c                  |   94 ++++++++++++++++++++++++++++
 arch/i386/kernel/io_apic.c                  |   26 ++-----
 include/asm-i386/mach-default/irq_vectors.h |    1 
 4 files changed, 105 insertions(+), 18 deletions(-)

Index: linux-2.6.17-rc6-mm2/arch/i386/kernel/intrvec.c
===================================================================
--- /dev/null
+++ linux-2.6.17-rc6-mm2/arch/i386/kernel/intrvec.c
@@ -0,0 +1,94 @@
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2006 Intel Corporation ([email protected])
+ *
+ */
+
+#include <linux/irq.h>
+
+/*
+ * Code to manage interrupt vectors to program for IO-APIC and PCI
+ * Message Signalled Interrupts (MSI/MSI-X)
+ */
+#define VECTOR_STRIDE 		8
+#define NUM_VECTORS		(FIRST_SYSTEM_VECTOR-FIRST_DEVICE_VECTOR)
+
+static DEFINE_SPINLOCK(intr_vector_lock);
+static DECLARE_BITMAP(vectors_used, NUM_VECTORS);
+int current_vector = FIRST_DEVICE_VECTOR;
+int offset = 0;
+
+static inline void mark_vector_used(int vector)
+{
+	if ((vector >= FIRST_DEVICE_VECTOR) && (vector < FIRST_SYSTEM_VECTOR))
+		set_bit((vector - FIRST_DEVICE_VECTOR), vectors_used);
+}
+
+static inline void mark_vector_free(int vector)
+{
+	if ((vector >= FIRST_DEVICE_VECTOR) && (vector < FIRST_SYSTEM_VECTOR))
+		clear_bit((vector - FIRST_DEVICE_VECTOR), vectors_used);
+}
+
+static inline int is_used(int vector)
+{
+	if ((vector < FIRST_DEVICE_VECTOR) || (vector >= FIRST_SYSTEM_VECTOR))
+		return 1;
+	return (test_bit((vector - FIRST_DEVICE_VECTOR), vectors_used));
+}
+
+int assign_vector(void)
+{
+	unsigned long flags;
+	int vector;
+
+	spin_lock_irqsave(&intr_vector_lock, flags);
+	if (bitmap_full(vectors_used, NUM_VECTORS)) {
+		spin_unlock_irqrestore(&intr_vector_lock, flags);
+		return -1;
+	}
+	vector = current_vector;
+	while (is_used(vector)) {
+		vector += VECTOR_STRIDE;
+		if (vector >= FIRST_SYSTEM_VECTOR)
+			vector = FIRST_DEVICE_VECTOR +
+				(++offset % VECTOR_STRIDE);
+	}
+	mark_vector_used(vector);
+	current_vector = vector;
+	spin_unlock_irqrestore(&intr_vector_lock, flags);
+	return vector;
+}
+
+void free_vector(int vector)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&intr_vector_lock, flags);
+	mark_vector_free(vector);
+	current_vector = vector; /* use this vector at next request */
+	spin_unlock_irqrestore(&intr_vector_lock, flags);
+}
+
+static int __init init_vector_array(void)
+{
+	mark_vector_used(IA32_SYSCALL_VECTOR);
+	return 0;
+}
+
+core_initcall(init_vector_array);
+
Index: linux-2.6.17-rc6-mm2/arch/i386/kernel/Makefile
===================================================================
--- linux-2.6.17-rc6-mm2.orig/arch/i386/kernel/Makefile
+++ linux-2.6.17-rc6-mm2/arch/i386/kernel/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.
 obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
-obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
+obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o intrvec.o
 obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
Index: linux-2.6.17-rc6-mm2/arch/i386/kernel/io_apic.c
===================================================================
--- linux-2.6.17-rc6-mm2.orig/arch/i386/kernel/io_apic.c
+++ linux-2.6.17-rc6-mm2/arch/i386/kernel/io_apic.c
@@ -95,6 +95,8 @@ int vector_irq[NR_VECTORS] __read_mostly
 #define vector_to_irq(vector)	(vector)
 #endif
 
+extern int assign_vector(void);
+
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
  * shared ISA-space IRQs, so we have to support them. We are super
@@ -1163,38 +1165,28 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mos
 
 int assign_irq_vector(int irq)
 {
-	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
-	unsigned long flags;
 	int vector;
 
 	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
 
-	spin_lock_irqsave(&vector_lock, flags);
+	spin_lock(&vector_lock);
 
 	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
-		spin_unlock_irqrestore(&vector_lock, flags);
+		spin_unlock(&vector_lock);
 		return IO_APIC_VECTOR(irq);
 	}
-next:
-	current_vector += 8;
-	if (current_vector == SYSCALL_VECTOR)
-		goto next;
 
-	if (current_vector >= FIRST_SYSTEM_VECTOR) {
-		offset++;
-		if (!(offset%8)) {
-			spin_unlock_irqrestore(&vector_lock, flags);
-			return -ENOSPC;
-		}
-		current_vector = FIRST_DEVICE_VECTOR + offset;
+	vector = assign_vector();
+	if (vector < 0) {
+		spin_unlock(&vector_lock);
+		return -1;
 	}
 
-	vector = current_vector;
 	vector_irq[vector] = irq;
 	if (irq != AUTO_ASSIGN)
 		IO_APIC_VECTOR(irq) = vector;
 
-	spin_unlock_irqrestore(&vector_lock, flags);
+	spin_unlock(&vector_lock);
 
 	return vector;
 }
Index: linux-2.6.17-rc6-mm2/include/asm-i386/mach-default/irq_vectors.h
===================================================================
--- linux-2.6.17-rc6-mm2.orig/include/asm-i386/mach-default/irq_vectors.h
+++ linux-2.6.17-rc6-mm2/include/asm-i386/mach-default/irq_vectors.h
@@ -29,6 +29,7 @@
 #define FIRST_EXTERNAL_VECTOR	0x20
 
 #define SYSCALL_VECTOR		0x80
+#define IA32_SYSCALL_VECTOR	SYSCALL_VECTOR
 
 /*
  * Vectors 0x20-0x2f are used for ISA interrupts.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux