diff options
Diffstat (limited to 'drivers/sh/intc/core.c')
| -rw-r--r-- | drivers/sh/intc/core.c | 57 |
1 files changed, 40 insertions, 17 deletions
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index e53e449b4ec..81f22980b2d 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -2,7 +2,7 @@ * Shared interrupt handling code for IPR and INTC2 types of IRQs. * * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009, 2010 Paul Mundt + * Copyright (C) 2009 - 2012 Paul Mundt * * Based on intc2.c and ipr.c * @@ -25,24 +25,26 @@ #include <linux/stat.h> #include <linux/interrupt.h> #include <linux/sh_intc.h> +#include <linux/irqdomain.h> #include <linux/device.h> #include <linux/syscore_ops.h> #include <linux/list.h> #include <linux/spinlock.h> #include <linux/radix-tree.h> #include <linux/export.h> +#include <linux/sort.h> #include "internals.h" LIST_HEAD(intc_list); DEFINE_RAW_SPINLOCK(intc_big_lock); -unsigned int nr_intc_controllers; +static unsigned int nr_intc_controllers; /* * Default priority level * - this needs to be at least 2 for 5-bit priorities on 7780 */ static unsigned int default_prio_level = 2; /* 2 - 16 */ -static unsigned int intc_prio_level[NR_IRQS]; /* for now */ +static unsigned int intc_prio_level[INTC_NR_IRQS]; /* for now */ unsigned int intc_get_dfl_prio_level(void) { @@ -78,12 +80,6 @@ static void __init intc_register_irq(struct intc_desc *desc, unsigned int data[2], primary; unsigned long flags; - /* - * Register the IRQ position with the global IRQ map, then insert - * it in to the radix tree. - */ - irq_reserve_irq(irq); - raw_spin_lock_irqsave(&intc_big_lock, flags); radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq)); raw_spin_unlock_irqrestore(&intc_big_lock, flags); @@ -267,6 +263,9 @@ int __init register_intc_controller(struct intc_desc *desc) k += save_reg(d, k, hw->prio_regs[i].set_reg, smp); k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp); } + + sort(d->prio, hw->nr_prio_regs, sizeof(*d->prio), + intc_handle_int_cmp, NULL); } if (hw->sense_regs) { @@ -277,6 +276,9 @@ int __init register_intc_controller(struct intc_desc *desc) for (i = 0; i < hw->nr_sense_regs; i++) k += save_reg(d, k, hw->sense_regs[i].reg, 0); + + sort(d->sense, hw->nr_sense_regs, sizeof(*d->sense), + intc_handle_int_cmp, NULL); } if (hw->subgroups) @@ -303,6 +305,8 @@ int __init register_intc_controller(struct intc_desc *desc) BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ + intc_irq_domain_init(d, hw); + /* register the vectors one by one */ for (i = 0; i < hw->nr_vectors; i++) { struct intc_vect *vect = hw->vectors + i; @@ -312,10 +316,18 @@ int __init register_intc_controller(struct intc_desc *desc) if (!vect->enum_id) continue; - res = irq_alloc_desc_at(irq, numa_node_id()); - if (res != irq && res != -EEXIST) { - pr_err("can't get irq_desc for %d\n", irq); - continue; + res = irq_create_identity_mapping(d->domain, irq); + if (unlikely(res)) { + if (res == -EEXIST) { + res = irq_domain_associate(d->domain, irq, irq); + if (unlikely(res)) { + pr_err("domain association failure\n"); + continue; + } + } else { + pr_err("can't identity map IRQ %d\n", irq); + continue; + } } intc_irq_xlate_set(irq, vect->enum_id, d); @@ -333,10 +345,21 @@ int __init register_intc_controller(struct intc_desc *desc) * IRQ support, each vector still needs to have * its own backing irq_desc. */ - res = irq_alloc_desc_at(irq2, numa_node_id()); - if (res != irq2 && res != -EEXIST) { - pr_err("can't get irq_desc for %d\n", irq2); - continue; + res = irq_create_identity_mapping(d->domain, irq2); + if (unlikely(res)) { + if (res == -EEXIST) { + res = irq_domain_associate(d->domain, + irq2, irq2); + if (unlikely(res)) { + pr_err("domain association " + "failure\n"); + continue; + } + } else { + pr_err("can't identity map IRQ %d\n", + irq); + continue; + } } vect2->enum_id = 0; |
