patch-2.4.4 linux/arch/ia64/sn/sn1/irq.c

Next file: linux/arch/ia64/sn/sn1/llsc4.c
Previous file: linux/arch/ia64/sn/sn1/iomv.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/irq.c linux/arch/ia64/sn/sn1/irq.c
@@ -4,11 +4,13 @@
  * Copyright (C) 2000   Silicon Graphics
  * Copyright (C) 2000   Jack Steiner (steiner@sgi.com)
  * Copyright (C) 2000   Alan Mayer (ajm@sgi.com)
+ * Copyright (C) 2000   Kanoj Sarcar (kanoj@sgi.com)
  */
 
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 #include <asm/current.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -30,28 +32,23 @@
 #include <asm/sn/sn1/arch.h>
 #include <asm/sn/synergy.h>
 
+#define IRQ_BIT_OFFSET 64
 
-int bit_pos_to_irq(int bit);
-int irq_to_bit_pos(int irq);
-void add_interrupt_randomness(int irq);
-void * kmalloc(size_t size, int flags);
-void kfree(const void *);
-int sgi_pci_intr_support (unsigned int, device_desc_t *, devfs_handle_t *, pciio_intr_line_t *, devfs_handle_t *);
-pciio_intr_t pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t);
-int request_irq(unsigned int, void (*)(int, void *, struct pt_regs *), unsigned long, const char *, void *);
-
-/* This should be dynamically allocated, at least part of it. */
-/* For the time being, though, we'll statically allocate it */
-/* because kmalloc hasn't been initiallized at the time this */
-/* array is initiallized.  One way to do it would be to statically */
-/* allocate the data for node 0, then let other nodes, as they */
-/* need it, dynamically allocate their own data space. */
-
-struct sn1_cnode_action_list *sn1_node_actions[MAX_COMPACT_NODES];
-struct sn1_cnode_action_list sn1_actions[MAX_COMPACT_NODES][256];
+int bit_pos_to_irq(int bit)
+{
+	if (bit > 118)
+		bit = 118;
+	return (bit + IRQ_BIT_OFFSET);
+}
 
+static inline int irq_to_bit_pos(int irq)
+{
+	int bit = irq - IRQ_BIT_OFFSET;
 
-extern int numnodes;
+	if (bit > 63)
+		bit -= 64;
+	return bit;
+}
 
 static unsigned int
 sn1_startup_irq(unsigned int irq)
@@ -82,6 +79,10 @@
 static void
 sn1_end_irq(unsigned int irq)
 {
+	int bit;
+
+	bit = irq_to_bit_pos(irq);
+	LOCAL_HUB_CLR_INTR(bit);
 }
 
 static void
@@ -89,38 +90,6 @@
 {
 }
 
-
-static void
-sn1_handle_irq(int irq, void *dummy, struct pt_regs *regs)
-{
-	int bit, cnode;
-	struct sn1_cnode_action_list *alp;
-	struct sn1_intr_action *ap;
-	void (*handler)(int, void *, struct pt_regs *);
-	unsigned long flags = 0;
-	int cpuid = smp_processor_id();
-
-
-	bit = irq_to_bit_pos(irq);
-	LOCAL_HUB_CLR_INTR(bit);
-	cnode = cpuid_to_cnodeid(cpuid);
-	alp = sn1_node_actions[cnode];
-	ap = alp[irq].action_list;
-	if (ap == NULL) {
-		return;
-	}
-	while (ap) {
-		flags |= ap->flags;
-		handler = ap->handler;
-		(*handler)(irq,ap->intr_arg,regs);
-		ap = ap->next;
-	}
-	if ((flags & SA_SAMPLE_RANDOM) != 0)
-                add_interrupt_randomness(irq);
-
-        return;
-}
-
 struct hw_interrupt_type irq_type_sn1 = {
         "sn1_irq",
         sn1_startup_irq,
@@ -132,134 +101,83 @@
         sn1_set_affinity_irq
 };
 
