|
@@ -15,6 +15,7 @@
|
|
|
#include <linux/seq_file.h>
|
|
|
|
|
|
#include <asm/cacheflush.h>
|
|
|
+#include <asm/cpudata.h>
|
|
|
#include <asm/pcic.h>
|
|
|
#include <asm/leon.h>
|
|
|
|
|
@@ -101,284 +102,163 @@ EXPORT_SYMBOL(arch_local_irq_restore);
|
|
|
* directed CPU interrupts using the existing enable/disable irq code
|
|
|
* with tweaks.
|
|
|
*
|
|
|
+ * Sun4d complicates things even further. IRQ numbers are arbitrary
|
|
|
+ * 32-bit values in that case. Since this is similar to sparc64,
|
|
|
+ * we adopt a virtual IRQ numbering scheme as is done there.
|
|
|
+ * Virutal interrupt numbers are allocated by build_irq(). So NR_IRQS
|
|
|
+ * just becomes a limit of how many interrupt sources we can handle in
|
|
|
+ * a single system. Even fully loaded SS2000 machines top off at
|
|
|
+ * about 32 interrupt sources or so, therefore a NR_IRQS value of 64
|
|
|
+ * is more than enough.
|
|
|
+ *
|
|
|
+ * We keep a map of per-PIL enable interrupts. These get wired
|
|
|
+ * up via the irq_chip->startup() method which gets invoked by
|
|
|
+ * the generic IRQ layer during request_irq().
|
|
|
*/
|
|
|
|
|
|
|
|
|
+/* Table of allocated irqs. Unused entries has irq == 0 */
|
|
|
+static struct irq_bucket irq_table[NR_IRQS];
|
|
|
+/* Protect access to irq_table */
|
|
|
+static DEFINE_SPINLOCK(irq_table_lock);
|
|
|
|
|
|
-/*
|
|
|
- * Dave Redman (djhr@tadpole.co.uk)
|
|
|
- *
|
|
|
- * There used to be extern calls and hard coded values here.. very sucky!
|
|
|
- * instead, because some of the devices attach very early, I do something
|
|
|
- * equally sucky but at least we'll never try to free statically allocated
|
|
|
- * space or call kmalloc before kmalloc_init :(.
|
|
|
- *
|
|
|
- * In fact it's the timer10 that attaches first.. then timer14
|
|
|
- * then kmalloc_init is called.. then the tty interrupts attach.
|
|
|
- * hmmm....
|
|
|
- *
|
|
|
- */
|
|
|
-#define MAX_STATIC_ALLOC 4
|
|
|
-struct irqaction static_irqaction[MAX_STATIC_ALLOC];
|
|
|
-int static_irq_count;
|
|
|
-
|
|
|
-static struct {
|
|
|
- struct irqaction *action;
|
|
|
- int flags;
|
|
|
-} sparc_irq[NR_IRQS];
|
|
|
-#define SPARC_IRQ_INPROGRESS 1
|
|
|
-
|
|
|
-/* Used to protect the IRQ action lists */
|
|
|
-DEFINE_SPINLOCK(irq_action_lock);
|
|
|
+/* Map between the irq identifier used in hw to the irq_bucket. */
|
|
|
+struct irq_bucket *irq_map[SUN4D_MAX_IRQ];
|
|
|
+/* Protect access to irq_map */
|
|
|
+static DEFINE_SPINLOCK(irq_map_lock);
|
|
|
|
|
|
-int show_interrupts(struct seq_file *p, void *v)
|
|
|
+/* Allocate a new irq from the irq_table */
|
|
|
+unsigned int irq_alloc(unsigned int real_irq, unsigned int pil)
|
|
|
{
|
|
|
- int i = *(loff_t *)v;
|
|
|
- struct irqaction *action;
|
|
|
unsigned long flags;
|
|
|
-#ifdef CONFIG_SMP
|
|
|
- int j;
|
|
|
-#endif
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&irq_table_lock, flags);
|
|
|
+ for (i = 1; i < NR_IRQS; i++) {
|
|
|
+ if (irq_table[i].real_irq == real_irq && irq_table[i].pil == pil)
|
|
|
+ goto found;
|
|
|
+ }
|
|
|
|
|
|
- if (sparc_cpu_model == sun4d)
|
|
|
- return show_sun4d_interrupts(p, v);
|
|
|
+ for (i = 1; i < NR_IRQS; i++) {
|
|
|
+ if (!irq_table[i].irq)
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- spin_lock_irqsave(&irq_action_lock, flags);
|
|
|
if (i < NR_IRQS) {
|
|
|
- action = sparc_irq[i].action;
|
|
|
- if (!action)
|
|
|
- goto out_unlock;
|
|
|
- seq_printf(p, "%3d: ", i);
|
|
|
-#ifndef CONFIG_SMP
|
|
|
- seq_printf(p, "%10u ", kstat_irqs(i));
|
|
|
-#else
|
|
|
- for_each_online_cpu(j) {
|
|
|
- seq_printf(p, "%10u ",
|
|
|
- kstat_cpu(j).irqs[i]);
|
|
|
- }
|
|
|
-#endif
|
|
|
- seq_printf(p, " %c %s",
|
|
|
- (action->flags & IRQF_DISABLED) ? '+' : ' ',
|
|
|
- action->name);
|
|
|
- for (action = action->next; action; action = action->next) {
|
|
|
- seq_printf(p, ",%s %s",
|
|
|
- (action->flags & IRQF_DISABLED) ? " +" : "",
|
|
|
- action->name);
|
|
|
- }
|
|
|
- seq_putc(p, '\n');
|
|
|
+ irq_table[i].real_irq = real_irq;
|
|
|
+ irq_table[i].irq = i;
|
|
|
+ irq_table[i].pil = pil;
|
|
|
+ } else {
|
|
|
+ printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
|
|
|
+ i = 0;
|
|
|
}
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&irq_action_lock, flags);
|
|
|
- return 0;
|
|
|
+found:
|
|
|
+ spin_unlock_irqrestore(&irq_table_lock, flags);
|
|
|
+
|
|
|
+ return i;
|
|
|
}
|
|
|
|
|
|
-void free_irq(unsigned int irq, void *dev_id)
|
|
|
+/* Based on a single pil handler_irq may need to call several
|
|
|
+ * interrupt handlers. Use irq_map as entry to irq_table,
|
|
|
+ * and let each entry in irq_table point to the next entry.
|
|
|
+ */
|
|
|
+void irq_link(unsigned int irq)
|
|
|
{
|
|
|
- struct irqaction *action;
|
|
|
- struct irqaction **actionp;
|
|
|
+ struct irq_bucket *p;
|
|
|
unsigned long flags;
|
|
|
- unsigned int cpu_irq;
|
|
|
+ unsigned int pil;
|
|
|
|
|
|
- if (sparc_cpu_model == sun4d) {
|
|
|
- sun4d_free_irq(irq, dev_id);
|
|
|
- return;
|
|
|
- }
|
|
|
- cpu_irq = irq & (NR_IRQS - 1);
|
|
|
- if (cpu_irq > 14) { /* 14 irq levels on the sparc */
|
|
|
- printk(KERN_ERR "Trying to free bogus IRQ %d\n", irq);
|
|
|
- return;
|
|
|
- }
|
|
|
+ BUG_ON(irq >= NR_IRQS);
|
|
|
|
|
|
- spin_lock_irqsave(&irq_action_lock, flags);
|
|
|
+ spin_lock_irqsave(&irq_map_lock, flags);
|
|
|
|
|
|
- actionp = &sparc_irq[cpu_irq].action;
|
|
|
- action = *actionp;
|
|
|
+ p = &irq_table[irq];
|
|
|
+ pil = p->pil;
|
|
|
+ BUG_ON(pil > SUN4D_MAX_IRQ);
|
|
|
+ p->next = irq_map[pil];
|
|
|
+ irq_map[pil] = p;
|
|
|
|
|
|
- if (!action->handler) {
|
|
|
- printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
- if (dev_id) {
|
|
|
- for (; action; action = action->next) {
|
|
|
- if (action->dev_id == dev_id)
|
|
|
- break;
|
|
|
- actionp = &action->next;
|
|
|
- }
|
|
|
- if (!action) {
|
|
|
- printk(KERN_ERR "Trying to free free shared IRQ%d\n",
|
|
|
- irq);
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
- } else if (action->flags & IRQF_SHARED) {
|
|
|
- printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n",
|
|
|
- irq);
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
- if (action->flags & SA_STATIC_ALLOC) {
|
|
|
- /*
|
|
|
- * This interrupt is marked as specially allocated
|
|
|
- * so it is a bad idea to free it.
|
|
|
- */
|
|
|
- printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n",
|
|
|
- irq, action->name);
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
- *actionp = action->next;
|
|
|
-
|
|
|
- spin_unlock_irqrestore(&irq_action_lock, flags);
|
|
|
+ spin_unlock_irqrestore(&irq_map_lock, flags);
|
|
|
+}
|
|
|
|
|
|
- synchronize_irq(irq);
|
|
|
+void irq_unlink(unsigned int irq)
|
|
|
+{
|
|
|
+ struct irq_bucket *p, **pnext;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
- spin_lock_irqsave(&irq_action_lock, flags);
|
|
|
+ BUG_ON(irq >= NR_IRQS);
|
|
|
|
|
|
- kfree(action);
|
|
|
+ spin_lock_irqsave(&irq_map_lock, flags);
|
|
|
|
|
|
- if (!sparc_irq[cpu_irq].action)
|
|
|
- __disable_irq(irq);
|
|
|
+ p = &irq_table[irq];
|
|
|
+ BUG_ON(p->pil > SUN4D_MAX_IRQ);
|
|
|
+ pnext = &irq_map[p->pil];
|
|
|
+ while (*pnext != p)
|
|
|
+ pnext = &(*pnext)->next;
|
|
|
+ *pnext = p->next;
|
|
|
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&irq_action_lock, flags);
|
|
|
+ spin_unlock_irqrestore(&irq_map_lock, flags);
|
|
|
}
|
|
|
-EXPORT_SYMBOL(free_irq);
|
|
|
|
|
|
-/*
|
|
|
- * This is called when we want to synchronize with
|
|
|
- * interrupts. We may for example tell a device to
|
|
|
- * stop sending interrupts: but to make sure there
|
|
|
- * are no interrupts that are executing on another
|
|
|
- * CPU we need to call this function.
|
|
|
- */
|
|
|
-#ifdef CONFIG_SMP
|
|
|
-void synchronize_irq(unsigned int irq)
|
|
|
-{
|
|
|
- unsigned int cpu_irq;
|
|
|
|
|
|
- cpu_irq = irq & (NR_IRQS - 1);
|
|
|
- while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
|
|
|
- cpu_relax();
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(synchronize_irq);
|
|
|
-#endif /* SMP */
|
|
|
-
|
|
|
-void unexpected_irq(int irq, void *dev_id, struct pt_regs *regs)
|
|
|
+/* /proc/interrupts printing */
|
|
|
+int arch_show_interrupts(struct seq_file *p, int prec)
|
|
|
{
|
|
|
- int i;
|
|
|
- struct irqaction *action;
|
|
|
- unsigned int cpu_irq;
|
|
|
+ int j;
|
|
|
|
|
|
- cpu_irq = irq & (NR_IRQS - 1);
|
|
|
- action = sparc_irq[cpu_irq].action;
|
|
|
-
|
|
|
- printk(KERN_ERR "IO device interrupt, irq = %d\n", irq);
|
|
|
- printk(KERN_ERR "PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
|
|
|
- regs->npc, regs->u_regs[14]);
|
|
|
- if (action) {
|
|
|
- printk(KERN_ERR "Expecting: ");
|
|
|
- for (i = 0; i < 16; i++)
|
|
|
- if (action->handler)
|
|
|
- printk(KERN_CONT "[%s:%d:0x%x] ", action->name,
|
|
|
- i, (unsigned int)action->handler);
|
|
|
- }
|
|
|
- printk(KERN_ERR "AIEEE\n");
|
|
|
- panic("bogus interrupt received");
|
|
|
+ seq_printf(p, "NMI: ");
|
|
|
+ for_each_online_cpu(j)
|
|
|
+ seq_printf(p, "%10u ", cpu_data(j).counter);
|
|
|
+ seq_printf(p, " Non-maskable interrupts\n");
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-void handler_irq(int pil, struct pt_regs *regs)
|
|
|
+void handler_irq(unsigned int pil, struct pt_regs *regs)
|
|
|
{
|
|
|
struct pt_regs *old_regs;
|
|
|
- struct irqaction *action;
|
|
|
- int cpu = smp_processor_id();
|
|
|
+ struct irq_bucket *p;
|
|
|
|
|
|
+ BUG_ON(pil > 15);
|
|
|
old_regs = set_irq_regs(regs);
|
|
|
irq_enter();
|
|
|
- disable_pil_irq(pil);
|
|
|
-#ifdef CONFIG_SMP
|
|
|
- /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */
|
|
|
- if ((sparc_cpu_model==sun4m) && (pil < 10))
|
|
|
- smp4m_irq_rotate(cpu);
|
|
|
-#endif
|
|
|
- action = sparc_irq[pil].action;
|
|
|
- sparc_irq[pil].flags |= SPARC_IRQ_INPROGRESS;
|
|
|
- kstat_cpu(cpu).irqs[pil]++;
|
|
|
- do {
|
|
|
- if (!action || !action->handler)
|
|
|
- unexpected_irq(pil, NULL, regs);
|
|
|
- action->handler(pil, action->dev_id);
|
|
|
- action = action->next;
|
|
|
- } while (action);
|
|
|
- sparc_irq[pil].flags &= ~SPARC_IRQ_INPROGRESS;
|
|
|
- enable_pil_irq(pil);
|
|
|
+
|
|
|
+ p = irq_map[pil];
|
|
|
+ while (p) {
|
|
|
+ struct irq_bucket *next = p->next;
|
|
|
+
|
|
|
+ generic_handle_irq(p->irq);
|
|
|
+ p = next;
|
|
|
+ }
|
|
|
irq_exit();
|
|
|
set_irq_regs(old_regs);
|
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
|
|
|
+static unsigned int floppy_irq;
|
|
|
|
|
|
-/*
|
|
|
- * Fast IRQs on the Sparc can only have one routine attached to them,
|
|
|
- * thus no sharing possible.
|
|
|
- */
|
|
|
-static int request_fast_irq(unsigned int irq,
|
|
|
- void (*handler)(void),
|
|
|
- unsigned long irqflags, const char *devname)
|
|
|
+int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)
|
|
|
{
|
|
|
- struct irqaction *action;
|
|
|
- unsigned long flags;
|
|
|
unsigned int cpu_irq;
|
|
|
- int ret;
|
|
|
+ int err;
|
|
|
+
|
|
|
#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
|
|
|
struct tt_entry *trap_table;
|
|
|
#endif
|
|
|
- cpu_irq = irq & (NR_IRQS - 1);
|
|
|
- if (cpu_irq > 14) {
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- if (!handler) {
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
|
|
|
- spin_lock_irqsave(&irq_action_lock, flags);
|
|
|
+ err = request_irq(irq, irq_handler, 0, "floppy", NULL);
|
|
|
+ if (err)
|
|
|
+ return -1;
|
|
|
|
|
|
- action = sparc_irq[cpu_irq].action;
|
|
|
- if (action) {
|
|
|
- if (action->flags & IRQF_SHARED)
|
|
|
- panic("Trying to register fast irq when already shared.\n");
|
|
|
- if (irqflags & IRQF_SHARED)
|
|
|
- panic("Trying to register fast irq as shared.\n");
|
|
|
+ /* Save for later use in floppy interrupt handler */
|
|
|
+ floppy_irq = irq;
|
|
|
|
|
|
- /* Anyway, someone already owns it so cannot be made fast. */
|
|
|
- printk(KERN_ERR "request_fast_irq: Trying to register yet already owned.\n");
|
|
|
- ret = -EBUSY;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * If this is flagged as statically allocated then we use our
|
|
|
- * private struct which is never freed.
|
|
|
- */
|
|
|
- if (irqflags & SA_STATIC_ALLOC) {
|
|
|
- if (static_irq_count < MAX_STATIC_ALLOC)
|
|
|
- action = &static_irqaction[static_irq_count++];
|
|
|
- else
|
|
|
- printk(KERN_ERR "Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
|
|
|
- irq, devname);
|
|
|
- }
|
|
|
-
|
|
|
- if (action == NULL)
|
|
|
- action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
|
|
|
- if (!action) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
+ cpu_irq = (irq & (NR_IRQS - 1));
|
|
|
|
|
|
/* Dork with trap table if we get this far. */
|
|
|
#define INSTANTIATE(table) \
|
|
|
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \
|
|
|
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \
|
|
|
- SPARC_BRANCH((unsigned long) handler, \
|
|
|
+ SPARC_BRANCH((unsigned long) floppy_hardint, \
|
|
|
(unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\
|
|
|
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \
|
|
|
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
|
|
@@ -399,22 +279,9 @@ static int request_fast_irq(unsigned int irq,
|
|
|
* writing we have no CPU-neutral interface to fine-grained flushes.
|
|
|
*/
|
|
|
flush_cache_all();
|
|
|
-
|
|
|
- action->flags = irqflags;
|
|
|
- action->name = devname;
|
|
|
- action->dev_id = NULL;
|
|
|
- action->next = NULL;
|
|
|
-
|
|
|
- sparc_irq[cpu_irq].action = action;
|
|
|
-
|
|
|
- __enable_irq(irq);
|
|
|
-
|
|
|
- ret = 0;
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&irq_action_lock, flags);
|
|
|
-out:
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
}
|
|
|
+EXPORT_SYMBOL(sparc_floppy_request_irq);
|
|
|
|
|
|
/*
|
|
|
* These variables are used to access state from the assembler
|
|
@@ -440,154 +307,23 @@ EXPORT_SYMBOL(pdma_base);
|
|
|
unsigned long pdma_areasize;
|
|
|
EXPORT_SYMBOL(pdma_areasize);
|
|
|
|
|
|
-static irq_handler_t floppy_irq_handler;
|
|
|
-
|
|
|
+/* Use the generic irq support to call floppy_interrupt
|
|
|
+ * which was setup using request_irq() in sparc_floppy_request_irq().
|
|
|
+ * We only have one floppy interrupt so we do not need to check
|
|
|
+ * for additional handlers being wired up by irq_link()
|
|
|
+ */
|
|
|
void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
|
|
|
{
|
|
|
struct pt_regs *old_regs;
|
|
|
- int cpu = smp_processor_id();
|
|
|
|
|
|
old_regs = set_irq_regs(regs);
|
|
|
- disable_pil_irq(irq);
|
|
|
irq_enter();
|
|
|
- kstat_cpu(cpu).irqs[irq]++;
|
|
|
- floppy_irq_handler(irq, dev_id);
|
|
|
+ generic_handle_irq(floppy_irq);
|
|
|
irq_exit();
|
|
|
- enable_pil_irq(irq);
|
|
|
set_irq_regs(old_regs);
|
|
|
- /*
|
|
|
- * XXX Eek, it's totally changed with preempt_count() and such
|
|
|
- * if (softirq_pending(cpu))
|
|
|
- * do_softirq();
|
|
|
- */
|
|
|
}
|
|
|
-
|
|
|
-int sparc_floppy_request_irq(int irq, unsigned long flags,
|
|
|
- irq_handler_t irq_handler)
|
|
|
-{
|
|
|
- floppy_irq_handler = irq_handler;
|
|
|
- return request_fast_irq(irq, floppy_hardint, flags, "floppy");
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(sparc_floppy_request_irq);
|
|
|
-
|
|
|
#endif
|
|
|
|
|
|
-int request_irq(unsigned int irq,
|
|
|
- irq_handler_t handler,
|
|
|
- unsigned long irqflags, const char *devname, void *dev_id)
|
|
|
-{
|
|
|
- struct irqaction *action, **actionp;
|
|
|
- unsigned long flags;
|
|
|
- unsigned int cpu_irq;
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (sparc_cpu_model == sun4d)
|
|
|
- return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
|
|
|
-
|
|
|
- cpu_irq = irq & (NR_IRQS - 1);
|
|
|
- if (cpu_irq > 14) {
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- if (!handler) {
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- spin_lock_irqsave(&irq_action_lock, flags);
|
|
|
-
|
|
|
- actionp = &sparc_irq[cpu_irq].action;
|
|
|
- action = *actionp;
|
|
|
- if (action) {
|
|
|
- if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) {
|
|
|
- ret = -EBUSY;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
- if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) {
|
|
|
- printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n",
|
|
|
- irq);
|
|
|
- ret = -EBUSY;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
- for ( ; action; action = *actionp)
|
|
|
- actionp = &action->next;
|
|
|
- }
|
|
|
-
|
|
|
- /* If this is flagged as statically allocated then we use our
|
|
|
- * private struct which is never freed.
|
|
|
- */
|
|
|
- if (irqflags & SA_STATIC_ALLOC) {
|
|
|
- if (static_irq_count < MAX_STATIC_ALLOC)
|
|
|
- action = &static_irqaction[static_irq_count++];
|
|
|
- else
|
|
|
- printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
|
|
|
- irq, devname);
|
|
|
- }
|
|
|
- if (action == NULL)
|
|
|
- action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
|
|
|
- if (!action) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
- action->handler = handler;
|
|
|
- action->flags = irqflags;
|
|
|
- action->name = devname;
|
|
|
- action->next = NULL;
|
|
|
- action->dev_id = dev_id;
|
|
|
-
|
|
|
- *actionp = action;
|
|
|
-
|
|
|
- __enable_irq(irq);
|
|
|
-
|
|
|
- ret = 0;
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&irq_action_lock, flags);
|
|
|
-out:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(request_irq);
|
|
|
-
|
|
|
-void disable_irq_nosync(unsigned int irq)
|
|
|
-{
|
|
|
- __disable_irq(irq);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(disable_irq_nosync);
|
|
|
-
|
|
|
-void disable_irq(unsigned int irq)
|
|
|
-{
|
|
|
- __disable_irq(irq);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(disable_irq);
|
|
|
-
|
|
|
-void enable_irq(unsigned int irq)
|
|
|
-{
|
|
|
- __enable_irq(irq);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(enable_irq);
|
|
|
-
|
|
|
-/*
|
|
|
- * We really don't need these at all on the Sparc. We only have
|
|
|
- * stubs here because they are exported to modules.
|
|
|
- */
|
|
|
-unsigned long probe_irq_on(void)
|
|
|
-{
|
|
|
- return 0;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(probe_irq_on);
|
|
|
-
|
|
|
-int probe_irq_off(unsigned long mask)
|
|
|
-{
|
|
|
- return 0;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(probe_irq_off);
|
|
|
-
|
|
|
-static unsigned int build_device_irq(struct platform_device *op,
|
|
|
- unsigned int real_irq)
|
|
|
-{
|
|
|
- return real_irq;
|
|
|
-}
|
|
|
-
|
|
|
/* djhr
|
|
|
* This could probably be made indirect too and assigned in the CPU
|
|
|
* bits of the code. That would be much nicer I think and would also
|
|
@@ -598,8 +334,6 @@ static unsigned int build_device_irq(struct platform_device *op,
|
|
|
|
|
|
void __init init_IRQ(void)
|
|
|
{
|
|
|
- sparc_irq_config.build_device_irq = build_device_irq;
|
|
|
-
|
|
|
switch (sparc_cpu_model) {
|
|
|
case sun4c:
|
|
|
case sun4:
|
|
@@ -629,9 +363,3 @@ void __init init_IRQ(void)
|
|
|
btfixup();
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_PROC_FS
|
|
|
-void init_irq_proc(void)
|
|
|
-{
|
|
|
- /* For now, nothing... */
|
|
|
-}
|
|
|
-#endif /* CONFIG_PROC_FS */
|