* [PATCH 0/6] General device tree irq domain infrastructure
@ 2011-04-28 20:01 Grant Likely
2011-04-28 20:01 ` [PATCH 1/6] powerpc: stop exporting irq_map Grant Likely
` (7 more replies)
0 siblings, 8 replies; 23+ messages in thread
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
Cc: devicetree-discuss, x86, linuxppc-dev
A lot of this series ends up being fixups to powerpc code; but the 4th
patch is of importance to every architecture using CONFIG_OF (except
SPARC, which has its own solution).
This series (finally!) factors out device tree irq domain decoding
from arch/powerpc and makes it generic for all architectures. The
infrastructure is quite simple. Any interrupt controller can embed
the of_irq_domain structure and register it with the core code. After
that, device nodes referencing interrupts on that device tree node
will trigger a call to the domain's map function.
PowerPC and x86 have been converted to use of_irq_domain. MIPS and
Microblaze have it enabled, but nothing actually registers domains
yet, so a workaround is in place to preserve the current behaviour
until it is fixed.
I'd really like to get patches 1-4 merged into 2.6.40. Please test.
I'm also running through build testing here, and when it's complete
I'll push it out to a 'devicetree/irq-domain' branch on
git://git.secretlab.ca/git/linux-2.6
It needs testing. I've booted it on a powerpc board here without any
apparent regressions, but that isn't a very big sample. I've also
build tested on everything I think is affected.
I'd also like to get it into linux-next. Ben, if things checkout okay
over the next few days, would you be okay with me adding it to
linux-next, say around Wednesday next week? As for merging, I think
this should probably go via your powerpc tree since the that's where
the bulk of the changes are, but I'm open to other suggestions).
Patches 5 & 6 are follow-on cleanup work to powerpc, but patch 6 is
RFC only since there is a locking problem that I haven't fixed yet.
Cheers,
g.
---
Grant Likely (6):
powerpc: stop exporting irq_map
powerpc: make irq_{alloc,free}_virt private and remove count argument
powerpc: Make struct irq_host semi-private by moving into irqhost.h
dt: generalize of_irq_parse_and_map()
powerpc: move irq_alloc_descs_at() call into irq_alloc_virt()
powerpc: use irq_alloc_desc() to manage irq allocations
arch/microblaze/kernel/irq.c | 7 -
arch/microblaze/kernel/setup.c | 2
arch/mips/kernel/prom.c | 14 -
arch/powerpc/include/asm/irq.h | 88 +------
arch/powerpc/include/asm/irqhost.h | 27 ++
arch/powerpc/kernel/irq.c | 260 ++++++++++++----------
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 5
arch/powerpc/platforms/52xx/media5200.c | 5
arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1
arch/powerpc/platforms/52xx/mpc52xx_pic.c | 80 +------
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 5
arch/powerpc/platforms/85xx/socrates_fpga_pic.c | 26 +-
arch/powerpc/platforms/86xx/gef_pic.c | 10 -
arch/powerpc/platforms/8xx/m8xx_setup.c | 2
arch/powerpc/platforms/cell/axon_msi.c | 15 +
arch/powerpc/platforms/cell/spider-pic.c | 19 +-
arch/powerpc/platforms/embedded6xx/flipper-pic.c | 9 -
arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 9 -
arch/powerpc/platforms/embedded6xx/wii.c | 6 -
arch/powerpc/platforms/iseries/irq.c | 10 -
arch/powerpc/platforms/powermac/pic.c | 12 +
arch/powerpc/platforms/pseries/ras.c | 4
arch/powerpc/platforms/pseries/xics.c | 14 +
arch/powerpc/sysdev/cpm1.c | 8 -
arch/powerpc/sysdev/cpm2_pic.c | 10 -
arch/powerpc/sysdev/fsl_msi.c | 3
arch/powerpc/sysdev/i8259.c | 3
arch/powerpc/sysdev/ipic.c | 19 +-
arch/powerpc/sysdev/mpc8xx_pic.c | 10 -
arch/powerpc/sysdev/mpc8xxx_gpio.c | 13 +
arch/powerpc/sysdev/mpic.c | 33 +--
arch/powerpc/sysdev/mpic_msi.c | 3
arch/powerpc/sysdev/mpic_pasemi_msi.c | 5
arch/powerpc/sysdev/mv64x60_pic.c | 14 +
arch/powerpc/sysdev/qe_lib/qe_ic.c | 9 -
arch/powerpc/sysdev/uic.c | 13 +
arch/powerpc/sysdev/xilinx_intc.c | 9 -
arch/x86/include/asm/irq_controller.h | 12 -
arch/x86/include/asm/prom.h | 1
arch/x86/kernel/devicetree.c | 77 +------
drivers/of/irq.c | 118 ++++++++++
include/linux/of_irq.h | 31 +++
42 files changed, 504 insertions(+), 517 deletions(-)
create mode 100644 arch/powerpc/include/asm/irqhost.h
delete mode 100644 arch/x86/include/asm/irq_controller.h
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 1/6] powerpc: stop exporting irq_map
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
@ 2011-04-28 20:01 ` Grant Likely
2011-05-03 1:44 ` Benjamin Herrenschmidt
2011-04-28 20:01 ` [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument Grant Likely
` (6 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
Cc: devicetree-discuss, x86, linuxppc-dev
First step in eliminating irq_map[] table entirely
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/include/asm/irq.h | 15 +---
arch/powerpc/kernel/irq.c | 26 +++++++
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 4 +
arch/powerpc/platforms/52xx/media5200.c | 4 +
arch/powerpc/platforms/52xx/mpc52xx_pic.c | 79 ++++------------------
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 4 +
arch/powerpc/platforms/85xx/socrates_fpga_pic.c | 26 ++-----
arch/powerpc/platforms/86xx/gef_pic.c | 10 +--
arch/powerpc/platforms/8xx/m8xx_setup.c | 2 -
arch/powerpc/platforms/cell/axon_msi.c | 2 -
arch/powerpc/platforms/cell/spider-pic.c | 10 +--
arch/powerpc/platforms/embedded6xx/flipper-pic.c | 8 +-
arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 8 +-
arch/powerpc/platforms/iseries/irq.c | 10 +--
arch/powerpc/platforms/powermac/pic.c | 12 ++-
arch/powerpc/platforms/pseries/ras.c | 4 +
arch/powerpc/platforms/pseries/xics.c | 14 ++--
arch/powerpc/sysdev/cpm1.c | 8 +-
arch/powerpc/sysdev/cpm2_pic.c | 10 +--
arch/powerpc/sysdev/ipic.c | 16 ++--
arch/powerpc/sysdev/mpc8xx_pic.c | 10 +--
arch/powerpc/sysdev/mpc8xxx_gpio.c | 12 ++-
arch/powerpc/sysdev/mpic.c | 28 ++++----
arch/powerpc/sysdev/mv64x60_pic.c | 14 ++--
arch/powerpc/sysdev/qe_lib/qe_ic.c | 6 +-
arch/powerpc/sysdev/uic.c | 12 +--
arch/powerpc/sysdev/xilinx_intc.c | 8 +-
27 files changed, 147 insertions(+), 215 deletions(-)
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index 67ab5fb..e1983d5 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -128,19 +128,10 @@ struct irq_host {
struct device_node *of_node;
};
-/* The main irq map itself is an array of NR_IRQ entries containing the
- * associate host and irq number. An entry with a host of NULL is free.
- * An entry can be allocated if it's free, the allocator always then sets
- * hwirq first to the host's invalid irq number and then fills ops.
- */
-struct irq_map_entry {
- irq_hw_number_t hwirq;
- struct irq_host *host;
-};
-
-extern struct irq_map_entry irq_map[NR_IRQS];
-
+struct irq_data;
+extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
extern irq_hw_number_t virq_to_hw(unsigned int virq);
+extern struct irq_host *virq_to_host(unsigned int virq);
/**
* irq_alloc_host - Allocate a new irq_host data structure
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index f621b7d..422672b 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -477,20 +477,42 @@ void do_softirq(void)
* IRQ controller and virtual interrupts
*/
+/* The main irq map itself is an array of NR_IRQ entries containing the
+ * associate host and irq number. An entry with a host of NULL is free.
+ * An entry can be allocated if it's free, the allocator always then sets
+ * hwirq first to the host's invalid irq number and then fills ops.
+ */
+struct irq_map_entry {
+ irq_hw_number_t hwirq;
+ struct irq_host *host;
+};
+
static LIST_HEAD(irq_hosts);
static DEFINE_RAW_SPINLOCK(irq_big_lock);
static unsigned int revmap_trees_allocated;
static DEFINE_MUTEX(revmap_trees_mutex);
-struct irq_map_entry irq_map[NR_IRQS];
+static struct irq_map_entry irq_map[NR_IRQS];
static unsigned int irq_virq_count = NR_IRQS;
static struct irq_host *irq_default_host;
+irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
+{
+ return irq_map[d->irq].hwirq;
+}
+EXPORT_SYMBOL_GPL(irqd_to_hwirq);
+
irq_hw_number_t virq_to_hw(unsigned int virq)
{
return irq_map[virq].hwirq;
}
EXPORT_SYMBOL_GPL(virq_to_hw);
+struct irq_host *virq_to_host(unsigned int virq)
+{
+ return irq_map[virq].host;
+}
+EXPORT_SYMBOL_GPL(virq_to_host);
+
static int default_irq_host_match(struct irq_host *h, struct device_node *np)
{
return h->of_node != NULL && h->of_node == np;
@@ -1098,7 +1120,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
struct irq_chip *chip;
seq_printf(m, "%5d ", i);
- seq_printf(m, "0x%05lx ", virq_to_hw(i));
+ seq_printf(m, "0x%05lx ", irq_map[i].hwirq);
chip = irq_desc_get_chip(desc);
if (chip && chip->name)
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
index cfc4b20..a8bc0d4 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
@@ -61,7 +61,7 @@ irq_to_pic_bit(unsigned int irq)
static void
cpld_mask_irq(struct irq_data *d)
{
- unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int cpld_irq = (unsigned int)irqd_to_hwirq(d);
void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
out_8(pic_mask,
@@ -71,7 +71,7 @@ cpld_mask_irq(struct irq_data *d)
static void
cpld_unmask_irq(struct irq_data *d)
{
- unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int cpld_irq = (unsigned int)irqd_to_hwirq(d);
void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
out_8(pic_mask,
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 57a6a34..96f85e5 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -56,7 +56,7 @@ static void media5200_irq_unmask(struct irq_data *d)
spin_lock_irqsave(&media5200_irq.lock, flags);
val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
- val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq);
+ val |= 1 << (MEDIA5200_IRQ_SHIFT + irqd_to_hwirq(d));
out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
spin_unlock_irqrestore(&media5200_irq.lock, flags);
}
@@ -68,7 +68,7 @@ static void media5200_irq_mask(struct irq_data *d)
spin_lock_irqsave(&media5200_irq.lock, flags);
val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
- val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq));
+ val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irqd_to_hwirq(d)));
out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
spin_unlock_irqrestore(&media5200_irq.lock, flags);
}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 1dd1540..bb61181 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -157,48 +157,30 @@ static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
*/
static void mpc52xx_extirq_mask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_clrbit(&intr->ctrl, 11 - l2irq);
}
static void mpc52xx_extirq_unmask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_setbit(&intr->ctrl, 11 - l2irq);
}
static void mpc52xx_extirq_ack(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_setbit(&intr->ctrl, 27-l2irq);
}
static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type)
{
u32 ctrl_reg, type;
- int irq;
- int l2irq;
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
void *handler = handle_level_irq;
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
- pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
+ pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__,
+ (int) irqd_to_hwirq(d), l2irq, flow_type);
switch (flow_type) {
case IRQF_TRIGGER_HIGH: type = 0; break;
@@ -237,23 +219,13 @@ static int mpc52xx_null_set_type(struct irq_data *d, unsigned int flow_type)
static void mpc52xx_main_mask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_setbit(&intr->main_mask, 16 - l2irq);
}
static void mpc52xx_main_unmask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_clrbit(&intr->main_mask, 16 - l2irq);
}
@@ -270,23 +242,13 @@ static struct irq_chip mpc52xx_main_irqchip = {
*/
static void mpc52xx_periph_mask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_setbit(&intr->per_mask, 31 - l2irq);
}
static void mpc52xx_periph_unmask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_clrbit(&intr->per_mask, 31 - l2irq);
}
@@ -303,34 +265,19 @@ static struct irq_chip mpc52xx_periph_irqchip = {
*/
static void mpc52xx_sdma_mask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_setbit(&sdma->IntMask, l2irq);
}
static void mpc52xx_sdma_unmask(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
io_be_clrbit(&sdma->IntMask, l2irq);
}
static void mpc52xx_sdma_ack(struct irq_data *d)
{
- int irq;
- int l2irq;
-
- irq = irq_map[d->irq].hwirq;
- l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+ int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
out_be32(&sdma->IntPend, 1 << l2irq);
}
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 4a4eb6f..5d6c34c 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -42,7 +42,7 @@ struct pq2ads_pci_pic {
static void pq2ads_pci_mask_irq(struct irq_data *d)
{
struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
- int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
+ int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;
if (irq != -1) {
unsigned long flags;
@@ -58,7 +58,7 @@ static void pq2ads_pci_mask_irq(struct irq_data *d)
static void pq2ads_pci_unmask_irq(struct irq_data *d)
{
struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
- int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
+ int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;
if (irq != -1) {
unsigned long flags;
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
index db86462..12cb9bb 100644
--- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -48,8 +48,6 @@ static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
[8] = {0, IRQ_TYPE_LEVEL_HIGH},
};
-#define socrates_fpga_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
-
static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);
static void __iomem *socrates_fpga_pic_iobase;
@@ -110,11 +108,9 @@ void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
static void socrates_fpga_pic_ack(struct irq_data *d)
{
unsigned long flags;
- unsigned int hwirq, irq_line;
+ unsigned int irq_line, hwirq = irqd_to_hwirq(d);
uint32_t mask;
- hwirq = socrates_fpga_irq_to_hw(d->irq);
-
irq_line = fpga_irqs[hwirq].irq_line;
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -127,12 +123,10 @@ static void socrates_fpga_pic_ack(struct irq_data *d)
static void socrates_fpga_pic_mask(struct irq_data *d)
{
unsigned long flags;
- unsigned int hwirq;
+ unsigned int hwirq = irqd_to_hwirq(d);
int irq_line;
u32 mask;
- hwirq = socrates_fpga_irq_to_hw(d->irq);
-
irq_line = fpga_irqs[hwirq].irq_line;
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -145,12 +139,10 @@ static void socrates_fpga_pic_mask(struct irq_data *d)
static void socrates_fpga_pic_mask_ack(struct irq_data *d)
{
unsigned long flags;
- unsigned int hwirq;
+ unsigned int hwirq = irqd_to_hwirq(d);
int irq_line;
u32 mask;
- hwirq = socrates_fpga_irq_to_hw(d->irq);
-
irq_line = fpga_irqs[hwirq].irq_line;
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -164,12 +156,10 @@ static void socrates_fpga_pic_mask_ack(struct irq_data *d)
static void socrates_fpga_pic_unmask(struct irq_data *d)
{
unsigned long flags;
- unsigned int hwirq;
+ unsigned int hwirq = irqd_to_hwirq(d);
int irq_line;
u32 mask;
- hwirq = socrates_fpga_irq_to_hw(d->irq);
-
irq_line = fpga_irqs[hwirq].irq_line;
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -182,12 +172,10 @@ static void socrates_fpga_pic_unmask(struct irq_data *d)
static void socrates_fpga_pic_eoi(struct irq_data *d)
{
unsigned long flags;
- unsigned int hwirq;
+ unsigned int hwirq = irqd_to_hwirq(d);
int irq_line;
u32 mask;
- hwirq = socrates_fpga_irq_to_hw(d->irq);
-
irq_line = fpga_irqs[hwirq].irq_line;
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -201,12 +189,10 @@ static int socrates_fpga_pic_set_type(struct irq_data *d,
unsigned int flow_type)
{
unsigned long flags;
- unsigned int hwirq;
+ unsigned int hwirq = irqd_to_hwirq(d);
int polarity;
u32 mask;
- hwirq = socrates_fpga_irq_to_hw(d->irq);
-
if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
return -EINVAL;
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c
index 0beec7d..94594e5 100644
--- a/arch/powerpc/platforms/86xx/gef_pic.c
+++ b/arch/powerpc/platforms/86xx/gef_pic.c
@@ -46,8 +46,6 @@
#define GEF_PIC_CPU0_MCP_MASK GEF_PIC_MCP_MASK(0)
#define GEF_PIC_CPU1_MCP_MASK GEF_PIC_MCP_MASK(1)
-#define gef_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
-
static DEFINE_RAW_SPINLOCK(gef_pic_lock);
@@ -113,11 +111,9 @@ void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
static void gef_pic_mask(struct irq_data *d)
{
unsigned long flags;
- unsigned int hwirq;
+ unsigned int hwirq = irqd_to_hwirq(d);
u32 mask;
- hwirq = gef_irq_to_hw(d->irq);
-
raw_spin_lock_irqsave(&gef_pic_lock, flags);
mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
mask &= ~(1 << hwirq);
@@ -136,11 +132,9 @@ static void gef_pic_mask_ack(struct irq_data *d)
static void gef_pic_unmask(struct irq_data *d)
{
unsigned long flags;
- unsigned int hwirq;
+ unsigned int hwirq = irqd_to_hwirq(d);
u32 mask;
- hwirq = gef_irq_to_hw(d->irq);
-
raw_spin_lock_irqsave(&gef_pic_lock, flags);
mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
mask |= (1 << hwirq);
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 9ecce99..1e12108 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -150,7 +150,7 @@ void __init mpc8xx_calibrate_decr(void)
*/
cpu = of_find_node_by_type(NULL, "cpu");
virq= irq_of_parse_and_map(cpu, 0);
- irq = irq_map[virq].hwirq;
+ irq = virq_to_hw(virq);
sys_tmr2 = immr_map(im_sit);
out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index bb5ebf8..1e3329e 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -113,7 +113,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
pr_devel("axon_msi: woff %x roff %x msi %x\n",
write_offset, msic->read_offset, msi);
- if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) {
+ if (msi < NR_IRQS && virq_to_host(msi) == msic->irq_host) {
generic_handle_irq(msi);
msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
} else {
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index c5cf50e..34d2b99 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -70,7 +70,7 @@ static struct spider_pic spider_pics[SPIDER_CHIP_COUNT];
static struct spider_pic *spider_virq_to_pic(unsigned int virq)
{
- return irq_map[virq].host->host_data;
+ return virq_to_host(virq)->host_data;
}
static void __iomem *spider_get_irq_config(struct spider_pic *pic,
@@ -82,7 +82,7 @@ static void __iomem *spider_get_irq_config(struct spider_pic *pic,
static void spider_unmask_irq(struct irq_data *d)
{
struct spider_pic *pic = spider_virq_to_pic(d->irq);
- void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
+ void __iomem *cfg = spider_get_irq_config(pic, irqd_to_hwirq(d));
out_be32(cfg, in_be32(cfg) | 0x30000000u);
}
@@ -90,7 +90,7 @@ static void spider_unmask_irq(struct irq_data *d)
static void spider_mask_irq(struct irq_data *d)
{
struct spider_pic *pic = spider_virq_to_pic(d->irq);
- void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
+ void __iomem *cfg = spider_get_irq_config(pic, irqd_to_hwirq(d));
out_be32(cfg, in_be32(cfg) & ~0x30000000u);
}
@@ -98,7 +98,7 @@ static void spider_mask_irq(struct irq_data *d)
static void spider_ack_irq(struct irq_data *d)
{
struct spider_pic *pic = spider_virq_to_pic(d->irq);
- unsigned int src = irq_map[d->irq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
/* Reset edge detection logic if necessary
*/
@@ -117,7 +117,7 @@ static int spider_set_irq_type(struct irq_data *d, unsigned int type)
{
unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
struct spider_pic *pic = spider_virq_to_pic(d->irq);
- unsigned int hw = irq_map[d->irq].hwirq;
+ unsigned int hw = irqd_to_hwirq(d);
void __iomem *cfg = spider_get_irq_config(pic, hw);
u32 old_mask;
u32 ic;
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
index 12aa62b..77cbe4c 100644
--- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -48,7 +48,7 @@
static void flipper_pic_mask_and_ack(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
u32 mask = 1 << irq;
@@ -59,7 +59,7 @@ static void flipper_pic_mask_and_ack(struct irq_data *d)
static void flipper_pic_ack(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
/* this is at least needed for RSW */
@@ -68,7 +68,7 @@ static void flipper_pic_ack(struct irq_data *d)
static void flipper_pic_mask(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
clrbits32(io_base + FLIPPER_IMR, 1 << irq);
@@ -76,7 +76,7 @@ static void flipper_pic_mask(struct irq_data *d)
static void flipper_pic_unmask(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
setbits32(io_base + FLIPPER_IMR, 1 << irq);
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
index 2bdddfc..44b398b 100644
--- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -43,7 +43,7 @@
static void hlwd_pic_mask_and_ack(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
u32 mask = 1 << irq;
@@ -53,7 +53,7 @@ static void hlwd_pic_mask_and_ack(struct irq_data *d)
static void hlwd_pic_ack(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
@@ -61,7 +61,7 @@ static void hlwd_pic_ack(struct irq_data *d)
static void hlwd_pic_mask(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
@@ -69,7 +69,7 @@ static void hlwd_pic_mask(struct irq_data *d)
static void hlwd_pic_unmask(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void __iomem *io_base = irq_data_get_irq_chip_data(d);
setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 52a6889..375c21c 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -171,7 +171,7 @@ static void iseries_enable_IRQ(struct irq_data *d)
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
/* The IRQ has already been locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
@@ -188,7 +188,7 @@ static unsigned int iseries_startup_IRQ(struct irq_data *d)
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
bus = REAL_IRQ_TO_BUS(rirq);
function = REAL_IRQ_TO_FUNC(rirq);
@@ -234,7 +234,7 @@ static void iseries_shutdown_IRQ(struct irq_data *d)
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
/* irq should be locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
@@ -257,7 +257,7 @@ static void iseries_disable_IRQ(struct irq_data *d)
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
/* The IRQ has already been locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
@@ -271,7 +271,7 @@ static void iseries_disable_IRQ(struct irq_data *d)
static void iseries_end_IRQ(struct irq_data *d)
{
- unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
(REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 023f240..2f34ad0 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -84,7 +84,7 @@ static void __pmac_retrigger(unsigned int irq_nr)
static void pmac_mask_and_ack_irq(struct irq_data *d)
{
- unsigned int src = irq_map[d->irq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
unsigned long bit = 1UL << (src & 0x1f);
int i = src >> 5;
unsigned long flags;
@@ -106,7 +106,7 @@ static void pmac_mask_and_ack_irq(struct irq_data *d)
static void pmac_ack_irq(struct irq_data *d)
{
- unsigned int src = irq_map[d->irq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
unsigned long bit = 1UL << (src & 0x1f);
int i = src >> 5;
unsigned long flags;
@@ -152,7 +152,7 @@ static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
static unsigned int pmac_startup_irq(struct irq_data *d)
{
unsigned long flags;
- unsigned int src = irq_map[d->irq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
unsigned long bit = 1UL << (src & 0x1f);
int i = src >> 5;
@@ -169,7 +169,7 @@ static unsigned int pmac_startup_irq(struct irq_data *d)
static void pmac_mask_irq(struct irq_data *d)
{
unsigned long flags;
- unsigned int src = irq_map[d->irq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
__clear_bit(src, ppc_cached_irq_mask);
@@ -180,7 +180,7 @@ static void pmac_mask_irq(struct irq_data *d)
static void pmac_unmask_irq(struct irq_data *d)
{
unsigned long flags;
- unsigned int src = irq_map[d->irq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
__set_bit(src, ppc_cached_irq_mask);
@@ -193,7 +193,7 @@ static int pmac_retrigger(struct irq_data *d)
unsigned long flags;
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
- __pmac_retrigger(irq_map[d->irq].hwirq);
+ __pmac_retrigger(irqd_to_hwirq(d));
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
return 1;
}
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index c55d7ad..164a8eb 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -122,7 +122,7 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
status = rtas_call(ras_check_exception_token, 6, 1, NULL,
RTAS_VECTOR_EXTERNAL_INTERRUPT,
- irq_map[irq].hwirq,
+ virq_to_hw(irq),
RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
critical, __pa(&ras_log_buf),
rtas_get_error_log_max());
@@ -157,7 +157,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
status = rtas_call(ras_check_exception_token, 6, 1, NULL,
RTAS_VECTOR_EXTERNAL_INTERRUPT,
- irq_map[irq].hwirq,
+ virq_to_hw(irq),
RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
__pa(&ras_log_buf),
rtas_get_error_log_max());
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index d690133..784e614 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -210,7 +210,7 @@ static void xics_unmask_irq(struct irq_data *d)
pr_devel("xics: unmask virq %d\n", d->irq);
- hwirq = (unsigned int)irq_map[d->irq].hwirq;
+ hwirq = (unsigned int)irqd_to_hwirq(d);
pr_devel(" -> map to hwirq 0x%x\n", hwirq);
if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
return;
@@ -280,7 +280,7 @@ static void xics_mask_irq(struct irq_data *d)
pr_devel("xics: mask virq %d\n", d->irq);
- hwirq = (unsigned int)irq_map[d->irq].hwirq;
+ hwirq = (unsigned int)irqd_to_hwirq(d);
if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
return;
xics_mask_real_irq(hwirq);
@@ -373,7 +373,7 @@ static unsigned char pop_cppr(void)
static void xics_eoi_direct(struct irq_data *d)
{
- unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int hwirq = (unsigned int)irqd_to_hwirq(d);
iosync();
direct_xirr_info_set((pop_cppr() << 24) | hwirq);
@@ -381,7 +381,7 @@ static void xics_eoi_direct(struct irq_data *d)
static void xics_eoi_lpar(struct irq_data *d)
{
- unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int hwirq = (unsigned int)irqd_to_hwirq(d);
iosync();
lpar_xirr_info_set((pop_cppr() << 24) | hwirq);
@@ -395,7 +395,7 @@ xics_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
int xics_status[2];
int irq_server;
- hwirq = (unsigned int)irq_map[d->irq].hwirq;
+ hwirq = (unsigned int)irqd_to_hwirq(d);
if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
return -1;
@@ -900,9 +900,9 @@ void xics_migrate_irqs_away(void)
/* We can't set affinity on ISA interrupts */
if (virq < NUM_ISA_INTERRUPTS)
continue;
- if (irq_map[virq].host != xics_host)
+ if (virq_to_host(virq) != xics_host)
continue;
- hwirq = (unsigned int)irq_map[virq].hwirq;
+ hwirq = (unsigned int)virq_to_hw(virq);
/* We need to get IPIs still. */
if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
continue;
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index e0bc944..350787c 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -58,21 +58,21 @@ static struct irq_host *cpm_pic_host;
static void cpm_mask_irq(struct irq_data *d)
{
- unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d);
clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
}
static void cpm_unmask_irq(struct irq_data *d)
{
- unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d);
setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
}
static void cpm_end_irq(struct irq_data *d)
{
- unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d);
out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
}
@@ -157,7 +157,7 @@ unsigned int cpm_pic_init(void)
goto end;
/* Initialize the CPM interrupt controller. */
- hwirq = (unsigned int)irq_map[sirq].hwirq;
+ hwirq = (unsigned int)virq_to_hw(sirq);
out_be32(&cpic_reg->cpic_cicr,
(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
((hwirq/2) << 13) | CICR_HP_MASK);
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 5495c1b..bcab50e 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -81,7 +81,7 @@ static const u_char irq_to_siubit[] = {
static void cpm2_mask_irq(struct irq_data *d)
{
int bit, word;
- unsigned int irq_nr = virq_to_hw(d->irq);
+ unsigned int irq_nr = irqd_to_hwirq(d);
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
@@ -93,7 +93,7 @@ static void cpm2_mask_irq(struct irq_data *d)
static void cpm2_unmask_irq(struct irq_data *d)
{
int bit, word;
- unsigned int irq_nr = virq_to_hw(d->irq);
+ unsigned int irq_nr = irqd_to_hwirq(d);
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
@@ -105,7 +105,7 @@ static void cpm2_unmask_irq(struct irq_data *d)
static void cpm2_ack(struct irq_data *d)
{
int bit, word;
- unsigned int irq_nr = virq_to_hw(d->irq);
+ unsigned int irq_nr = irqd_to_hwirq(d);
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
@@ -116,7 +116,7 @@ static void cpm2_ack(struct irq_data *d)
static void cpm2_end_irq(struct irq_data *d)
{
int bit, word;
- unsigned int irq_nr = virq_to_hw(d->irq);
+ unsigned int irq_nr = irqd_to_hwirq(d);
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
@@ -133,7 +133,7 @@ static void cpm2_end_irq(struct irq_data *d)
static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
- unsigned int src = virq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned int vold, vnew, edibit;
/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index fa438be..f0ece79 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -521,12 +521,10 @@ static inline struct ipic * ipic_from_irq(unsigned int virq)
return primary_ipic;
}
-#define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
-
static void ipic_unmask_irq(struct irq_data *d)
{
struct ipic *ipic = ipic_from_irq(d->irq);
- unsigned int src = ipic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 temp;
@@ -542,7 +540,7 @@ static void ipic_unmask_irq(struct irq_data *d)
static void ipic_mask_irq(struct irq_data *d)
{
struct ipic *ipic = ipic_from_irq(d->irq);
- unsigned int src = ipic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 temp;
@@ -562,7 +560,7 @@ static void ipic_mask_irq(struct irq_data *d)
static void ipic_ack_irq(struct irq_data *d)
{
struct ipic *ipic = ipic_from_irq(d->irq);
- unsigned int src = ipic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 temp;
@@ -581,7 +579,7 @@ static void ipic_ack_irq(struct irq_data *d)
static void ipic_mask_irq_and_ack(struct irq_data *d)
{
struct ipic *ipic = ipic_from_irq(d->irq);
- unsigned int src = ipic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 temp;
@@ -604,7 +602,7 @@ static void ipic_mask_irq_and_ack(struct irq_data *d)
static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
struct ipic *ipic = ipic_from_irq(d->irq);
- unsigned int src = ipic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned int vold, vnew, edibit;
if (flow_type == IRQ_TYPE_NONE)
@@ -793,7 +791,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
int ipic_set_priority(unsigned int virq, unsigned int priority)
{
struct ipic *ipic = ipic_from_irq(virq);
- unsigned int src = ipic_irq_to_hw(virq);
+ unsigned int src = virq_to_hw(virq);
u32 temp;
if (priority > 7)
@@ -821,7 +819,7 @@ int ipic_set_priority(unsigned int virq, unsigned int priority)
void ipic_set_highest_priority(unsigned int virq)
{
struct ipic *ipic = ipic_from_irq(virq);
- unsigned int src = ipic_irq_to_hw(virq);
+ unsigned int src = virq_to_hw(virq);
u32 temp;
temp = ipic_read(ipic->regs, IPIC_SICFR);
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index a88800f..20924f2 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -28,7 +28,7 @@ int cpm_get_irq(struct pt_regs *regs);
static void mpc8xx_unmask_irq(struct irq_data *d)
{
int bit, word;
- unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
bit = irq_nr & 0x1f;
word = irq_nr >> 5;
@@ -40,7 +40,7 @@ static void mpc8xx_unmask_irq(struct irq_data *d)
static void mpc8xx_mask_irq(struct irq_data *d)
{
int bit, word;
- unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
bit = irq_nr & 0x1f;
word = irq_nr >> 5;
@@ -52,7 +52,7 @@ static void mpc8xx_mask_irq(struct irq_data *d)
static void mpc8xx_ack(struct irq_data *d)
{
int bit;
- unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
bit = irq_nr & 0x1f;
out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
@@ -61,7 +61,7 @@ static void mpc8xx_ack(struct irq_data *d)
static void mpc8xx_end_irq(struct irq_data *d)
{
int bit, word;
- unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+ unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
bit = irq_nr & 0x1f;
word = irq_nr >> 5;
@@ -73,7 +73,7 @@ static void mpc8xx_end_irq(struct irq_data *d)
static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
if (flow_type & IRQ_TYPE_EDGE_FALLING) {
- irq_hw_number_t hw = (unsigned int)irq_map[d->irq].hwirq;
+ irq_hw_number_t hw = (unsigned int)irqd_to_hwirq(d);
unsigned int siel = in_be32(&siu_reg->sc_siel);
/* only external IRQ senses are programmable */
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index 0892a28..fb4963a 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -163,7 +163,7 @@ static void mpc8xxx_irq_unmask(struct irq_data *d)
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
- setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+ setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
@@ -176,7 +176,7 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
- clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+ clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
@@ -186,7 +186,7 @@ static void mpc8xxx_irq_ack(struct irq_data *d)
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
- out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+ out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
}
static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
@@ -199,14 +199,14 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
case IRQ_TYPE_EDGE_FALLING:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
setbits32(mm->regs + GPIO_ICR,
- mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+ mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break;
case IRQ_TYPE_EDGE_BOTH:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrbits32(mm->regs + GPIO_ICR,
- mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+ mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break;
@@ -221,7 +221,7 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
- unsigned long gpio = virq_to_hw(d->irq);
+ unsigned long gpio = irqd_to_hwirq(d);
void __iomem *reg;
unsigned int shift;
unsigned long flags;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index f91c065..824a94f 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -607,8 +607,6 @@ static int irq_choose_cpu(const struct cpumask *mask)
}
#endif
-#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
-
/* Find an mpic associated with a given linux interrupt */
static struct mpic *mpic_find(unsigned int irq)
{
@@ -621,7 +619,7 @@ static struct mpic *mpic_find(unsigned int irq)
/* Determine if the linux irq is an IPI */
static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq)
{
- unsigned int src = mpic_irq_to_hw(irq);
+ unsigned int src = virq_to_hw(irq);
return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
}
@@ -674,7 +672,7 @@ void mpic_unmask_irq(struct irq_data *d)
{
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
@@ -695,7 +693,7 @@ void mpic_mask_irq(struct irq_data *d)
{
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
@@ -733,7 +731,7 @@ void mpic_end_irq(struct irq_data *d)
static void mpic_unmask_ht_irq(struct irq_data *d)
{
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
mpic_unmask_irq(d);
@@ -744,7 +742,7 @@ static void mpic_unmask_ht_irq(struct irq_data *d)
static unsigned int mpic_startup_ht_irq(struct irq_data *d)
{
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
mpic_unmask_irq(d);
mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d));
@@ -755,7 +753,7 @@ static unsigned int mpic_startup_ht_irq(struct irq_data *d)
static void mpic_shutdown_ht_irq(struct irq_data *d)
{
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
mpic_shutdown_ht_interrupt(mpic, src);
mpic_mask_irq(d);
@@ -764,7 +762,7 @@ static void mpic_shutdown_ht_irq(struct irq_data *d)
static void mpic_end_ht_irq(struct irq_data *d)
{
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
#ifdef DEBUG_IRQ
DBG("%s: end_irq: %d\n", mpic->name, d->irq);
@@ -785,7 +783,7 @@ static void mpic_end_ht_irq(struct irq_data *d)
static void mpic_unmask_ipi(struct irq_data *d)
{
struct mpic *mpic = mpic_from_ipi(d);
- unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0];
+ unsigned int src = virq_to_hw(d->irq) - mpic->ipi_vecs[0];
DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
@@ -816,7 +814,7 @@ int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
bool force)
{
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
int cpuid = irq_choose_cpu(cpumask);
@@ -862,7 +860,7 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
struct mpic *mpic = mpic_from_irq_data(d);
- unsigned int src = mpic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned int vecpri, vold, vnew;
DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
@@ -898,7 +896,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
void mpic_set_vector(unsigned int virq, unsigned int vector)
{
struct mpic *mpic = mpic_from_irq(virq);
- unsigned int src = mpic_irq_to_hw(virq);
+ unsigned int src = virq_to_hw(virq);
unsigned int vecpri;
DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
@@ -916,7 +914,7 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
void mpic_set_destination(unsigned int virq, unsigned int cpuid)
{
struct mpic *mpic = mpic_from_irq(virq);
- unsigned int src = mpic_irq_to_hw(virq);
+ unsigned int src = virq_to_hw(virq);
DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
mpic, virq, src, cpuid);
@@ -1427,7 +1425,7 @@ void __init mpic_set_serial_int(struct mpic *mpic, int enable)
void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
{
struct mpic *mpic = mpic_find(irq);
- unsigned int src = mpic_irq_to_hw(irq);
+ unsigned int src = virq_to_hw(irq);
unsigned long flags;
u32 reg;
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
index e9c633c..14d1302 100644
--- a/arch/powerpc/sysdev/mv64x60_pic.c
+++ b/arch/powerpc/sysdev/mv64x60_pic.c
@@ -78,7 +78,7 @@ static struct irq_host *mv64x60_irq_host;
static void mv64x60_mask_low(struct irq_data *d)
{
- int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+ int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
unsigned long flags;
spin_lock_irqsave(&mv64x60_lock, flags);
@@ -91,7 +91,7 @@ static void mv64x60_mask_low(struct irq_data *d)
static void mv64x60_unmask_low(struct irq_data *d)
{
- int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+ int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
unsigned long flags;
spin_lock_irqsave(&mv64x60_lock, flags);
@@ -115,7 +115,7 @@ static struct irq_chip mv64x60_chip_low = {
static void mv64x60_mask_high(struct irq_data *d)
{
- int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+ int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
unsigned long flags;
spin_lock_irqsave(&mv64x60_lock, flags);
@@ -128,7 +128,7 @@ static void mv64x60_mask_high(struct irq_data *d)
static void mv64x60_unmask_high(struct irq_data *d)
{
- int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+ int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
unsigned long flags;
spin_lock_irqsave(&mv64x60_lock, flags);
@@ -152,7 +152,7 @@ static struct irq_chip mv64x60_chip_high = {
static void mv64x60_mask_gpp(struct irq_data *d)
{
- int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+ int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
unsigned long flags;
spin_lock_irqsave(&mv64x60_lock, flags);
@@ -165,7 +165,7 @@ static void mv64x60_mask_gpp(struct irq_data *d)
static void mv64x60_mask_ack_gpp(struct irq_data *d)
{
- int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+ int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
unsigned long flags;
spin_lock_irqsave(&mv64x60_lock, flags);
@@ -180,7 +180,7 @@ static void mv64x60_mask_ack_gpp(struct irq_data *d)
static void mv64x60_unmask_gpp(struct irq_data *d)
{
- int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+ int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
unsigned long flags;
spin_lock_irqsave(&mv64x60_lock, flags);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 832d692..b2acda0 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -197,12 +197,10 @@ static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
return irq_data_get_irq_chip_data(d);
}
-#define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
-
static void qe_ic_unmask_irq(struct irq_data *d)
{
struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
- unsigned int src = virq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 temp;
@@ -218,7 +216,7 @@ static void qe_ic_unmask_irq(struct irq_data *d)
static void qe_ic_mask_irq(struct irq_data *d)
{
struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
- unsigned int src = virq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 temp;
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 5d91385..984cd20 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -41,8 +41,6 @@
#define UIC_VR 0x7
#define UIC_VCR 0x8
-#define uic_irq_to_hw(virq) (irq_map[virq].hwirq)
-
struct uic *primary_uic;
struct uic {
@@ -58,7 +56,7 @@ struct uic {
static void uic_unmask_irq(struct irq_data *d)
{
struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = uic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 er, sr;
@@ -76,7 +74,7 @@ static void uic_unmask_irq(struct irq_data *d)
static void uic_mask_irq(struct irq_data *d)
{
struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = uic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 er;
@@ -90,7 +88,7 @@ static void uic_mask_irq(struct irq_data *d)
static void uic_ack_irq(struct irq_data *d)
{
struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = uic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
spin_lock_irqsave(&uic->lock, flags);
@@ -101,7 +99,7 @@ static void uic_ack_irq(struct irq_data *d)
static void uic_mask_ack_irq(struct irq_data *d)
{
struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = uic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
u32 er, sr;
@@ -126,7 +124,7 @@ static void uic_mask_ack_irq(struct irq_data *d)
static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = uic_irq_to_hw(d->irq);
+ unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
int trigger, polarity;
u32 tr, pr, mask;
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 0a13fc1..6183799 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -71,7 +71,7 @@ static unsigned char xilinx_intc_map_senses[] = {
*/
static void xilinx_intc_mask(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void * regs = irq_data_get_irq_chip_data(d);
pr_debug("mask: %d\n", irq);
out_be32(regs + XINTC_CIE, 1 << irq);
@@ -87,7 +87,7 @@ static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
*/
static void xilinx_intc_level_unmask(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void * regs = irq_data_get_irq_chip_data(d);
pr_debug("unmask: %d\n", irq);
out_be32(regs + XINTC_SIE, 1 << irq);
@@ -112,7 +112,7 @@ static struct irq_chip xilinx_intc_level_irqchip = {
*/
static void xilinx_intc_edge_unmask(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void *regs = irq_data_get_irq_chip_data(d);
pr_debug("unmask: %d\n", irq);
out_be32(regs + XINTC_SIE, 1 << irq);
@@ -120,7 +120,7 @@ static void xilinx_intc_edge_unmask(struct irq_data *d)
static void xilinx_intc_edge_ack(struct irq_data *d)
{
- int irq = virq_to_hw(d->irq);
+ int irq = irqd_to_hwirq(d);
void * regs = irq_data_get_irq_chip_data(d);
pr_debug("ack: %d\n", irq);
out_be32(regs + XINTC_IAR, 1 << irq);
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
2011-04-28 20:01 ` [PATCH 1/6] powerpc: stop exporting irq_map Grant Likely
@ 2011-04-28 20:01 ` Grant Likely
2011-05-03 1:47 ` Benjamin Herrenschmidt
2011-04-28 20:01 ` [PATCH 3/6] powerpc: Make struct irq_host semi-private by moving into irqhost.h Grant Likely
` (5 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
Cc: devicetree-discuss, x86, linuxppc-dev
irq_alloc_virt() and irq_free_virt() aren't called anywhere but from
arch/powerpc/kernel/irq.c, and they are only ever called with count=1.
This patch removes the prototypes from the header file, removes the
count arguments, and cuts out the dead code.
Also removes obsolete references to irq_early_init()
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/microblaze/kernel/setup.c | 2 -
arch/powerpc/include/asm/irq.h | 32 ----------------
arch/powerpc/kernel/irq.c | 82 ++++++++++++++++++++--------------------
3 files changed, 40 insertions(+), 76 deletions(-)
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 8e2c09b..19d3ab7 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -51,8 +51,6 @@ void __init setup_arch(char **cmdline_p)
unflatten_device_tree();
- /* NOTE I think that this function is not necessary to call */
- /* irq_early_init(); */
setup_cpuinfo();
microblaze_cache_init();
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index e1983d5..4d2cc6f 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -264,38 +264,6 @@ extern unsigned int irq_linear_revmap(struct irq_host *host,
irq_hw_number_t hwirq);
-
-/**
- * irq_alloc_virt - Allocate virtual irq numbers
- * @host: host owning these new virtual irqs
- * @count: number of consecutive numbers to allocate
- * @hint: pass a hint number, the allocator will try to use a 1:1 mapping
- *
- * This is a low level function that is used internally by irq_create_mapping()
- * and that can be used by some irq controllers implementations for things
- * like allocating ranges of numbers for MSIs. The revmaps are left untouched.
- */
-extern unsigned int irq_alloc_virt(struct irq_host *host,
- unsigned int count,
- unsigned int hint);
-
-/**
- * irq_free_virt - Free virtual irq numbers
- * @virq: virtual irq number of the first interrupt to free
- * @count: number of interrupts to free
- *
- * This function is the opposite of irq_alloc_virt. It will not clear reverse
- * maps, this should be done previously by unmap'ing the interrupt. In fact,
- * all interrupts covered by the range being freed should have been unmapped
- * prior to calling this.
- */
-extern void irq_free_virt(unsigned int virq, unsigned int count);
-
-/**
- * irq_early_init - Init irq remapping subsystem
- */
-extern void irq_early_init(void);
-
static __inline__ int irq_canonicalize(int irq)
{
return irq;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 422672b..5ccf38f 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -647,6 +647,9 @@ void irq_set_virq_count(unsigned int count)
irq_virq_count = count;
}
+static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint);
+static void irq_free_virt(unsigned int virq);
+
static int irq_setup_virq(struct irq_host *host, unsigned int virq,
irq_hw_number_t hwirq)
{
@@ -675,7 +678,7 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
errdesc:
irq_free_descs(virq, 1);
error:
- irq_free_virt(virq, 1);
+ irq_free_virt(virq);
return -1;
}
@@ -689,7 +692,7 @@ unsigned int irq_create_direct_mapping(struct irq_host *host)
BUG_ON(host == NULL);
WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
- virq = irq_alloc_virt(host, 1, 0);
+ virq = irq_alloc_virt(host, 0);
if (virq == NO_IRQ) {
pr_debug("irq: create_direct virq allocation failed\n");
return NO_IRQ;
@@ -742,7 +745,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
} else {
/* Allocate a virtual interrupt number */
hint = hwirq % irq_virq_count;
- virq = irq_alloc_virt(host, 1, hint);
+ virq = irq_alloc_virt(host, hint);
if (virq == NO_IRQ) {
pr_debug("irq: -> virq allocation failed\n");
return NO_IRQ;
@@ -856,7 +859,7 @@ void irq_dispose_mapping(unsigned int virq)
irq_free_descs(virq, 1);
/* Free it */
- irq_free_virt(virq, 1);
+ irq_free_virt(virq);
}
EXPORT_SYMBOL_GPL(irq_dispose_mapping);
@@ -974,36 +977,31 @@ unsigned int irq_linear_revmap(struct irq_host *host,
return revmap[hwirq];
}
-unsigned int irq_alloc_virt(struct irq_host *host,
- unsigned int count,
- unsigned int hint)
+/**
+ * irq_alloc_virt() - Allocate virtual irq numbers
+ * @host: host owning these new virtual irqs
+ * @hint: pass a hint number, the allocator will try to use a 1:1 mapping
+ *
+ * This is a low level function that is used internally by irq_create_mapping()
+ */
+static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
{
unsigned long flags;
unsigned int i, j, found = NO_IRQ;
- if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS))
- return NO_IRQ;
-
raw_spin_lock_irqsave(&irq_big_lock, flags);
/* Use hint for 1 interrupt if any */
- if (count == 1 && hint >= NUM_ISA_INTERRUPTS &&
+ if (hint >= NUM_ISA_INTERRUPTS &&
hint < irq_virq_count && irq_map[hint].host == NULL) {
found = hint;
goto hint_found;
}
- /* Look for count consecutive numbers in the allocatable
- * (non-legacy) space
- */
+ /* Look for a free virq in the allocatable (non-legacy) space */
for (i = NUM_ISA_INTERRUPTS, j = 0; i < irq_virq_count; i++) {
- if (irq_map[i].host != NULL)
- j = 0;
- else
- j++;
-
- if (j == count) {
- found = i - count + 1;
+ if (irq_map[i].host == NULL) {
+ found = i;
break;
}
}
@@ -1012,36 +1010,36 @@ unsigned int irq_alloc_virt(struct irq_host *host,
return NO_IRQ;
}
hint_found:
- for (i = found; i < (found + count); i++) {
- irq_map[i].hwirq = host->inval_irq;
- smp_wmb();
- irq_map[i].host = host;
- }
+ irq_map[found].hwirq = host->inval_irq;
+ smp_wmb();
+ irq_map[found].host = host;
raw_spin_unlock_irqrestore(&irq_big_lock, flags);
return found;
}
-void irq_free_virt(unsigned int virq, unsigned int count)
+/**
+ * irq_free_virt() - Free virtual irq numbers
+ * @virq: virtual irq number of the first interrupt to free
+ *
+ * This function is the opposite of irq_alloc_virt. It will not clear reverse
+ * maps, this should be done previously by unmap'ing the interrupt. In fact,
+ * the interrupts being freed should have been unmapped prior to calling this.
+ */
+static void irq_free_virt(unsigned int virq)
{
unsigned long flags;
- unsigned int i;
+ struct irq_host *host;
- WARN_ON (virq < NUM_ISA_INTERRUPTS);
- WARN_ON (count == 0 || (virq + count) > irq_virq_count);
+ if ((virq < NUM_ISA_INTERRUPTS) || (virq >= irq_virq_count)) {
+ WARN_ON(1);
+ return;
+ }
raw_spin_lock_irqsave(&irq_big_lock, flags);
- for (i = virq; i < (virq + count); i++) {
- struct irq_host *host;
-
- if (i < NUM_ISA_INTERRUPTS ||
- (virq + count) > irq_virq_count)
- continue;
-
- host = irq_map[i].host;
- irq_map[i].hwirq = host->inval_irq;
- smp_wmb();
- irq_map[i].host = NULL;
- }
+ host = irq_map[virq].host;
+ irq_map[virq].hwirq = host->inval_irq;
+ smp_wmb();
+ irq_map[virq].host = NULL;
raw_spin_unlock_irqrestore(&irq_big_lock, flags);
}
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 3/6] powerpc: Make struct irq_host semi-private by moving into irqhost.h
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
2011-04-28 20:01 ` [PATCH 1/6] powerpc: stop exporting irq_map Grant Likely
2011-04-28 20:01 ` [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument Grant Likely
@ 2011-04-28 20:01 ` Grant Likely
2011-05-03 1:48 ` Benjamin Herrenschmidt
2011-04-28 20:02 ` [PATCH 4/6] dt: generalize irq_of_create_mapping() Grant Likely
` (4 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
Cc: devicetree-discuss, x86, linuxppc-dev
Very few files actually need direct access to struct irq_host members.
This patch moves the irq_host definition into another file so that it
isn't brought in by default, and to prepare for the addition of
struct of_irq_domain, which will factor some of the irq_host behaviour
out into common code. This needs to be done because of_irq_domain
will be embedded inside struct irq_host, and to do that it needs to be
guaranteed that struct of_irq_domain gets fully defined first.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/include/asm/irq.h | 20 +--------------
arch/powerpc/include/asm/irqhost.h | 29 ++++++++++++++++++++++
arch/powerpc/kernel/irq.c | 1 +
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 1 +
arch/powerpc/platforms/52xx/media5200.c | 1 +
arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1 +
arch/powerpc/platforms/52xx/mpc52xx_pic.c | 1 +
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 1 +
arch/powerpc/platforms/cell/axon_msi.c | 1 +
arch/powerpc/platforms/cell/spider-pic.c | 1 +
arch/powerpc/platforms/embedded6xx/flipper-pic.c | 1 +
arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 1 +
arch/powerpc/platforms/embedded6xx/wii.c | 6 +++--
arch/powerpc/sysdev/fsl_msi.c | 1 +
arch/powerpc/sysdev/i8259.c | 1 +
arch/powerpc/sysdev/ipic.c | 1 +
arch/powerpc/sysdev/mpc8xxx_gpio.c | 1 +
arch/powerpc/sysdev/mpic.c | 1 +
arch/powerpc/sysdev/mpic_msi.c | 1 +
arch/powerpc/sysdev/mpic_pasemi_msi.c | 1 +
arch/powerpc/sysdev/qe_lib/qe_ic.c | 1 +
arch/powerpc/sysdev/uic.c | 1 +
arch/powerpc/sysdev/xilinx_intc.c | 1 +
23 files changed, 54 insertions(+), 21 deletions(-)
create mode 100644 arch/powerpc/include/asm/irqhost.h
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index 4d2cc6f..a44be93 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -104,29 +104,11 @@ struct irq_host_ops {
irq_hw_number_t *out_hwirq, unsigned int *out_type);
};
-struct irq_host {
- struct list_head link;
-
- /* type of reverse mapping technique */
- unsigned int revmap_type;
+/* Reverse map types; pass into irq_alloc_host revmap_type argument */
#define IRQ_HOST_MAP_LEGACY 0 /* legacy 8259, gets irqs 1..15 */
#define IRQ_HOST_MAP_NOMAP 1 /* no fast reverse mapping */
#define IRQ_HOST_MAP_LINEAR 2 /* linear map of interrupts */
#define IRQ_HOST_MAP_TREE 3 /* radix tree */
- union {
- struct {
- unsigned int size;
- unsigned int *revmap;
- } linear;
- struct radix_tree_root tree;
- } revmap_data;
- struct irq_host_ops *ops;
- void *host_data;
- irq_hw_number_t inval_irq;
-
- /* Optional device node pointer */
- struct device_node *of_node;
-};
struct irq_data;
extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
diff --git a/arch/powerpc/include/asm/irqhost.h b/arch/powerpc/include/asm/irqhost.h
new file mode 100644
index 0000000..958e6c1
--- /dev/null
+++ b/arch/powerpc/include/asm/irqhost.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_POWERPC_IRQHOST_H
+#define _ASM_POWERPC_IRQHOST_H
+
+#include <linux/list.h>
+#include <linux/radix-tree.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+
+struct irq_host {
+ struct list_head link;
+
+ /* type of reverse mapping technique */
+ unsigned int revmap_type;
+ union {
+ struct {
+ unsigned int size;
+ unsigned int *revmap;
+ } linear;
+ struct radix_tree_root tree;
+ } revmap_data;
+ struct irq_host_ops *ops;
+ void *host_data;
+ irq_hw_number_t inval_irq;
+
+ /* Optional device node pointer */
+ struct device_node *of_node;
+};
+
+#endif /* _ASM_POWERPC_IRQHOST_H */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5ccf38f..b961b19 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -56,6 +56,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
+#include <asm/irqhost.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
index a8bc0d4..162bbb7 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <asm/irqhost.h>
#include <asm/prom.h>
static struct device_node *cpld_pic_node;
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 96f85e5..e03f2cb 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -25,6 +25,7 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <asm/irqhost.h>
#include <asm/time.h>
#include <asm/prom.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index 6c39b9c..55b2d26 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -67,6 +67,7 @@
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
+#include <asm/irqhost.h>
#include <asm/div64.h>
#include <asm/mpc52xx.h>
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index bb61181..65bbfd1 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -101,6 +101,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/mpc52xx.h>
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 5d6c34c..0ca79e0 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -19,6 +19,7 @@
#include <linux/bootmem.h>
#include <linux/slab.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/cpm2.h>
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 1e3329e..e1469ae 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -17,6 +17,7 @@
#include <linux/debugfs.h>
#include <linux/slab.h>
+#include <asm/irqhost.h>
#include <asm/dcr.h>
#include <asm/machdep.h>
#include <asm/prom.h>
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 34d2b99..73a5494 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -24,6 +24,7 @@
#include <linux/irq.h>
#include <linux/ioport.h>
+#include <asm/irqhost.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/io.h>
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
index 77cbe4c..1b60a34 100644
--- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/of.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include "flipper-pic.h"
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
index 44b398b..4f87661 100644
--- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/of.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include "hlwd-pic.h"
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 1b5dc1a..c9176a9 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -85,9 +85,11 @@ void __init wii_memory_fixups(void)
wii_hole_start = p[0].base + p[0].size;
wii_hole_size = p[1].base - wii_hole_start;
- pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size);
+ pr_info("MEM1: <%08llx %08llx>\n",
+ (unsigned long long)p[0].base, (unsigned long long)p[0].size);
pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size);
- pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size);
+ pr_info("MEM2: <%08llx %08llx>\n",
+ (unsigned long long)p[1].base, (unsigned long long)p[1].size);
p[0].size += wii_hole_size + p[1].size;
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index d5679dc..2c11b3e 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
+#include <asm/irqhost.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 142770c..30869f0 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/delay.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include <asm/i8259.h>
#include <asm/prom.h>
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index f0ece79..fc3751f 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/fsl_devices.h>
#include <asm/irq.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/ipic.h>
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index fb4963a..f6839a7 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -17,6 +17,7 @@
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/irq.h>
+#include <asm/irqhost.h>
#define MPC8XXX_GPIO_PINS 32
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 824a94f..6e9e594 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
+#include <asm/irqhost.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
#include <asm/io.h>
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 0f67cd7..50176ed 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -11,6 +11,7 @@
#include <linux/irq.h>
#include <linux/bitmap.h>
#include <linux/msi.h>
+#include <asm/irqhost.h>
#include <asm/mpic.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 38e6238..6b11a89 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -18,6 +18,7 @@
#include <linux/irq.h>
#include <linux/bootmem.h>
#include <linux/msi.h>
+#include <asm/irqhost.h>
#include <asm/mpic.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index b2acda0..9dd7746 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -26,6 +26,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/spinlock.h>
+#include <asm/irqhost.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/prom.h>
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 984cd20..a097f4c 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <asm/irq.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/dcr.h>
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 6183799..28d4ded 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/of.h>
+#include <asm/irqhost.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/i8259.h>
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 4/6] dt: generalize irq_of_create_mapping()
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
` (2 preceding siblings ...)
2011-04-28 20:01 ` [PATCH 3/6] powerpc: Make struct irq_host semi-private by moving into irqhost.h Grant Likely
@ 2011-04-28 20:02 ` Grant Likely
2011-05-03 1:50 ` Benjamin Herrenschmidt
2011-04-28 20:02 ` [PATCH 5/6] powerpc: move irq_alloc_descs_at() call into irq_alloc_virt() Grant Likely
` (3 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-04-28 20:02 UTC (permalink / raw)
To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
Cc: devicetree-discuss, x86, linuxppc-dev
This patch creates a common implementation of irq_of_create_mapping()
and factors out the interrupt domain translation code from powerpc to
make it available for all architectures.
It creates a new structure, struct of_irq_domain, which can be
embedded into the private data structure of an interrupt controller.
Any interrupt controller can call of_irq_domain_add() to register a
structure with a .map() hook that can translate irq specifiers from
the device tree into linux irq numbers.
The patch also modifies the powerpc irq_host to embed the
of_irq_domain structure and use the new common infrastructure for
registering domains. This separates the reverse mapping and irq
allocation infrastructure of irq_host from the domain registration
infrastructure. I elected to split the functionality this way for
several reasons. First, with the major irq cleanup done by Thomas
Gleixner, dynamic allocation of irqs can be handled gracefully with
irq_alloc_desc*() and interrupt controllers may not need or want an
irq_host layer to manage it for them. For example, the new
irq_chip_generic() already has a method for mapping between hwirq and
Linux irq.
Second, the irq_host code currently has a lot of complexity to handle
all the different reverse mapping types from a single structure. The
radix mapping in particular has a lot of support code, but only one
user. I didn't want to bring that complexity into the common code
as-is. Instead, I'd prefer to create a separate encapsulating
structure for each revmap, and each type would have a separate .map
hook.
For now, the mapping code remains powerpc-specific and further
generalization will happen in subsequent patches.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/microblaze/kernel/irq.c | 7 --
arch/mips/kernel/prom.c | 14 ----
arch/powerpc/include/asm/irq.h | 21 +++--
arch/powerpc/include/asm/irqhost.h | 4 -
arch/powerpc/kernel/irq.c | 99 ++++++++++++++-----------
arch/powerpc/platforms/cell/axon_msi.c | 12 ++-
arch/powerpc/platforms/cell/spider-pic.c | 8 +-
arch/powerpc/sysdev/fsl_msi.c | 2 -
arch/powerpc/sysdev/i8259.c | 2 -
arch/powerpc/sysdev/ipic.c | 2 -
arch/powerpc/sysdev/mpic.c | 4 +
arch/powerpc/sysdev/mpic_msi.c | 2 -
arch/powerpc/sysdev/mpic_pasemi_msi.c | 4 +
arch/powerpc/sysdev/qe_lib/qe_ic.c | 2 -
arch/x86/include/asm/irq_controller.h | 12 ---
arch/x86/include/asm/prom.h | 1
arch/x86/kernel/devicetree.c | 77 ++++----------------
drivers/of/irq.c | 118 ++++++++++++++++++++++++++++++
include/linux/of_irq.h | 31 ++++++++
19 files changed, 248 insertions(+), 174 deletions(-)
delete mode 100644 arch/x86/include/asm/irq_controller.h
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index ce7ac84..59bb560 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -54,10 +54,3 @@ unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
return hwirq;
}
EXPORT_SYMBOL_GPL(irq_create_mapping);
-
-unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
-{
- return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index a19811e9..0b82f98 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -60,20 +60,6 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,
}
#endif
-/*
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
-{
- return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-
void __init early_init_devtree(void *params)
{
/* Setup flat device-tree pointer */
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index a44be93..ccefc8c 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -55,11 +55,18 @@ typedef unsigned long irq_hw_number_t;
* model). It's the host callbacks that are responsible for setting the
* irq_chip on a given irq_desc after it's been mapped.
*
+ * irq_host builds upon the of_irq_domain code in drivers/of/irq.c.
+ * of_irq_domain provides all of the translation hooks for registering irq
+ * controllers. irq_host add mapping infrastructure to and from hardware
+ * irq numbers. IRQ controllers that don't need the mapping infrastructure
+ * can use irq_domain directly.
+ *
* The host code and data structures are fairly agnostic to the fact that
* we use an open firmware device-tree. We do have references to struct
- * device_node in two places: in irq_find_host() to find the host matching
- * a given interrupt controller node, and of course as an argument to its
- * counterpart host->ops->match() callback. However, those are treated as
+ * device_node in two places: in of_irq_domain_find() to find the host matching
+ * a given interrupt controller node (which is actually common of_irq_domain
+ * code), and of course as an argument to its counterpart host->ops->match()
+ * and host->domain->match() callbacks. However, those are treated as
* generic pointers by the core and the fact that it's actually a device-node
* pointer is purely a convention between callers and implementation. This
* code could thus be used on other architectures by replacing those two
@@ -137,14 +144,6 @@ extern struct irq_host *irq_alloc_host(struct device_node *of_node,
struct irq_host_ops *ops,
irq_hw_number_t inval_irq);
-
-/**
- * irq_find_host - Locates a host for a given device node
- * @node: device-tree node of the interrupt controller
- */
-extern struct irq_host *irq_find_host(struct device_node *node);
-
-
/**
* irq_set_default_host - Set a "default" host
* @host: default host pointer
diff --git a/arch/powerpc/include/asm/irqhost.h b/arch/powerpc/include/asm/irqhost.h
index 958e6c1..a97a513 100644
--- a/arch/powerpc/include/asm/irqhost.h
+++ b/arch/powerpc/include/asm/irqhost.h
@@ -8,6 +8,7 @@
struct irq_host {
struct list_head link;
+ struct of_irq_domain domain;
/* type of reverse mapping technique */
unsigned int revmap_type;
@@ -21,9 +22,6 @@ struct irq_host {
struct irq_host_ops *ops;
void *host_data;
irq_hw_number_t inval_irq;
-
- /* Optional device node pointer */
- struct device_node *of_node;
};
#endif /* _ASM_POWERPC_IRQHOST_H */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index b961b19..9300e1c 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -514,11 +514,40 @@ struct irq_host *virq_to_host(unsigned int virq)
}
EXPORT_SYMBOL_GPL(virq_to_host);
-static int default_irq_host_match(struct irq_host *h, struct device_node *np)
+/**
+ * irq_host_domain_match() - irq_domain hook to call irq_host match ops.
+ *
+ * This functions gets set as the irq domain match function for irq_host
+ * instances *if* the ->ops->match() hook is populated. If ->match() is
+ * not populated, then the default irq_domain matching behaviour is used
+ * instead.
+ */
+static bool irq_host_domain_match(struct of_irq_domain *domain,
+ struct device_node *controller)
{
- return h->of_node != NULL && h->of_node == np;
+ struct irq_host *host = container_of(domain, struct irq_host, domain);
+ return host->ops->match(host, controller);
}
+static unsigned int irq_host_domain_map(struct of_irq_domain *domain,
+ struct device_node *controller,
+ const u32 *intspec,
+ unsigned int intsize);
+
+/**
+ * irq_alloc_host() - Allocate and register an irq_host
+ * @of_node: Device node of the irq controller; this is used mainly as an
+ * anonymouns context pointer.
+ * @revmap_type: One of IRQ_HOST_MAP_* defined in arch/powerpc/include/asm/irq.h
+ * Defines the type of reverse map to be used by the irq_host.
+ * @revmap_arg: Currently only used by the IRQ_HOST_MAP_LINEAR which uses it
+ * to define the size of the reverse map.
+ * @ops: irq_host ops structure for match/map/unmap/remap/xlate operations.
+ * @inval_irq: Value used by irq controller to indicate an invalid irq.
+ *
+ * irq_host implements mapping between hardware irq numbers and the linux
+ * virq number space. This function allocates and registers an irq_host.
+ */
struct irq_host *irq_alloc_host(struct device_node *of_node,
unsigned int revmap_type,
unsigned int revmap_arg,
@@ -542,10 +571,10 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
host->revmap_type = revmap_type;
host->inval_irq = inval_irq;
host->ops = ops;
- host->of_node = of_node_get(of_node);
-
- if (host->ops->match == NULL)
- host->ops->match = default_irq_host_match;
+ host->domain.controller = of_node_get(of_node);
+ host->domain.map = irq_host_domain_map;
+ if (host->ops->match != NULL)
+ host->domain.match = irq_host_domain_match;
raw_spin_lock_irqsave(&irq_big_lock, flags);
@@ -561,7 +590,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
* instead of the current cruft
*/
if (mem_init_done) {
- of_node_put(host->of_node);
+ of_node_put(host->domain.controller);
kfree(host);
}
return NULL;
@@ -572,6 +601,8 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
list_add(&host->link, &irq_hosts);
raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+ of_irq_domain_add(&host->domain);
+
/* Additional setups per revmap type */
switch(revmap_type) {
case IRQ_HOST_MAP_LEGACY:
@@ -611,32 +642,12 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
return host;
}
-struct irq_host *irq_find_host(struct device_node *node)
-{
- struct irq_host *h, *found = NULL;
- unsigned long flags;
-
- /* We might want to match the legacy controller last since
- * it might potentially be set to match all interrupts in
- * the absence of a device node. This isn't a problem so far
- * yet though...
- */
- raw_spin_lock_irqsave(&irq_big_lock, flags);
- list_for_each_entry(h, &irq_hosts, link)
- if (h->ops->match(h, node)) {
- found = h;
- break;
- }
- raw_spin_unlock_irqrestore(&irq_big_lock, flags);
- return found;
-}
-EXPORT_SYMBOL_GPL(irq_find_host);
-
void irq_set_default_host(struct irq_host *host)
{
pr_debug("irq: Default host set to @0x%p\n", host);
irq_default_host = host;
+ of_irq_set_default_domain(&host->domain);
}
void irq_set_virq_count(unsigned int count)
@@ -757,30 +768,29 @@ unsigned int irq_create_mapping(struct irq_host *host,
return NO_IRQ;
printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n",
- hwirq, host->of_node ? host->of_node->full_name : "null", virq);
+ hwirq, host->domain.controller ? host->domain.controller->full_name : "null", virq);
return virq;
}
EXPORT_SYMBOL_GPL(irq_create_mapping);
-unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
+/**
+ * irq_host_domain_map() - Map device tree irq to linux irq number
+ * This hook implements all of the powerpc 'irq_host' behaviour, which means
+ * - calling the ->ops->xlate hook to get the hardware irq number,
+ * - calling of_create_mapping to translate/allocate a linux virq number
+ * - calling irq_set_irq_type() if necessary
+ */
+static unsigned int irq_host_domain_map(struct of_irq_domain *domain,
+ struct device_node *controller,
+ const u32 *intspec,
+ unsigned int intsize)
{
- struct irq_host *host;
+ struct irq_host *host = container_of(domain, struct irq_host, domain);
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
unsigned int virq;
- if (controller == NULL)
- host = irq_default_host;
- else
- host = irq_find_host(controller);
- if (host == NULL) {
- printk(KERN_WARNING "irq: no irq host found for %s !\n",
- controller->full_name);
- return NO_IRQ;
- }
-
/* If host has no translation, then we assume interrupt line */
if (host->ops->xlate == NULL)
hwirq = intspec[0];
@@ -801,7 +811,6 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
irq_set_irq_type(virq, type);
return virq;
}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
void irq_dispose_mapping(unsigned int virq)
{
@@ -1128,8 +1137,8 @@ static int virq_debug_show(struct seq_file *m, void *private)
p = none;
seq_printf(m, "%-15s ", p);
- if (irq_map[i].host && irq_map[i].host->of_node)
- p = irq_map[i].host->of_node->full_name;
+ if (irq_map[i].host && irq_map[i].host->domain.controller)
+ p = irq_map[i].host->domain.controller->full_name;
else
p = none;
seq_printf(m, "%s\n", p);
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index e1469ae..f125673 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -152,7 +152,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
static struct axon_msic *find_msi_translator(struct pci_dev *dev)
{
- struct irq_host *irq_host;
+ struct of_irq_domain *irq_domain;
struct device_node *dn, *tmp;
const phandle *ph;
struct axon_msic *msic = NULL;
@@ -184,14 +184,14 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
goto out_error;
}
- irq_host = irq_find_host(dn);
- if (!irq_host) {
+ irq_domain = of_irq_domain_find(dn);
+ if (!irq_domain) {
dev_dbg(&dev->dev, "axon_msi: no irq_host found for node %s\n",
dn->full_name);
goto out_error;
}
- msic = irq_host->host_data;
+ msic = irq_domain->priv;
out_error:
of_node_put(dn);
@@ -336,7 +336,7 @@ static void axon_msi_shutdown(struct platform_device *device)
u32 tmp;
pr_devel("axon_msi: disabling %s\n",
- msic->irq_host->of_node->full_name);
+ msic->irq_host->domain.controller->full_name);
tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
@@ -399,7 +399,7 @@ static int axon_msi_probe(struct platform_device *device)
goto out_free_fifo;
}
- msic->irq_host->host_data = msic;
+ msic->irq_host->domain.priv = msic;
irq_set_handler_data(virq, msic);
irq_set_chained_handler(virq, axon_msi_cascade);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 73a5494..5bf36ab 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -236,18 +236,20 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
* tree in case the device-tree is ever fixed
*/
struct of_irq oirq;
- if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) {
+ if (of_irq_map_one(pic->host->domain.controller, 0, &oirq) == 0) {
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
return virq;
}
/* Now do the horrible hacks */
- tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
+ tmp = of_get_property(pic->host->domain.controller,
+ "#interrupt-cells", NULL);
if (tmp == NULL)
return NO_IRQ;
intsize = *tmp;
- imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen);
+ imap = of_get_property(pic->host->domain.controller,
+ "interrupt-map", &imaplen);
if (imap == NULL || imaplen < (intsize + 1))
return NO_IRQ;
iic = of_find_node_by_phandle(imap[intsize]);
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 2c11b3e..b45a25a 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -82,7 +82,7 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
int rc;
rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
- msi_data->irqhost->of_node);
+ msi_data->irqhost->domain.controller);
if (rc)
return rc;
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 30869f0..a6f78fb 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -166,7 +166,7 @@ static struct resource pic_edgectrl_iores = {
static int i8259_host_match(struct irq_host *h, struct device_node *node)
{
- return h->of_node == NULL || h->of_node == node;
+ return h->domain.controller == NULL || h->domain.controller == node;
}
static int i8259_host_map(struct irq_host *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index fc3751f..5805c7b 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -676,7 +676,7 @@ static struct irq_chip ipic_edge_irq_chip = {
static int ipic_host_match(struct irq_host *h, struct device_node *node)
{
/* Exact match, unless ipic node is NULL */
- return h->of_node == NULL || h->of_node == node;
+ return h->domain.controller == NULL || h->domain.controller == node;
}
static int ipic_host_map(struct irq_host *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6e9e594..cafc364 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -956,7 +956,7 @@ static struct irq_chip mpic_irq_ht_chip = {
static int mpic_host_match(struct irq_host *h, struct device_node *node)
{
/* Exact match, unless mpic node is NULL */
- return h->of_node == NULL || h->of_node == node;
+ return h->domain.controller == NULL || h->domain.controller == node;
}
static int mpic_host_map(struct irq_host *h, unsigned int virq,
@@ -1296,7 +1296,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
BUG_ON(isu_num >= MPIC_MAX_ISU);
- mpic_map(mpic, mpic->irqhost->of_node,
+ mpic_map(mpic, mpic->irqhost->domain.controller,
paddr, &mpic->isus[isu_num], 0,
MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 50176ed..ddf79c7 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -85,7 +85,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
int rc;
rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count,
- mpic->irqhost->of_node);
+ mpic->irqhost->domain.controller);
if (rc)
return rc;
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 6b11a89..857be51 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -153,8 +153,8 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
{
int rc;
- if (!mpic->irqhost->of_node ||
- !of_device_is_compatible(mpic->irqhost->of_node,
+ if (!mpic->irqhost->domain.controller ||
+ !of_device_is_compatible(mpic->irqhost->domain.controller,
"pasemi,pwrficient-openpic"))
return -ENODEV;
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 9dd7746..c2ccafa 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -250,7 +250,7 @@ static struct irq_chip qe_ic_irq_chip = {
static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
{
/* Exact match, unless qe_ic node is NULL */
- return h->of_node == NULL || h->of_node == node;
+ return h->domain.controller == NULL || h->domain.controller == node;
}
static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h
deleted file mode 100644
index 423bbbd..0000000
--- a/arch/x86/include/asm/irq_controller.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __IRQ_CONTROLLER__
-#define __IRQ_CONTROLLER__
-
-struct irq_domain {
- int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize,
- u32 *out_hwirq, u32 *out_type);
- void *priv;
- struct device_node *controller;
- struct list_head l;
-};
-
-#endif
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index 971e0b4..eb9d5ab 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -21,7 +21,6 @@
#include <asm/irq.h>
#include <asm/atomic.h>
#include <asm/setup.h>
-#include <asm/irq_controller.h>
#ifdef CONFIG_OF
extern int of_ioapic;
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 706a9fb..651e724 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -15,64 +15,14 @@
#include <linux/of_pci.h>
#include <asm/hpet.h>
-#include <asm/irq_controller.h>
#include <asm/apic.h>
#include <asm/pci_x86.h>
__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
-static LIST_HEAD(irq_domains);
-static DEFINE_RAW_SPINLOCK(big_irq_lock);
int __initdata of_ioapic;
-#ifdef CONFIG_X86_IO_APIC
-static void add_interrupt_host(struct irq_domain *ih)
-{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&big_irq_lock, flags);
- list_add(&ih->l, &irq_domains);
- raw_spin_unlock_irqrestore(&big_irq_lock, flags);
-}
-#endif
-
-static struct irq_domain *get_ih_from_node(struct device_node *controller)
-{
- struct irq_domain *ih, *found = NULL;
- unsigned long flags;
-
- raw_spin_lock_irqsave(&big_irq_lock, flags);
- list_for_each_entry(ih, &irq_domains, l) {
- if (ih->controller == controller) {
- found = ih;
- break;
- }
- }
- raw_spin_unlock_irqrestore(&big_irq_lock, flags);
- return found;
-}
-
-unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
-{
- struct irq_domain *ih;
- u32 virq, type;
- int ret;
-
- ih = get_ih_from_node(controller);
- if (!ih)
- return 0;
- ret = ih->xlate(ih, intspec, intsize, &virq, &type);
- if (ret)
- return 0;
- if (type == IRQ_TYPE_NONE)
- return virq;
- irq_set_irq_type(virq, type);
- return virq;
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-
unsigned long pci_address_to_pio(phys_addr_t address)
{
/*
@@ -366,32 +316,33 @@ static struct of_ioapic_type of_ioapic_type[] =
},
};
-static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
- u32 *out_hwirq, u32 *out_type)
+static unsigned int ioapic_of_irq_map(struct of_irq_domain *id,
+ struct device_node *np,
+ const u32 *intspec, u32 intsize)
{
struct io_apic_irq_attr attr;
struct of_ioapic_type *it;
- u32 line, idx, type;
+ u32 line, idx, type, hwirq;
if (intsize < 2)
- return -EINVAL;
+ return 0;
line = *intspec;
idx = (u32) id->priv;
- *out_hwirq = line + mp_gsi_routing[idx].gsi_base;
+ hwirq = line + mp_gsi_routing[idx].gsi_base;
intspec++;
type = *intspec;
if (type >= ARRAY_SIZE(of_ioapic_type))
- return -EINVAL;
+ return 0;
it = of_ioapic_type + type;
- *out_type = it->out_type;
-
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
- return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
+ if (io_apic_setup_irq_pin(hwirq, cpu_to_node(0), &attr))
+ return 0;
+ return hwirq;
}
static void __init ioapic_add_ofnode(struct device_node *np)
@@ -408,14 +359,14 @@ static void __init ioapic_add_ofnode(struct device_node *np)
for (i = 0; i < nr_ioapics; i++) {
if (r.start == mp_ioapics[i].apicaddr) {
- struct irq_domain *id;
+ struct of_irq_domain *id;
id = kzalloc(sizeof(*id), GFP_KERNEL);
BUG_ON(!id);
- id->controller = np;
- id->xlate = ioapic_xlate;
+ id->controller = of_node_get(np);
+ id->map = ioapic_of_irq_map;
id->priv = (void *)i;
- add_interrupt_host(id);
+ of_irq_domain_add(id);
return;
}
}
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 75b0d3c..6da0964 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -19,6 +19,7 @@
*/
#include <linux/errno.h>
+#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
@@ -29,6 +30,123 @@
#define NO_IRQ 0
#endif
+/*
+ * Device Tree IRQ domains
+ *
+ * IRQ domains provide translation from device tree irq controller nodes to
+ * linux IRQ numbers. IRQ controllers register an irq_domain with a .map()
+ * hook that performs everything needed to decode and configure a device
+ * tree specified interrupt.
+ */
+static LIST_HEAD(of_irq_domains);
+static DEFINE_RAW_SPINLOCK(of_irq_lock);
+static struct of_irq_domain *of_irq_default_domain;
+
+/**
+ * of_irq_domain_default_match() - Return true if the controller pointers match
+ *
+ * Default match behaviour for of_irq_domains. If the device tree node pointer
+ * matches the value stored in the domain structure, then return true.
+ */
+static bool of_irq_domain_default_match(struct of_irq_domain *domain,
+ struct device_node *controller)
+{
+ return domain->controller == controller;
+}
+
+/**
+ * of_irq_domain_add() - Register a device tree irq domain
+ * @domain: pointer to domain structure to be registered.
+ *
+ * Adds an of_irq_domain to the global list of domains.
+ */
+void of_irq_domain_add(struct of_irq_domain *domain)
+{
+ unsigned long flags;
+
+ if (!domain->match)
+ domain->match = of_irq_domain_default_match;
+ if (!domain->map) {
+ WARN_ON(1);
+ return;
+ }
+
+ raw_spin_lock_irqsave(&of_irq_lock, flags);
+ list_add(&domain->list, &of_irq_domains);
+ raw_spin_unlock_irqrestore(&of_irq_lock, flags);
+}
+
+/**
+ * of_irq_domain_find() - Find the domain that handles a given device tree node
+ *
+ * Returns the pointer to an of_irq_domain capable of translating irq specifiers
+ * for the given irq controller device tree node. Returns NULL if a suitable
+ * domain could not be found.
+ */
+struct of_irq_domain *of_irq_domain_find(struct device_node *controller)
+{
+ struct of_irq_domain *domain, *found = NULL;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&of_irq_lock, flags);
+ list_for_each_entry(domain, &of_irq_domains, list) {
+ if (domain->match(domain, controller)) {
+ found = domain;
+ break;
+ }
+ }
+ raw_spin_unlock_irqrestore(&of_irq_lock, flags);
+ return found;
+}
+
+/**
+ * of_irq_set_default_domain() - Set a "default" host
+ * @domain: default domain pointer
+ *
+ * For convenience, it's possible to set a "default" host that will be used
+ * whenever NULL is passed to irq_of_create_mapping(). It makes life easier
+ * for platforms that want to manipulate a few hard coded interrupt numbers
+ * that aren't properly represented in the device-tree.
+ */
+void of_irq_set_default_domain(struct of_irq_domain *domain)
+{
+ pr_debug("irq: Default host set to @0x%p\n", domain);
+ of_irq_default_domain = domain;
+}
+
+/**
+ * irq_create_of_mapping() - Map a linux irq # from a device tree specifier
+ * @controller - interrupt-controller node in the device tree
+ * @intspec - array of interrupt specifier data. Points to an array of u32
+ * values. Data is *cpu-native* endian u32 values.
+ * @intsize - size of intspec array.
+ *
+ * Given an interrupt controller node pointer and an interrupt specifier, this
+ * function looks up the linux irq number.
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+ const u32 *intspec, unsigned int intsize)
+{
+ struct of_irq_domain *domain;
+
+ domain = of_irq_domain_find(controller);
+ if (!domain)
+ domain = of_irq_default_domain;
+ if (!domain) {
+ pr_warn("error: no irq host found for %s !\n",
+ controller->full_name);
+#if defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE)
+ /* FIXME: make Microblaze and MIPS register irq domains */
+ return intspec[0];
+#else /* defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE) */
+ return NO_IRQ;
+#endif /* defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE) */
+ }
+
+ return domain->map(domain, controller, intspec, intsize);
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
/**
* irq_of_parse_and_map - Parse and map an interrupt into linux virq space
* @device: Device node of the device whose interrupt is to be mapped
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 109e013..511dbc3 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -33,6 +33,37 @@ struct of_irq {
u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
};
+/**
+ * struct of_irq_domain - Translation domain from device tree to linux irq
+ * @list: Linked list node entry
+ * @match: (optional) Called to determine if the passed device_node
+ * interrupt-controller can be translated by this irq domain.
+ * Returns 'true' if it can.
+ * @decode: Translation callback; returns virq, or NO_IRQ if this irq
+ * domain cannot translate it.
+ * @controller: (optional) pointer to OF node. By default, if
+ * 'match' is not set, then this of_irq_domain will only
+ * be used if the device tree node passed in matches the
+ * controller pointer.
+ * @priv: Private data pointer, not touched by core of_irq_domain code.
+ */
+struct of_irq_domain {
+ struct list_head list;
+ bool (*match)(struct of_irq_domain *d, struct device_node *np);
+ unsigned int (*map)(struct of_irq_domain *d, struct device_node *np,
+ const u32 *intspec, u32 intsize);
+ struct device_node *controller;
+ void *priv;
+};
+
+/**
+ * of_irq_domain_add() - Add a device tree interrupt translation domain
+ * @domain: interrupt domain to add.
+ */
+extern void of_irq_domain_add(struct of_irq_domain *domain);
+extern void of_irq_set_default_domain(struct of_irq_domain *host);
+extern struct of_irq_domain *of_irq_domain_find(struct device_node *controller);
+
/*
* Workarounds only applied to 32bit powermac machines
*/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 5/6] powerpc: move irq_alloc_descs_at() call into irq_alloc_virt()
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
` (3 preceding siblings ...)
2011-04-28 20:02 ` [PATCH 4/6] dt: generalize irq_of_create_mapping() Grant Likely
@ 2011-04-28 20:02 ` Grant Likely
2011-04-28 20:02 ` [PATCH 6/6] powerpc: use irq_alloc_desc() to manage irq allocations Grant Likely
` (2 subsequent siblings)
7 siblings, 0 replies; 23+ messages in thread
From: Grant Likely @ 2011-04-28 20:02 UTC (permalink / raw)
To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
Cc: devicetree-discuss, x86, linuxppc-dev
This is a stepping stone to using core code for allocating virqs
instead of the powerpc architecture specific code. A subsequent patch
will drop the algorithm that searches for a free irq and replaces it
with irq_alloc_desc()
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/kernel/irq.c | 49 ++++++++++++++++++++++++++-------------------
1 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 9300e1c..0fb90ab 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -665,16 +665,6 @@ static void irq_free_virt(unsigned int virq);
static int irq_setup_virq(struct irq_host *host, unsigned int virq,
irq_hw_number_t hwirq)
{
- int res;
-
- res = irq_alloc_desc_at(virq, 0);
- if (res != virq) {
- pr_debug("irq: -> allocating desc failed\n");
- goto error;
- }
-
- irq_clear_status_flags(virq, IRQ_NOREQUEST);
-
/* map it */
smp_wmb();
irq_map[virq].hwirq = hwirq;
@@ -688,8 +678,6 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
return 0;
errdesc:
- irq_free_descs(virq, 1);
-error:
irq_free_virt(virq);
return -1;
}
@@ -754,14 +742,14 @@ unsigned int irq_create_mapping(struct irq_host *host,
if (virq == 0 || virq >= NUM_ISA_INTERRUPTS)
return NO_IRQ;
return virq;
- } else {
- /* Allocate a virtual interrupt number */
- hint = hwirq % irq_virq_count;
- virq = irq_alloc_virt(host, hint);
- if (virq == NO_IRQ) {
- pr_debug("irq: -> virq allocation failed\n");
- return NO_IRQ;
- }
+ }
+
+ /* Allocate a virtual interrupt number */
+ hint = hwirq % irq_virq_count;
+ virq = irq_alloc_virt(host, hint);
+ if (virq == NO_IRQ) {
+ pr_debug("irq: -> virq allocation failed\n");
+ return NO_IRQ;
}
if (irq_setup_virq(host, virq, hwirq))
@@ -867,7 +855,6 @@ void irq_dispose_mapping(unsigned int virq)
irq_set_status_flags(virq, IRQ_NOREQUEST);
- irq_free_descs(virq, 1);
/* Free it */
irq_free_virt(virq);
}
@@ -998,6 +985,7 @@ static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
{
unsigned long flags;
unsigned int i, j, found = NO_IRQ;
+ int res;
raw_spin_lock_irqsave(&irq_big_lock, flags);
@@ -1024,7 +1012,25 @@ static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
smp_wmb();
irq_map[found].host = host;
raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+
+ res = irq_alloc_desc_at(found, 0);
+ if (res != found) {
+ pr_debug("irq: -> allocating desc failed\n");
+ goto error_desc;
+ }
+
+ irq_clear_status_flags(found, IRQ_NOREQUEST);
+
return found;
+
+ error_desc:
+ raw_spin_lock_irqsave(&irq_big_lock, flags);
+ host = irq_map[found].host;
+ irq_map[found].hwirq = host->inval_irq;
+ smp_wmb();
+ irq_map[found].host = NULL;
+ raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+ return NO_IRQ;
}
/**
@@ -1045,6 +1051,7 @@ static void irq_free_virt(unsigned int virq)
return;
}
+ irq_free_descs(virq, 1);
raw_spin_lock_irqsave(&irq_big_lock, flags);
host = irq_map[virq].host;
irq_map[virq].hwirq = host->inval_irq;
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 6/6] powerpc: use irq_alloc_desc() to manage irq allocations
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
` (4 preceding siblings ...)
2011-04-28 20:02 ` [PATCH 5/6] powerpc: move irq_alloc_descs_at() call into irq_alloc_virt() Grant Likely
@ 2011-04-28 20:02 ` Grant Likely
2011-04-29 16:16 ` [PATCH 0/6] General device tree irq domain infrastructure Sebastian Andrzej Siewior
2011-05-03 1:43 ` Benjamin Herrenschmidt
7 siblings, 0 replies; 23+ messages in thread
From: Grant Likely @ 2011-04-28 20:02 UTC (permalink / raw)
To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
Cc: devicetree-discuss, x86, linuxppc-dev
This patch drops the architecture specific code for managing irq
assignments and uses core code instead.
*RFC*
This patch is *not* ready for merging. The locking is messed up where
the irq_map is still used to find out if a mapping is already established,
but irq_alloc_desc() is now called before the irq_map is updated which
creates a race condition. I've not completely sorted out how to solve
this yet. The solution may very well be to convert the irq_big_lock
to a mutex (but I'm not sure if anything that sleeps calls the affected
code), and hold the mutex over the entire operation.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/kernel/irq.c | 51 ++++++++++++---------------------------------
1 files changed, 14 insertions(+), 37 deletions(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 0fb90ab..e4a6646 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -984,53 +984,29 @@ unsigned int irq_linear_revmap(struct irq_host *host,
static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
{
unsigned long flags;
- unsigned int i, j, found = NO_IRQ;
- int res;
+ int found;
- raw_spin_lock_irqsave(&irq_big_lock, flags);
-
- /* Use hint for 1 interrupt if any */
- if (hint >= NUM_ISA_INTERRUPTS &&
- hint < irq_virq_count && irq_map[hint].host == NULL) {
- found = hint;
- goto hint_found;
- }
-
- /* Look for a free virq in the allocatable (non-legacy) space */
- for (i = NUM_ISA_INTERRUPTS, j = 0; i < irq_virq_count; i++) {
- if (irq_map[i].host == NULL) {
- found = i;
- break;
- }
- }
- if (found == NO_IRQ) {
- raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+ /*
+ * Find an unused interrupt. First, attempt to allocate
+ * 'hint'. If that fails, then just allocate any free one.
+ */
+ found = irq_alloc_desc_at(hint, 0);
+ if (found <= NO_IRQ)
+ found = irq_alloc_desc(0);
+ if (found <= NO_IRQ) {
+ pr_debug("irq: -> allocating desc failed\n");
return NO_IRQ;
}
- hint_found:
+
+ raw_spin_lock_irqsave(&irq_big_lock, flags);
irq_map[found].hwirq = host->inval_irq;
smp_wmb();
irq_map[found].host = host;
raw_spin_unlock_irqrestore(&irq_big_lock, flags);
- res = irq_alloc_desc_at(found, 0);
- if (res != found) {
- pr_debug("irq: -> allocating desc failed\n");
- goto error_desc;
- }
-
irq_clear_status_flags(found, IRQ_NOREQUEST);
return found;
-
- error_desc:
- raw_spin_lock_irqsave(&irq_big_lock, flags);
- host = irq_map[found].host;
- irq_map[found].hwirq = host->inval_irq;
- smp_wmb();
- irq_map[found].host = NULL;
- raw_spin_unlock_irqrestore(&irq_big_lock, flags);
- return NO_IRQ;
}
/**
@@ -1051,13 +1027,14 @@ static void irq_free_virt(unsigned int virq)
return;
}
- irq_free_descs(virq, 1);
raw_spin_lock_irqsave(&irq_big_lock, flags);
host = irq_map[virq].host;
irq_map[virq].hwirq = host->inval_irq;
smp_wmb();
irq_map[virq].host = NULL;
raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+
+ irq_free_descs(virq, 1);
}
int arch_early_irq_init(void)
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
` (5 preceding siblings ...)
2011-04-28 20:02 ` [PATCH 6/6] powerpc: use irq_alloc_desc() to manage irq allocations Grant Likely
@ 2011-04-29 16:16 ` Sebastian Andrzej Siewior
2011-04-29 17:43 ` Grant Likely
2011-05-03 1:43 ` Benjamin Herrenschmidt
7 siblings, 1 reply; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-04-29 16:16 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, devicetree-discuss, x86, linux-kernel, Ralf Baechle,
hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev
Grant Likely wrote:
> I'd really like to get patches 1-4 merged into 2.6.40. Please test.
> I'm also running through build testing here, and when it's complete
> I'll push it out to a 'devicetree/irq-domain' branch on
> git://git.secretlab.ca/git/linux-2.6
I pulled this, built and booted my x86-dt box and nothing exploded so far.
If you merge Linus' tree then you will get a conflict (sooner or later) in
ioapic_of_irq_map() in arch/x86/kernel/devicetree.c:
- return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);
- if (io_apic_setup_irq_pin(hwirq, cpu_to_node(0), &attr))
++ if (io_apic_setup_irq_pin_once(hwirq, cpu_to_node(0), &attr))
Sebastian
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-04-29 16:16 ` [PATCH 0/6] General device tree irq domain infrastructure Sebastian Andrzej Siewior
@ 2011-04-29 17:43 ` Grant Likely
0 siblings, 0 replies; 23+ messages in thread
From: Grant Likely @ 2011-04-29 17:43 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Michal Simek, devicetree-discuss, x86, linux-kernel, Ralf Baechle,
hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev
On Fri, Apr 29, 2011 at 06:16:33PM +0200, Sebastian Andrzej Siewior wrote:
> Grant Likely wrote:
> >I'd really like to get patches 1-4 merged into 2.6.40. Please test.
> >I'm also running through build testing here, and when it's complete
> >I'll push it out to a 'devicetree/irq-domain' branch on
> >git://git.secretlab.ca/git/linux-2.6
>
> I pulled this, built and booted my x86-dt box and nothing exploded so far.
>
> If you merge Linus' tree then you will get a conflict (sooner or later) in
> ioapic_of_irq_map() in arch/x86/kernel/devicetree.c:
>
> - return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);
> - if (io_apic_setup_irq_pin(hwirq, cpu_to_node(0), &attr))
> ++ if (io_apic_setup_irq_pin_once(hwirq, cpu_to_node(0), &attr))
>
> Sebastian
Thanks Sebastian. Unless you say otherwise, I'll take that as an Acked-by. :-)
g.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
` (6 preceding siblings ...)
2011-04-29 16:16 ` [PATCH 0/6] General device tree irq domain infrastructure Sebastian Andrzej Siewior
@ 2011-05-03 1:43 ` Benjamin Herrenschmidt
2011-05-04 15:52 ` Grant Likely
7 siblings, 1 reply; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-03 1:43 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Thu, 2011-04-28 at 14:01 -0600, Grant Likely wrote:
> A lot of this series ends up being fixups to powerpc code; but the 4th
> patch is of importance to every architecture using CONFIG_OF (except
> SPARC, which has its own solution).
>
> This series (finally!) factors out device tree irq domain decoding
> from arch/powerpc and makes it generic for all architectures. The
> infrastructure is quite simple. Any interrupt controller can embed
> the of_irq_domain structure and register it with the core code. After
> that, device nodes referencing interrupts on that device tree node
> will trigger a call to the domain's map function.
This leads to an immediate reaction from me : why "of_irq_domain" ?
The concept of interrupt domains is completely orthogonal to "OF" and
whether you use the device-tree or not.
Having a remapping mechanism allowing to deal with multiple interrupt
domains without playing stupid numbering tricks is generally useful for
architectures, regardless of their adoption of the device-tree.
The irq domain has one and -only one- op that is related to OF which
allows to map a device node to a domain, but that's 'optional' and only
use if you use the OF resolving process. The whole mechanism can be (and
is under some circumstances on ppc) without a device-tree relationship.
We instanciate IRQs within domains manually in some cases, either
because we lack proper DT informations or bcs the IRQs come from the
firmware or as "created" out of the blue (device-tree). A domain pointer
(or NULL for the default domain) is all is needed.
Thus I object to tying this infrastructure generically to "OF" even if
it's just a mater of naming of the domain structure and location of the
code in the kernel tree.
It should basically all go into kernel/irq/domains.c or something like
that.
Cheers,
Ben.
> PowerPC and x86 have been converted to use of_irq_domain. MIPS and
> Microblaze have it enabled, but nothing actually registers domains
> yet, so a workaround is in place to preserve the current behaviour
> until it is fixed.
>
> I'd really like to get patches 1-4 merged into 2.6.40. Please test.
> I'm also running through build testing here, and when it's complete
> I'll push it out to a 'devicetree/irq-domain' branch on
> git://git.secretlab.ca/git/linux-2.6
>
> It needs testing. I've booted it on a powerpc board here without any
> apparent regressions, but that isn't a very big sample. I've also
> build tested on everything I think is affected.
>
> I'd also like to get it into linux-next. Ben, if things checkout okay
> over the next few days, would you be okay with me adding it to
> linux-next, say around Wednesday next week? As for merging, I think
> this should probably go via your powerpc tree since the that's where
> the bulk of the changes are, but I'm open to other suggestions).
>
> Patches 5 & 6 are follow-on cleanup work to powerpc, but patch 6 is
> RFC only since there is a locking problem that I haven't fixed yet.
>
> Cheers,
> g.
>
> ---
>
> Grant Likely (6):
> powerpc: stop exporting irq_map
> powerpc: make irq_{alloc,free}_virt private and remove count argument
> powerpc: Make struct irq_host semi-private by moving into irqhost.h
> dt: generalize of_irq_parse_and_map()
> powerpc: move irq_alloc_descs_at() call into irq_alloc_virt()
> powerpc: use irq_alloc_desc() to manage irq allocations
>
>
> arch/microblaze/kernel/irq.c | 7 -
> arch/microblaze/kernel/setup.c | 2
> arch/mips/kernel/prom.c | 14 -
> arch/powerpc/include/asm/irq.h | 88 +------
> arch/powerpc/include/asm/irqhost.h | 27 ++
> arch/powerpc/kernel/irq.c | 260 ++++++++++++----------
> arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 5
> arch/powerpc/platforms/52xx/media5200.c | 5
> arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1
> arch/powerpc/platforms/52xx/mpc52xx_pic.c | 80 +------
> arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 5
> arch/powerpc/platforms/85xx/socrates_fpga_pic.c | 26 +-
> arch/powerpc/platforms/86xx/gef_pic.c | 10 -
> arch/powerpc/platforms/8xx/m8xx_setup.c | 2
> arch/powerpc/platforms/cell/axon_msi.c | 15 +
> arch/powerpc/platforms/cell/spider-pic.c | 19 +-
> arch/powerpc/platforms/embedded6xx/flipper-pic.c | 9 -
> arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 9 -
> arch/powerpc/platforms/embedded6xx/wii.c | 6 -
> arch/powerpc/platforms/iseries/irq.c | 10 -
> arch/powerpc/platforms/powermac/pic.c | 12 +
> arch/powerpc/platforms/pseries/ras.c | 4
> arch/powerpc/platforms/pseries/xics.c | 14 +
> arch/powerpc/sysdev/cpm1.c | 8 -
> arch/powerpc/sysdev/cpm2_pic.c | 10 -
> arch/powerpc/sysdev/fsl_msi.c | 3
> arch/powerpc/sysdev/i8259.c | 3
> arch/powerpc/sysdev/ipic.c | 19 +-
> arch/powerpc/sysdev/mpc8xx_pic.c | 10 -
> arch/powerpc/sysdev/mpc8xxx_gpio.c | 13 +
> arch/powerpc/sysdev/mpic.c | 33 +--
> arch/powerpc/sysdev/mpic_msi.c | 3
> arch/powerpc/sysdev/mpic_pasemi_msi.c | 5
> arch/powerpc/sysdev/mv64x60_pic.c | 14 +
> arch/powerpc/sysdev/qe_lib/qe_ic.c | 9 -
> arch/powerpc/sysdev/uic.c | 13 +
> arch/powerpc/sysdev/xilinx_intc.c | 9 -
> arch/x86/include/asm/irq_controller.h | 12 -
> arch/x86/include/asm/prom.h | 1
> arch/x86/kernel/devicetree.c | 77 +------
> drivers/of/irq.c | 118 ++++++++++
> include/linux/of_irq.h | 31 +++
> 42 files changed, 504 insertions(+), 517 deletions(-)
> create mode 100644 arch/powerpc/include/asm/irqhost.h
> delete mode 100644 arch/x86/include/asm/irq_controller.h
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/6] powerpc: stop exporting irq_map
2011-04-28 20:01 ` [PATCH 1/6] powerpc: stop exporting irq_map Grant Likely
@ 2011-05-03 1:44 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-03 1:44 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Thu, 2011-04-28 at 14:01 -0600, Grant Likely wrote:
> First step in eliminating irq_map[] table entirely
>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
>
Ack in principle, needs scrutiny and testing of course :-)
Cheers,
Ben.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument
2011-04-28 20:01 ` [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument Grant Likely
@ 2011-05-03 1:47 ` Benjamin Herrenschmidt
2011-05-04 15:59 ` Grant Likely
0 siblings, 1 reply; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-03 1:47 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Thu, 2011-04-28 at 14:01 -0600, Grant Likely wrote:
> irq_alloc_virt() and irq_free_virt() aren't called anywhere but from
> arch/powerpc/kernel/irq.c, and they are only ever called with count=1.
> This patch removes the prototypes from the header file, removes the
> count arguments, and cuts out the dead code.
>
> Also removes obsolete references to irq_early_init()
Nack.
The count was intended to be able to allocate blocks of interrupts. This
was not used so far because we didn't support MSI blocks (for non-X
MSIs) but that is coming, and unfortunately, the API that was designed
for that is crap and requires contiguous IRQ numbers on the linux side
as well as on the device side (well device side is a HW requirement but
we could have been smarter on the Linux side).
So the ability to allocate blocks will be needed. In fact it's not clear
yet whether we'll also need them to be naturally aligned powers of two
or not at this stage. It depends how the bloody API is going to be used
by drivers.
Cheers,
Ben.
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> arch/microblaze/kernel/setup.c | 2 -
> arch/powerpc/include/asm/irq.h | 32 ----------------
> arch/powerpc/kernel/irq.c | 82 ++++++++++++++++++++--------------------
> 3 files changed, 40 insertions(+), 76 deletions(-)
>
> diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
> index 8e2c09b..19d3ab7 100644
> --- a/arch/microblaze/kernel/setup.c
> +++ b/arch/microblaze/kernel/setup.c
> @@ -51,8 +51,6 @@ void __init setup_arch(char **cmdline_p)
>
> unflatten_device_tree();
>
> - /* NOTE I think that this function is not necessary to call */
> - /* irq_early_init(); */
> setup_cpuinfo();
>
> microblaze_cache_init();
> diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
> index e1983d5..4d2cc6f 100644
> --- a/arch/powerpc/include/asm/irq.h
> +++ b/arch/powerpc/include/asm/irq.h
> @@ -264,38 +264,6 @@ extern unsigned int irq_linear_revmap(struct irq_host *host,
> irq_hw_number_t hwirq);
>
>
> -
> -/**
> - * irq_alloc_virt - Allocate virtual irq numbers
> - * @host: host owning these new virtual irqs
> - * @count: number of consecutive numbers to allocate
> - * @hint: pass a hint number, the allocator will try to use a 1:1 mapping
> - *
> - * This is a low level function that is used internally by irq_create_mapping()
> - * and that can be used by some irq controllers implementations for things
> - * like allocating ranges of numbers for MSIs. The revmaps are left untouched.
> - */
> -extern unsigned int irq_alloc_virt(struct irq_host *host,
> - unsigned int count,
> - unsigned int hint);
> -
> -/**
> - * irq_free_virt - Free virtual irq numbers
> - * @virq: virtual irq number of the first interrupt to free
> - * @count: number of interrupts to free
> - *
> - * This function is the opposite of irq_alloc_virt. It will not clear reverse
> - * maps, this should be done previously by unmap'ing the interrupt. In fact,
> - * all interrupts covered by the range being freed should have been unmapped
> - * prior to calling this.
> - */
> -extern void irq_free_virt(unsigned int virq, unsigned int count);
> -
> -/**
> - * irq_early_init - Init irq remapping subsystem
> - */
> -extern void irq_early_init(void);
> -
> static __inline__ int irq_canonicalize(int irq)
> {
> return irq;
> diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
> index 422672b..5ccf38f 100644
> --- a/arch/powerpc/kernel/irq.c
> +++ b/arch/powerpc/kernel/irq.c
> @@ -647,6 +647,9 @@ void irq_set_virq_count(unsigned int count)
> irq_virq_count = count;
> }
>
> +static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint);
> +static void irq_free_virt(unsigned int virq);
> +
> static int irq_setup_virq(struct irq_host *host, unsigned int virq,
> irq_hw_number_t hwirq)
> {
> @@ -675,7 +678,7 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
> errdesc:
> irq_free_descs(virq, 1);
> error:
> - irq_free_virt(virq, 1);
> + irq_free_virt(virq);
> return -1;
> }
>
> @@ -689,7 +692,7 @@ unsigned int irq_create_direct_mapping(struct irq_host *host)
> BUG_ON(host == NULL);
> WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
>
> - virq = irq_alloc_virt(host, 1, 0);
> + virq = irq_alloc_virt(host, 0);
> if (virq == NO_IRQ) {
> pr_debug("irq: create_direct virq allocation failed\n");
> return NO_IRQ;
> @@ -742,7 +745,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
> } else {
> /* Allocate a virtual interrupt number */
> hint = hwirq % irq_virq_count;
> - virq = irq_alloc_virt(host, 1, hint);
> + virq = irq_alloc_virt(host, hint);
> if (virq == NO_IRQ) {
> pr_debug("irq: -> virq allocation failed\n");
> return NO_IRQ;
> @@ -856,7 +859,7 @@ void irq_dispose_mapping(unsigned int virq)
>
> irq_free_descs(virq, 1);
> /* Free it */
> - irq_free_virt(virq, 1);
> + irq_free_virt(virq);
> }
> EXPORT_SYMBOL_GPL(irq_dispose_mapping);
>
> @@ -974,36 +977,31 @@ unsigned int irq_linear_revmap(struct irq_host *host,
> return revmap[hwirq];
> }
>
> -unsigned int irq_alloc_virt(struct irq_host *host,
> - unsigned int count,
> - unsigned int hint)
> +/**
> + * irq_alloc_virt() - Allocate virtual irq numbers
> + * @host: host owning these new virtual irqs
> + * @hint: pass a hint number, the allocator will try to use a 1:1 mapping
> + *
> + * This is a low level function that is used internally by irq_create_mapping()
> + */
> +static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
> {
> unsigned long flags;
> unsigned int i, j, found = NO_IRQ;
>
> - if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS))
> - return NO_IRQ;
> -
> raw_spin_lock_irqsave(&irq_big_lock, flags);
>
> /* Use hint for 1 interrupt if any */
> - if (count == 1 && hint >= NUM_ISA_INTERRUPTS &&
> + if (hint >= NUM_ISA_INTERRUPTS &&
> hint < irq_virq_count && irq_map[hint].host == NULL) {
> found = hint;
> goto hint_found;
> }
>
> - /* Look for count consecutive numbers in the allocatable
> - * (non-legacy) space
> - */
> + /* Look for a free virq in the allocatable (non-legacy) space */
> for (i = NUM_ISA_INTERRUPTS, j = 0; i < irq_virq_count; i++) {
> - if (irq_map[i].host != NULL)
> - j = 0;
> - else
> - j++;
> -
> - if (j == count) {
> - found = i - count + 1;
> + if (irq_map[i].host == NULL) {
> + found = i;
> break;
> }
> }
> @@ -1012,36 +1010,36 @@ unsigned int irq_alloc_virt(struct irq_host *host,
> return NO_IRQ;
> }
> hint_found:
> - for (i = found; i < (found + count); i++) {
> - irq_map[i].hwirq = host->inval_irq;
> - smp_wmb();
> - irq_map[i].host = host;
> - }
> + irq_map[found].hwirq = host->inval_irq;
> + smp_wmb();
> + irq_map[found].host = host;
> raw_spin_unlock_irqrestore(&irq_big_lock, flags);
> return found;
> }
>
> -void irq_free_virt(unsigned int virq, unsigned int count)
> +/**
> + * irq_free_virt() - Free virtual irq numbers
> + * @virq: virtual irq number of the first interrupt to free
> + *
> + * This function is the opposite of irq_alloc_virt. It will not clear reverse
> + * maps, this should be done previously by unmap'ing the interrupt. In fact,
> + * the interrupts being freed should have been unmapped prior to calling this.
> + */
> +static void irq_free_virt(unsigned int virq)
> {
> unsigned long flags;
> - unsigned int i;
> + struct irq_host *host;
>
> - WARN_ON (virq < NUM_ISA_INTERRUPTS);
> - WARN_ON (count == 0 || (virq + count) > irq_virq_count);
> + if ((virq < NUM_ISA_INTERRUPTS) || (virq >= irq_virq_count)) {
> + WARN_ON(1);
> + return;
> + }
>
> raw_spin_lock_irqsave(&irq_big_lock, flags);
> - for (i = virq; i < (virq + count); i++) {
> - struct irq_host *host;
> -
> - if (i < NUM_ISA_INTERRUPTS ||
> - (virq + count) > irq_virq_count)
> - continue;
> -
> - host = irq_map[i].host;
> - irq_map[i].hwirq = host->inval_irq;
> - smp_wmb();
> - irq_map[i].host = NULL;
> - }
> + host = irq_map[virq].host;
> + irq_map[virq].hwirq = host->inval_irq;
> + smp_wmb();
> + irq_map[virq].host = NULL;
> raw_spin_unlock_irqrestore(&irq_big_lock, flags);
> }
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/6] powerpc: Make struct irq_host semi-private by moving into irqhost.h
2011-04-28 20:01 ` [PATCH 3/6] powerpc: Make struct irq_host semi-private by moving into irqhost.h Grant Likely
@ 2011-05-03 1:48 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-03 1:48 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Thu, 2011-04-28 at 14:01 -0600, Grant Likely wrote:
> Very few files actually need direct access to struct irq_host members.
> This patch moves the irq_host definition into another file so that it
> isn't brought in by default, and to prepare for the addition of
> struct of_irq_domain, which will factor some of the irq_host behaviour
> out into common code. This needs to be done because of_irq_domain
> will be embedded inside struct irq_host, and to do that it needs to be
> guaranteed that struct of_irq_domain gets fully defined first.
Why do you want to separate the irq "host" as used by powerpc with the
generic irq domain ? They should be one single thing...
Cheers,
Ben.
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> arch/powerpc/include/asm/irq.h | 20 +--------------
> arch/powerpc/include/asm/irqhost.h | 29 ++++++++++++++++++++++
> arch/powerpc/kernel/irq.c | 1 +
> arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 1 +
> arch/powerpc/platforms/52xx/media5200.c | 1 +
> arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1 +
> arch/powerpc/platforms/52xx/mpc52xx_pic.c | 1 +
> arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 1 +
> arch/powerpc/platforms/cell/axon_msi.c | 1 +
> arch/powerpc/platforms/cell/spider-pic.c | 1 +
> arch/powerpc/platforms/embedded6xx/flipper-pic.c | 1 +
> arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 1 +
> arch/powerpc/platforms/embedded6xx/wii.c | 6 +++--
> arch/powerpc/sysdev/fsl_msi.c | 1 +
> arch/powerpc/sysdev/i8259.c | 1 +
> arch/powerpc/sysdev/ipic.c | 1 +
> arch/powerpc/sysdev/mpc8xxx_gpio.c | 1 +
> arch/powerpc/sysdev/mpic.c | 1 +
> arch/powerpc/sysdev/mpic_msi.c | 1 +
> arch/powerpc/sysdev/mpic_pasemi_msi.c | 1 +
> arch/powerpc/sysdev/qe_lib/qe_ic.c | 1 +
> arch/powerpc/sysdev/uic.c | 1 +
> arch/powerpc/sysdev/xilinx_intc.c | 1 +
> 23 files changed, 54 insertions(+), 21 deletions(-)
> create mode 100644 arch/powerpc/include/asm/irqhost.h
>
> diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
> index 4d2cc6f..a44be93 100644
> --- a/arch/powerpc/include/asm/irq.h
> +++ b/arch/powerpc/include/asm/irq.h
> @@ -104,29 +104,11 @@ struct irq_host_ops {
> irq_hw_number_t *out_hwirq, unsigned int *out_type);
> };
>
> -struct irq_host {
> - struct list_head link;
> -
> - /* type of reverse mapping technique */
> - unsigned int revmap_type;
> +/* Reverse map types; pass into irq_alloc_host revmap_type argument */
> #define IRQ_HOST_MAP_LEGACY 0 /* legacy 8259, gets irqs 1..15 */
> #define IRQ_HOST_MAP_NOMAP 1 /* no fast reverse mapping */
> #define IRQ_HOST_MAP_LINEAR 2 /* linear map of interrupts */
> #define IRQ_HOST_MAP_TREE 3 /* radix tree */
> - union {
> - struct {
> - unsigned int size;
> - unsigned int *revmap;
> - } linear;
> - struct radix_tree_root tree;
> - } revmap_data;
> - struct irq_host_ops *ops;
> - void *host_data;
> - irq_hw_number_t inval_irq;
> -
> - /* Optional device node pointer */
> - struct device_node *of_node;
> -};
>
> struct irq_data;
> extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
> diff --git a/arch/powerpc/include/asm/irqhost.h b/arch/powerpc/include/asm/irqhost.h
> new file mode 100644
> index 0000000..958e6c1
> --- /dev/null
> +++ b/arch/powerpc/include/asm/irqhost.h
> @@ -0,0 +1,29 @@
> +#ifndef _ASM_POWERPC_IRQHOST_H
> +#define _ASM_POWERPC_IRQHOST_H
> +
> +#include <linux/list.h>
> +#include <linux/radix-tree.h>
> +#include <linux/irq.h>
> +#include <linux/of.h>
> +
> +struct irq_host {
> + struct list_head link;
> +
> + /* type of reverse mapping technique */
> + unsigned int revmap_type;
> + union {
> + struct {
> + unsigned int size;
> + unsigned int *revmap;
> + } linear;
> + struct radix_tree_root tree;
> + } revmap_data;
> + struct irq_host_ops *ops;
> + void *host_data;
> + irq_hw_number_t inval_irq;
> +
> + /* Optional device node pointer */
> + struct device_node *of_node;
> +};
> +
> +#endif /* _ASM_POWERPC_IRQHOST_H */
> diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
> index 5ccf38f..b961b19 100644
> --- a/arch/powerpc/kernel/irq.c
> +++ b/arch/powerpc/kernel/irq.c
> @@ -56,6 +56,7 @@
> #include <linux/of.h>
> #include <linux/of_irq.h>
>
> +#include <asm/irqhost.h>
> #include <asm/uaccess.h>
> #include <asm/system.h>
> #include <asm/io.h>
> diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
> index a8bc0d4..162bbb7 100644
> --- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
> +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
> @@ -18,6 +18,7 @@
> #include <linux/interrupt.h>
> #include <linux/irq.h>
> #include <linux/io.h>
> +#include <asm/irqhost.h>
> #include <asm/prom.h>
>
> static struct device_node *cpld_pic_node;
> diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
> index 96f85e5..e03f2cb 100644
> --- a/arch/powerpc/platforms/52xx/media5200.c
> +++ b/arch/powerpc/platforms/52xx/media5200.c
> @@ -25,6 +25,7 @@
> #include <linux/irq.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> +#include <asm/irqhost.h>
> #include <asm/time.h>
> #include <asm/prom.h>
> #include <asm/machdep.h>
> diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> index 6c39b9c..55b2d26 100644
> --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> @@ -67,6 +67,7 @@
> #include <linux/watchdog.h>
> #include <linux/miscdevice.h>
> #include <linux/uaccess.h>
> +#include <asm/irqhost.h>
> #include <asm/div64.h>
> #include <asm/mpc52xx.h>
>
> diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
> index bb61181..65bbfd1 100644
> --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
> +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
> @@ -101,6 +101,7 @@
> #include <linux/interrupt.h>
> #include <linux/irq.h>
> #include <linux/of.h>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
> #include <asm/prom.h>
> #include <asm/mpc52xx.h>
> diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
> index 5d6c34c..0ca79e0 100644
> --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
> +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
> @@ -19,6 +19,7 @@
> #include <linux/bootmem.h>
> #include <linux/slab.h>
>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
> #include <asm/prom.h>
> #include <asm/cpm2.h>
> diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
> index 1e3329e..e1469ae 100644
> --- a/arch/powerpc/platforms/cell/axon_msi.c
> +++ b/arch/powerpc/platforms/cell/axon_msi.c
> @@ -17,6 +17,7 @@
> #include <linux/debugfs.h>
> #include <linux/slab.h>
>
> +#include <asm/irqhost.h>
> #include <asm/dcr.h>
> #include <asm/machdep.h>
> #include <asm/prom.h>
> diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
> index 34d2b99..73a5494 100644
> --- a/arch/powerpc/platforms/cell/spider-pic.c
> +++ b/arch/powerpc/platforms/cell/spider-pic.c
> @@ -24,6 +24,7 @@
> #include <linux/irq.h>
> #include <linux/ioport.h>
>
> +#include <asm/irqhost.h>
> #include <asm/pgtable.h>
> #include <asm/prom.h>
> #include <asm/io.h>
> diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
> index 77cbe4c..1b60a34 100644
> --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c
> +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
> @@ -18,6 +18,7 @@
> #include <linux/init.h>
> #include <linux/irq.h>
> #include <linux/of.h>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
>
> #include "flipper-pic.h"
> diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
> index 44b398b..4f87661 100644
> --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
> +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
> @@ -18,6 +18,7 @@
> #include <linux/init.h>
> #include <linux/irq.h>
> #include <linux/of.h>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
>
> #include "hlwd-pic.h"
> diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
> index 1b5dc1a..c9176a9 100644
> --- a/arch/powerpc/platforms/embedded6xx/wii.c
> +++ b/arch/powerpc/platforms/embedded6xx/wii.c
> @@ -85,9 +85,11 @@ void __init wii_memory_fixups(void)
> wii_hole_start = p[0].base + p[0].size;
> wii_hole_size = p[1].base - wii_hole_start;
>
> - pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size);
> + pr_info("MEM1: <%08llx %08llx>\n",
> + (unsigned long long)p[0].base, (unsigned long long)p[0].size);
> pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size);
> - pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size);
> + pr_info("MEM2: <%08llx %08llx>\n",
> + (unsigned long long)p[1].base, (unsigned long long)p[1].size);
>
> p[0].size += wii_hole_size + p[1].size;
>
> diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
> index d5679dc..2c11b3e 100644
> --- a/arch/powerpc/sysdev/fsl_msi.c
> +++ b/arch/powerpc/sysdev/fsl_msi.c
> @@ -19,6 +19,7 @@
> #include <linux/slab.h>
> #include <linux/of_platform.h>
> #include <sysdev/fsl_soc.h>
> +#include <asm/irqhost.h>
> #include <asm/prom.h>
> #include <asm/hw_irq.h>
> #include <asm/ppc-pci.h>
> diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
> index 142770c..30869f0 100644
> --- a/arch/powerpc/sysdev/i8259.c
> +++ b/arch/powerpc/sysdev/i8259.c
> @@ -13,6 +13,7 @@
> #include <linux/interrupt.h>
> #include <linux/kernel.h>
> #include <linux/delay.h>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
> #include <asm/i8259.h>
> #include <asm/prom.h>
> diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
> index f0ece79..fc3751f 100644
> --- a/arch/powerpc/sysdev/ipic.c
> +++ b/arch/powerpc/sysdev/ipic.c
> @@ -24,6 +24,7 @@
> #include <linux/spinlock.h>
> #include <linux/fsl_devices.h>
> #include <asm/irq.h>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
> #include <asm/prom.h>
> #include <asm/ipic.h>
> diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
> index fb4963a..f6839a7 100644
> --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
> +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
> @@ -17,6 +17,7 @@
> #include <linux/gpio.h>
> #include <linux/slab.h>
> #include <linux/irq.h>
> +#include <asm/irqhost.h>
>
> #define MPC8XXX_GPIO_PINS 32
>
> diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> index 824a94f..6e9e594 100644
> --- a/arch/powerpc/sysdev/mpic.c
> +++ b/arch/powerpc/sysdev/mpic.c
> @@ -28,6 +28,7 @@
> #include <linux/pci.h>
> #include <linux/slab.h>
>
> +#include <asm/irqhost.h>
> #include <asm/ptrace.h>
> #include <asm/signal.h>
> #include <asm/io.h>
> diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
> index 0f67cd7..50176ed 100644
> --- a/arch/powerpc/sysdev/mpic_msi.c
> +++ b/arch/powerpc/sysdev/mpic_msi.c
> @@ -11,6 +11,7 @@
> #include <linux/irq.h>
> #include <linux/bitmap.h>
> #include <linux/msi.h>
> +#include <asm/irqhost.h>
> #include <asm/mpic.h>
> #include <asm/prom.h>
> #include <asm/hw_irq.h>
> diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> index 38e6238..6b11a89 100644
> --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
> +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> @@ -18,6 +18,7 @@
> #include <linux/irq.h>
> #include <linux/bootmem.h>
> #include <linux/msi.h>
> +#include <asm/irqhost.h>
> #include <asm/mpic.h>
> #include <asm/prom.h>
> #include <asm/hw_irq.h>
> diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
> index b2acda0..9dd7746 100644
> --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
> +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
> @@ -26,6 +26,7 @@
> #include <linux/device.h>
> #include <linux/bootmem.h>
> #include <linux/spinlock.h>
> +#include <asm/irqhost.h>
> #include <asm/irq.h>
> #include <asm/io.h>
> #include <asm/prom.h>
> diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
> index 984cd20..a097f4c 100644
> --- a/arch/powerpc/sysdev/uic.c
> +++ b/arch/powerpc/sysdev/uic.c
> @@ -26,6 +26,7 @@
> #include <linux/interrupt.h>
> #include <linux/kernel_stat.h>
> #include <asm/irq.h>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
> #include <asm/prom.h>
> #include <asm/dcr.h>
> diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
> index 6183799..28d4ded 100644
> --- a/arch/powerpc/sysdev/xilinx_intc.c
> +++ b/arch/powerpc/sysdev/xilinx_intc.c
> @@ -23,6 +23,7 @@
> #include <linux/kernel.h>
> #include <linux/irq.h>
> #include <linux/of.h>
> +#include <asm/irqhost.h>
> #include <asm/io.h>
> #include <asm/processor.h>
> #include <asm/i8259.h>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/6] dt: generalize irq_of_create_mapping()
2011-04-28 20:02 ` [PATCH 4/6] dt: generalize irq_of_create_mapping() Grant Likely
@ 2011-05-03 1:50 ` Benjamin Herrenschmidt
2011-05-04 16:05 ` Grant Likely
0 siblings, 1 reply; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-03 1:50 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Thu, 2011-04-28 at 14:02 -0600, Grant Likely wrote:
> This patch creates a common implementation of irq_of_create_mapping()
> and factors out the interrupt domain translation code from powerpc to
> make it available for all architectures.
I think you are going the wrong way around.
First thing first, is to make the irq domain / mapping API generic
without the OF bits.
IE. move the IRQ domain generically, get rid of irq_map by putting the
domain ptr & hw numbers in the irq desc/data etc...
Then you can move over the OF specific bits which are optional and
orthogonal to a large extent.
Cheers,
Ben.
> It creates a new structure, struct of_irq_domain, which can be
> embedded into the private data structure of an interrupt controller.
> Any interrupt controller can call of_irq_domain_add() to register a
> structure with a .map() hook that can translate irq specifiers from
> the device tree into linux irq numbers.
>
> The patch also modifies the powerpc irq_host to embed the
> of_irq_domain structure and use the new common infrastructure for
> registering domains. This separates the reverse mapping and irq
> allocation infrastructure of irq_host from the domain registration
> infrastructure. I elected to split the functionality this way for
> several reasons. First, with the major irq cleanup done by Thomas
> Gleixner, dynamic allocation of irqs can be handled gracefully with
> irq_alloc_desc*() and interrupt controllers may not need or want an
> irq_host layer to manage it for them. For example, the new
> irq_chip_generic() already has a method for mapping between hwirq and
> Linux irq.
>
> Second, the irq_host code currently has a lot of complexity to handle
> all the different reverse mapping types from a single structure. The
> radix mapping in particular has a lot of support code, but only one
> user. I didn't want to bring that complexity into the common code
> as-is. Instead, I'd prefer to create a separate encapsulating
> structure for each revmap, and each type would have a separate .map
> hook.
>
> For now, the mapping code remains powerpc-specific and further
> generalization will happen in subsequent patches.
>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> arch/microblaze/kernel/irq.c | 7 --
> arch/mips/kernel/prom.c | 14 ----
> arch/powerpc/include/asm/irq.h | 21 +++--
> arch/powerpc/include/asm/irqhost.h | 4 -
> arch/powerpc/kernel/irq.c | 99 ++++++++++++++-----------
> arch/powerpc/platforms/cell/axon_msi.c | 12 ++-
> arch/powerpc/platforms/cell/spider-pic.c | 8 +-
> arch/powerpc/sysdev/fsl_msi.c | 2 -
> arch/powerpc/sysdev/i8259.c | 2 -
> arch/powerpc/sysdev/ipic.c | 2 -
> arch/powerpc/sysdev/mpic.c | 4 +
> arch/powerpc/sysdev/mpic_msi.c | 2 -
> arch/powerpc/sysdev/mpic_pasemi_msi.c | 4 +
> arch/powerpc/sysdev/qe_lib/qe_ic.c | 2 -
> arch/x86/include/asm/irq_controller.h | 12 ---
> arch/x86/include/asm/prom.h | 1
> arch/x86/kernel/devicetree.c | 77 ++++----------------
> drivers/of/irq.c | 118 ++++++++++++++++++++++++++++++
> include/linux/of_irq.h | 31 ++++++++
> 19 files changed, 248 insertions(+), 174 deletions(-)
> delete mode 100644 arch/x86/include/asm/irq_controller.h
>
> diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
> index ce7ac84..59bb560 100644
> --- a/arch/microblaze/kernel/irq.c
> +++ b/arch/microblaze/kernel/irq.c
> @@ -54,10 +54,3 @@ unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
> return hwirq;
> }
> EXPORT_SYMBOL_GPL(irq_create_mapping);
> -
> -unsigned int irq_create_of_mapping(struct device_node *controller,
> - const u32 *intspec, unsigned int intsize)
> -{
> - return intspec[0];
> -}
> -EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
> index a19811e9..0b82f98 100644
> --- a/arch/mips/kernel/prom.c
> +++ b/arch/mips/kernel/prom.c
> @@ -60,20 +60,6 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,
> }
> #endif
>
> -/*
> - * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
> - *
> - * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
> - * mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not
> - * supported.
> - */
> -unsigned int irq_create_of_mapping(struct device_node *controller,
> - const u32 *intspec, unsigned int intsize)
> -{
> - return intspec[0];
> -}
> -EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> -
> void __init early_init_devtree(void *params)
> {
> /* Setup flat device-tree pointer */
> diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
> index a44be93..ccefc8c 100644
> --- a/arch/powerpc/include/asm/irq.h
> +++ b/arch/powerpc/include/asm/irq.h
> @@ -55,11 +55,18 @@ typedef unsigned long irq_hw_number_t;
> * model). It's the host callbacks that are responsible for setting the
> * irq_chip on a given irq_desc after it's been mapped.
> *
> + * irq_host builds upon the of_irq_domain code in drivers/of/irq.c.
> + * of_irq_domain provides all of the translation hooks for registering irq
> + * controllers. irq_host add mapping infrastructure to and from hardware
> + * irq numbers. IRQ controllers that don't need the mapping infrastructure
> + * can use irq_domain directly.
> + *
> * The host code and data structures are fairly agnostic to the fact that
> * we use an open firmware device-tree. We do have references to struct
> - * device_node in two places: in irq_find_host() to find the host matching
> - * a given interrupt controller node, and of course as an argument to its
> - * counterpart host->ops->match() callback. However, those are treated as
> + * device_node in two places: in of_irq_domain_find() to find the host matching
> + * a given interrupt controller node (which is actually common of_irq_domain
> + * code), and of course as an argument to its counterpart host->ops->match()
> + * and host->domain->match() callbacks. However, those are treated as
> * generic pointers by the core and the fact that it's actually a device-node
> * pointer is purely a convention between callers and implementation. This
> * code could thus be used on other architectures by replacing those two
> @@ -137,14 +144,6 @@ extern struct irq_host *irq_alloc_host(struct device_node *of_node,
> struct irq_host_ops *ops,
> irq_hw_number_t inval_irq);
>
> -
> -/**
> - * irq_find_host - Locates a host for a given device node
> - * @node: device-tree node of the interrupt controller
> - */
> -extern struct irq_host *irq_find_host(struct device_node *node);
> -
> -
> /**
> * irq_set_default_host - Set a "default" host
> * @host: default host pointer
> diff --git a/arch/powerpc/include/asm/irqhost.h b/arch/powerpc/include/asm/irqhost.h
> index 958e6c1..a97a513 100644
> --- a/arch/powerpc/include/asm/irqhost.h
> +++ b/arch/powerpc/include/asm/irqhost.h
> @@ -8,6 +8,7 @@
>
> struct irq_host {
> struct list_head link;
> + struct of_irq_domain domain;
>
> /* type of reverse mapping technique */
> unsigned int revmap_type;
> @@ -21,9 +22,6 @@ struct irq_host {
> struct irq_host_ops *ops;
> void *host_data;
> irq_hw_number_t inval_irq;
> -
> - /* Optional device node pointer */
> - struct device_node *of_node;
> };
>
> #endif /* _ASM_POWERPC_IRQHOST_H */
> diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
> index b961b19..9300e1c 100644
> --- a/arch/powerpc/kernel/irq.c
> +++ b/arch/powerpc/kernel/irq.c
> @@ -514,11 +514,40 @@ struct irq_host *virq_to_host(unsigned int virq)
> }
> EXPORT_SYMBOL_GPL(virq_to_host);
>
> -static int default_irq_host_match(struct irq_host *h, struct device_node *np)
> +/**
> + * irq_host_domain_match() - irq_domain hook to call irq_host match ops.
> + *
> + * This functions gets set as the irq domain match function for irq_host
> + * instances *if* the ->ops->match() hook is populated. If ->match() is
> + * not populated, then the default irq_domain matching behaviour is used
> + * instead.
> + */
> +static bool irq_host_domain_match(struct of_irq_domain *domain,
> + struct device_node *controller)
> {
> - return h->of_node != NULL && h->of_node == np;
> + struct irq_host *host = container_of(domain, struct irq_host, domain);
> + return host->ops->match(host, controller);
> }
>
> +static unsigned int irq_host_domain_map(struct of_irq_domain *domain,
> + struct device_node *controller,
> + const u32 *intspec,
> + unsigned int intsize);
> +
> +/**
> + * irq_alloc_host() - Allocate and register an irq_host
> + * @of_node: Device node of the irq controller; this is used mainly as an
> + * anonymouns context pointer.
> + * @revmap_type: One of IRQ_HOST_MAP_* defined in arch/powerpc/include/asm/irq.h
> + * Defines the type of reverse map to be used by the irq_host.
> + * @revmap_arg: Currently only used by the IRQ_HOST_MAP_LINEAR which uses it
> + * to define the size of the reverse map.
> + * @ops: irq_host ops structure for match/map/unmap/remap/xlate operations.
> + * @inval_irq: Value used by irq controller to indicate an invalid irq.
> + *
> + * irq_host implements mapping between hardware irq numbers and the linux
> + * virq number space. This function allocates and registers an irq_host.
> + */
> struct irq_host *irq_alloc_host(struct device_node *of_node,
> unsigned int revmap_type,
> unsigned int revmap_arg,
> @@ -542,10 +571,10 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
> host->revmap_type = revmap_type;
> host->inval_irq = inval_irq;
> host->ops = ops;
> - host->of_node = of_node_get(of_node);
> -
> - if (host->ops->match == NULL)
> - host->ops->match = default_irq_host_match;
> + host->domain.controller = of_node_get(of_node);
> + host->domain.map = irq_host_domain_map;
> + if (host->ops->match != NULL)
> + host->domain.match = irq_host_domain_match;
>
> raw_spin_lock_irqsave(&irq_big_lock, flags);
>
> @@ -561,7 +590,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
> * instead of the current cruft
> */
> if (mem_init_done) {
> - of_node_put(host->of_node);
> + of_node_put(host->domain.controller);
> kfree(host);
> }
> return NULL;
> @@ -572,6 +601,8 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
> list_add(&host->link, &irq_hosts);
> raw_spin_unlock_irqrestore(&irq_big_lock, flags);
>
> + of_irq_domain_add(&host->domain);
> +
> /* Additional setups per revmap type */
> switch(revmap_type) {
> case IRQ_HOST_MAP_LEGACY:
> @@ -611,32 +642,12 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
> return host;
> }
>
> -struct irq_host *irq_find_host(struct device_node *node)
> -{
> - struct irq_host *h, *found = NULL;
> - unsigned long flags;
> -
> - /* We might want to match the legacy controller last since
> - * it might potentially be set to match all interrupts in
> - * the absence of a device node. This isn't a problem so far
> - * yet though...
> - */
> - raw_spin_lock_irqsave(&irq_big_lock, flags);
> - list_for_each_entry(h, &irq_hosts, link)
> - if (h->ops->match(h, node)) {
> - found = h;
> - break;
> - }
> - raw_spin_unlock_irqrestore(&irq_big_lock, flags);
> - return found;
> -}
> -EXPORT_SYMBOL_GPL(irq_find_host);
> -
> void irq_set_default_host(struct irq_host *host)
> {
> pr_debug("irq: Default host set to @0x%p\n", host);
>
> irq_default_host = host;
> + of_irq_set_default_domain(&host->domain);
> }
>
> void irq_set_virq_count(unsigned int count)
> @@ -757,30 +768,29 @@ unsigned int irq_create_mapping(struct irq_host *host,
> return NO_IRQ;
>
> printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n",
> - hwirq, host->of_node ? host->of_node->full_name : "null", virq);
> + hwirq, host->domain.controller ? host->domain.controller->full_name : "null", virq);
>
> return virq;
> }
> EXPORT_SYMBOL_GPL(irq_create_mapping);
>
> -unsigned int irq_create_of_mapping(struct device_node *controller,
> - const u32 *intspec, unsigned int intsize)
> +/**
> + * irq_host_domain_map() - Map device tree irq to linux irq number
> + * This hook implements all of the powerpc 'irq_host' behaviour, which means
> + * - calling the ->ops->xlate hook to get the hardware irq number,
> + * - calling of_create_mapping to translate/allocate a linux virq number
> + * - calling irq_set_irq_type() if necessary
> + */
> +static unsigned int irq_host_domain_map(struct of_irq_domain *domain,
> + struct device_node *controller,
> + const u32 *intspec,
> + unsigned int intsize)
> {
> - struct irq_host *host;
> + struct irq_host *host = container_of(domain, struct irq_host, domain);
> irq_hw_number_t hwirq;
> unsigned int type = IRQ_TYPE_NONE;
> unsigned int virq;
>
> - if (controller == NULL)
> - host = irq_default_host;
> - else
> - host = irq_find_host(controller);
> - if (host == NULL) {
> - printk(KERN_WARNING "irq: no irq host found for %s !\n",
> - controller->full_name);
> - return NO_IRQ;
> - }
> -
> /* If host has no translation, then we assume interrupt line */
> if (host->ops->xlate == NULL)
> hwirq = intspec[0];
> @@ -801,7 +811,6 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
> irq_set_irq_type(virq, type);
> return virq;
> }
> -EXPORT_SYMBOL_GPL(irq_create_of_mapping);
>
> void irq_dispose_mapping(unsigned int virq)
> {
> @@ -1128,8 +1137,8 @@ static int virq_debug_show(struct seq_file *m, void *private)
> p = none;
> seq_printf(m, "%-15s ", p);
>
> - if (irq_map[i].host && irq_map[i].host->of_node)
> - p = irq_map[i].host->of_node->full_name;
> + if (irq_map[i].host && irq_map[i].host->domain.controller)
> + p = irq_map[i].host->domain.controller->full_name;
> else
> p = none;
> seq_printf(m, "%s\n", p);
> diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
> index e1469ae..f125673 100644
> --- a/arch/powerpc/platforms/cell/axon_msi.c
> +++ b/arch/powerpc/platforms/cell/axon_msi.c
> @@ -152,7 +152,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
>
> static struct axon_msic *find_msi_translator(struct pci_dev *dev)
> {
> - struct irq_host *irq_host;
> + struct of_irq_domain *irq_domain;
> struct device_node *dn, *tmp;
> const phandle *ph;
> struct axon_msic *msic = NULL;
> @@ -184,14 +184,14 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
> goto out_error;
> }
>
> - irq_host = irq_find_host(dn);
> - if (!irq_host) {
> + irq_domain = of_irq_domain_find(dn);
> + if (!irq_domain) {
> dev_dbg(&dev->dev, "axon_msi: no irq_host found for node %s\n",
> dn->full_name);
> goto out_error;
> }
>
> - msic = irq_host->host_data;
> + msic = irq_domain->priv;
>
> out_error:
> of_node_put(dn);
> @@ -336,7 +336,7 @@ static void axon_msi_shutdown(struct platform_device *device)
> u32 tmp;
>
> pr_devel("axon_msi: disabling %s\n",
> - msic->irq_host->of_node->full_name);
> + msic->irq_host->domain.controller->full_name);
> tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
> tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
> msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
> @@ -399,7 +399,7 @@ static int axon_msi_probe(struct platform_device *device)
> goto out_free_fifo;
> }
>
> - msic->irq_host->host_data = msic;
> + msic->irq_host->domain.priv = msic;
>
> irq_set_handler_data(virq, msic);
> irq_set_chained_handler(virq, axon_msi_cascade);
> diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
> index 73a5494..5bf36ab 100644
> --- a/arch/powerpc/platforms/cell/spider-pic.c
> +++ b/arch/powerpc/platforms/cell/spider-pic.c
> @@ -236,18 +236,20 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
> * tree in case the device-tree is ever fixed
> */
> struct of_irq oirq;
> - if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) {
> + if (of_irq_map_one(pic->host->domain.controller, 0, &oirq) == 0) {
> virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
> oirq.size);
> return virq;
> }
>
> /* Now do the horrible hacks */
> - tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
> + tmp = of_get_property(pic->host->domain.controller,
> + "#interrupt-cells", NULL);
> if (tmp == NULL)
> return NO_IRQ;
> intsize = *tmp;
> - imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen);
> + imap = of_get_property(pic->host->domain.controller,
> + "interrupt-map", &imaplen);
> if (imap == NULL || imaplen < (intsize + 1))
> return NO_IRQ;
> iic = of_find_node_by_phandle(imap[intsize]);
> diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
> index 2c11b3e..b45a25a 100644
> --- a/arch/powerpc/sysdev/fsl_msi.c
> +++ b/arch/powerpc/sysdev/fsl_msi.c
> @@ -82,7 +82,7 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
> int rc;
>
> rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
> - msi_data->irqhost->of_node);
> + msi_data->irqhost->domain.controller);
> if (rc)
> return rc;
>
> diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
> index 30869f0..a6f78fb 100644
> --- a/arch/powerpc/sysdev/i8259.c
> +++ b/arch/powerpc/sysdev/i8259.c
> @@ -166,7 +166,7 @@ static struct resource pic_edgectrl_iores = {
>
> static int i8259_host_match(struct irq_host *h, struct device_node *node)
> {
> - return h->of_node == NULL || h->of_node == node;
> + return h->domain.controller == NULL || h->domain.controller == node;
> }
>
> static int i8259_host_map(struct irq_host *h, unsigned int virq,
> diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
> index fc3751f..5805c7b 100644
> --- a/arch/powerpc/sysdev/ipic.c
> +++ b/arch/powerpc/sysdev/ipic.c
> @@ -676,7 +676,7 @@ static struct irq_chip ipic_edge_irq_chip = {
> static int ipic_host_match(struct irq_host *h, struct device_node *node)
> {
> /* Exact match, unless ipic node is NULL */
> - return h->of_node == NULL || h->of_node == node;
> + return h->domain.controller == NULL || h->domain.controller == node;
> }
>
> static int ipic_host_map(struct irq_host *h, unsigned int virq,
> diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> index 6e9e594..cafc364 100644
> --- a/arch/powerpc/sysdev/mpic.c
> +++ b/arch/powerpc/sysdev/mpic.c
> @@ -956,7 +956,7 @@ static struct irq_chip mpic_irq_ht_chip = {
> static int mpic_host_match(struct irq_host *h, struct device_node *node)
> {
> /* Exact match, unless mpic node is NULL */
> - return h->of_node == NULL || h->of_node == node;
> + return h->domain.controller == NULL || h->domain.controller == node;
> }
>
> static int mpic_host_map(struct irq_host *h, unsigned int virq,
> @@ -1296,7 +1296,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
>
> BUG_ON(isu_num >= MPIC_MAX_ISU);
>
> - mpic_map(mpic, mpic->irqhost->of_node,
> + mpic_map(mpic, mpic->irqhost->domain.controller,
> paddr, &mpic->isus[isu_num], 0,
> MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
>
> diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
> index 50176ed..ddf79c7 100644
> --- a/arch/powerpc/sysdev/mpic_msi.c
> +++ b/arch/powerpc/sysdev/mpic_msi.c
> @@ -85,7 +85,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
> int rc;
>
> rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count,
> - mpic->irqhost->of_node);
> + mpic->irqhost->domain.controller);
> if (rc)
> return rc;
>
> diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> index 6b11a89..857be51 100644
> --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
> +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> @@ -153,8 +153,8 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
> {
> int rc;
>
> - if (!mpic->irqhost->of_node ||
> - !of_device_is_compatible(mpic->irqhost->of_node,
> + if (!mpic->irqhost->domain.controller ||
> + !of_device_is_compatible(mpic->irqhost->domain.controller,
> "pasemi,pwrficient-openpic"))
> return -ENODEV;
>
> diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
> index 9dd7746..c2ccafa 100644
> --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
> +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
> @@ -250,7 +250,7 @@ static struct irq_chip qe_ic_irq_chip = {
> static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
> {
> /* Exact match, unless qe_ic node is NULL */
> - return h->of_node == NULL || h->of_node == node;
> + return h->domain.controller == NULL || h->domain.controller == node;
> }
>
> static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
> diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h
> deleted file mode 100644
> index 423bbbd..0000000
> --- a/arch/x86/include/asm/irq_controller.h
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -#ifndef __IRQ_CONTROLLER__
> -#define __IRQ_CONTROLLER__
> -
> -struct irq_domain {
> - int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize,
> - u32 *out_hwirq, u32 *out_type);
> - void *priv;
> - struct device_node *controller;
> - struct list_head l;
> -};
> -
> -#endif
> diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
> index 971e0b4..eb9d5ab 100644
> --- a/arch/x86/include/asm/prom.h
> +++ b/arch/x86/include/asm/prom.h
> @@ -21,7 +21,6 @@
> #include <asm/irq.h>
> #include <asm/atomic.h>
> #include <asm/setup.h>
> -#include <asm/irq_controller.h>
>
> #ifdef CONFIG_OF
> extern int of_ioapic;
> diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
> index 706a9fb..651e724 100644
> --- a/arch/x86/kernel/devicetree.c
> +++ b/arch/x86/kernel/devicetree.c
> @@ -15,64 +15,14 @@
> #include <linux/of_pci.h>
>
> #include <asm/hpet.h>
> -#include <asm/irq_controller.h>
> #include <asm/apic.h>
> #include <asm/pci_x86.h>
>
> __initdata u64 initial_dtb;
> char __initdata cmd_line[COMMAND_LINE_SIZE];
> -static LIST_HEAD(irq_domains);
> -static DEFINE_RAW_SPINLOCK(big_irq_lock);
>
> int __initdata of_ioapic;
>
> -#ifdef CONFIG_X86_IO_APIC
> -static void add_interrupt_host(struct irq_domain *ih)
> -{
> - unsigned long flags;
> -
> - raw_spin_lock_irqsave(&big_irq_lock, flags);
> - list_add(&ih->l, &irq_domains);
> - raw_spin_unlock_irqrestore(&big_irq_lock, flags);
> -}
> -#endif
> -
> -static struct irq_domain *get_ih_from_node(struct device_node *controller)
> -{
> - struct irq_domain *ih, *found = NULL;
> - unsigned long flags;
> -
> - raw_spin_lock_irqsave(&big_irq_lock, flags);
> - list_for_each_entry(ih, &irq_domains, l) {
> - if (ih->controller == controller) {
> - found = ih;
> - break;
> - }
> - }
> - raw_spin_unlock_irqrestore(&big_irq_lock, flags);
> - return found;
> -}
> -
> -unsigned int irq_create_of_mapping(struct device_node *controller,
> - const u32 *intspec, unsigned int intsize)
> -{
> - struct irq_domain *ih;
> - u32 virq, type;
> - int ret;
> -
> - ih = get_ih_from_node(controller);
> - if (!ih)
> - return 0;
> - ret = ih->xlate(ih, intspec, intsize, &virq, &type);
> - if (ret)
> - return 0;
> - if (type == IRQ_TYPE_NONE)
> - return virq;
> - irq_set_irq_type(virq, type);
> - return virq;
> -}
> -EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> -
> unsigned long pci_address_to_pio(phys_addr_t address)
> {
> /*
> @@ -366,32 +316,33 @@ static struct of_ioapic_type of_ioapic_type[] =
> },
> };
>
> -static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
> - u32 *out_hwirq, u32 *out_type)
> +static unsigned int ioapic_of_irq_map(struct of_irq_domain *id,
> + struct device_node *np,
> + const u32 *intspec, u32 intsize)
> {
> struct io_apic_irq_attr attr;
> struct of_ioapic_type *it;
> - u32 line, idx, type;
> + u32 line, idx, type, hwirq;
>
> if (intsize < 2)
> - return -EINVAL;
> + return 0;
>
> line = *intspec;
> idx = (u32) id->priv;
> - *out_hwirq = line + mp_gsi_routing[idx].gsi_base;
> + hwirq = line + mp_gsi_routing[idx].gsi_base;
>
> intspec++;
> type = *intspec;
>
> if (type >= ARRAY_SIZE(of_ioapic_type))
> - return -EINVAL;
> + return 0;
>
> it = of_ioapic_type + type;
> - *out_type = it->out_type;
> -
> set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
>
> - return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
> + if (io_apic_setup_irq_pin(hwirq, cpu_to_node(0), &attr))
> + return 0;
> + return hwirq;
> }
>
> static void __init ioapic_add_ofnode(struct device_node *np)
> @@ -408,14 +359,14 @@ static void __init ioapic_add_ofnode(struct device_node *np)
>
> for (i = 0; i < nr_ioapics; i++) {
> if (r.start == mp_ioapics[i].apicaddr) {
> - struct irq_domain *id;
> + struct of_irq_domain *id;
>
> id = kzalloc(sizeof(*id), GFP_KERNEL);
> BUG_ON(!id);
> - id->controller = np;
> - id->xlate = ioapic_xlate;
> + id->controller = of_node_get(np);
> + id->map = ioapic_of_irq_map;
> id->priv = (void *)i;
> - add_interrupt_host(id);
> + of_irq_domain_add(id);
> return;
> }
> }
> diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> index 75b0d3c..6da0964 100644
> --- a/drivers/of/irq.c
> +++ b/drivers/of/irq.c
> @@ -19,6 +19,7 @@
> */
>
> #include <linux/errno.h>
> +#include <linux/list.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_irq.h>
> @@ -29,6 +30,123 @@
> #define NO_IRQ 0
> #endif
>
> +/*
> + * Device Tree IRQ domains
> + *
> + * IRQ domains provide translation from device tree irq controller nodes to
> + * linux IRQ numbers. IRQ controllers register an irq_domain with a .map()
> + * hook that performs everything needed to decode and configure a device
> + * tree specified interrupt.
> + */
> +static LIST_HEAD(of_irq_domains);
> +static DEFINE_RAW_SPINLOCK(of_irq_lock);
> +static struct of_irq_domain *of_irq_default_domain;
> +
> +/**
> + * of_irq_domain_default_match() - Return true if the controller pointers match
> + *
> + * Default match behaviour for of_irq_domains. If the device tree node pointer
> + * matches the value stored in the domain structure, then return true.
> + */
> +static bool of_irq_domain_default_match(struct of_irq_domain *domain,
> + struct device_node *controller)
> +{
> + return domain->controller == controller;
> +}
> +
> +/**
> + * of_irq_domain_add() - Register a device tree irq domain
> + * @domain: pointer to domain structure to be registered.
> + *
> + * Adds an of_irq_domain to the global list of domains.
> + */
> +void of_irq_domain_add(struct of_irq_domain *domain)
> +{
> + unsigned long flags;
> +
> + if (!domain->match)
> + domain->match = of_irq_domain_default_match;
> + if (!domain->map) {
> + WARN_ON(1);
> + return;
> + }
> +
> + raw_spin_lock_irqsave(&of_irq_lock, flags);
> + list_add(&domain->list, &of_irq_domains);
> + raw_spin_unlock_irqrestore(&of_irq_lock, flags);
> +}
> +
> +/**
> + * of_irq_domain_find() - Find the domain that handles a given device tree node
> + *
> + * Returns the pointer to an of_irq_domain capable of translating irq specifiers
> + * for the given irq controller device tree node. Returns NULL if a suitable
> + * domain could not be found.
> + */
> +struct of_irq_domain *of_irq_domain_find(struct device_node *controller)
> +{
> + struct of_irq_domain *domain, *found = NULL;
> + unsigned long flags;
> +
> + raw_spin_lock_irqsave(&of_irq_lock, flags);
> + list_for_each_entry(domain, &of_irq_domains, list) {
> + if (domain->match(domain, controller)) {
> + found = domain;
> + break;
> + }
> + }
> + raw_spin_unlock_irqrestore(&of_irq_lock, flags);
> + return found;
> +}
> +
> +/**
> + * of_irq_set_default_domain() - Set a "default" host
> + * @domain: default domain pointer
> + *
> + * For convenience, it's possible to set a "default" host that will be used
> + * whenever NULL is passed to irq_of_create_mapping(). It makes life easier
> + * for platforms that want to manipulate a few hard coded interrupt numbers
> + * that aren't properly represented in the device-tree.
> + */
> +void of_irq_set_default_domain(struct of_irq_domain *domain)
> +{
> + pr_debug("irq: Default host set to @0x%p\n", domain);
> + of_irq_default_domain = domain;
> +}
> +
> +/**
> + * irq_create_of_mapping() - Map a linux irq # from a device tree specifier
> + * @controller - interrupt-controller node in the device tree
> + * @intspec - array of interrupt specifier data. Points to an array of u32
> + * values. Data is *cpu-native* endian u32 values.
> + * @intsize - size of intspec array.
> + *
> + * Given an interrupt controller node pointer and an interrupt specifier, this
> + * function looks up the linux irq number.
> + */
> +unsigned int irq_create_of_mapping(struct device_node *controller,
> + const u32 *intspec, unsigned int intsize)
> +{
> + struct of_irq_domain *domain;
> +
> + domain = of_irq_domain_find(controller);
> + if (!domain)
> + domain = of_irq_default_domain;
> + if (!domain) {
> + pr_warn("error: no irq host found for %s !\n",
> + controller->full_name);
> +#if defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE)
> + /* FIXME: make Microblaze and MIPS register irq domains */
> + return intspec[0];
> +#else /* defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE) */
> + return NO_IRQ;
> +#endif /* defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE) */
> + }
> +
> + return domain->map(domain, controller, intspec, intsize);
> +}
> +EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> +
> /**
> * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
> * @device: Device node of the device whose interrupt is to be mapped
> diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
> index 109e013..511dbc3 100644
> --- a/include/linux/of_irq.h
> +++ b/include/linux/of_irq.h
> @@ -33,6 +33,37 @@ struct of_irq {
> u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
> };
>
> +/**
> + * struct of_irq_domain - Translation domain from device tree to linux irq
> + * @list: Linked list node entry
> + * @match: (optional) Called to determine if the passed device_node
> + * interrupt-controller can be translated by this irq domain.
> + * Returns 'true' if it can.
> + * @decode: Translation callback; returns virq, or NO_IRQ if this irq
> + * domain cannot translate it.
> + * @controller: (optional) pointer to OF node. By default, if
> + * 'match' is not set, then this of_irq_domain will only
> + * be used if the device tree node passed in matches the
> + * controller pointer.
> + * @priv: Private data pointer, not touched by core of_irq_domain code.
> + */
> +struct of_irq_domain {
> + struct list_head list;
> + bool (*match)(struct of_irq_domain *d, struct device_node *np);
> + unsigned int (*map)(struct of_irq_domain *d, struct device_node *np,
> + const u32 *intspec, u32 intsize);
> + struct device_node *controller;
> + void *priv;
> +};
> +
> +/**
> + * of_irq_domain_add() - Add a device tree interrupt translation domain
> + * @domain: interrupt domain to add.
> + */
> +extern void of_irq_domain_add(struct of_irq_domain *domain);
> +extern void of_irq_set_default_domain(struct of_irq_domain *host);
> +extern struct of_irq_domain *of_irq_domain_find(struct device_node *controller);
> +
> /*
> * Workarounds only applied to 32bit powermac machines
> */
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-05-03 1:43 ` Benjamin Herrenschmidt
@ 2011-05-04 15:52 ` Grant Likely
2011-05-05 0:39 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-05-04 15:52 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Tue, May 03, 2011 at 11:43:19AM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-28 at 14:01 -0600, Grant Likely wrote:
> > A lot of this series ends up being fixups to powerpc code; but the 4th
> > patch is of importance to every architecture using CONFIG_OF (except
> > SPARC, which has its own solution).
> >
> > This series (finally!) factors out device tree irq domain decoding
> > from arch/powerpc and makes it generic for all architectures. The
> > infrastructure is quite simple. Any interrupt controller can embed
> > the of_irq_domain structure and register it with the core code. After
> > that, device nodes referencing interrupts on that device tree node
> > will trigger a call to the domain's map function.
>
> This leads to an immediate reaction from me : why "of_irq_domain" ?
>
> The concept of interrupt domains is completely orthogonal to "OF" and
> whether you use the device-tree or not.
>
> Having a remapping mechanism allowing to deal with multiple interrupt
> domains without playing stupid numbering tricks is generally useful for
> architectures, regardless of their adoption of the device-tree.
>
> The irq domain has one and -only one- op that is related to OF which
> allows to map a device node to a domain, but that's 'optional' and only
> use if you use the OF resolving process. The whole mechanism can be (and
> is under some circumstances on ppc) without a device-tree relationship.
>
> We instanciate IRQs within domains manually in some cases, either
> because we lack proper DT informations or bcs the IRQs come from the
> firmware or as "created" out of the blue (device-tree). A domain pointer
> (or NULL for the default domain) is all is needed.
>
> Thus I object to tying this infrastructure generically to "OF" even if
> it's just a mater of naming of the domain structure and location of the
> code in the kernel tree.
>
> It should basically all go into kernel/irq/domains.c or something like
> that.
I completely agree that irq domains are a generically useful feature
for architectures, and it should be made available. I also completely
agree that it is orthogonal to device tree translations, which in a
large part is why I've structured this series and the new code the
way I have.
In this series I'm specifically addressing device tree translation,
which is the one bit that is DT specific, and is important regardless
of the backend translation mechanism. In fact, the more I looked at
it, the more it seems that the DT api really is orthogonal to the
backend irq mapping and I don't think that the way irq_host ties them
together is necessarily the best way to do it. Many of the interrupt
controllers which need to gain dt irq parsing have already been
converted to using the irq_alloc_desc*() apis and have all the mapping
mechanism they need, but lack a method of exposing it for DT
translation.
As for the mapping, I agree that the functionality is generally
useful, I'm just not fond of the current implementation. I think it
is more complex than it needs to be and I'm not excited about bring it
over to the other architectures as-is.
For the majority of fixed hw interrupt controllers it is overkill.
There is no need for a map table when all the irq descs (<=32 of them)
get allocated when the irq controller is instantiated and the mapping
consists of 'virq = hw_irq + virq_base'. For instance, with the arm
irq controllers, it's be more than sufficient to use irq_alloc_descs
to obtain a range of irq numbers and then a simple of_irq_domain
registration to handle the parsing.
For the cases where an interrupt controller isn't able to alloc all
the irq descs at once, like for MSI, then yes the LINEAR and RADIX
mappings are important. What bothers me though is the way irq_host
needs to use unions and the ->revmap_type value to implement multiple
behaviours into a single type. That's the sort of thing that can be
broken out into a library and instantiated only by the interrupt
controllers that actually need it. Similarly, it bothers me that that
radix mapping makes up a significant portion of the code, yet it has
only one user. I'd be happier if each kind of mapping had its own
structure that embedded a generic irq_host/irq_domain with mapping
specific ops populated to manipulate it.
Regardless, the immediate priority is to implement a mapper that will
work for all architectures (or at least everything but powerpc and
sparc). x86 has already implemented a skeleton irq_domain because
there wasn't any common code for it to use. ARM also needs the
functionality immediately, and I don't want to see yet another
arch-specific implementation. I'd like to get the framework in place
now, and grafting in mapping features as follow on patches. That way
the new DT users aren't blocked while waiting for us to hammer down
the features that the other architectures don't need yet.
What I /could/ have done I suppose was called it 'struct irq_domain'
as you suggest, and allowed each translation mechanism to define its
own match/map pair of routines, with device tree being the only one
actually implemented at this point. Yes, I understand that the
core code treats the controller pointer as an anonymous cookie, but
the api is still very device tree centric, and I'm not convinced that
the assumption that all firmware irq representations will be an array
of u32 values is going to hold up. I'd rather state upfront that the
device tree translation really is device tree and let translations for
other representation have the option of defining their own API.
However, that is not a strong objection, and if Thomas agrees with you
then I'm okay with renaming of_irq_domain to irq_domain and moving it
to kernel/irq/irqdomain.c. The mapping functionality I think should
stay out for now until we come to agreement on how it should look, and
I'll fix up any users if the API needs to change at a later date.
g.
>
> > PowerPC and x86 have been converted to use of_irq_domain. MIPS and
> > Microblaze have it enabled, but nothing actually registers domains
> > yet, so a workaround is in place to preserve the current behaviour
> > until it is fixed.
> >
> > I'd really like to get patches 1-4 merged into 2.6.40. Please test.
> > I'm also running through build testing here, and when it's complete
> > I'll push it out to a 'devicetree/irq-domain' branch on
> > git://git.secretlab.ca/git/linux-2.6
> >
> > It needs testing. I've booted it on a powerpc board here without any
> > apparent regressions, but that isn't a very big sample. I've also
> > build tested on everything I think is affected.
> >
> > I'd also like to get it into linux-next. Ben, if things checkout okay
> > over the next few days, would you be okay with me adding it to
> > linux-next, say around Wednesday next week? As for merging, I think
> > this should probably go via your powerpc tree since the that's where
> > the bulk of the changes are, but I'm open to other suggestions).
> >
> > Patches 5 & 6 are follow-on cleanup work to powerpc, but patch 6 is
> > RFC only since there is a locking problem that I haven't fixed yet.
> >
> > Cheers,
> > g.
> >
> > ---
> >
> > Grant Likely (6):
> > powerpc: stop exporting irq_map
> > powerpc: make irq_{alloc,free}_virt private and remove count argument
> > powerpc: Make struct irq_host semi-private by moving into irqhost.h
> > dt: generalize of_irq_parse_and_map()
> > powerpc: move irq_alloc_descs_at() call into irq_alloc_virt()
> > powerpc: use irq_alloc_desc() to manage irq allocations
> >
> >
> > arch/microblaze/kernel/irq.c | 7 -
> > arch/microblaze/kernel/setup.c | 2
> > arch/mips/kernel/prom.c | 14 -
> > arch/powerpc/include/asm/irq.h | 88 +------
> > arch/powerpc/include/asm/irqhost.h | 27 ++
> > arch/powerpc/kernel/irq.c | 260 ++++++++++++----------
> > arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 5
> > arch/powerpc/platforms/52xx/media5200.c | 5
> > arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1
> > arch/powerpc/platforms/52xx/mpc52xx_pic.c | 80 +------
> > arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 5
> > arch/powerpc/platforms/85xx/socrates_fpga_pic.c | 26 +-
> > arch/powerpc/platforms/86xx/gef_pic.c | 10 -
> > arch/powerpc/platforms/8xx/m8xx_setup.c | 2
> > arch/powerpc/platforms/cell/axon_msi.c | 15 +
> > arch/powerpc/platforms/cell/spider-pic.c | 19 +-
> > arch/powerpc/platforms/embedded6xx/flipper-pic.c | 9 -
> > arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 9 -
> > arch/powerpc/platforms/embedded6xx/wii.c | 6 -
> > arch/powerpc/platforms/iseries/irq.c | 10 -
> > arch/powerpc/platforms/powermac/pic.c | 12 +
> > arch/powerpc/platforms/pseries/ras.c | 4
> > arch/powerpc/platforms/pseries/xics.c | 14 +
> > arch/powerpc/sysdev/cpm1.c | 8 -
> > arch/powerpc/sysdev/cpm2_pic.c | 10 -
> > arch/powerpc/sysdev/fsl_msi.c | 3
> > arch/powerpc/sysdev/i8259.c | 3
> > arch/powerpc/sysdev/ipic.c | 19 +-
> > arch/powerpc/sysdev/mpc8xx_pic.c | 10 -
> > arch/powerpc/sysdev/mpc8xxx_gpio.c | 13 +
> > arch/powerpc/sysdev/mpic.c | 33 +--
> > arch/powerpc/sysdev/mpic_msi.c | 3
> > arch/powerpc/sysdev/mpic_pasemi_msi.c | 5
> > arch/powerpc/sysdev/mv64x60_pic.c | 14 +
> > arch/powerpc/sysdev/qe_lib/qe_ic.c | 9 -
> > arch/powerpc/sysdev/uic.c | 13 +
> > arch/powerpc/sysdev/xilinx_intc.c | 9 -
> > arch/x86/include/asm/irq_controller.h | 12 -
> > arch/x86/include/asm/prom.h | 1
> > arch/x86/kernel/devicetree.c | 77 +------
> > drivers/of/irq.c | 118 ++++++++++
> > include/linux/of_irq.h | 31 +++
> > 42 files changed, 504 insertions(+), 517 deletions(-)
> > create mode 100644 arch/powerpc/include/asm/irqhost.h
> > delete mode 100644 arch/x86/include/asm/irq_controller.h
>
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument
2011-05-03 1:47 ` Benjamin Herrenschmidt
@ 2011-05-04 15:59 ` Grant Likely
2011-05-05 0:39 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-05-04 15:59 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Tue, May 03, 2011 at 11:47:47AM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-28 at 14:01 -0600, Grant Likely wrote:
> > irq_alloc_virt() and irq_free_virt() aren't called anywhere but from
> > arch/powerpc/kernel/irq.c, and they are only ever called with count=1.
> > This patch removes the prototypes from the header file, removes the
> > count arguments, and cuts out the dead code.
> >
> > Also removes obsolete references to irq_early_init()
>
> Nack.
>
> The count was intended to be able to allocate blocks of interrupts. This
> was not used so far because we didn't support MSI blocks (for non-X
> MSIs) but that is coming, and unfortunately, the API that was designed
> for that is crap and requires contiguous IRQ numbers on the linux side
> as well as on the device side (well device side is a HW requirement but
> we could have been smarter on the Linux side).
>
> So the ability to allocate blocks will be needed. In fact it's not clear
> yet whether we'll also need them to be naturally aligned powers of two
> or not at this stage. It depends how the bloody API is going to be used
> by drivers.
Heh, I wondered about that, but there hasn't been any users for at
least 5 years (as evidenced by commit e12514650b, "Fix loop logic in
irq_alloc_virt()") so it was looking pretty dead, and it made the
patch to switch to using irq_alloc_desc*() quite a bit simpler if it
was removed. :-)
I'm not particularly attached to this patch, so I can drop it from the
series.
g.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/6] dt: generalize irq_of_create_mapping()
2011-05-03 1:50 ` Benjamin Herrenschmidt
@ 2011-05-04 16:05 ` Grant Likely
2011-05-05 0:43 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-05-04 16:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Tue, May 03, 2011 at 11:50:22AM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-28 at 14:02 -0600, Grant Likely wrote:
> > This patch creates a common implementation of irq_of_create_mapping()
> > and factors out the interrupt domain translation code from powerpc to
> > make it available for all architectures.
>
> I think you are going the wrong way around.
>
> First thing first, is to make the irq domain / mapping API generic
> without the OF bits.
>
> IE. move the IRQ domain generically, get rid of irq_map by putting the
> domain ptr & hw numbers in the irq desc/data etc...
>
> Then you can move over the OF specific bits which are optional and
> orthogonal to a large extent.
As discussed in my other reply, I disagree. There isn't an immediate
need for the mapping interface in common code. It would be useful,
sure, for some interrupt controllers, but for many of them
irq_alloc_descs() and an irq_base value is all the functionality that
is needed, and irq_host doesn't gain anything.
The OF translation on the other hand is needed immediately by several
architectures and are very much non-optional in that regard.
g.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-05-04 15:52 ` Grant Likely
@ 2011-05-05 0:39 ` Benjamin Herrenschmidt
2011-05-05 8:37 ` Thomas Gleixner
0 siblings, 1 reply; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-05 0:39 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
> I completely agree that irq domains are a generically useful feature
> for architectures, and it should be made available. I also completely
> agree that it is orthogonal to device tree translations, which in a
> large part is why I've structured this series and the new code the
> way I have.
>
> In this series I'm specifically addressing device tree translation,
> which is the one bit that is DT specific, and is important regardless
> of the backend translation mechanism. In fact, the more I looked at
> it, the more it seems that the DT api really is orthogonal to the
> backend irq mapping and I don't think that the way irq_host ties them
> together is necessarily the best way to do it. Many of the interrupt
> controllers which need to gain dt irq parsing have already been
> converted to using the irq_alloc_desc*() apis and have all the mapping
> mechanism they need, but lack a method of exposing it for DT
> translation.
But irq_alloc_desc() is purely about allocating the linux side irq
descriptors. Nothing to do with HW numbers here.
You still need a mapping mechanism, regardless of the device-tree, to
map those linux number to your HW numbers.
This is simple and eventually even 1:1 on things like x86, but the
minute you start having cascaded IRQ controllers, multiple IRQ domains,
and/or very large HW numbers that encode node IDs etc... this falls
appart.
And this is still completely orthogonal to the device-tree.
Mapping is the important functionality. Whatever the actual allocator is
is indeed irrelevant.
> As for the mapping, I agree that the functionality is generally
> useful, I'm just not fond of the current implementation. I think it
> is more complex than it needs to be and I'm not excited about bring it
> over to the other architectures as-is.
Nobody cares about the current implementation. What is important is
indeed the functionality. The basic thing I think everybody agrees is
that you need to extend the irq_desc (or data, whatever tglx prefers)
with two bits of information: Some identifier of the domain and some
identifier of the interrupt number within that domain.
In addition, PIC code will need a way to perform efficient reverse
mapping. You may decide that for simple IRQ controllers that handle a
small linear range of interrupts, it's kosher to simply reserve a linear
range of descriptors and use a simple offset, I'm find with that now
that we no longer live in a world constrained by NR_IRQ.
But the need for the radix tree remains for things that have massively
large potential HW numbers such as we have on powerpc.
> For the majority of fixed hw interrupt controllers it is overkill.
> There is no need for a map table when all the irq descs (<=32 of them)
> get allocated when the irq controller is instantiated and the mapping
> consists of 'virq = hw_irq + virq_base'. For instance, with the arm
> irq controllers, it's be more than sufficient to use irq_alloc_descs
> to obtain a range of irq numbers and then a simple of_irq_domain
> registration to handle the parsing.
That's true if and only if you make NR_IRQ a non issue and if you accept
the general wastage due to unused interrupts.
The main problem has always been that hard limit which made me chose a
more efficient mechanisms. Take a mac with 2 cascaded MPICs with 256
sources each which are mostly never used. I would need an NR_IRQs of 512
with your scheme (plus 16 because I do want to continue avoiding the
"ISA" numbers), which is a waste of space, even with SPARSE_IRQ.
Now I hope eventually NR_IRQ will go away and we'll have a more
efficient mechanism to allocate descriptors and so it will become less
of an issue.
> For the cases where an interrupt controller isn't able to alloc all
> the irq descs at once, like for MSI, then yes the LINEAR and RADIX
> mappings are important. What bothers me though is the way irq_host
> needs to use unions and the ->revmap_type value to implement multiple
> behaviours into a single type. That's the sort of thing that can be
> broken out into a library and instantiated only by the interrupt
> controllers that actually need it.
But that's what it is really. You'll notice that on the fast path the
interrupt controller code calls directly into the "right" type of revmap
routine. You may want to refactor things a bit if you want, but the
union served me well simply because I didnt have to bother doing lots of
different alloc_bootmem back then. Nowadays, kmalloc is available much
earlier so it might have become a non issue too.
> Similarly, it bothers me that that
> radix mapping makes up a significant portion of the code, yet it has
> only one user.
"significant" ? Seriously ? Like 3 function calls ? It's nothing. We use
an existing radix tree facility, and the amount of code in our irq.c is
actually very small.
Originally it was living in xics in fact, but I moved it out
specifically because I wanted a common interface to remapping, so for
example, I can expose the linux -> hw mapping in debugfs generically,
among others.
> I'd be happier if each kind of mapping had its own
> structure that embedded a generic irq_host/irq_domain with mapping
> specific ops populated to manipulate it.
Whatever, that's just plumbing, I don't care either way, that doesn't
change the fact that the concept of domain doesn't have much to do with
OF :-)
> Regardless, the immediate priority is to implement a mapper that will
> work for all architectures (or at least everything but powerpc and
> sparc).
I oppose the implementation of a new mapper that doesn't include
powerpc, that would be stupid. Either re-use ours or implement a new one
that encompass our needs. I can't talk for sparc but I wouldn't be
surprised if David thought about the same lines.
> x86 has already implemented a skeleton irq_domain because
> there wasn't any common code for it to use. ARM also needs the
> functionality immediately, and I don't want to see yet another
> arch-specific implementation. I'd like to get the framework in place
> now, and grafting in mapping features as follow on patches. That way
> the new DT users aren't blocked while waiting for us to hammer down
> the features that the other architectures don't need yet.
But the mapping code exist already. It returns a device-node as the
interrupt controller. What you then need is to establish the
relationship between that device-node and a domain in linux, and have
code to decode the content of the interrupts property.
So you need the concept of domain first, generic, and -then- you can
start adding a way to bind it to OF.
> What I /could/ have done I suppose was called it 'struct irq_domain'
> as you suggest, and allowed each translation mechanism to define its
> own match/map pair of routines, with device tree being the only one
> actually implemented at this point. Yes, I understand that the
> core code treats the controller pointer as an anonymous cookie, but
> the api is still very device tree centric, and I'm not convinced that
> the assumption that all firmware irq representations will be an array
> of u32 values is going to hold up.
How so ?
> I'd rather state upfront that the
> device tree translation really is device tree and let translations for
> other representation have the option of defining their own API.
>
> However, that is not a strong objection, and if Thomas agrees with you
> then I'm okay with renaming of_irq_domain to irq_domain and moving it
> to kernel/irq/irqdomain.c. The mapping functionality I think should
> stay out for now until we come to agreement on how it should look, and
> I'll fix up any users if the API needs to change at a later date.
But I think the mapping functionality is what needs to be sorted first.
Cheers
Ben.
> g.
>
>
>
> >
> > > PowerPC and x86 have been converted to use of_irq_domain. MIPS and
> > > Microblaze have it enabled, but nothing actually registers domains
> > > yet, so a workaround is in place to preserve the current behaviour
> > > until it is fixed.
> > >
> > > I'd really like to get patches 1-4 merged into 2.6.40. Please test.
> > > I'm also running through build testing here, and when it's complete
> > > I'll push it out to a 'devicetree/irq-domain' branch on
> > > git://git.secretlab.ca/git/linux-2.6
> > >
> > > It needs testing. I've booted it on a powerpc board here without any
> > > apparent regressions, but that isn't a very big sample. I've also
> > > build tested on everything I think is affected.
> > >
> > > I'd also like to get it into linux-next. Ben, if things checkout okay
> > > over the next few days, would you be okay with me adding it to
> > > linux-next, say around Wednesday next week? As for merging, I think
> > > this should probably go via your powerpc tree since the that's where
> > > the bulk of the changes are, but I'm open to other suggestions).
> > >
> > > Patches 5 & 6 are follow-on cleanup work to powerpc, but patch 6 is
> > > RFC only since there is a locking problem that I haven't fixed yet.
> > >
> > > Cheers,
> > > g.
> > >
> > > ---
> > >
> > > Grant Likely (6):
> > > powerpc: stop exporting irq_map
> > > powerpc: make irq_{alloc,free}_virt private and remove count argument
> > > powerpc: Make struct irq_host semi-private by moving into irqhost.h
> > > dt: generalize of_irq_parse_and_map()
> > > powerpc: move irq_alloc_descs_at() call into irq_alloc_virt()
> > > powerpc: use irq_alloc_desc() to manage irq allocations
> > >
> > >
> > > arch/microblaze/kernel/irq.c | 7 -
> > > arch/microblaze/kernel/setup.c | 2
> > > arch/mips/kernel/prom.c | 14 -
> > > arch/powerpc/include/asm/irq.h | 88 +------
> > > arch/powerpc/include/asm/irqhost.h | 27 ++
> > > arch/powerpc/kernel/irq.c | 260 ++++++++++++----------
> > > arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 5
> > > arch/powerpc/platforms/52xx/media5200.c | 5
> > > arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1
> > > arch/powerpc/platforms/52xx/mpc52xx_pic.c | 80 +------
> > > arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 5
> > > arch/powerpc/platforms/85xx/socrates_fpga_pic.c | 26 +-
> > > arch/powerpc/platforms/86xx/gef_pic.c | 10 -
> > > arch/powerpc/platforms/8xx/m8xx_setup.c | 2
> > > arch/powerpc/platforms/cell/axon_msi.c | 15 +
> > > arch/powerpc/platforms/cell/spider-pic.c | 19 +-
> > > arch/powerpc/platforms/embedded6xx/flipper-pic.c | 9 -
> > > arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 9 -
> > > arch/powerpc/platforms/embedded6xx/wii.c | 6 -
> > > arch/powerpc/platforms/iseries/irq.c | 10 -
> > > arch/powerpc/platforms/powermac/pic.c | 12 +
> > > arch/powerpc/platforms/pseries/ras.c | 4
> > > arch/powerpc/platforms/pseries/xics.c | 14 +
> > > arch/powerpc/sysdev/cpm1.c | 8 -
> > > arch/powerpc/sysdev/cpm2_pic.c | 10 -
> > > arch/powerpc/sysdev/fsl_msi.c | 3
> > > arch/powerpc/sysdev/i8259.c | 3
> > > arch/powerpc/sysdev/ipic.c | 19 +-
> > > arch/powerpc/sysdev/mpc8xx_pic.c | 10 -
> > > arch/powerpc/sysdev/mpc8xxx_gpio.c | 13 +
> > > arch/powerpc/sysdev/mpic.c | 33 +--
> > > arch/powerpc/sysdev/mpic_msi.c | 3
> > > arch/powerpc/sysdev/mpic_pasemi_msi.c | 5
> > > arch/powerpc/sysdev/mv64x60_pic.c | 14 +
> > > arch/powerpc/sysdev/qe_lib/qe_ic.c | 9 -
> > > arch/powerpc/sysdev/uic.c | 13 +
> > > arch/powerpc/sysdev/xilinx_intc.c | 9 -
> > > arch/x86/include/asm/irq_controller.h | 12 -
> > > arch/x86/include/asm/prom.h | 1
> > > arch/x86/kernel/devicetree.c | 77 +------
> > > drivers/of/irq.c | 118 ++++++++++
> > > include/linux/of_irq.h | 31 +++
> > > 42 files changed, 504 insertions(+), 517 deletions(-)
> > > create mode 100644 arch/powerpc/include/asm/irqhost.h
> > > delete mode 100644 arch/x86/include/asm/irq_controller.h
> >
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument
2011-05-04 15:59 ` Grant Likely
@ 2011-05-05 0:39 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-05 0:39 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Wed, 2011-05-04 at 09:59 -0600, Grant Likely wrote:
>
> Heh, I wondered about that, but there hasn't been any users for at
> least 5 years (as evidenced by commit e12514650b, "Fix loop logic in
> irq_alloc_virt()") so it was looking pretty dead, and it made the
> patch to switch to using irq_alloc_desc*() quite a bit simpler if it
> was removed. :-)
>
> I'm not particularly attached to this patch, so I can drop it from the
> series.
Well, Willy recently added support for the MSI block allocation so ...
Cheers,
Ben.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/6] dt: generalize irq_of_create_mapping()
2011-05-04 16:05 ` Grant Likely
@ 2011-05-05 0:43 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 23+ messages in thread
From: Benjamin Herrenschmidt @ 2011-05-05 0:43 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev,
devicetree-discuss
On Wed, 2011-05-04 at 10:05 -0600, Grant Likely wrote:
> > I think you are going the wrong way around.
> >
> > First thing first, is to make the irq domain / mapping API generic
> > without the OF bits.
> >
> > IE. move the IRQ domain generically, get rid of irq_map by putting
> the
> > domain ptr & hw numbers in the irq desc/data etc...
> >
> > Then you can move over the OF specific bits which are optional and
> > orthogonal to a large extent.
>
> As discussed in my other reply, I disagree. There isn't an immediate
> need for the mapping interface in common code. It would be useful,
> sure, for some interrupt controllers, but for many of them
> irq_alloc_descs() and an irq_base value is all the functionality that
> is needed, and irq_host doesn't gain anything.
No but the concept of domain is a pre-requisite. Even if it's an opaque
data structure. And I don't want to have it be some "of" specific thing.
> The OF translation on the other hand is needed immediately by several
> architectures and are very much non-optional in that regard.
But it relies on having an underlying mapping. I don't see how you can
do one without the other, even if your mapping in effect is just an
offset.
And it is -not- related to OF.
Whether you obtain that your interrupt you are interested it is
interrupt 5 of your PIC "foo" via the device-tree or any other way (an
arch quirk for example), you need the mechanism to associate them
together, whether it's a simple offset as you propose (I'm ok with that
for simple things, I just didn't think it was the right approach for
powerpc but it's perfectly valid as an option generically) or a more
complex radix-tree style mapping.
Thus sort out the mapping interfaces first. _Then_ layout the
device-tree bits on top.
The basic parsing for the DT is already there. It will return a parent
node and a __be32* pointer.
Cheers,
Ben.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-05-05 0:39 ` Benjamin Herrenschmidt
@ 2011-05-05 8:37 ` Thomas Gleixner
2011-05-05 14:07 ` Grant Likely
0 siblings, 1 reply; 23+ messages in thread
From: Thomas Gleixner @ 2011-05-05 8:37 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, linuxppc-dev,
devicetree-discuss
On Thu, 5 May 2011, Benjamin Herrenschmidt wrote:
> > As for the mapping, I agree that the functionality is generally
> > useful, I'm just not fond of the current implementation. I think it
> > is more complex than it needs to be and I'm not excited about bring it
> > over to the other architectures as-is.
>
> Nobody cares about the current implementation. What is important is
> indeed the functionality. The basic thing I think everybody agrees is
> that you need to extend the irq_desc (or data, whatever tglx prefers)
> with two bits of information: Some identifier of the domain and some
> identifier of the interrupt number within that domain.
irq_data because that's what is handed into the callbacks and you
probably want to have the HW number there.
> In addition, PIC code will need a way to perform efficient reverse
> mapping. You may decide that for simple IRQ controllers that handle a
> small linear range of interrupts, it's kosher to simply reserve a linear
> range of descriptors and use a simple offset, I'm find with that now
> that we no longer live in a world constrained by NR_IRQ.
>
> But the need for the radix tree remains for things that have massively
> large potential HW numbers such as we have on powerpc.
>
> > For the majority of fixed hw interrupt controllers it is overkill.
> > There is no need for a map table when all the irq descs (<=32 of them)
> > get allocated when the irq controller is instantiated and the mapping
> > consists of 'virq = hw_irq + virq_base'. For instance, with the arm
> > irq controllers, it's be more than sufficient to use irq_alloc_descs
> > to obtain a range of irq numbers and then a simple of_irq_domain
> > registration to handle the parsing.
>
> That's true if and only if you make NR_IRQ a non issue and if you accept
> the general wastage due to unused interrupts.
>
> The main problem has always been that hard limit which made me chose a
> more efficient mechanisms. Take a mac with 2 cascaded MPICs with 256
> sources each which are mostly never used. I would need an NR_IRQs of 512
> with your scheme (plus 16 because I do want to continue avoiding the
> "ISA" numbers), which is a waste of space, even with SPARSE_IRQ.
>
> Now I hope eventually NR_IRQ will go away and we'll have a more
> efficient mechanism to allocate descriptors and so it will become less
> of an issue.
Well, NR_IRQS in the sparse case is irrelevant already and I'm looking
into a way to remove the !SPARSE code completely.
One thing we can do to avoid allocating 512 irq descriptors for the
MAC case is to reserve the space and only allocate the descriptors you
really need to be operational.
> > For the cases where an interrupt controller isn't able to alloc all
> > the irq descs at once, like for MSI, then yes the LINEAR and RADIX
> > mappings are important. What bothers me though is the way irq_host
> > needs to use unions and the ->revmap_type value to implement multiple
> > behaviours into a single type. That's the sort of thing that can be
> > broken out into a library and instantiated only by the interrupt
> > controllers that actually need it.
>
> But that's what it is really. You'll notice that on the fast path the
> interrupt controller code calls directly into the "right" type of revmap
> routine. You may want to refactor things a bit if you want, but the
> union served me well simply because I didnt have to bother doing lots of
> different alloc_bootmem back then. Nowadays, kmalloc is available much
> earlier so it might have become a non issue too.
>
> > Similarly, it bothers me that that
> > radix mapping makes up a significant portion of the code, yet it has
> > only one user.
>
> "significant" ? Seriously ? Like 3 function calls ? It's nothing. We use
> an existing radix tree facility, and the amount of code in our irq.c is
> actually very small.
>
> Originally it was living in xics in fact, but I moved it out
> specifically because I wanted a common interface to remapping, so for
> example, I can expose the linux -> hw mapping in debugfs generically,
> among others.
And there is another reverse mapping implementation in the superH
code.
> > I'd be happier if each kind of mapping had its own
> > structure that embedded a generic irq_host/irq_domain with mapping
> > specific ops populated to manipulate it.
>
> Whatever, that's just plumbing, I don't care either way, that doesn't
> change the fact that the concept of domain doesn't have much to do with
> OF :-)
>
> > Regardless, the immediate priority is to implement a mapper that will
> > work for all architectures (or at least everything but powerpc and
> > sparc).
>
> I oppose the implementation of a new mapper that doesn't include
> powerpc, that would be stupid. Either re-use ours or implement a new one
> that encompass our needs. I can't talk for sparc but I wouldn't be
> surprised if David thought about the same lines.
>
> > x86 has already implemented a skeleton irq_domain because
> > there wasn't any common code for it to use. ARM also needs the
> > functionality immediately, and I don't want to see yet another
> > arch-specific implementation. I'd like to get the framework in place
> > now, and grafting in mapping features as follow on patches. That way
> > the new DT users aren't blocked while waiting for us to hammer down
> > the features that the other architectures don't need yet.
>
> But the mapping code exist already. It returns a device-node as the
> interrupt controller. What you then need is to establish the
> relationship between that device-node and a domain in linux, and have
> code to decode the content of the interrupts property.
>
> So you need the concept of domain first, generic, and -then- you can
> start adding a way to bind it to OF.
Ack.
Thanks,
tglx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-05-05 8:37 ` Thomas Gleixner
@ 2011-05-05 14:07 ` Grant Likely
2011-05-05 14:14 ` Sebastian Andrzej Siewior
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-05-05 14:07 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, linuxppc-dev,
devicetree-discuss
On Thu, May 5, 2011 at 2:37 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> On Thu, 5 May 2011, Benjamin Herrenschmidt wrote:
>> > As for the mapping, I agree that the functionality is generally
>> > useful, I'm just not fond of the current implementation. =A0I think it
>> > is more complex than it needs to be and I'm not excited about bring it
>> > over to the other architectures as-is.
>>
>> Nobody cares about the current implementation. What is important is
>> indeed the functionality. The basic thing I think everybody agrees is
>> that you need to extend the irq_desc (or data, whatever tglx prefers)
>> with two bits of information: Some identifier of the domain and some
>> identifier of the interrupt number within that domain.
>
> irq_data because that's what is handed into the callbacks and you
> probably want to have the HW number there.
Okay, I'll take another hack at it. Unfortunately I've got a great
big unmaskable interrupt in the form of UDS next week, but I'll be
back on it the week after.
g.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/6] General device tree irq domain infrastructure
2011-05-05 14:07 ` Grant Likely
@ 2011-05-05 14:14 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-05-05 14:14 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, devicetree-discuss, x86, linux-kernel, Ralf Baechle,
hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev
Grant Likely wrote:
> Okay, I'll take another hack at it. Unfortunately I've got a great
> big unmaskable interrupt in the form of UDS next week, but I'll be
> back on it the week after.
And I thought you were a NMI.
>
> g.
Sebastian
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2011-05-05 14:14 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-28 20:01 [PATCH 0/6] General device tree irq domain infrastructure Grant Likely
2011-04-28 20:01 ` [PATCH 1/6] powerpc: stop exporting irq_map Grant Likely
2011-05-03 1:44 ` Benjamin Herrenschmidt
2011-04-28 20:01 ` [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument Grant Likely
2011-05-03 1:47 ` Benjamin Herrenschmidt
2011-05-04 15:59 ` Grant Likely
2011-05-05 0:39 ` Benjamin Herrenschmidt
2011-04-28 20:01 ` [PATCH 3/6] powerpc: Make struct irq_host semi-private by moving into irqhost.h Grant Likely
2011-05-03 1:48 ` Benjamin Herrenschmidt
2011-04-28 20:02 ` [PATCH 4/6] dt: generalize irq_of_create_mapping() Grant Likely
2011-05-03 1:50 ` Benjamin Herrenschmidt
2011-05-04 16:05 ` Grant Likely
2011-05-05 0:43 ` Benjamin Herrenschmidt
2011-04-28 20:02 ` [PATCH 5/6] powerpc: move irq_alloc_descs_at() call into irq_alloc_virt() Grant Likely
2011-04-28 20:02 ` [PATCH 6/6] powerpc: use irq_alloc_desc() to manage irq allocations Grant Likely
2011-04-29 16:16 ` [PATCH 0/6] General device tree irq domain infrastructure Sebastian Andrzej Siewior
2011-04-29 17:43 ` Grant Likely
2011-05-03 1:43 ` Benjamin Herrenschmidt
2011-05-04 15:52 ` Grant Likely
2011-05-05 0:39 ` Benjamin Herrenschmidt
2011-05-05 8:37 ` Thomas Gleixner
2011-05-05 14:07 ` Grant Likely
2011-05-05 14:14 ` Sebastian Andrzej Siewior
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).