-struct irqaction sn1_irqaction = {
-	sn1_handle_irq,
-	0,
-	0,
-	NULL,
-	NULL,
-	NULL,
-};
 
 void
 sn1_irq_init (void)
 {
-	int i,j;
+	int i;
 
 	for (i = 0; i <= NR_IRQS; ++i) {
-		if (irq_desc[i].handler == &no_irq_type) {
-			irq_desc[i].handler = &irq_type_sn1;
-			if (i >=71 && i <= 181) {
-				irq_desc[i].action = &sn1_irqaction;
-			}
-		}
-	}
-
-	for (i = 0; i < numnodes; i++) {
-		sn1_node_actions[i] = sn1_actions[i];
-		memset(sn1_node_actions[i], 0,
-			sizeof(struct sn1_cnode_action_list) *
-			(IA64_MAX_VECTORED_IRQ + 1));
-		for (j=0; j<IA64_MAX_VECTORED_IRQ+1; j++) {
-			spin_lock_init(&sn1_node_actions[i][j].action_list_lock);
+		if (idesc_from_vector(i)->handler == &no_irq_type) {
+			idesc_from_vector(i)->handler = &irq_type_sn1;
 		}
 	}
 }
 
 
-int          
-sn1_request_irq (unsigned int requested_irq, void (*handler)(int, void *, struct pt_regs *),
-             unsigned long irqflags, const char * devname, void *dev_id)
-{ 
-	devfs_handle_t curr_dev;
-	devfs_handle_t dev;
-	pciio_intr_t intr_handle;
-	pciio_intr_line_t line;
-	device_desc_t dev_desc;
-        int cpuid, bit, cnode;
-	struct sn1_intr_action *ap, *new_ap;
-	struct sn1_cnode_action_list *alp;
-	int irq;
-
-	if ( (requested_irq & 0xff) == 0 ) {
-		int ret;
-
-		sgi_pci_intr_support(requested_irq,
-			&dev_desc, &dev, &line, &curr_dev);
-		intr_handle = pciio_intr_alloc(curr_dev, NULL, line, curr_dev);
-		bit = intr_handle->pi_irq;
-		cpuid = intr_handle->pi_cpu;
-		irq = bit_pos_to_irq(bit);
-		cnode = cpuid_to_cnodeid(cpuid);
-		new_ap = (struct sn1_intr_action *)kmalloc(
-			sizeof(struct sn1_intr_action), GFP_KERNEL);
-		irq_desc[irq].status = 0;
-		new_ap->handler = handler;
-		new_ap->intr_arg = dev_id;
-		new_ap->flags = irqflags;
-		new_ap->next = NULL;
-		alp = sn1_node_actions[cnode];
-
-		spin_lock(&alp[irq].action_list_lock);
-		ap = alp[irq].action_list;
-		/* check action list for "share" consistency */
-		while (ap){
-			if (!(ap->flags & irqflags & SA_SHIRQ) ) {
-				return(-EBUSY);
-				spin_unlock(&alp[irq].action_list_lock);
-			}
-			ap = ap->next;
-		}
-		ap = alp[irq].action_list;
-		if (ap) {
-			while (ap->next) {
-				ap = ap->next;
-			}
-			ap->next = new_ap;
-		} else {
-			alp[irq].action_list = new_ap;
-		}
-		ret = pciio_intr_connect(intr_handle, (intr_func_t)handler, dev_id, NULL);
-		if (ret) { /* connect failed, undo what we did. */
-			new_ap = alp[irq].action_list;
-			if (new_ap == ap) {
-				alp[irq].action_list = NULL;
-				kfree(ap);
-			} else {
-				while (new_ap->next && new_ap->next != ap) {
-					new_ap = new_ap->next;
-				}
-				if (new_ap->next == ap) {
-					new_ap->next = ap->next;
-					kfree(ap);
-				}
-			}
-		}
-			
-		spin_unlock(&alp[irq].action_list_lock);
-		return(ret);
-	} else {
-		return(request_irq(requested_irq, handler, irqflags, devname, dev_id));
-	}
-}
 
-#if !defined(CONFIG_IA64_SGI_IO)
+#if !defined(CONFIG_IA64_SGI_SN1)
 void
 sn1_pci_fixup(int arg)
 {
 }
 #endif
 
-int
-bit_pos_to_irq(int bit) {
-#define BIT_TO_IRQ 64
+#ifdef CONFIG_PERCPU_IRQ
+
+extern irq_desc_t irq_descX[NR_IRQS];
+irq_desc_t *irq_desc_ptr[NR_CPUS] = { irq_descX };
+
+/*
+ * Each slave AP allocates its own irq table.
+ */
+int __init cpu_irq_init(void)
+{
+	irq_desc_ptr[smp_processor_id()] = (irq_desc_t *)kmalloc(sizeof(irq_descX), GFP_KERNEL);
+	if (irq_desc_ptr[smp_processor_id()] == 0)
+		return(-1);
+	memcpy(irq_desc_ptr[smp_processor_id()], irq_desc_ptr[0], 
+							sizeof(irq_descX));
+	return(0);
+}
+
+/*
+ * This can also allocate the irq tables for the other cpus, specifically
+ * on their nodes.
+ */
+int __init master_irq_init(void)
+{
+	return(0);
+}
+
+/*
+ * The input is an ivt level.
+ */
+irq_desc_t *idesc_from_vector(unsigned int ivnum)
+{
+	return(irq_desc_ptr[smp_processor_id()] + ivnum);
+}
 
-        return bit + BIT_TO_IRQ;
+/*
+ * The input is a "soft" level, that we encoded in.
+ */
+irq_desc_t *idesc_from_irq(unsigned int irq)
+{
+	return(irq_desc_ptr[irq >> 8] + (irq & 0xff));
 }
 
-int
-irq_to_bit_pos(int irq) {
-#define IRQ_TO_BIT 64
+unsigned int ivector_from_irq(unsigned int irq)
+{
+	return(irq & 0xff);
+}
 
-        return irq - IRQ_TO_BIT;
+/*
+ * This should return the Linux irq # for the i/p vector on the
+ * i/p cpu. We currently do not track this.
+ */
+unsigned int irq_from_cpuvector(int cpunum, unsigned int vector)
+{
+	return (vector);
 }
+
+#endif /* CONFIG_PERCPU_IRQ */

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