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
- Lines: 299
- Date:
Thu Apr 5 12:51:47 2001
- Orig file:
v2.4.3/linux/arch/ia64/sn/sn1/irq.c
- Orig date:
Thu Jan 4 15:25:55 2001
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)