Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
new file mode 100644
index 0000000..d848b94
--- /dev/null
+++ b/arch/cris/kernel/irq.c
@@ -0,0 +1,297 @@
+/*
+ *
+ *	linux/arch/cris/kernel/irq.c
+ *
+ *      Copyright (c) 2000,2001 Axis Communications AB
+ *
+ *      Authors: Bjorn Wesen (bjornw@axis.com)
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ *
+ * Notice Linux/CRIS: these routines do not care about SMP
+ *
+ */
+
+/*
+ * IRQ's are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/errno.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+
+/* Defined in arch specific irq.c */
+extern void arch_setup_irq(int irq);
+extern void arch_free_irq(int irq);
+
+void
+disable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	
+	local_save_flags(flags);
+	local_irq_disable();
+	mask_irq(irq_nr);
+	local_irq_restore(flags);
+}
+
+void
+enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	local_save_flags(flags);
+	local_irq_disable();
+	unmask_irq(irq_nr);
+	local_irq_restore(flags);
+}
+
+unsigned long
+probe_irq_on()
+{
+	return 0;
+}
+
+EXPORT_SYMBOL(probe_irq_on);
+
+int
+probe_irq_off(unsigned long x)
+{
+	return 0;
+}
+
+EXPORT_SYMBOL(probe_irq_off);
+
+/*
+ * Initial irq handlers.
+ */
+
+static struct irqaction *irq_action[NR_IRQS];
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	int i = *(loff_t *) v;
+	struct irqaction * action;
+	unsigned long flags;
+
+	if (i < NR_IRQS) {
+		local_irq_save(flags);
+		action = irq_action[i];
+		if (!action) 
+			goto skip;
+		seq_printf(p, "%2d: %10u %c %s",
+			i, kstat_this_cpu.irqs[i],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action = action->next; action; action = action->next) {
+			seq_printf(p, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
+	}
+	return 0;
+}
+
+/* called by the assembler IRQ entry functions defined in irq.h
+ * to dispatch the interrupts to registred handlers
+ * interrupts are disabled upon entry - depending on if the
+ * interrupt was registred with SA_INTERRUPT or not, interrupts
+ * are re-enabled or not.
+ */
+
+asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+        int ret, retval = 0;
+
+        cpu = smp_processor_id();
+        irq_enter();
+	kstat_cpu(cpu).irqs[irq - FIRST_IRQ]++;
+	action = irq_action[irq - FIRST_IRQ];
+
+        if (action) {
+                if (!(action->flags & SA_INTERRUPT))
+                        local_irq_enable();
+                do_random = 0;
+                do {
+			ret = action->handler(irq, action->dev_id, regs);
+			if (ret == IRQ_HANDLED)
+				do_random |= action->flags;
+                        retval |= ret;
+                        action = action->next;
+                } while (action);
+
+                if (retval != 1) {
+			if (retval) {
+				printk("irq event %d: bogus retval mask %x\n",
+					irq, retval);
+			} else {
+				printk("irq %d: nobody cared\n", irq);
+			}
+		}
+
+                if (do_random & SA_SAMPLE_RANDOM)
+                        add_interrupt_randomness(irq);
+		local_irq_disable();
+        }
+        irq_exit();
+}
+
+/* this function links in a handler into the chain of handlers for the
+   given irq, and if the irq has never been registred, the appropriate
+   handler is entered into the interrupt vector
+*/
+
+int setup_irq(int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
+
+	p = irq_action + irq - FIRST_IRQ;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ))
+			return -EBUSY;
+
+		/* Can't share interrupts unless both are same type */
+		if ((old->flags ^ new->flags) & SA_INTERRUPT)
+			return -EBUSY;
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	if (new->flags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
+
+	local_save_flags(flags);
+	local_irq_disable();
+	*p = new;
+
+	if (!shared) {
+		/* if the irq wasn't registred before, enter it into the vector table
+		   and unmask it physically 
+		*/
+		arch_setup_irq(irq);
+		unmask_irq(irq);
+	}
+	
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* this function is called by a driver to register an irq handler
+   Valid flags:
+   SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and
+                   no signal checking etc is performed upon exit
+   SA_SHIRQ -> the interrupt can be shared between different handlers, the handler
+                is required to check if the irq was "aimed" at it explicitely
+   SA_RANDOM -> the interrupt will add to the random generators entropy
+*/
+
+int request_irq(unsigned int irq, 
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
+{
+	int retval;
+	struct irqaction * action;
+
+	if(!handler)
+		return -EINVAL;
+
+	/* allocate and fill in a handler structure and setup the irq */
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	cpus_clear(action->mask);
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = setup_irq(irq, action);
+
+	if (retval)
+		kfree(action);
+	return retval;
+}
+
+EXPORT_SYMBOL(request_irq);
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction * action, **p;
+	unsigned long flags;
+
+	if (irq >= NR_IRQS) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+	for (p = irq - FIRST_IRQ + irq_action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		local_save_flags(flags);
+		local_irq_disable();
+		*p = action->next;
+		if (!irq_action[irq - FIRST_IRQ]) {
+			mask_irq(irq);
+			arch_free_irq(irq);
+		}
+		local_irq_restore(flags);
+		kfree(action);
+		return;
+	}
+	printk("Trying to free free IRQ%d\n",irq);
+}
+
+EXPORT_SYMBOL(free_irq);
+
+void weird_irq(void)
+{
+	local_irq_disable();
+	printk("weird irq\n");
+	while(1);
+}
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
+/* Used by other archs to show/control IRQ steering during SMP */
+void __init
+init_irq_proc(void)
+{
+}
+#endif