* [RFC patch 1/8] genirq: generic chip: Remove the local cur_regs() function
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
[not found] ` <20130503214629.397359626-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2013-05-03 21:50 ` [RFC patch 2/8] genirq: generic chip: Add support for per chip type mask cache Thomas Gleixner
` (8 subsequent siblings)
9 siblings, 1 reply; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, linux-doc-u79uwXL29TY76Z2rM5mHXA, Joey Oravec,
Lennert Buytenhek, Russell King - ARM Linux, Jason Gunthorpe,
Holger Brunck, Grant Likely, Sebastian Hesselbarth, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring, Ben Dooks,
Simon Guinot, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Jean-Francois Moine, Gerlando Falauto
[-- Attachment #1: genirq-cosmetic-remove-cur_regs.patch --]
[-- Type: text/plain, Size: 5284 bytes --]
From: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Since we already have an irq_data_get_chip_type() function which returns
a pointer to irq_chip_type, use that instead of cur_regs().
Signed-off-by: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: Lennert Buytenhek <kernel-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org>
Cc: Simon Guinot <simon-jKBdWWKqtFpg9hUCZPvPmw@public.gmane.org>
Cc: Joey Oravec <joravec-Vf0cVmJFnCtWk0Htik3J/w@public.gmane.org>
Cc: Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: Nicolas Pitre <nico-vtqb6HGKxmzR7s880joybQ@public.gmane.org>
Cc: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
Cc: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Cc: Holger Brunck <Holger.Brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
kernel/irq/generic-chip.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
Index: tip/kernel/irq/generic-chip.c
===================================================================
--- tip.orig/kernel/irq/generic-chip.c
+++ tip/kernel/irq/generic-chip.c
@@ -16,11 +16,6 @@
static LIST_HEAD(gc_list);
static DEFINE_RAW_SPINLOCK(gc_lock);
-static inline struct irq_chip_regs *cur_regs(struct irq_data *d)
-{
- return &container_of(d->chip, struct irq_chip_type, chip)->regs;
-}
-
/**
* irq_gc_noop - NOOP function
* @d: irq_data
@@ -39,10 +34,11 @@ void irq_gc_noop(struct irq_data *d)
void irq_gc_mask_disable_reg(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.disable);
gc->mask_cache &= ~mask;
irq_gc_unlock(gc);
}
@@ -57,11 +53,12 @@ void irq_gc_mask_disable_reg(struct irq_
void irq_gc_mask_set_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache |= mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -75,11 +72,12 @@ void irq_gc_mask_set_bit(struct irq_data
void irq_gc_mask_clr_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache &= ~mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -93,10 +91,11 @@ void irq_gc_mask_clr_bit(struct irq_data
void irq_gc_unmask_enable_reg(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.enable);
gc->mask_cache |= mask;
irq_gc_unlock(gc);
}
@@ -108,10 +107,11 @@ void irq_gc_unmask_enable_reg(struct irq
void irq_gc_ack_set_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
irq_gc_unlock(gc);
}
@@ -122,10 +122,11 @@ void irq_gc_ack_set_bit(struct irq_data
void irq_gc_ack_clr_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = ~(1 << (d->irq - gc->irq_base));
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
irq_gc_unlock(gc);
}
@@ -136,11 +137,12 @@ void irq_gc_ack_clr_bit(struct irq_data
void irq_gc_mask_disable_reg_and_ack(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.mask);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
irq_gc_unlock(gc);
}
@@ -151,10 +153,11 @@ void irq_gc_mask_disable_reg_and_ack(str
void irq_gc_eoi(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.eoi);
irq_gc_unlock(gc);
}
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 2/8] genirq: generic chip: Add support for per chip type mask cache
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
2013-05-03 21:50 ` [RFC patch 1/8] genirq: generic chip: Remove the local cur_regs() function Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
2013-05-03 21:50 ` [RFC patch 3/8] genirq: generic chip: Handle separate mask registers Thomas Gleixner
` (7 subsequent siblings)
9 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, linux-doc-u79uwXL29TY76Z2rM5mHXA, Simon Guinot,
Lennert Buytenhek, Russell King - ARM Linux, Jason Gunthorpe,
Holger Brunck, Grant Likely, Sebastian Hesselbarth, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring, Ben Dooks,
Simon Guinot, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Jean-Francois Moine, Gerlando Falauto
[-- Attachment #1: genirq-add-mask_cache-and-pmask_cache-into-struct-irq_chip_type.patch --]
[-- Type: text/plain, Size: 4548 bytes --]
From: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Today the same interrupt mask cache (stored within struct irq_chip_generic)
is shared between all the irq_chip_type instances. As there are instances
where each irq_chip_type uses a distinct mask register (as it is the case
for Orion SoCs), sharing a single mask cache may be incorrect.
So add a distinct pointer for each irq_chip_type, which for now
points to the original mask register within irq_chip_generic.
So no functional changes here.
[ tglx: Minor cosmetic tweaks ]
Reported-by: Joey Oravec <joravec-Vf0cVmJFnCtWk0Htik3J/w@public.gmane.org>
Signed-off-by: Simon Guinot <sguinot-D+JDLXUtGQkAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Holger Brunck <holger.brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: Lennert Buytenhek <kernel-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org>
Cc: Simon Guinot <simon-jKBdWWKqtFpg9hUCZPvPmw@public.gmane.org>
Cc: Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: Nicolas Pitre <nico-vtqb6HGKxmzR7s880joybQ@public.gmane.org>
Cc: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
Cc: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Cc: Holger Brunck <Holger.Brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
include/linux/irq.h | 6 +++++-
kernel/irq/generic-chip.c | 16 ++++++++++------
2 files changed, 15 insertions(+), 7 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -644,6 +644,8 @@ struct irq_chip_regs {
* @regs: Register offsets for this chip
* @handler: Flow handler associated with this chip
* @type: Chip can handle these flow types
+ * @mask_cache_priv: Cached mask register private to the chip type
+ * @mask_cache: Pointer to cached mask register
*
* A irq_generic_chip can have several instances of irq_chip_type when
* it requires different functions and register offsets for different
@@ -654,6 +656,8 @@ struct irq_chip_type {
struct irq_chip_regs regs;
irq_flow_handler_t handler;
u32 type;
+ u32 mask_cache_priv;
+ u32 *mask_cache;
};
/**
@@ -662,7 +666,7 @@ struct irq_chip_type {
* @reg_base: Register base address (virtual)
* @irq_base: Interrupt base nr for this chip
* @irq_cnt: Number of interrupts handled by this chip
- * @mask_cache: Cached mask register
+ * @mask_cache: Cached mask register shared between all chip types
* @type_cache: Cached type register
* @polarity_cache: Cached polarity register
* @wake_enabled: Interrupt can wakeup from suspend
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -39,7 +39,7 @@ void irq_gc_mask_disable_reg(struct irq_
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.disable);
- gc->mask_cache &= ~mask;
+ *ct->mask_cache &= ~mask;
irq_gc_unlock(gc);
}
@@ -57,8 +57,8 @@ void irq_gc_mask_set_bit(struct irq_data
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache |= mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
+ *ct->mask_cache |= mask;
+ irq_reg_writel(*ct->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -76,8 +76,8 @@ void irq_gc_mask_clr_bit(struct irq_data
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache &= ~mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
+ *ct->mask_cache &= ~mask;
+ irq_reg_writel(*ct->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -96,7 +96,7 @@ void irq_gc_unmask_enable_reg(struct irq
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.enable);
- gc->mask_cache |= mask;
+ *ct->mask_cache |= mask;
irq_gc_unlock(gc);
}
@@ -250,6 +250,10 @@ void irq_setup_generic_chip(struct irq_c
if (flags & IRQ_GC_INIT_MASK_CACHE)
gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
+ /* Initialize mask cache pointer */
+ for (i = 0; i < gc->num_ct; i++)
+ ct[i].mask_cache = &gc->mask_cache;
+
for (i = gc->irq_base; msk; msk >>= 1, i++) {
if (!(msk & 0x01))
continue;
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 3/8] genirq: generic chip: Handle separate mask registers
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
2013-05-03 21:50 ` [RFC patch 1/8] genirq: generic chip: Remove the local cur_regs() function Thomas Gleixner
2013-05-03 21:50 ` [RFC patch 2/8] genirq: generic chip: Add support for per chip type mask cache Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
2013-05-03 21:50 ` [RFC patch 4/8] genirq: generic chip: Cache per irq bit mask Thomas Gleixner
` (6 subsequent siblings)
9 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, linux-doc-u79uwXL29TY76Z2rM5mHXA, Joey Oravec,
Lennert Buytenhek, Russell King - ARM Linux, Jason Gunthorpe,
Holger Brunck, Grant Likely, Sebastian Hesselbarth, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring, Ben Dooks,
Simon Guinot, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Jean-Francois Moine, Gerlando Falauto
[-- Attachment #1: genirq-handle-separate-mask-registers.patch --]
[-- Type: text/plain, Size: 3066 bytes --]
From: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
There are cases where all irq_chip_type instances have separate mask
registers, making a shared mask register cache unsuitable for the
purpose.
Introduce a new flag IRQ_GC_MASK_CACHE_PER_TYPE. If set, point the per
chip mask pointer to the per chip private mask cache instead.
[ tglx: Simplified code, renamed flag and massaged changelog ]
Signed-off-by: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: Lennert Buytenhek <kernel-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org>
Cc: Simon Guinot <simon-jKBdWWKqtFpg9hUCZPvPmw@public.gmane.org>
Cc: Joey Oravec <joravec-Vf0cVmJFnCtWk0Htik3J/w@public.gmane.org>
Cc: Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: Nicolas Pitre <nico-vtqb6HGKxmzR7s880joybQ@public.gmane.org>
Cc: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
Cc: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Cc: Holger Brunck <Holger.Brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
include/linux/irq.h | 2 ++
kernel/irq/generic-chip.c | 17 ++++++++++-------
2 files changed, 12 insertions(+), 7 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -704,10 +704,12 @@ struct irq_chip_generic {
* @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for
* irq chips which need to call irq_set_wake() on
* the parent irq. Usually GPIO implementations
+ * @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private
*/
enum irq_gc_flags {
IRQ_GC_INIT_MASK_CACHE = 1 << 0,
IRQ_GC_INIT_NESTED_LOCK = 1 << 1,
+ IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2,
};
/* Generic chip callback functions */
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -241,18 +241,21 @@ void irq_setup_generic_chip(struct irq_c
{
struct irq_chip_type *ct = gc->chip_types;
unsigned int i;
+ u32 *mskptr = &gc->mask_cache, mskreg = ct->regs.mask;
raw_spin_lock(&gc_lock);
list_add_tail(&gc->list, &gc_list);
raw_spin_unlock(&gc_lock);
- /* Init mask cache ? */
- if (flags & IRQ_GC_INIT_MASK_CACHE)
- gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
-
- /* Initialize mask cache pointer */
- for (i = 0; i < gc->num_ct; i++)
- ct[i].mask_cache = &gc->mask_cache;
+ for (i = 0; i < gc->num_ct; i++) {
+ if (flags & IRQ_GC_MASK_CACHE_PER_TYPE) {
+ mskptr = &ct[i].mask_cache_priv;
+ mskreg = ct[i].regs.mask;
+ }
+ ct[i].mask_cache = mskptr;
+ if (flags & IRQ_GC_INIT_MASK_CACHE)
+ *mskptr = irq_reg_readl(gc->reg_base + mskreg);
+ }
for (i = gc->irq_base; msk; msk >>= 1, i++) {
if (!(msk & 0x01))
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 4/8] genirq: generic chip: Cache per irq bit mask
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
` (2 preceding siblings ...)
2013-05-03 21:50 ` [RFC patch 3/8] genirq: generic chip: Handle separate mask registers Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
2013-05-03 22:24 ` Russell King - ARM Linux
2013-05-03 21:50 ` [RFC patch 5/8] genirq: Add a mask calculation function Thomas Gleixner
` (5 subsequent siblings)
9 siblings, 1 reply; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, Russell King - ARM Linux, Jason Cooper,
Jean-Francois Moine, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Jason Gunthorpe,
Gerlando Falauto, Grant Likely,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Sebastian Hesselbarth
[-- Attachment #1: genirq-generic-chip-cache-mask.patch --]
[-- Type: text/plain, Size: 4882 bytes --]
Cache the per irq bit mask instead of recalculating it over and over.
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
include/linux/irq.h | 4 ++++
kernel/irq/generic-chip.c | 23 ++++++++++++++---------
2 files changed, 18 insertions(+), 9 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -119,6 +119,7 @@ struct irq_domain;
/**
* struct irq_data - per irq and irq chip data passed down to chip functions
+ * @mask: precomputed bitmask for accessing the chip registers
* @irq: interrupt number
* @hwirq: hardware interrupt number, local to the interrupt domain
* @node: node index useful for balancing
@@ -138,6 +139,7 @@ struct irq_domain;
* irq_data.
*/
struct irq_data {
+ u32 mask;
unsigned int irq;
unsigned long hwirq;
unsigned int node;
@@ -705,11 +707,13 @@ struct irq_chip_generic {
* irq chips which need to call irq_set_wake() on
* the parent irq. Usually GPIO implementations
* @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private
+ * @IRQ_GC_NO_MASK: Do not calculate irq_data->mask
*/
enum irq_gc_flags {
IRQ_GC_INIT_MASK_CACHE = 1 << 0,
IRQ_GC_INIT_NESTED_LOCK = 1 << 1,
IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2,
+ IRQ_GC_NO_MASK = 1 << 3,
};
/* Generic chip callback functions */
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -35,7 +35,7 @@ void irq_gc_mask_disable_reg(struct irq_
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.disable);
@@ -54,7 +54,7 @@ void irq_gc_mask_set_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
*ct->mask_cache |= mask;
@@ -73,7 +73,7 @@ void irq_gc_mask_clr_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
*ct->mask_cache &= ~mask;
@@ -92,7 +92,7 @@ void irq_gc_unmask_enable_reg(struct irq
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.enable);
@@ -108,7 +108,7 @@ void irq_gc_ack_set_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
@@ -123,7 +123,7 @@ void irq_gc_ack_clr_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = ~(1 << (d->irq - gc->irq_base));
+ u32 mask = ~(d->mask);
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
@@ -138,7 +138,7 @@ void irq_gc_mask_disable_reg_and_ack(str
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.mask);
@@ -154,7 +154,7 @@ void irq_gc_eoi(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.eoi);
@@ -172,7 +172,7 @@ void irq_gc_eoi(struct irq_data *d)
int irq_gc_set_wake(struct irq_data *d, unsigned int on)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
if (!(mask & gc->wake_enabled))
return -EINVAL;
@@ -264,6 +264,11 @@ void irq_setup_generic_chip(struct irq_c
if (flags & IRQ_GC_INIT_NESTED_LOCK)
irq_set_lockdep_class(i, &irq_nested_lock_class);
+ if (!(flags & IRQ_GC_NO_MASK)) {
+ struct irq_data *d = irq_get_irq_data(i);
+
+ d->mask = 1 << (i - gc->irq_base);
+ }
irq_set_chip_and_handler(i, &ct->chip, ct->handler);
irq_set_chip_data(i, gc);
irq_modify_status(i, clr, set);
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 4/8] genirq: generic chip: Cache per irq bit mask
2013-05-03 21:50 ` [RFC patch 4/8] genirq: generic chip: Cache per irq bit mask Thomas Gleixner
@ 2013-05-03 22:24 ` Russell King - ARM Linux
2013-05-03 22:39 ` Thomas Gleixner
0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2013-05-03 22:24 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Sebastian Hesselbarth, Grant Likely, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On Fri, May 03, 2013 at 09:50:50PM -0000, Thomas Gleixner wrote:
> - u32 mask = ~(1 << (d->irq - gc->irq_base));
> + u32 mask = ~(d->mask);
I suspect the above changes are all a result of a search-and-replace
which results in the cosmetic parens remaining. Would be nice to get
rid of them too as they're completely unnecessary.
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 4/8] genirq: generic chip: Cache per irq bit mask
2013-05-03 22:24 ` Russell King - ARM Linux
@ 2013-05-03 22:39 ` Thomas Gleixner
0 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 22:39 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: LKML, Sebastian Hesselbarth, Grant Likely, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On Fri, 3 May 2013, Russell King - ARM Linux wrote:
> On Fri, May 03, 2013 at 09:50:50PM -0000, Thomas Gleixner wrote:
> > - u32 mask = ~(1 << (d->irq - gc->irq_base));
> > + u32 mask = ~(d->mask);
>
> I suspect the above changes are all a result of a search-and-replace
> which results in the cosmetic parens remaining. Would be nice to get
> rid of them too as they're completely unnecessary.
Fair enough.
Thanks,
tglx
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 5/8] genirq: Add a mask calculation function
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
` (3 preceding siblings ...)
2013-05-03 21:50 ` [RFC patch 4/8] genirq: generic chip: Cache per irq bit mask Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
2013-05-03 21:50 ` [RFC patch 6/8] genirq: Split out code in generic chip Thomas Gleixner
` (4 subsequent siblings)
9 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, Russell King - ARM Linux, Jason Cooper,
Jean-Francois Moine, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Jason Gunthorpe,
Gerlando Falauto, Grant Likely,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Sebastian Hesselbarth
[-- Attachment #1: genirq-generic-chip-add-mask-calculation-function.patch --]
[-- Type: text/plain, Size: 2202 bytes --]
Some chips have weird bit mask access patterns instead of the linear
you expect. Allow them to calculate the cached mask themself.
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
include/linux/irq.h | 3 +++
kernel/irq/generic-chip.c | 8 ++++++--
2 files changed, 9 insertions(+), 2 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -296,6 +296,7 @@ static inline irq_hw_number_t irqd_to_hw
* @irq_suspend: function called from core code on suspend once per chip
* @irq_resume: function called from core code on resume once per chip
* @irq_pm_shutdown: function called from core code on shutdown once per chip
+ * @irq_calc_mask: Optional function to set irq_data.mask for special cases
* @irq_print_chip: optional to print special chip info in show_interrupts
* @flags: chip specific flags
*/
@@ -327,6 +328,8 @@ struct irq_chip {
void (*irq_resume)(struct irq_data *data);
void (*irq_pm_shutdown)(struct irq_data *data);
+ void (*irq_calc_mask)(struct irq_data *data);
+
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
unsigned long flags;
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -240,6 +240,7 @@ void irq_setup_generic_chip(struct irq_c
unsigned int set)
{
struct irq_chip_type *ct = gc->chip_types;
+ struct irq_chip *chip = &ct->chip;
unsigned int i;
u32 *mskptr = &gc->mask_cache, mskreg = ct->regs.mask;
@@ -267,9 +268,12 @@ void irq_setup_generic_chip(struct irq_c
if (!(flags & IRQ_GC_NO_MASK)) {
struct irq_data *d = irq_get_irq_data(i);
- d->mask = 1 << (i - gc->irq_base);
+ if (chip->irq_calc_mask)
+ chip->irq_calc_mask(d);
+ else
+ d->mask = 1 << (i - gc->irq_base);
}
- irq_set_chip_and_handler(i, &ct->chip, ct->handler);
+ irq_set_chip_and_handler(i, chip, ct->handler);
irq_set_chip_data(i, gc);
irq_modify_status(i, clr, set);
}
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 6/8] genirq: Split out code in generic chip
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
` (4 preceding siblings ...)
2013-05-03 21:50 ` [RFC patch 5/8] genirq: Add a mask calculation function Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
2013-05-27 13:45 ` Grant Likely
2013-05-03 21:50 ` [RFC patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
` (3 subsequent siblings)
9 siblings, 1 reply; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: genirq-generic-chip-split-out-code.patch --]
[-- Type: text/plain, Size: 1375 bytes --]
Preparatory patch for linear interrupt domains.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/generic-chip.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -186,6 +186,19 @@ int irq_gc_set_wake(struct irq_data *d,
return 0;
}
+static void
+irq_init_generic_chip(struct irq_chip_generic *gc, const char *name,
+ int num_ct, unsigned int irq_base,
+ void __iomem *reg_base, irq_flow_handler_t handler)
+{
+ raw_spin_lock_init(&gc->lock);
+ gc->num_ct = num_ct;
+ gc->irq_base = irq_base;
+ gc->reg_base = reg_base;
+ gc->chip_types->chip.name = name;
+ gc->chip_types->handler = handler;
+}
+
/**
* irq_alloc_generic_chip - Allocate a generic chip and initialize it
* @name: Name of the irq chip
@@ -206,12 +219,8 @@ irq_alloc_generic_chip(const char *name,
gc = kzalloc(sz, GFP_KERNEL);
if (gc) {
- raw_spin_lock_init(&gc->lock);
- gc->num_ct = num_ct;
- gc->irq_base = irq_base;
- gc->reg_base = reg_base;
- gc->chip_types->chip.name = name;
- gc->chip_types->handler = handler;
+ irq_init_generic_chip(gc, name, num_ct, irq_base, reg_base,
+ handler);
}
return gc;
}
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 6/8] genirq: Split out code in generic chip
2013-05-03 21:50 ` [RFC patch 6/8] genirq: Split out code in generic chip Thomas Gleixner
@ 2013-05-27 13:45 ` Grant Likely
0 siblings, 0 replies; 74+ messages in thread
From: Grant Likely @ 2013-05-27 13:45 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Sebastian Hesselbarth, Russell King - ARM Linux,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
On Fri, May 3, 2013 at 10:50 PM, Thomas Gleixner <tglx@linutronix.de> wrote:
> Preparatory patch for linear interrupt domains.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
The first 6 are pretty straight forward. On patches 1-6:
Acked-by: Grant Likely <grant.likely@linaro.org>
I'm reading through 7 & 8 now.
g.
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
` (5 preceding siblings ...)
2013-05-03 21:50 ` [RFC patch 6/8] genirq: Split out code in generic chip Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
2013-05-03 22:23 ` Russell King - ARM Linux
` (2 more replies)
2013-05-03 21:50 ` [RFC patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
` (2 subsequent siblings)
9 siblings, 3 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: genirq-add-linear-domain-support.patch --]
[-- Type: text/plain, Size: 11263 bytes --]
Provide infrastructure for irq chip implementations which work on
linear irq domains.
- Interface to allocate multiple generic chips which are associated to
the irq domain.
- Interface to get the generic chip pointer for a particular hardware
interrupt in the domain.
- irq domain mapping function to install the chip for a particular
interrupt.
Note: This lacks a removal function for now, but this is a draft patch
the ARM folks to work on.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/irq.h | 30 +++++++
include/linux/irqdomain.h | 12 +++
kernel/irq/generic-chip.c | 179 ++++++++++++++++++++++++++++++++++++++++++++--
kernel/irq/irqdomain.c | 6 -
4 files changed, 215 insertions(+), 12 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -678,6 +678,8 @@ struct irq_chip_type {
* @wake_active: Interrupt is marked as an wakeup from suspend source
* @num_ct: Number of available irq_chip_type instances (usually 1)
* @private: Private data for non generic chip callbacks
+ * @installed: bitfield to denote installed interrupts
+ * @domain: irq domain pointer
* @list: List head for keeping track of instances
* @chip_types: Array of interrupt irq_chip_types
*
@@ -699,6 +701,8 @@ struct irq_chip_generic {
u32 wake_active;
unsigned int num_ct;
void *private;
+ unsigned long installed;
+ struct irq_domain *domain;
struct list_head list;
struct irq_chip_type chip_types[0];
};
@@ -719,6 +723,24 @@ enum irq_gc_flags {
IRQ_GC_NO_MASK = 1 << 3,
};
+/*
+ * struct irq_domain_chip_generic - Generic irq chip data structure for irq domains
+ * @irqs_per_chip: Number of interrupts per chip
+ * @num_chips: Number of chips
+ * @irq_flags_to_set: IRQ* flags to set on irq setup
+ * @irq_flags_to_clear: IRQ* flags to clear on irq setup
+ * @gc_flags: Generic chip specific setup flags
+ * @gc: Array of generic interrupt chips
+ */
+struct irq_domain_chip_generic {
+ unsigned int irqs_per_chip;
+ unsigned int num_chips;
+ unsigned int irq_flags_to_clear;
+ unsigned int irq_flags_to_set;
+ enum irq_gc_flags gc_flags;
+ struct irq_chip_generic gc[0];
+};
+
/* Generic chip callback functions */
void irq_gc_noop(struct irq_data *d);
void irq_gc_mask_disable_reg(struct irq_data *d);
@@ -742,6 +764,14 @@ int irq_setup_alt_chip(struct irq_data *
void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
unsigned int clr, unsigned int set);
+struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq);
+int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
+ int num_ct, const char *name,
+ irq_flow_handler_t handler,
+ unsigned int clr, unsigned int set,
+ enum irq_gc_flags flags);
+
+
static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
{
return container_of(d->chip, struct irq_chip_type, chip);
Index: linux-2.6/include/linux/irqdomain.h
===================================================================
--- linux-2.6.orig/include/linux/irqdomain.h
+++ linux-2.6/include/linux/irqdomain.h
@@ -66,6 +66,10 @@ struct irq_domain_ops {
unsigned long *out_hwirq, unsigned int *out_type);
};
+extern struct irq_domain_ops irq_generic_chip_ops;
+
+struct irq_domain_chip_generic;
+
/**
* struct irq_domain - Hardware interrupt number translation object
* @link: Element in global irq_domain list.
@@ -109,8 +113,16 @@ struct irq_domain {
/* Optional device node pointer */
struct device_node *of_node;
+ /* Optional pointer to generic interrupt chips */
+ struct irq_domain_chip_generic *gc;
};
+#define IRQ_DOMAIN_MAP_LEGACY 0 /* driver allocated fixed range of irqs.
+ * ie. legacy 8259, gets irqs 1..15 */
+#define IRQ_DOMAIN_MAP_NOMAP 1 /* no fast reverse mapping */
+#define IRQ_DOMAIN_MAP_LINEAR 2 /* linear map of interrupts */
+#define IRQ_DOMAIN_MAP_TREE 3 /* radix tree */
+
#ifdef CONFIG_IRQ_DOMAIN
struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
unsigned int size,
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -7,6 +7,7 @@
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/syscore_ops.h>
@@ -226,6 +227,84 @@ irq_alloc_generic_chip(const char *name,
}
EXPORT_SYMBOL_GPL(irq_alloc_generic_chip);
+/**
+ * irq_alloc_domain_generic_chip - Allocate generic chips for an irq domain
+ * @d: irq domain for which to allocate chips
+ * @irqs_per_chip: Number of interrupts each chip handles
+ * @num_ct: Number of irq_chip_type instances associated with this
+ * @name: Name of the irq chip
+ * @handler: Default flow handler associated with these chips
+ * @clr: IRQ_* bits to clear in the mapping function
+ * @set: IRQ_* bits to set in the mapping function
+ */
+int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
+ int num_ct, const char *name,
+ irq_flow_handler_t handler,
+ unsigned int clr, unsigned int set,
+ enum irq_gc_flags gcflags)
+{
+ struct irq_domain_chip_generic *dgc;
+ struct irq_chip_generic *gc;
+ int numchips, sz, i;
+ unsigned long flags;
+
+ if (d->gc)
+ return -EBUSY;
+
+ if (d->revmap_type != IRQ_DOMAIN_MAP_LINEAR)
+ return -EINVAL;
+
+ numchips = d->revmap_data.linear.size / irqs_per_chip;
+ if (!numchips)
+ return -EINVAL;
+
+ sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
+ sz *= numchips;
+ sz += sizeof(*dgc);
+
+ dgc = kzalloc(sz, GFP_KERNEL);
+ if (!dgc)
+ return -ENOMEM;
+ dgc->irqs_per_chip = irqs_per_chip;
+ dgc->num_chips = numchips;
+ dgc->irq_flags_to_set = set;
+ dgc->irq_flags_to_clear = clr;
+ dgc->gc_flags = gcflags;
+ gc = dgc->gc;
+
+ for (i = 0; i < numchips; i++, gc++) {
+ irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip,
+ NULL, handler);
+ gc->domain = d;
+ raw_spin_lock_irqsave(&gc_lock, flags);
+ list_add_tail(&gc->list, &gc_list);
+ raw_spin_unlock_irqrestore(&gc_lock, flags);
+ }
+ d->gc = dgc;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(irq_alloc_domain_generic_chips);
+
+/**
+ * irq_get_domain_generic_chip - Get a pointer to the generic chip of a hw_irq
+ * @d: irq domain pointer
+ * @hw_irq: Hardware interrupt number
+ */
+struct irq_chip_generic *
+irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq)
+{
+ struct irq_domain_chip_generic *dgc = d->gc;
+ int idx;
+
+ if (!dgc)
+ return NULL;
+ idx = hw_irq / dgc->irqs_per_chip;
+ if (idx >= dgc->num_chips)
+ return NULL;
+ return &dgc->gc[idx];
+}
+EXPORT_SYMBOL_GPL(irq_get_domain_generic_chip);
+
/*
* Separate lockdep class for interrupt chip which can nest irq_desc
* lock.
@@ -233,6 +312,64 @@ EXPORT_SYMBOL_GPL(irq_alloc_generic_chip
static struct lock_class_key irq_nested_lock_class;
/**
+ * irq_map_generic_chip - Map a generic chip for an irq domain
+ */
+static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw_irq)
+{
+ struct irq_data *data = irq_get_irq_data(virq);
+ struct irq_domain_chip_generic *dgc = d->gc;
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+ struct irq_chip *chip;
+ unsigned long flags;
+ int idx;
+
+ if (!d->gc)
+ return -ENODEV;
+
+ idx = hw_irq / dgc->irqs_per_chip;
+ if (idx >= dgc->num_chips)
+ return -EINVAL;
+ gc = &dgc->gc[idx];
+
+ idx = hw_irq % dgc->irqs_per_chip;
+
+ if (test_bit(idx, &gc->installed))
+ return -EBUSY;
+
+ set_bit(idx, &gc->installed);
+ ct = gc->chip_types;
+ chip = &ct->chip;
+
+ /* Init mask cache ? */
+ if (dgc->gc_flags & IRQ_GC_INIT_MASK_CACHE) {
+ raw_spin_lock_irqsave(&gc->lock, flags);
+ gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
+ raw_spin_unlock_irqrestore(&gc->lock, flags);
+ }
+
+ if (dgc->gc_flags & IRQ_GC_INIT_NESTED_LOCK)
+ irq_set_lockdep_class(virq, &irq_nested_lock_class);
+
+ if (chip->irq_calc_mask)
+ chip->irq_calc_mask(data);
+ else
+ data->mask = 1 << idx;
+
+ irq_set_chip_and_handler(virq, chip, ct->handler);
+ irq_set_chip_data(virq, gc);
+ irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set);
+ return 0;
+}
+
+struct irq_domain_ops irq_generic_chip_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = irq_domain_xlate_onecell,
+};
+EXPORT_SYMBOL_GPL(irq_generic_chip_ops);
+
+/**
* irq_setup_generic_chip - Setup a range of interrupts with a generic chip
* @gc: Generic irq chip holding all data
* @msk: Bitmask holding the irqs to initialize relative to gc->irq_base
@@ -345,6 +482,24 @@ void irq_remove_generic_chip(struct irq_
}
EXPORT_SYMBOL_GPL(irq_remove_generic_chip);
+static struct irq_data *irq_gc_get_irq_data(struct irq_chip_generic *gc)
+{
+ unsigned int virq;
+
+ if (!gc->domain)
+ return irq_get_irq_data(gc->irq_base);
+
+ /*
+ * We don't know which of the irqs has been actually
+ * installed. Use the first one.
+ */
+ if (!gc->installed)
+ return NULL;
+
+ virq = irq_find_mapping(gc->domain, gc->irq_base + __ffs(gc->installed));
+ return virq ? irq_get_irq_data(virq) : NULL;
+}
+
#ifdef CONFIG_PM
static int irq_gc_suspend(void)
{
@@ -353,8 +508,12 @@ static int irq_gc_suspend(void)
list_for_each_entry(gc, &gc_list, list) {
struct irq_chip_type *ct = gc->chip_types;
- if (ct->chip.irq_suspend)
- ct->chip.irq_suspend(irq_get_irq_data(gc->irq_base));
+ if (ct->chip.irq_suspend) {
+ struct irq_data *data = irq_gc_get_irq_data(gc);
+
+ if (data)
+ ct->chip.irq_suspend(data);
+ }
}
return 0;
}
@@ -366,8 +525,12 @@ static void irq_gc_resume(void)
list_for_each_entry(gc, &gc_list, list) {
struct irq_chip_type *ct = gc->chip_types;
- if (ct->chip.irq_resume)
- ct->chip.irq_resume(irq_get_irq_data(gc->irq_base));
+ if (ct->chip.irq_resume) {
+ struct irq_data *data = irq_gc_get_irq_data(gc);
+
+ if (data)
+ ct->chip.irq_resume(data);
+ }
}
}
#else
@@ -382,8 +545,12 @@ static void irq_gc_shutdown(void)
list_for_each_entry(gc, &gc_list, list) {
struct irq_chip_type *ct = gc->chip_types;
- if (ct->chip.irq_pm_shutdown)
- ct->chip.irq_pm_shutdown(irq_get_irq_data(gc->irq_base));
+ if (ct->chip.irq_pm_shutdown) {
+ struct irq_data *data = irq_gc_get_irq_data(gc);
+
+ if (data)
+ ct->chip.irq_pm_shutdown(data);
+ }
}
}
Index: linux-2.6/kernel/irq/irqdomain.c
===================================================================
--- linux-2.6.orig/kernel/irq/irqdomain.c
+++ linux-2.6/kernel/irq/irqdomain.c
@@ -16,12 +16,6 @@
#include <linux/smp.h>
#include <linux/fs.h>
-#define IRQ_DOMAIN_MAP_LEGACY 0 /* driver allocated fixed range of irqs.
- * ie. legacy 8259, gets irqs 1..15 */
-#define IRQ_DOMAIN_MAP_NOMAP 1 /* no fast reverse mapping */
-#define IRQ_DOMAIN_MAP_LINEAR 2 /* linear map of interrupts */
-#define IRQ_DOMAIN_MAP_TREE 3 /* radix tree */
-
static LIST_HEAD(irq_domain_list);
static DEFINE_MUTEX(irq_domain_mutex);
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-03 21:50 ` [RFC patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
@ 2013-05-03 22:23 ` Russell King - ARM Linux
2013-05-03 22:38 ` Thomas Gleixner
2013-05-04 2:30 ` Sebastian Hesselbarth
2013-05-06 12:32 ` [RFC patch 7/8] fixup 1/2: " Sebastian Hesselbarth
2 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2013-05-03 22:23 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Sebastian Hesselbarth, Grant Likely, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On Fri, May 03, 2013 at 09:50:53PM -0000, Thomas Gleixner wrote:
> + /* Init mask cache ? */
> + if (dgc->gc_flags & IRQ_GC_INIT_MASK_CACHE) {
> + raw_spin_lock_irqsave(&gc->lock, flags);
> + gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
> + raw_spin_unlock_irqrestore(&gc->lock, flags);
> + }
This looks a little weird to me - it seems that it'll re-read this
each time any irq is mapped in the domain, which is probably not
wanted.
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-03 22:23 ` Russell King - ARM Linux
@ 2013-05-03 22:38 ` Thomas Gleixner
0 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 22:38 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: LKML, Sebastian Hesselbarth, Grant Likely, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On Fri, 3 May 2013, Russell King - ARM Linux wrote:
> On Fri, May 03, 2013 at 09:50:53PM -0000, Thomas Gleixner wrote:
> > + /* Init mask cache ? */
> > + if (dgc->gc_flags & IRQ_GC_INIT_MASK_CACHE) {
> > + raw_spin_lock_irqsave(&gc->lock, flags);
> > + gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
> > + raw_spin_unlock_irqrestore(&gc->lock, flags);
> > + }
>
> This looks a little weird to me - it seems that it'll re-read this
> each time any irq is mapped in the domain, which is probably not
> wanted.
Yes, it's sloppy in two aspects.
1) It does not respect the per irq type mask cache, which got
introduced in the same series
2) It rereads the mask cache for each mapping, but thats harmless
because it's proper serialized. We can avoid that by clearing the
IRQ_GC_INIT_MASK_CACHE bit when the first irq of that chip is
mapped.
Congrats, you found a bug and as I said:
WARNING: It's compile tested only. So if you find bugs you can keep
them and fix them yourself :)
Thanks,
tglx
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-03 21:50 ` [RFC patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
2013-05-03 22:23 ` Russell King - ARM Linux
@ 2013-05-04 2:30 ` Sebastian Hesselbarth
2013-05-04 8:04 ` Thomas Gleixner
2013-05-06 12:32 ` [RFC patch 7/8] fixup 1/2: " Sebastian Hesselbarth
2 siblings, 1 reply; 74+ messages in thread
From: Sebastian Hesselbarth @ 2013-05-04 2:30 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Russell King - ARM Linux, Grant Likely, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On 05/03/2013 11:50 PM, Thomas Gleixner wrote:
> Provide infrastructure for irq chip implementations which work on
> linear irq domains.
Thomas,
I am happy that I put you into rant mode. It took me little more
than an hour to read through your patches, prepare orion irqchip
driver on top of them and finally got it working.
Anyway, I found some more issues.
> Index: linux-2.6/kernel/irq/generic-chip.c
> ===================================================================
> --- linux-2.6.orig/kernel/irq/generic-chip.c
> +++ linux-2.6/kernel/irq/generic-chip.c
> @@ -7,6 +7,7 @@
[...]
> +int irq_alloc_domain_generic_chips(struct irq_domain *d, int
irqs_per_chip,
> + int num_ct, const char *name,
> + irq_flow_handler_t handler,
> + unsigned int clr, unsigned int set,
> + enum irq_gc_flags gcflags)
> +{
> + struct irq_domain_chip_generic *dgc;
> + struct irq_chip_generic *gc;
> + int numchips, sz, i;
> + unsigned long flags;
> +
> + if (d->gc)
> + return -EBUSY;
> +
> + if (d->revmap_type != IRQ_DOMAIN_MAP_LINEAR)
> + return -EINVAL;
> +
> + numchips = d->revmap_data.linear.size / irqs_per_chip;
> + if (!numchips)
> + return -EINVAL;
> +
> + sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
> + sz *= numchips;
> + sz += sizeof(*dgc);
> +
> + dgc = kzalloc(sz, GFP_KERNEL);
> + if (!dgc)
> + return -ENOMEM;
> + dgc->irqs_per_chip = irqs_per_chip;
> + dgc->num_chips = numchips;
> + dgc->irq_flags_to_set = set;
> + dgc->irq_flags_to_clear = clr;
> + dgc->gc_flags = gcflags;
> + gc = dgc->gc;
> +
> + for (i = 0; i < numchips; i++, gc++) {
The memory you allocated for gc, num_ct * ct, and dgc doesn't allow
to increment through gc. gc is struct irq_chip_generic * but next
gc is at sizeof(*gc) + num_ct * sizeof(struct irq_chip_type).
This also affects indexing dgc->gc later.
I chose to fix it by having an index helper but that first maps
dgc-gc to unsigned char * and then adds the correct offset. Not
nice but it works. Maybe having real array of ptr to gc is more
intuitive here even if we will have to have split kzallocs.
> + irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip,
> + NULL, handler);
irq_init_generic_chip does not take care of initalizing ct
mask_cache ptr. This should be done here.
> + gc->domain = d;
> + raw_spin_lock_irqsave(&gc_lock, flags);
> + list_add_tail(&gc->list, &gc_list);
> + raw_spin_unlock_irqrestore(&gc_lock, flags);
> + }
> + d->gc = dgc;
Moving this assignment above the for loop allows to get
gc by index as indexing helper relies on domain, not domain
generic chip.
You want me to prepare patches for the above? Maybe you can
split your RFC into 1-6 and 7-8. Then you can have 1-6 applied
independently of irq_domain_generic_chip stuff.
Thanks for the RFC again!
Sebastian
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-04 2:30 ` Sebastian Hesselbarth
@ 2013-05-04 8:04 ` Thomas Gleixner
0 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-04 8:04 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: LKML, Russell King - ARM Linux, Grant Likely, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On Sat, 4 May 2013, Sebastian Hesselbarth wrote:
> On 05/03/2013 11:50 PM, Thomas Gleixner wrote:
> > Provide infrastructure for irq chip implementations which work on
> > linear irq domains.
>
> Thomas,
>
> I am happy that I put you into rant mode. It took me little more
> than an hour to read through your patches, prepare orion irqchip
> driver on top of them and finally got it working.
Cool.
> Anyway, I found some more issues.
That was expected. :)
> > + for (i = 0; i < numchips; i++, gc++) {
>
> The memory you allocated for gc, num_ct * ct, and dgc doesn't allow
> to increment through gc. gc is struct irq_chip_generic * but next
> gc is at sizeof(*gc) + num_ct * sizeof(struct irq_chip_type).
> This also affects indexing dgc->gc later.
Indeed.
> I chose to fix it by having an index helper but that first maps
> dgc-gc to unsigned char * and then adds the correct offset. Not
void * is the preferred over uchar *
> nice but it works. Maybe having real array of ptr to gc is more
> intuitive here even if we will have to have split kzallocs.
No, you still can have a single kzalloc. It's just a matter of setting
the pointers correctly.
> > + irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip,
> > + NULL, handler);
>
> irq_init_generic_chip does not take care of initalizing ct
> mask_cache ptr. This should be done here.
Right.
> > + gc->domain = d;
> > + raw_spin_lock_irqsave(&gc_lock, flags);
> > + list_add_tail(&gc->list, &gc_list);
> > + raw_spin_unlock_irqrestore(&gc_lock, flags);
> > + }
> > + d->gc = dgc;
>
> Moving this assignment above the for loop allows to get
> gc by index as indexing helper relies on domain, not domain
> generic chip.
>
> You want me to prepare patches for the above? Maybe you can
That'd be nice.
> split your RFC into 1-6 and 7-8. Then you can have 1-6 applied
> independently of irq_domain_generic_chip stuff.
> Thanks for the RFC again!
Welcome. Have fun!
tglx
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 7/8] fixup 1/2: genirq: generic chip: Add linear irq domain support
2013-05-03 21:50 ` [RFC patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
2013-05-03 22:23 ` Russell King - ARM Linux
2013-05-04 2:30 ` Sebastian Hesselbarth
@ 2013-05-06 12:32 ` Sebastian Hesselbarth
2013-05-06 12:32 ` [RFC patch 7/8] fixup 2/2: " Sebastian Hesselbarth
2013-05-06 13:25 ` [RFC patch 7/8] fixup 1/2: " Thomas Gleixner
2 siblings, 2 replies; 74+ messages in thread
From: Sebastian Hesselbarth @ 2013-05-06 12:32 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Thomas Gleixner, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, Uwe Kleine-Koenig, devicetree-discuss,
linux-doc, linux-arm-kernel, linux-kernel
irq_domain_chip_generic is allocating and indexing irq_chip_generic
itself. However, the size of irq_chip_generic varies with number of
irq_chip_types. This fixup moves irq_chip_generic helt by
irq_domain_chip_generic to array of ptr and fixes the pointer arith
used by irq_alloc_domain_generic_chip.
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Jean-Francois Moine <moinejf@free.fr>
Cc: Gerlando Falauto <gerlando.falauto@keymile.com>
Cc: Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
include/linux/irq.h | 4 ++--
kernel/irq/generic-chip.c | 20 +++++++++++++-------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 7315155..fd2d7cb 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -730,7 +730,7 @@ enum irq_gc_flags {
* @irq_flags_to_set: IRQ* flags to set on irq setup
* @irq_flags_to_clear: IRQ* flags to clear on irq setup
* @gc_flags: Generic chip specific setup flags
- * @gc: Array of generic interrupt chips
+ * @gc: Array of pointer to generic interrupt chips
*/
struct irq_domain_chip_generic {
unsigned int irqs_per_chip;
@@ -738,7 +738,7 @@ struct irq_domain_chip_generic {
unsigned int irq_flags_to_clear;
unsigned int irq_flags_to_set;
enum irq_gc_flags gc_flags;
- struct irq_chip_generic gc[0];
+ struct irq_chip_generic *gc[0];
};
/* Generic chip callback functions */
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
index e212b26..3dbfe2e 100644
--- a/kernel/irq/generic-chip.c
+++ b/kernel/irq/generic-chip.c
@@ -247,6 +247,7 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
struct irq_chip_generic *gc;
int numchips, sz, i;
unsigned long flags;
+ void *p;
if (d->gc)
return -EBUSY;
@@ -260,9 +261,9 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
sz *= numchips;
- sz += sizeof(*dgc);
+ sz += sizeof(*dgc) + numchips * sizeof(void *);
- dgc = kzalloc(sz, GFP_KERNEL);
+ p = dgc = kzalloc(sz, GFP_KERNEL);
if (!dgc)
return -ENOMEM;
dgc->irqs_per_chip = irqs_per_chip;
@@ -270,17 +271,22 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
dgc->irq_flags_to_set = set;
dgc->irq_flags_to_clear = clr;
dgc->gc_flags = gcflags;
- gc = dgc->gc;
+ d->gc = dgc;
- for (i = 0; i < numchips; i++, gc++) {
+ p += sizeof(*dgc) + numchips * sizeof(void *);
+ for (i = 0; i < numchips; i++) {
+ gc = (struct irq_chip_generic *)p;
+ dgc->gc[i] = gc;
irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip,
NULL, handler);
gc->domain = d;
+
raw_spin_lock_irqsave(&gc_lock, flags);
list_add_tail(&gc->list, &gc_list);
raw_spin_unlock_irqrestore(&gc_lock, flags);
+
+ p += sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
}
- d->gc = dgc;
return 0;
}
EXPORT_SYMBOL_GPL(irq_alloc_domain_generic_chips);
@@ -301,7 +307,7 @@ irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq)
idx = hw_irq / dgc->irqs_per_chip;
if (idx >= dgc->num_chips)
return NULL;
- return &dgc->gc[idx];
+ return dgc->gc[idx];
}
EXPORT_SYMBOL_GPL(irq_get_domain_generic_chip);
@@ -331,7 +337,7 @@ static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
idx = hw_irq / dgc->irqs_per_chip;
if (idx >= dgc->num_chips)
return -EINVAL;
- gc = &dgc->gc[idx];
+ gc = dgc->gc[idx];
idx = hw_irq % dgc->irqs_per_chip;
--
1.7.2.5
^ permalink raw reply related [flat|nested] 74+ messages in thread
* [RFC patch 7/8] fixup 2/2: genirq: generic chip: Add linear irq domain support
2013-05-06 12:32 ` [RFC patch 7/8] fixup 1/2: " Sebastian Hesselbarth
@ 2013-05-06 12:32 ` Sebastian Hesselbarth
2013-05-06 13:31 ` Thomas Gleixner
2013-05-06 13:25 ` [RFC patch 7/8] fixup 1/2: " Thomas Gleixner
1 sibling, 1 reply; 74+ messages in thread
From: Sebastian Hesselbarth @ 2013-05-06 12:32 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Thomas Gleixner, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, Uwe Kleine-Koenig, devicetree-discuss,
linux-doc, linux-arm-kernel, linux-kernel
mask_cache pointer also needs to be initialized for domain generic
chips.
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Jean-Francois Moine <moinejf@free.fr>
Cc: Gerlando Falauto <gerlando.falauto@keymile.com>
Cc: Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
kernel/irq/generic-chip.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
index 3dbfe2e..3e0312f 100644
--- a/kernel/irq/generic-chip.c
+++ b/kernel/irq/generic-chip.c
@@ -275,12 +275,22 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
p += sizeof(*dgc) + numchips * sizeof(void *);
for (i = 0; i < numchips; i++) {
+ int k;
+
gc = (struct irq_chip_generic *)p;
dgc->gc[i] = gc;
irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip,
NULL, handler);
gc->domain = d;
+ for (k = 0; k < gc->num_ct; k++) {
+ struct irq_chip_type *ct = &gc->chip_types[k];
+ if (gcflags & IRQ_GC_MASK_CACHE_PER_TYPE)
+ ct->mask_cache = &ct->mask_cache_priv;
+ else
+ ct->mask_cache = &gc->mask_cache;
+ }
+
raw_spin_lock_irqsave(&gc_lock, flags);
list_add_tail(&gc->list, &gc_list);
raw_spin_unlock_irqrestore(&gc_lock, flags);
--
1.7.2.5
^ permalink raw reply related [flat|nested] 74+ messages in thread
* Re: [RFC patch 7/8] fixup 2/2: genirq: generic chip: Add linear irq domain support
2013-05-06 12:32 ` [RFC patch 7/8] fixup 2/2: " Sebastian Hesselbarth
@ 2013-05-06 13:31 ` Thomas Gleixner
0 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 13:31 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Russell King - ARM Linux, Grant Likely, Rob Herring, Rob Landley,
Arnd Bergmann, Jason Cooper, Andrew Lunn, Jason Gunthorpe,
Thomas Petazzoni, Gregory Clement, Ezequiel Garcia, Maxime Ripard,
Jean-Francois Moine, Gerlando Falauto, Uwe Kleine-Koenig,
devicetree-discuss, linux-doc, linux-arm-kernel, linux-kernel
On Mon, 6 May 2013, Sebastian Hesselbarth wrote:
> mask_cache pointer also needs to be initialized for domain generic
> chips.
It's not only the mask cache pointer. We also need to initialize the
mask cache itself. I solved it by spitting out that code from
irq_setup_generic_chip().
Thanks,
tglx
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 7/8] fixup 1/2: genirq: generic chip: Add linear irq domain support
2013-05-06 12:32 ` [RFC patch 7/8] fixup 1/2: " Sebastian Hesselbarth
2013-05-06 12:32 ` [RFC patch 7/8] fixup 2/2: " Sebastian Hesselbarth
@ 2013-05-06 13:25 ` Thomas Gleixner
1 sibling, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 13:25 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Russell King - ARM Linux, Grant Likely, Rob Herring, Rob Landley,
Arnd Bergmann, Jason Cooper, Andrew Lunn, Jason Gunthorpe,
Thomas Petazzoni, Gregory Clement, Ezequiel Garcia, Maxime Ripard,
Jean-Francois Moine, Gerlando Falauto, Uwe Kleine-Koenig,
devicetree-discuss, linux-doc, linux-arm-kernel, linux-kernel
On Mon, 6 May 2013, Sebastian Hesselbarth wrote:
> irq_domain_chip_generic is allocating and indexing irq_chip_generic
> itself. However, the size of irq_chip_generic varies with number of
> irq_chip_types. This fixup moves irq_chip_generic helt by
> irq_domain_chip_generic to array of ptr and fixes the pointer arith
> used by irq_alloc_domain_generic_chip.
Thanks. I folded it in.
^ permalink raw reply [flat|nested] 74+ messages in thread
* [RFC patch 8/8] irqchip: sun4i: Convert to generic irq chip
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
` (6 preceding siblings ...)
2013-05-03 21:50 ` [RFC patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
@ 2013-05-03 21:50 ` Thomas Gleixner
2013-05-04 2:37 ` Sebastian Hesselbarth
2013-05-06 9:48 ` [RFC patch 0/8] genirq: Support for irq domains in " Uwe Kleine-König
[not found] ` <20130503212258.385818955-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
9 siblings, 1 reply; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-03 21:50 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: irqchip-convert-sun4i.patch --]
[-- Type: text/plain, Size: 4825 bytes --]
Proof of concept patch to demonstrate the new irqdomain support for
the generic irq chip. Untested !!
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/irqchip/irq-sun4i.c | 100 ++++++++++++--------------------------------
1 file changed, 29 insertions(+), 71 deletions(-)
Index: linux-2.6/drivers/irqchip/irq-sun4i.c
===================================================================
--- linux-2.6.orig/drivers/irqchip/irq-sun4i.c
+++ linux-2.6/drivers/irqchip/irq-sun4i.c
@@ -32,70 +32,43 @@
#define SUN4I_IRQ_FIQ_PENDING_REG(x) (0x20 + 0x4 * x)
#define SUN4I_IRQ_ENABLE_REG(x) (0x40 + 0x4 * x)
#define SUN4I_IRQ_MASK_REG(x) (0x50 + 0x4 * x)
+#define SUN4I_NUM_CHIPS 3
+#define SUN4I_IRQS_PER_CHIP 32
static void __iomem *sun4i_irq_base;
static struct irq_domain *sun4i_irq_domain;
static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs);
-void sun4i_irq_ack(struct irq_data *irqd)
+static int __init sun4i_init_domain_chips(void)
{
- unsigned int irq = irqd_to_hwirq(irqd);
- unsigned int irq_off = irq % 32;
- int reg = irq / 32;
- u32 val;
-
- val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
- writel(val | (1 << irq_off),
- sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
-}
-
-static void sun4i_irq_mask(struct irq_data *irqd)
-{
- unsigned int irq = irqd_to_hwirq(irqd);
- unsigned int irq_off = irq % 32;
- int reg = irq / 32;
- u32 val;
-
- val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
- writel(val & ~(1 << irq_off),
- sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
-}
-
-static void sun4i_irq_unmask(struct irq_data *irqd)
-{
- unsigned int irq = irqd_to_hwirq(irqd);
- unsigned int irq_off = irq % 32;
- int reg = irq / 32;
- u32 val;
-
- val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
- writel(val | (1 << irq_off),
- sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
-}
-
-static struct irq_chip sun4i_irq_chip = {
- .name = "sun4i_irq",
- .irq_ack = sun4i_irq_ack,
- .irq_mask = sun4i_irq_mask,
- .irq_unmask = sun4i_irq_unmask,
-};
-
-static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw)
-{
- irq_set_chip_and_handler(virq, &sun4i_irq_chip,
- handle_level_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
+ unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+ struct irq_chip_generic *gc;
+ int i, ret, base = 0;
+
+ ret = irq_alloc_domain_generic_chips(d, SUN4I_IRQS_PER_CHIP, 1,
+ "sun4i_irq", handle_level_irq,
+ clr, 0, IRQ_GC_INIT_MASK_CACHE);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < SUN4I_NUM_CHIPS; i++, base += SUN4I_IRQS_PER_CHIP) {
+ gc = irq_get_domain_generic_chip(sun4i_irq_domain, base);
+ gc->reg_base = sun4i_irq_base;
+ gc->chip_types[0].regs.mask = SUN4I_IRQ_ENABLE_REG(i);
+ gc->chip_types[0].regs.ack = SUN4I_IRQ_PENDING_REG(i);
+ gc->chip_types[0].chip.mask = irq_gc_mask_clr_bit;
+ gc->chip_types[0].chip.ack = irq_gc_ack_set_bit;
+ gc->chip_types[0].chip.unmask = irq_gc_mask_set_bit;
+
+ /* Disable, mask and clear all pending interrupts */
+ writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(i));
+ writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(i));
+ writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(i));
+ }
return 0;
}
-static struct irq_domain_ops sun4i_irq_ops = {
- .map = sun4i_irq_map,
- .xlate = irq_domain_xlate_onecell,
-};
-
static int __init sun4i_of_init(struct device_node *node,
struct device_node *parent)
{
@@ -104,21 +77,6 @@ static int __init sun4i_of_init(struct d
panic("%s: unable to map IC registers\n",
node->full_name);
- /* Disable all interrupts */
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(0));
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
-
- /* Mask all the interrupts */
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
-
- /* Clear all the pending interrupts */
- writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
- writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(1));
- writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(2));
-
/* Enable protection mode */
writel(0x01, sun4i_irq_base + SUN4I_IRQ_PROTECTION_REG);
@@ -126,8 +84,8 @@ static int __init sun4i_of_init(struct d
writel(0x00, sun4i_irq_base + SUN4I_IRQ_NMI_CTRL_REG);
sun4i_irq_domain = irq_domain_add_linear(node, 3 * 32,
- &sun4i_irq_ops, NULL);
- if (!sun4i_irq_domain)
+ &irq_generic_chip_ops, NULL);
+ if (!sun4i_irq_domain || sun4i_init_domain_chips())
panic("%s: unable to create IRQ domain\n", node->full_name);
set_handle_irq(sun4i_handle_irq);
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 8/8] irqchip: sun4i: Convert to generic irq chip
2013-05-03 21:50 ` [RFC patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
@ 2013-05-04 2:37 ` Sebastian Hesselbarth
0 siblings, 0 replies; 74+ messages in thread
From: Sebastian Hesselbarth @ 2013-05-04 2:37 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Russell King - ARM Linux, Grant Likely, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On 05/03/2013 11:50 PM, Thomas Gleixner wrote:
> Proof of concept patch to demonstrate the new irqdomain support for
> the generic irq chip. Untested !!
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
...
> + gc->reg_base = sun4i_irq_base;
> + gc->chip_types[0].regs.mask = SUN4I_IRQ_ENABLE_REG(i);
> + gc->chip_types[0].regs.ack = SUN4I_IRQ_PENDING_REG(i);
> + gc->chip_types[0].chip.mask = irq_gc_mask_clr_bit;
> + gc->chip_types[0].chip.ack = irq_gc_ack_set_bit;
> + gc->chip_types[0].chip.unmask = irq_gc_mask_set_bit;
To help Maxime debug, the three callbacks must be prepended by irq_,
i.e. chip.irq_mask, ...
Sebastian
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [RFC patch 0/8] genirq: Support for irq domains in generic irq chip
2013-05-03 21:50 ` [RFC patch 0/8] genirq: Support for irq domains in generic irq chip Thomas Gleixner
` (7 preceding siblings ...)
2013-05-03 21:50 ` [RFC patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
@ 2013-05-06 9:48 ` Uwe Kleine-König
[not found] ` <20130503212258.385818955-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
9 siblings, 0 replies; 74+ messages in thread
From: Uwe Kleine-König @ 2013-05-06 9:48 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Thomas Petazzoni, Andrew Lunn, Russell King - ARM Linux,
Jason Cooper, Arnd Bergmann, Jean-Francois Moine,
devicetree-discuss, linux-doc, Rob Herring, Jason Gunthorpe,
Gregory Clement, Gerlando Falauto, Rob Landley, Grant Likely,
Maxime Ripard, Ezequiel Garcia, linux-arm-kernel,
Sebastian Hesselbarth
Hello,
On Fri, May 03, 2013 at 09:50:43PM -0000, Thomas Gleixner wrote:
> The ongoing device tree support for ARM is creating new irq chip
> drivers in drivers/irqchip/ in a frenzy. Quite some of them are
> ripping out the generic irq chip implementation from arch/arm/* and
> just creating the same mess of duplicated code again, which was
> cleaned up with the generic irq chip implementation with a lot of
> effort. Sigh!
>
> I already prodded a few people in reviews to tackle that issue with no
> outcome. Even more sigh!
>
> Poor Sebastian triggered me into rant mode, but he ad hoc
> volunteered to give it a try. YAY!
>
> Though he asked for a bit of kickstart help. So I squeezed out a few
> spare cycles and implemented the basics as far as I think that they
> should work.
>
> The following series contains the missing bits and pieces including a
> somehow forgotten and now slightly modified series from Gerlando
> adding support for irq chips which need separate mask caches for
> different chip (control flow) types.
>
> At the moment this supports only linear irq domains, but it could be
> extended to other types as well if the need arises. Though the ARM
> chips are pretty much all about linear domains AFAICT.
Is there a tree/set of patches that have already fixed the issues
pointed out by Russell and Sebastian? I'd like to use it to get forward
with my nvic patch and want to avert double work and merging different
approaches.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 74+ messages in thread
[parent not found: <20130503212258.385818955-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>]
* [patch 0/8] genirq: Support for irq domains in generic irq chip - V2
[not found] ` <20130503212258.385818955-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 14:30 ` [patch 1/8] genirq: generic chip: Remove the local cur_regs() function Thomas Gleixner
` (7 more replies)
0 siblings, 8 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, Russell King - ARM Linux, Jason Cooper,
Jean-Francois Moine, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Jason Gunthorpe,
Gerlando Falauto, Grant Likely,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Sebastian Hesselbarth
Changes vs. V1:
- Fixed the generic chip pointer thinko (Sebastian Hesselbarth)
- Proper support for mask cache
- Read mask hardware only for the first map of an generic chip
instance
- sun4i prefix irq functions proper
Thanks,
tglx
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 1/8] genirq: generic chip: Remove the local cur_regs() function
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 14:30 ` [patch 2/8] genirq: generic chip: Add support for per chip type mask cache Thomas Gleixner
` (6 subsequent siblings)
7 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, linux-doc-u79uwXL29TY76Z2rM5mHXA, Joey Oravec,
Lennert Buytenhek, Russell King - ARM Linux, Jason Gunthorpe,
Holger Brunck, Grant Likely, Sebastian Hesselbarth, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring, Ben Dooks,
Simon Guinot, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Jean-Francois Moine, Gerlando Falauto
[-- Attachment #1: genirq-cosmetic-remove-cur_regs.patch --]
[-- Type: text/plain, Size: 5284 bytes --]
From: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Since we already have an irq_data_get_chip_type() function which returns
a pointer to irq_chip_type, use that instead of cur_regs().
Signed-off-by: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: Lennert Buytenhek <kernel-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org>
Cc: Simon Guinot <simon-jKBdWWKqtFpg9hUCZPvPmw@public.gmane.org>
Cc: Joey Oravec <joravec-Vf0cVmJFnCtWk0Htik3J/w@public.gmane.org>
Cc: Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: Nicolas Pitre <nico-vtqb6HGKxmzR7s880joybQ@public.gmane.org>
Cc: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
Cc: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Cc: Holger Brunck <Holger.Brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
kernel/irq/generic-chip.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
Index: tip/kernel/irq/generic-chip.c
===================================================================
--- tip.orig/kernel/irq/generic-chip.c
+++ tip/kernel/irq/generic-chip.c
@@ -16,11 +16,6 @@
static LIST_HEAD(gc_list);
static DEFINE_RAW_SPINLOCK(gc_lock);
-static inline struct irq_chip_regs *cur_regs(struct irq_data *d)
-{
- return &container_of(d->chip, struct irq_chip_type, chip)->regs;
-}
-
/**
* irq_gc_noop - NOOP function
* @d: irq_data
@@ -39,10 +34,11 @@ void irq_gc_noop(struct irq_data *d)
void irq_gc_mask_disable_reg(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.disable);
gc->mask_cache &= ~mask;
irq_gc_unlock(gc);
}
@@ -57,11 +53,12 @@ void irq_gc_mask_disable_reg(struct irq_
void irq_gc_mask_set_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache |= mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -75,11 +72,12 @@ void irq_gc_mask_set_bit(struct irq_data
void irq_gc_mask_clr_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache &= ~mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -93,10 +91,11 @@ void irq_gc_mask_clr_bit(struct irq_data
void irq_gc_unmask_enable_reg(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.enable);
gc->mask_cache |= mask;
irq_gc_unlock(gc);
}
@@ -108,10 +107,11 @@ void irq_gc_unmask_enable_reg(struct irq
void irq_gc_ack_set_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
irq_gc_unlock(gc);
}
@@ -122,10 +122,11 @@ void irq_gc_ack_set_bit(struct irq_data
void irq_gc_ack_clr_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = ~(1 << (d->irq - gc->irq_base));
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
irq_gc_unlock(gc);
}
@@ -136,11 +137,12 @@ void irq_gc_ack_clr_bit(struct irq_data
void irq_gc_mask_disable_reg_and_ack(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.mask);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
irq_gc_unlock(gc);
}
@@ -151,10 +153,11 @@ void irq_gc_mask_disable_reg_and_ack(str
void irq_gc_eoi(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi);
+ irq_reg_writel(mask, gc->reg_base + ct->regs.eoi);
irq_gc_unlock(gc);
}
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 2/8] genirq: generic chip: Add support for per chip type mask cache
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
2013-05-06 14:30 ` [patch 1/8] genirq: generic chip: Remove the local cur_regs() function Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 14:30 ` [patch 3/8] genirq: generic chip: Handle separate mask registers Thomas Gleixner
` (5 subsequent siblings)
7 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, linux-doc-u79uwXL29TY76Z2rM5mHXA, Simon Guinot,
Lennert Buytenhek, Russell King - ARM Linux, Jason Gunthorpe,
Holger Brunck, Grant Likely, Sebastian Hesselbarth, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring, Ben Dooks,
Simon Guinot, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Jean-Francois Moine, Gerlando Falauto
[-- Attachment #1: genirq-add-mask_cache-and-pmask_cache-into-struct-irq_chip_type.patch --]
[-- Type: text/plain, Size: 4548 bytes --]
From: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Today the same interrupt mask cache (stored within struct irq_chip_generic)
is shared between all the irq_chip_type instances. As there are instances
where each irq_chip_type uses a distinct mask register (as it is the case
for Orion SoCs), sharing a single mask cache may be incorrect.
So add a distinct pointer for each irq_chip_type, which for now
points to the original mask register within irq_chip_generic.
So no functional changes here.
[ tglx: Minor cosmetic tweaks ]
Reported-by: Joey Oravec <joravec-Vf0cVmJFnCtWk0Htik3J/w@public.gmane.org>
Signed-off-by: Simon Guinot <sguinot-D+JDLXUtGQkAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Holger Brunck <holger.brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: Lennert Buytenhek <kernel-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org>
Cc: Simon Guinot <simon-jKBdWWKqtFpg9hUCZPvPmw@public.gmane.org>
Cc: Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: Nicolas Pitre <nico-vtqb6HGKxmzR7s880joybQ@public.gmane.org>
Cc: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
Cc: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Cc: Holger Brunck <Holger.Brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
include/linux/irq.h | 6 +++++-
kernel/irq/generic-chip.c | 16 ++++++++++------
2 files changed, 15 insertions(+), 7 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -644,6 +644,8 @@ struct irq_chip_regs {
* @regs: Register offsets for this chip
* @handler: Flow handler associated with this chip
* @type: Chip can handle these flow types
+ * @mask_cache_priv: Cached mask register private to the chip type
+ * @mask_cache: Pointer to cached mask register
*
* A irq_generic_chip can have several instances of irq_chip_type when
* it requires different functions and register offsets for different
@@ -654,6 +656,8 @@ struct irq_chip_type {
struct irq_chip_regs regs;
irq_flow_handler_t handler;
u32 type;
+ u32 mask_cache_priv;
+ u32 *mask_cache;
};
/**
@@ -662,7 +666,7 @@ struct irq_chip_type {
* @reg_base: Register base address (virtual)
* @irq_base: Interrupt base nr for this chip
* @irq_cnt: Number of interrupts handled by this chip
- * @mask_cache: Cached mask register
+ * @mask_cache: Cached mask register shared between all chip types
* @type_cache: Cached type register
* @polarity_cache: Cached polarity register
* @wake_enabled: Interrupt can wakeup from suspend
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -39,7 +39,7 @@ void irq_gc_mask_disable_reg(struct irq_
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.disable);
- gc->mask_cache &= ~mask;
+ *ct->mask_cache &= ~mask;
irq_gc_unlock(gc);
}
@@ -57,8 +57,8 @@ void irq_gc_mask_set_bit(struct irq_data
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache |= mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
+ *ct->mask_cache |= mask;
+ irq_reg_writel(*ct->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -76,8 +76,8 @@ void irq_gc_mask_clr_bit(struct irq_data
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache &= ~mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
+ *ct->mask_cache &= ~mask;
+ irq_reg_writel(*ct->mask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -96,7 +96,7 @@ void irq_gc_unmask_enable_reg(struct irq
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.enable);
- gc->mask_cache |= mask;
+ *ct->mask_cache |= mask;
irq_gc_unlock(gc);
}
@@ -250,6 +250,10 @@ void irq_setup_generic_chip(struct irq_c
if (flags & IRQ_GC_INIT_MASK_CACHE)
gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
+ /* Initialize mask cache pointer */
+ for (i = 0; i < gc->num_ct; i++)
+ ct[i].mask_cache = &gc->mask_cache;
+
for (i = gc->irq_base; msk; msk >>= 1, i++) {
if (!(msk & 0x01))
continue;
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 3/8] genirq: generic chip: Handle separate mask registers
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
2013-05-06 14:30 ` [patch 1/8] genirq: generic chip: Remove the local cur_regs() function Thomas Gleixner
2013-05-06 14:30 ` [patch 2/8] genirq: generic chip: Add support for per chip type mask cache Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 14:30 ` [patch 4/8] genirq: generic chip: Cache per irq bit mask Thomas Gleixner
` (4 subsequent siblings)
7 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Andrew Lunn, linux-doc-u79uwXL29TY76Z2rM5mHXA, Joey Oravec,
Lennert Buytenhek, Russell King - ARM Linux, Jason Gunthorpe,
Holger Brunck, Grant Likely, Sebastian Hesselbarth, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring, Ben Dooks,
Simon Guinot, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Jean-Francois Moine, Gerlando Falauto
[-- Attachment #1: genirq-handle-separate-mask-registers.patch --]
[-- Type: text/plain, Size: 3066 bytes --]
From: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
There are cases where all irq_chip_type instances have separate mask
registers, making a shared mask register cache unsuitable for the
purpose.
Introduce a new flag IRQ_GC_MASK_CACHE_PER_TYPE. If set, point the per
chip mask pointer to the per chip private mask cache instead.
[ tglx: Simplified code, renamed flag and massaged changelog ]
Signed-off-by: Gerlando Falauto <gerlando.falauto-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: Lennert Buytenhek <kernel-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org>
Cc: Simon Guinot <simon-jKBdWWKqtFpg9hUCZPvPmw@public.gmane.org>
Cc: Joey Oravec <joravec-Vf0cVmJFnCtWk0Htik3J/w@public.gmane.org>
Cc: Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: Nicolas Pitre <nico-vtqb6HGKxmzR7s880joybQ@public.gmane.org>
Cc: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
Cc: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Cc: Holger Brunck <Holger.Brunck-SkAbAL50j+5BDgjK7y7TUQ@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Signed-off-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
include/linux/irq.h | 2 ++
kernel/irq/generic-chip.c | 17 ++++++++++-------
2 files changed, 12 insertions(+), 7 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -704,10 +704,12 @@ struct irq_chip_generic {
* @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for
* irq chips which need to call irq_set_wake() on
* the parent irq. Usually GPIO implementations
+ * @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private
*/
enum irq_gc_flags {
IRQ_GC_INIT_MASK_CACHE = 1 << 0,
IRQ_GC_INIT_NESTED_LOCK = 1 << 1,
+ IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2,
};
/* Generic chip callback functions */
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -241,18 +241,21 @@ void irq_setup_generic_chip(struct irq_c
{
struct irq_chip_type *ct = gc->chip_types;
unsigned int i;
+ u32 *mskptr = &gc->mask_cache, mskreg = ct->regs.mask;
raw_spin_lock(&gc_lock);
list_add_tail(&gc->list, &gc_list);
raw_spin_unlock(&gc_lock);
- /* Init mask cache ? */
- if (flags & IRQ_GC_INIT_MASK_CACHE)
- gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
-
- /* Initialize mask cache pointer */
- for (i = 0; i < gc->num_ct; i++)
- ct[i].mask_cache = &gc->mask_cache;
+ for (i = 0; i < gc->num_ct; i++) {
+ if (flags & IRQ_GC_MASK_CACHE_PER_TYPE) {
+ mskptr = &ct[i].mask_cache_priv;
+ mskreg = ct[i].regs.mask;
+ }
+ ct[i].mask_cache = mskptr;
+ if (flags & IRQ_GC_INIT_MASK_CACHE)
+ *mskptr = irq_reg_readl(gc->reg_base + mskreg);
+ }
for (i = gc->irq_base; msk; msk >>= 1, i++) {
if (!(msk & 0x01))
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 4/8] genirq: generic chip: Cache per irq bit mask
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
` (2 preceding siblings ...)
2013-05-06 14:30 ` [patch 3/8] genirq: generic chip: Handle separate mask registers Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 14:30 ` [patch 5/8] genirq: Add a mask calculation function Thomas Gleixner
` (3 subsequent siblings)
7 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: genirq-generic-chip-cache-mask.patch --]
[-- Type: text/plain, Size: 4854 bytes --]
Cache the per irq bit mask instead of recalculating it over and over.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/irq.h | 4 ++++
kernel/irq/generic-chip.c | 23 ++++++++++++++---------
2 files changed, 18 insertions(+), 9 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -119,6 +119,7 @@ struct irq_domain;
/**
* struct irq_data - per irq and irq chip data passed down to chip functions
+ * @mask: precomputed bitmask for accessing the chip registers
* @irq: interrupt number
* @hwirq: hardware interrupt number, local to the interrupt domain
* @node: node index useful for balancing
@@ -138,6 +139,7 @@ struct irq_domain;
* irq_data.
*/
struct irq_data {
+ u32 mask;
unsigned int irq;
unsigned long hwirq;
unsigned int node;
@@ -705,11 +707,13 @@ struct irq_chip_generic {
* irq chips which need to call irq_set_wake() on
* the parent irq. Usually GPIO implementations
* @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private
+ * @IRQ_GC_NO_MASK: Do not calculate irq_data->mask
*/
enum irq_gc_flags {
IRQ_GC_INIT_MASK_CACHE = 1 << 0,
IRQ_GC_INIT_NESTED_LOCK = 1 << 1,
IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2,
+ IRQ_GC_NO_MASK = 1 << 3,
};
/* Generic chip callback functions */
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -35,7 +35,7 @@ void irq_gc_mask_disable_reg(struct irq_
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.disable);
@@ -54,7 +54,7 @@ void irq_gc_mask_set_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
*ct->mask_cache |= mask;
@@ -73,7 +73,7 @@ void irq_gc_mask_clr_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
*ct->mask_cache &= ~mask;
@@ -92,7 +92,7 @@ void irq_gc_unmask_enable_reg(struct irq
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.enable);
@@ -108,7 +108,7 @@ void irq_gc_ack_set_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
@@ -123,7 +123,7 @@ void irq_gc_ack_clr_bit(struct irq_data
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = ~(1 << (d->irq - gc->irq_base));
+ u32 mask = ~d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.ack);
@@ -138,7 +138,7 @@ void irq_gc_mask_disable_reg_and_ack(str
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.mask);
@@ -154,7 +154,7 @@ void irq_gc_eoi(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.eoi);
@@ -172,7 +172,7 @@ void irq_gc_eoi(struct irq_data *d)
int irq_gc_set_wake(struct irq_data *d, unsigned int on)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- u32 mask = 1 << (d->irq - gc->irq_base);
+ u32 mask = d->mask;
if (!(mask & gc->wake_enabled))
return -EINVAL;
@@ -264,6 +264,11 @@ void irq_setup_generic_chip(struct irq_c
if (flags & IRQ_GC_INIT_NESTED_LOCK)
irq_set_lockdep_class(i, &irq_nested_lock_class);
+ if (!(flags & IRQ_GC_NO_MASK)) {
+ struct irq_data *d = irq_get_irq_data(i);
+
+ d->mask = 1 << (i - gc->irq_base);
+ }
irq_set_chip_and_handler(i, &ct->chip, ct->handler);
irq_set_chip_data(i, gc);
irq_modify_status(i, clr, set);
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 5/8] genirq: Add a mask calculation function
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
` (3 preceding siblings ...)
2013-05-06 14:30 ` [patch 4/8] genirq: generic chip: Cache per irq bit mask Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 14:30 ` [patch 6/8] genirq: Split out code in generic chip Thomas Gleixner
` (2 subsequent siblings)
7 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: genirq-generic-chip-add-mask-calculation-function.patch --]
[-- Type: text/plain, Size: 2176 bytes --]
Some chips have weird bit mask access patterns instead of the linear
you expect. Allow them to calculate the cached mask themself.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/irq.h | 3 +++
kernel/irq/generic-chip.c | 8 ++++++--
2 files changed, 9 insertions(+), 2 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -296,6 +296,7 @@ static inline irq_hw_number_t irqd_to_hw
* @irq_suspend: function called from core code on suspend once per chip
* @irq_resume: function called from core code on resume once per chip
* @irq_pm_shutdown: function called from core code on shutdown once per chip
+ * @irq_calc_mask: Optional function to set irq_data.mask for special cases
* @irq_print_chip: optional to print special chip info in show_interrupts
* @flags: chip specific flags
*/
@@ -327,6 +328,8 @@ struct irq_chip {
void (*irq_resume)(struct irq_data *data);
void (*irq_pm_shutdown)(struct irq_data *data);
+ void (*irq_calc_mask)(struct irq_data *data);
+
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
unsigned long flags;
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -240,6 +240,7 @@ void irq_setup_generic_chip(struct irq_c
unsigned int set)
{
struct irq_chip_type *ct = gc->chip_types;
+ struct irq_chip *chip = &ct->chip;
unsigned int i;
u32 *mskptr = &gc->mask_cache, mskreg = ct->regs.mask;
@@ -267,9 +268,12 @@ void irq_setup_generic_chip(struct irq_c
if (!(flags & IRQ_GC_NO_MASK)) {
struct irq_data *d = irq_get_irq_data(i);
- d->mask = 1 << (i - gc->irq_base);
+ if (chip->irq_calc_mask)
+ chip->irq_calc_mask(d);
+ else
+ d->mask = 1 << (i - gc->irq_base);
}
- irq_set_chip_and_handler(i, &ct->chip, ct->handler);
+ irq_set_chip_and_handler(i, chip, ct->handler);
irq_set_chip_data(i, gc);
irq_modify_status(i, clr, set);
}
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 6/8] genirq: Split out code in generic chip
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
` (4 preceding siblings ...)
2013-05-06 14:30 ` [patch 5/8] genirq: Add a mask calculation function Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 14:30 ` [patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
2013-05-06 14:30 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
7 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: genirq-generic-chip-split-out-code.patch --]
[-- Type: text/plain, Size: 2729 bytes --]
Preparatory patch for linear interrupt domains.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/generic-chip.c | 50 +++++++++++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 16 deletions(-)
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -186,6 +186,19 @@ int irq_gc_set_wake(struct irq_data *d,
return 0;
}
+static void
+irq_init_generic_chip(struct irq_chip_generic *gc, const char *name,
+ int num_ct, unsigned int irq_base,
+ void __iomem *reg_base, irq_flow_handler_t handler)
+{
+ raw_spin_lock_init(&gc->lock);
+ gc->num_ct = num_ct;
+ gc->irq_base = irq_base;
+ gc->reg_base = reg_base;
+ gc->chip_types->chip.name = name;
+ gc->chip_types->handler = handler;
+}
+
/**
* irq_alloc_generic_chip - Allocate a generic chip and initialize it
* @name: Name of the irq chip
@@ -206,17 +219,31 @@ irq_alloc_generic_chip(const char *name,
gc = kzalloc(sz, GFP_KERNEL);
if (gc) {
- raw_spin_lock_init(&gc->lock);
- gc->num_ct = num_ct;
- gc->irq_base = irq_base;
- gc->reg_base = reg_base;
- gc->chip_types->chip.name = name;
- gc->chip_types->handler = handler;
+ irq_init_generic_chip(gc, name, num_ct, irq_base, reg_base,
+ handler);
}
return gc;
}
EXPORT_SYMBOL_GPL(irq_alloc_generic_chip);
+static void
+irq_gc_init_mask_cache(struct irq_chip_generic *gc, enum irq_gc_flags flags)
+{
+ struct irq_chip_type *ct = gc->chip_types;
+ u32 *mskptr = &gc->mask_cache, mskreg = ct->regs.mask;
+ int i;
+
+ for (i = 0; i < gc->num_ct; i++) {
+ if (flags & IRQ_GC_MASK_CACHE_PER_TYPE) {
+ mskptr = &ct[i].mask_cache_priv;
+ mskreg = ct[i].regs.mask;
+ }
+ ct[i].mask_cache = mskptr;
+ if (flags & IRQ_GC_INIT_MASK_CACHE)
+ *mskptr = irq_reg_readl(gc->reg_base + mskreg);
+ }
+}
+
/*
* Separate lockdep class for interrupt chip which can nest irq_desc
* lock.
@@ -242,21 +269,12 @@ void irq_setup_generic_chip(struct irq_c
struct irq_chip_type *ct = gc->chip_types;
struct irq_chip *chip = &ct->chip;
unsigned int i;
- u32 *mskptr = &gc->mask_cache, mskreg = ct->regs.mask;
raw_spin_lock(&gc_lock);
list_add_tail(&gc->list, &gc_list);
raw_spin_unlock(&gc_lock);
- for (i = 0; i < gc->num_ct; i++) {
- if (flags & IRQ_GC_MASK_CACHE_PER_TYPE) {
- mskptr = &ct[i].mask_cache_priv;
- mskreg = ct[i].regs.mask;
- }
- ct[i].mask_cache = mskptr;
- if (flags & IRQ_GC_INIT_MASK_CACHE)
- *mskptr = irq_reg_readl(gc->reg_base + mskreg);
- }
+ irq_gc_init_mask_cache(gc, flags);
for (i = gc->irq_base; msk; msk >>= 1, i++) {
if (!(msk & 0x01))
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
` (5 preceding siblings ...)
2013-05-06 14:30 ` [patch 6/8] genirq: Split out code in generic chip Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-29 2:22 ` Grant Likely
2013-05-06 14:30 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
7 siblings, 1 reply; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: genirq-add-linear-domain-support.patch --]
[-- Type: text/plain, Size: 11702 bytes --]
Provide infrastructure for irq chip implementations which work on
linear irq domains.
- Interface to allocate multiple generic chips which are associated to
the irq domain.
- Interface to get the generic chip pointer for a particular hardware
interrupt in the domain.
- irq domain mapping function to install the chip for a particular
interrupt.
Note: This lacks a removal function for now, but this is a draft patch
the ARM folks to work on.
[ Sebastian Hesselbarth: Mask cache and pointer math fixups ]
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/irq.h | 30 +++++++
include/linux/irqdomain.h | 12 ++
kernel/irq/generic-chip.c | 187 ++++++++++++++++++++++++++++++++++++++++++++--
kernel/irq/irqdomain.c | 6 -
4 files changed, 223 insertions(+), 12 deletions(-)
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -678,6 +678,8 @@ struct irq_chip_type {
* @wake_active: Interrupt is marked as an wakeup from suspend source
* @num_ct: Number of available irq_chip_type instances (usually 1)
* @private: Private data for non generic chip callbacks
+ * @installed: bitfield to denote installed interrupts
+ * @domain: irq domain pointer
* @list: List head for keeping track of instances
* @chip_types: Array of interrupt irq_chip_types
*
@@ -699,6 +701,8 @@ struct irq_chip_generic {
u32 wake_active;
unsigned int num_ct;
void *private;
+ unsigned long installed;
+ struct irq_domain *domain;
struct list_head list;
struct irq_chip_type chip_types[0];
};
@@ -719,6 +723,24 @@ enum irq_gc_flags {
IRQ_GC_NO_MASK = 1 << 3,
};
+/*
+ * struct irq_domain_chip_generic - Generic irq chip data structure for irq domains
+ * @irqs_per_chip: Number of interrupts per chip
+ * @num_chips: Number of chips
+ * @irq_flags_to_set: IRQ* flags to set on irq setup
+ * @irq_flags_to_clear: IRQ* flags to clear on irq setup
+ * @gc_flags: Generic chip specific setup flags
+ * @gc: Array of pointers to generic interrupt chips
+ */
+struct irq_domain_chip_generic {
+ unsigned int irqs_per_chip;
+ unsigned int num_chips;
+ unsigned int irq_flags_to_clear;
+ unsigned int irq_flags_to_set;
+ enum irq_gc_flags gc_flags;
+ struct irq_chip_generic *gc[0];
+};
+
/* Generic chip callback functions */
void irq_gc_noop(struct irq_data *d);
void irq_gc_mask_disable_reg(struct irq_data *d);
@@ -742,6 +764,14 @@ int irq_setup_alt_chip(struct irq_data *
void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
unsigned int clr, unsigned int set);
+struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq);
+int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
+ int num_ct, const char *name,
+ irq_flow_handler_t handler,
+ unsigned int clr, unsigned int set,
+ enum irq_gc_flags flags);
+
+
static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
{
return container_of(d->chip, struct irq_chip_type, chip);
Index: linux-2.6/include/linux/irqdomain.h
===================================================================
--- linux-2.6.orig/include/linux/irqdomain.h
+++ linux-2.6/include/linux/irqdomain.h
@@ -66,6 +66,10 @@ struct irq_domain_ops {
unsigned long *out_hwirq, unsigned int *out_type);
};
+extern struct irq_domain_ops irq_generic_chip_ops;
+
+struct irq_domain_chip_generic;
+
/**
* struct irq_domain - Hardware interrupt number translation object
* @link: Element in global irq_domain list.
@@ -109,8 +113,16 @@ struct irq_domain {
/* Optional device node pointer */
struct device_node *of_node;
+ /* Optional pointer to generic interrupt chips */
+ struct irq_domain_chip_generic *gc;
};
+#define IRQ_DOMAIN_MAP_LEGACY 0 /* driver allocated fixed range of irqs.
+ * ie. legacy 8259, gets irqs 1..15 */
+#define IRQ_DOMAIN_MAP_NOMAP 1 /* no fast reverse mapping */
+#define IRQ_DOMAIN_MAP_LINEAR 2 /* linear map of interrupts */
+#define IRQ_DOMAIN_MAP_TREE 3 /* radix tree */
+
#ifdef CONFIG_IRQ_DOMAIN
struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
unsigned int size,
Index: linux-2.6/kernel/irq/generic-chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/generic-chip.c
+++ linux-2.6/kernel/irq/generic-chip.c
@@ -7,6 +7,7 @@
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/syscore_ops.h>
@@ -244,6 +245,90 @@ irq_gc_init_mask_cache(struct irq_chip_g
}
}
+/**
+ * irq_alloc_domain_generic_chip - Allocate generic chips for an irq domain
+ * @d: irq domain for which to allocate chips
+ * @irqs_per_chip: Number of interrupts each chip handles
+ * @num_ct: Number of irq_chip_type instances associated with this
+ * @name: Name of the irq chip
+ * @handler: Default flow handler associated with these chips
+ * @clr: IRQ_* bits to clear in the mapping function
+ * @set: IRQ_* bits to set in the mapping function
+ */
+int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
+ int num_ct, const char *name,
+ irq_flow_handler_t handler,
+ unsigned int clr, unsigned int set,
+ enum irq_gc_flags gcflags)
+{
+ struct irq_domain_chip_generic *dgc;
+ struct irq_chip_generic *gc;
+ int numchips, sz, i;
+ unsigned long flags;
+ void *tmp;
+
+ if (d->gc)
+ return -EBUSY;
+
+ if (d->revmap_type != IRQ_DOMAIN_MAP_LINEAR)
+ return -EINVAL;
+
+ numchips = d->revmap_data.linear.size / irqs_per_chip;
+ if (!numchips)
+ return -EINVAL;
+
+ /* Allocate a pointer, generic chip and chiptypes for each chip */
+ sz = sizeof(*dgc) + numchips * sizeof(gc);
+ sz += numchips * (sizeof(*gc) + num_ct * sizeof(struct irq_chip_type));
+
+ tmp = dgc = kzalloc(sz, GFP_KERNEL);
+ if (!dgc)
+ return -ENOMEM;
+ dgc->irqs_per_chip = irqs_per_chip;
+ dgc->num_chips = numchips;
+ dgc->irq_flags_to_set = set;
+ dgc->irq_flags_to_clear = clr;
+ dgc->gc_flags = gcflags;
+ d->gc = dgc;
+
+ /* Calc pointer to the first generic chip */
+ tmp += sizeof(*dgc) + numchips * sizeof(gc);
+ for (i = 0; i < numchips; i++) {
+ /* Store the pointer to the generic chip */
+ dgc->gc[i] = gc = tmp;
+ irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip,
+ NULL, handler);
+ gc->domain = d;
+ raw_spin_lock_irqsave(&gc_lock, flags);
+ list_add_tail(&gc->list, &gc_list);
+ raw_spin_unlock_irqrestore(&gc_lock, flags);
+ /* Calc pointer to the next generic chip */
+ tmp += sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(irq_alloc_domain_generic_chips);
+
+/**
+ * irq_get_domain_generic_chip - Get a pointer to the generic chip of a hw_irq
+ * @d: irq domain pointer
+ * @hw_irq: Hardware interrupt number
+ */
+struct irq_chip_generic *
+irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq)
+{
+ struct irq_domain_chip_generic *dgc = d->gc;
+ int idx;
+
+ if (!dgc)
+ return NULL;
+ idx = hw_irq / dgc->irqs_per_chip;
+ if (idx >= dgc->num_chips)
+ return NULL;
+ return dgc->gc[idx];
+}
+EXPORT_SYMBOL_GPL(irq_get_domain_generic_chip);
+
/*
* Separate lockdep class for interrupt chip which can nest irq_desc
* lock.
@@ -251,6 +336,66 @@ irq_gc_init_mask_cache(struct irq_chip_g
static struct lock_class_key irq_nested_lock_class;
/**
+ * irq_map_generic_chip - Map a generic chip for an irq domain
+ */
+static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw_irq)
+{
+ struct irq_data *data = irq_get_irq_data(virq);
+ struct irq_domain_chip_generic *dgc = d->gc;
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+ struct irq_chip *chip;
+ unsigned long flags;
+ int idx;
+
+ if (!d->gc)
+ return -ENODEV;
+
+ idx = hw_irq / dgc->irqs_per_chip;
+ if (idx >= dgc->num_chips)
+ return -EINVAL;
+ gc = dgc->gc[idx];
+
+ idx = hw_irq % dgc->irqs_per_chip;
+
+ if (test_bit(idx, &gc->installed))
+ return -EBUSY;
+
+ ct = gc->chip_types;
+ chip = &ct->chip;
+
+ /* We only init the cache for the first mapping of a generic chip */
+ if (!gc->installed) {
+ raw_spin_lock_irqsave(&gc->lock, flags);
+ irq_gc_init_mask_cache(gc, dgc->gc_flags);
+ raw_spin_unlock_irqrestore(&gc->lock, flags);
+ }
+
+ /* Mark the interrupt as installed */
+ set_bit(idx, &gc->installed);
+
+ if (dgc->gc_flags & IRQ_GC_INIT_NESTED_LOCK)
+ irq_set_lockdep_class(virq, &irq_nested_lock_class);
+
+ if (chip->irq_calc_mask)
+ chip->irq_calc_mask(data);
+ else
+ data->mask = 1 << idx;
+
+ irq_set_chip_and_handler(virq, chip, ct->handler);
+ irq_set_chip_data(virq, gc);
+ irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set);
+ return 0;
+}
+
+struct irq_domain_ops irq_generic_chip_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = irq_domain_xlate_onecell,
+};
+EXPORT_SYMBOL_GPL(irq_generic_chip_ops);
+
+/**
* irq_setup_generic_chip - Setup a range of interrupts with a generic chip
* @gc: Generic irq chip holding all data
* @msk: Bitmask holding the irqs to initialize relative to gc->irq_base
@@ -354,6 +499,24 @@ void irq_remove_generic_chip(struct irq_
}
EXPORT_SYMBOL_GPL(irq_remove_generic_chip);
+static struct irq_data *irq_gc_get_irq_data(struct irq_chip_generic *gc)
+{
+ unsigned int virq;
+
+ if (!gc->domain)
+ return irq_get_irq_data(gc->irq_base);
+
+ /*
+ * We don't know which of the irqs has been actually
+ * installed. Use the first one.
+ */
+ if (!gc->installed)
+ return NULL;
+
+ virq = irq_find_mapping(gc->domain, gc->irq_base + __ffs(gc->installed));
+ return virq ? irq_get_irq_data(virq) : NULL;
+}
+
#ifdef CONFIG_PM
static int irq_gc_suspend(void)
{
@@ -362,8 +525,12 @@ static int irq_gc_suspend(void)
list_for_each_entry(gc, &gc_list, list) {
struct irq_chip_type *ct = gc->chip_types;
- if (ct->chip.irq_suspend)
- ct->chip.irq_suspend(irq_get_irq_data(gc->irq_base));
+ if (ct->chip.irq_suspend) {
+ struct irq_data *data = irq_gc_get_irq_data(gc);
+
+ if (data)
+ ct->chip.irq_suspend(data);
+ }
}
return 0;
}
@@ -375,8 +542,12 @@ static void irq_gc_resume(void)
list_for_each_entry(gc, &gc_list, list) {
struct irq_chip_type *ct = gc->chip_types;
- if (ct->chip.irq_resume)
- ct->chip.irq_resume(irq_get_irq_data(gc->irq_base));
+ if (ct->chip.irq_resume) {
+ struct irq_data *data = irq_gc_get_irq_data(gc);
+
+ if (data)
+ ct->chip.irq_resume(data);
+ }
}
}
#else
@@ -391,8 +562,12 @@ static void irq_gc_shutdown(void)
list_for_each_entry(gc, &gc_list, list) {
struct irq_chip_type *ct = gc->chip_types;
- if (ct->chip.irq_pm_shutdown)
- ct->chip.irq_pm_shutdown(irq_get_irq_data(gc->irq_base));
+ if (ct->chip.irq_pm_shutdown) {
+ struct irq_data *data = irq_gc_get_irq_data(gc);
+
+ if (data)
+ ct->chip.irq_pm_shutdown(data);
+ }
}
}
Index: linux-2.6/kernel/irq/irqdomain.c
===================================================================
--- linux-2.6.orig/kernel/irq/irqdomain.c
+++ linux-2.6/kernel/irq/irqdomain.c
@@ -16,12 +16,6 @@
#include <linux/smp.h>
#include <linux/fs.h>
-#define IRQ_DOMAIN_MAP_LEGACY 0 /* driver allocated fixed range of irqs.
- * ie. legacy 8259, gets irqs 1..15 */
-#define IRQ_DOMAIN_MAP_NOMAP 1 /* no fast reverse mapping */
-#define IRQ_DOMAIN_MAP_LINEAR 2 /* linear map of interrupts */
-#define IRQ_DOMAIN_MAP_TREE 3 /* radix tree */
-
static LIST_HEAD(irq_domain_list);
static DEFINE_MUTEX(irq_domain_mutex);
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-06 14:30 ` [patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
@ 2013-05-29 2:22 ` Grant Likely
2013-05-29 8:23 ` Thomas Gleixner
0 siblings, 1 reply; 74+ messages in thread
From: Grant Likely @ 2013-05-29 2:22 UTC (permalink / raw)
To: Thomas Gleixner, LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Rob Herring,
Rob Landley, Arnd Bergmann, Jason Cooper, Andrew Lunn,
Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On Mon, 06 May 2013 14:30:27 -0000, Thomas Gleixner <tglx@linutronix.de> wrote:
> Provide infrastructure for irq chip implementations which work on
> linear irq domains.
>
> - Interface to allocate multiple generic chips which are associated to
> the irq domain.
>
> - Interface to get the generic chip pointer for a particular hardware
> interrupt in the domain.
>
> - irq domain mapping function to install the chip for a particular
> interrupt.
>
> Note: This lacks a removal function for now, but this is a draft patch
> the ARM folks to work on.
>
> [ Sebastian Hesselbarth: Mask cache and pointer math fixups ]
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Hi Thomas,
Acked-by: Grant Likely <grant.likely@linaro.org>
But I have some comments below...
> ---
> include/linux/irq.h | 30 +++++++
> include/linux/irqdomain.h | 12 ++
> kernel/irq/generic-chip.c | 187 ++++++++++++++++++++++++++++++++++++++++++++--
> kernel/irq/irqdomain.c | 6 -
> 4 files changed, 223 insertions(+), 12 deletions(-)
>
> Index: linux-2.6/include/linux/irq.h
> ===================================================================
> --- linux-2.6.orig/include/linux/irq.h
> +++ linux-2.6/include/linux/irq.h
> @@ -678,6 +678,8 @@ struct irq_chip_type {
> * @wake_active: Interrupt is marked as an wakeup from suspend source
> * @num_ct: Number of available irq_chip_type instances (usually 1)
> * @private: Private data for non generic chip callbacks
> + * @installed: bitfield to denote installed interrupts
> + * @domain: irq domain pointer
> * @list: List head for keeping track of instances
> * @chip_types: Array of interrupt irq_chip_types
> *
> @@ -699,6 +701,8 @@ struct irq_chip_generic {
> u32 wake_active;
> unsigned int num_ct;
> void *private;
> + unsigned long installed;
This is probably something that the irqdomain should be keeping track of
internally, but that's an issue for a separate patch series.
[...]
> +struct irq_domain_ops irq_generic_chip_ops = {
> + .map = irq_map_generic_chip,
> + .xlate = irq_domain_xlate_onecell,
As discussed on IRC, should use onetwocell here for greater
compatibility with existing bindings.
Cheers,
g.
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [patch 7/8] genirq: generic chip: Add linear irq domain support
2013-05-29 2:22 ` Grant Likely
@ 2013-05-29 8:23 ` Thomas Gleixner
0 siblings, 0 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-29 8:23 UTC (permalink / raw)
To: Grant Likely
Cc: LKML, Sebastian Hesselbarth, Russell King - ARM Linux,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
On Wed, 29 May 2013, Grant Likely wrote:
> > --- linux-2.6.orig/include/linux/irq.h
> > +++ linux-2.6/include/linux/irq.h
> > @@ -678,6 +678,8 @@ struct irq_chip_type {
> > * @wake_active: Interrupt is marked as an wakeup from suspend source
> > * @num_ct: Number of available irq_chip_type instances (usually 1)
> > * @private: Private data for non generic chip callbacks
> > + * @installed: bitfield to denote installed interrupts
> > + * @domain: irq domain pointer
> > * @list: List head for keeping track of instances
> > * @chip_types: Array of interrupt irq_chip_types
> > *
> > @@ -699,6 +701,8 @@ struct irq_chip_generic {
> > u32 wake_active;
> > unsigned int num_ct;
> > void *private;
> > + unsigned long installed;
>
> This is probably something that the irqdomain should be keeping track of
> internally, but that's an issue for a separate patch series.
Ok. I just need access to that information, so I can figure out if
it's the first irq of the chip which gets mapped. I need this for
initializing the mask cache.
> [...]
> > +struct irq_domain_ops irq_generic_chip_ops = {
> > + .map = irq_map_generic_chip,
> > + .xlate = irq_domain_xlate_onecell,
>
> As discussed on IRC, should use onetwocell here for greater
> compatibility with existing bindings.
Changed that.
Thanks,
tglx
^ permalink raw reply [flat|nested] 74+ messages in thread
* [patch 8/8] irqchip: sun4i: Convert to generic irq chip
2013-05-06 14:30 ` [patch 0/8] genirq: Support for irq domains in generic irq chip - V2 Thomas Gleixner
` (6 preceding siblings ...)
2013-05-06 14:30 ` [patch 7/8] genirq: generic chip: Add linear irq domain support Thomas Gleixner
@ 2013-05-06 14:30 ` Thomas Gleixner
2013-05-06 15:18 ` Rob Herring
` (2 more replies)
7 siblings, 3 replies; 74+ messages in thread
From: Thomas Gleixner @ 2013-05-06 14:30 UTC (permalink / raw)
To: LKML
Cc: Sebastian Hesselbarth, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Maxime Ripard, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
[-- Attachment #1: irqchip-convert-sun4i.patch --]
[-- Type: text/plain, Size: 4825 bytes --]
Proof of concept patch to demonstrate the new irqdomain support for
the generic irq chip. Untested !!
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/irqchip/irq-sun4i.c | 100 ++++++++++++--------------------------------
1 file changed, 29 insertions(+), 71 deletions(-)
Index: linux-2.6/drivers/irqchip/irq-sun4i.c
===================================================================
--- linux-2.6.orig/drivers/irqchip/irq-sun4i.c
+++ linux-2.6/drivers/irqchip/irq-sun4i.c
@@ -32,70 +32,43 @@
#define SUN4I_IRQ_FIQ_PENDING_REG(x) (0x20 + 0x4 * x)
#define SUN4I_IRQ_ENABLE_REG(x) (0x40 + 0x4 * x)
#define SUN4I_IRQ_MASK_REG(x) (0x50 + 0x4 * x)
+#define SUN4I_NUM_CHIPS 3
+#define SUN4I_IRQS_PER_CHIP 32
static void __iomem *sun4i_irq_base;
static struct irq_domain *sun4i_irq_domain;
static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs);
-void sun4i_irq_ack(struct irq_data *irqd)
+static int __init sun4i_init_domain_chips(void)
{
- unsigned int irq = irqd_to_hwirq(irqd);
- unsigned int irq_off = irq % 32;
- int reg = irq / 32;
- u32 val;
-
- val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
- writel(val | (1 << irq_off),
- sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
-}
-
-static void sun4i_irq_mask(struct irq_data *irqd)
-{
- unsigned int irq = irqd_to_hwirq(irqd);
- unsigned int irq_off = irq % 32;
- int reg = irq / 32;
- u32 val;
-
- val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
- writel(val & ~(1 << irq_off),
- sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
-}
-
-static void sun4i_irq_unmask(struct irq_data *irqd)
-{
- unsigned int irq = irqd_to_hwirq(irqd);
- unsigned int irq_off = irq % 32;
- int reg = irq / 32;
- u32 val;
-
- val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
- writel(val | (1 << irq_off),
- sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
-}
-
-static struct irq_chip sun4i_irq_chip = {
- .name = "sun4i_irq",
- .irq_ack = sun4i_irq_ack,
- .irq_mask = sun4i_irq_mask,
- .irq_unmask = sun4i_irq_unmask,
-};
-
-static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw)
-{
- irq_set_chip_and_handler(virq, &sun4i_irq_chip,
- handle_level_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
+ unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+ struct irq_chip_generic *gc;
+ int i, ret, base = 0;
+
+ ret = irq_alloc_domain_generic_chips(d, SUN4I_IRQS_PER_CHIP, 1,
+ "sun4i_irq", handle_level_irq,
+ clr, 0, IRQ_GC_INIT_MASK_CACHE);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < SUN4I_NUM_CHIPS; i++, base += SUN4I_IRQS_PER_CHIP) {
+ gc = irq_get_domain_generic_chip(sun4i_irq_domain, base);
+ gc->reg_base = sun4i_irq_base;
+ gc->chip_types[0].regs.mask = SUN4I_IRQ_ENABLE_REG(i);
+ gc->chip_types[0].regs.ack = SUN4I_IRQ_PENDING_REG(i);
+ gc->chip_types[0].chip.mask = irq_gc_mask_clr_bit;
+ gc->chip_types[0].chip.ack = irq_gc_ack_set_bit;
+ gc->chip_types[0].chip.unmask = irq_gc_mask_set_bit;
+
+ /* Disable, mask and clear all pending interrupts */
+ writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(i));
+ writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(i));
+ writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(i));
+ }
return 0;
}
-static struct irq_domain_ops sun4i_irq_ops = {
- .map = sun4i_irq_map,
- .xlate = irq_domain_xlate_onecell,
-};
-
static int __init sun4i_of_init(struct device_node *node,
struct device_node *parent)
{
@@ -104,21 +77,6 @@ static int __init sun4i_of_init(struct d
panic("%s: unable to map IC registers\n",
node->full_name);
- /* Disable all interrupts */
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(0));
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
-
- /* Mask all the interrupts */
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
-
- /* Clear all the pending interrupts */
- writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
- writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(1));
- writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(2));
-
/* Enable protection mode */
writel(0x01, sun4i_irq_base + SUN4I_IRQ_PROTECTION_REG);
@@ -126,8 +84,8 @@ static int __init sun4i_of_init(struct d
writel(0x00, sun4i_irq_base + SUN4I_IRQ_NMI_CTRL_REG);
sun4i_irq_domain = irq_domain_add_linear(node, 3 * 32,
- &sun4i_irq_ops, NULL);
- if (!sun4i_irq_domain)
+ &irq_generic_chip_ops, NULL);
+ if (!sun4i_irq_domain || sun4i_init_domain_chips())
panic("%s: unable to create IRQ domain\n", node->full_name);
set_handle_irq(sun4i_handle_irq);
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [patch 8/8] irqchip: sun4i: Convert to generic irq chip
2013-05-06 14:30 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
@ 2013-05-06 15:18 ` Rob Herring
2013-05-12 14:05 ` [PATCH] irq-sun4i: Fix trivial build errors Maxime Ripard
2013-05-12 14:08 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Maxime Ripard
2 siblings, 0 replies; 74+ messages in thread
From: Rob Herring @ 2013-05-06 15:18 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Andrew Lunn, Russell King - ARM Linux, Jason Cooper,
Jean-Francois Moine, devicetree-discuss, linux-doc, Rob Herring,
Jason Gunthorpe, Gerlando Falauto, Grant Likely, linux-arm-kernel,
Sebastian Hesselbarth
On 05/06/2013 09:30 AM, Thomas Gleixner wrote:
> Proof of concept patch to demonstrate the new irqdomain support for
> the generic irq chip. Untested !!
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> drivers/irqchip/irq-sun4i.c | 100 ++++++++++++--------------------------------
> 1 file changed, 29 insertions(+), 71 deletions(-)
>
> Index: linux-2.6/drivers/irqchip/irq-sun4i.c
> ===================================================================
> --- linux-2.6.orig/drivers/irqchip/irq-sun4i.c
> +++ linux-2.6/drivers/irqchip/irq-sun4i.c
> @@ -32,70 +32,43 @@
> #define SUN4I_IRQ_FIQ_PENDING_REG(x) (0x20 + 0x4 * x)
> #define SUN4I_IRQ_ENABLE_REG(x) (0x40 + 0x4 * x)
> #define SUN4I_IRQ_MASK_REG(x) (0x50 + 0x4 * x)
> +#define SUN4I_NUM_CHIPS 3
> +#define SUN4I_IRQS_PER_CHIP 32
>
> static void __iomem *sun4i_irq_base;
> static struct irq_domain *sun4i_irq_domain;
>
> static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs);
>
> -void sun4i_irq_ack(struct irq_data *irqd)
> +static int __init sun4i_init_domain_chips(void)
> {
> - unsigned int irq = irqd_to_hwirq(irqd);
> - unsigned int irq_off = irq % 32;
> - int reg = irq / 32;
> - u32 val;
> -
> - val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
> - writel(val | (1 << irq_off),
> - sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
> -}
> -
> -static void sun4i_irq_mask(struct irq_data *irqd)
> -{
> - unsigned int irq = irqd_to_hwirq(irqd);
> - unsigned int irq_off = irq % 32;
> - int reg = irq / 32;
> - u32 val;
> -
> - val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
> - writel(val & ~(1 << irq_off),
> - sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
> -}
> -
> -static void sun4i_irq_unmask(struct irq_data *irqd)
> -{
> - unsigned int irq = irqd_to_hwirq(irqd);
> - unsigned int irq_off = irq % 32;
> - int reg = irq / 32;
> - u32 val;
> -
> - val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
> - writel(val | (1 << irq_off),
> - sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
> -}
> -
> -static struct irq_chip sun4i_irq_chip = {
> - .name = "sun4i_irq",
> - .irq_ack = sun4i_irq_ack,
> - .irq_mask = sun4i_irq_mask,
> - .irq_unmask = sun4i_irq_unmask,
> -};
> -
> -static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
> - irq_hw_number_t hw)
> -{
> - irq_set_chip_and_handler(virq, &sun4i_irq_chip,
> - handle_level_irq);
> - set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
> -
> + unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
> + struct irq_chip_generic *gc;
> + int i, ret, base = 0;
> +
> + ret = irq_alloc_domain_generic_chips(d, SUN4I_IRQS_PER_CHIP, 1,
1 should be SUN4I_NUM_CHIPS.
> + "sun4i_irq", handle_level_irq,
> + clr, 0, IRQ_GC_INIT_MASK_CACHE);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < SUN4I_NUM_CHIPS; i++, base += SUN4I_IRQS_PER_CHIP) {
> + gc = irq_get_domain_generic_chip(sun4i_irq_domain, base);
Perhaps this could be an iterator macro.
> + gc->reg_base = sun4i_irq_base;
> + gc->chip_types[0].regs.mask = SUN4I_IRQ_ENABLE_REG(i);
> + gc->chip_types[0].regs.ack = SUN4I_IRQ_PENDING_REG(i);
> + gc->chip_types[0].chip.mask = irq_gc_mask_clr_bit;
> + gc->chip_types[0].chip.ack = irq_gc_ack_set_bit;
> + gc->chip_types[0].chip.unmask = irq_gc_mask_set_bit;
> +
> + /* Disable, mask and clear all pending interrupts */
> + writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(i));
> + writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(i));
> + writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(i));
> + }
> return 0;
> }
>
> -static struct irq_domain_ops sun4i_irq_ops = {
> - .map = sun4i_irq_map,
> - .xlate = irq_domain_xlate_onecell,
> -};
> -
> static int __init sun4i_of_init(struct device_node *node,
> struct device_node *parent)
> {
> @@ -104,21 +77,6 @@ static int __init sun4i_of_init(struct d
> panic("%s: unable to map IC registers\n",
> node->full_name);
>
> - /* Disable all interrupts */
> - writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(0));
> - writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
> - writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
> -
> - /* Mask all the interrupts */
> - writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
> - writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
> - writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
> -
> - /* Clear all the pending interrupts */
> - writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
> - writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(1));
> - writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(2));
> -
> /* Enable protection mode */
> writel(0x01, sun4i_irq_base + SUN4I_IRQ_PROTECTION_REG);
>
> @@ -126,8 +84,8 @@ static int __init sun4i_of_init(struct d
> writel(0x00, sun4i_irq_base + SUN4I_IRQ_NMI_CTRL_REG);
>
> sun4i_irq_domain = irq_domain_add_linear(node, 3 * 32,
s/3 * 32/SUN4I_NUM_CHIPS * SUN4I_IRQS_PER_CHIP/
> - &sun4i_irq_ops, NULL);
> - if (!sun4i_irq_domain)
> + &irq_generic_chip_ops, NULL);
> + if (!sun4i_irq_domain || sun4i_init_domain_chips())
> panic("%s: unable to create IRQ domain\n", node->full_name);
>
> set_handle_irq(sun4i_handle_irq);
>
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH] irq-sun4i: Fix trivial build errors
2013-05-06 14:30 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
2013-05-06 15:18 ` Rob Herring
@ 2013-05-12 14:05 ` Maxime Ripard
2013-05-12 14:08 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Maxime Ripard
2 siblings, 0 replies; 74+ messages in thread
From: Maxime Ripard @ 2013-05-12 14:05 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Maxime Ripard, Russell King - ARM Linux, Grant Likely,
Rob Herring, Rob Landley, Arnd Bergmann, Jason Cooper,
Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni, Gregory Clement,
Ezequiel Garcia, Jean-Francois Moine, Gerlando Falauto,
Uwe Kleine-Koenig, devicetree-discuss, linux-doc,
linux-arm-kernel, linux-kernel, Jiri Kosina
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Jean-Francois Moine <moinejf@free.fr>
Cc: Gerlando Falauto <gerlando.falauto@keymile.com>
Cc: Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
drivers/irqchip/irq-sun4i.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
index 0191f2c..cab36b1 100644
--- a/drivers/irqchip/irq-sun4i.c
+++ b/drivers/irqchip/irq-sun4i.c
@@ -46,7 +46,8 @@ static int __init sun4i_init_domain_chips(void)
struct irq_chip_generic *gc;
int i, ret, base = 0;
- ret = irq_alloc_domain_generic_chips(d, SUN4I_IRQS_PER_CHIP, 1,
+ ret = irq_alloc_domain_generic_chips(sun4i_irq_domain,
+ SUN4I_IRQS_PER_CHIP, 1,
"sun4i_irq", handle_level_irq,
clr, 0, IRQ_GC_INIT_MASK_CACHE);
if (ret)
@@ -57,9 +58,9 @@ static int __init sun4i_init_domain_chips(void)
gc->reg_base = sun4i_irq_base;
gc->chip_types[0].regs.mask = SUN4I_IRQ_ENABLE_REG(i);
gc->chip_types[0].regs.ack = SUN4I_IRQ_PENDING_REG(i);
- gc->chip_types[0].chip.mask = irq_gc_mask_clr_bit;
- gc->chip_types[0].chip.ack = irq_gc_ack_set_bit;
- gc->chip_types[0].chip.unmask = irq_gc_mask_set_bit;
+ gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
+ gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
+ gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
/* Disable, mask and clear all pending interrupts */
writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(i));
--
1.8.1.2
^ permalink raw reply related [flat|nested] 74+ messages in thread
* Re: [patch 8/8] irqchip: sun4i: Convert to generic irq chip
2013-05-06 14:30 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Thomas Gleixner
2013-05-06 15:18 ` Rob Herring
2013-05-12 14:05 ` [PATCH] irq-sun4i: Fix trivial build errors Maxime Ripard
@ 2013-05-12 14:08 ` Maxime Ripard
2013-05-12 14:14 ` Maxime Ripard
2 siblings, 1 reply; 74+ messages in thread
From: Maxime Ripard @ 2013-05-12 14:08 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Sebastian Hesselbarth, Russell King - ARM Linux,
Grant Likely, Rob Herring, Rob Landley, Arnd Bergmann,
Jason Cooper, Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni,
Gregory Clement, Ezequiel Garcia, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
Hi Thomas,
Le 06/05/2013 16:30, Thomas Gleixner a écrit :
> Proof of concept patch to demonstrate the new irqdomain support for
> the generic irq chip. Untested !!
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
I just tested it, and with the minor patch I sent, it's working fine.
You can add my
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [patch 8/8] irqchip: sun4i: Convert to generic irq chip
2013-05-12 14:08 ` [patch 8/8] irqchip: sun4i: Convert to generic irq chip Maxime Ripard
@ 2013-05-12 14:14 ` Maxime Ripard
0 siblings, 0 replies; 74+ messages in thread
From: Maxime Ripard @ 2013-05-12 14:14 UTC (permalink / raw)
To: Thomas Gleixner
Cc: LKML, Sebastian Hesselbarth, Russell King - ARM Linux,
Grant Likely, Rob Herring, Rob Landley, Arnd Bergmann,
Jason Cooper, Andrew Lunn, Jason Gunthorpe, Thomas Petazzoni,
Gregory Clement, Ezequiel Garcia, Jean-Francois Moine,
Gerlando Falauto, devicetree-discuss, linux-doc, linux-arm-kernel
Le 12/05/2013 16:08, Maxime Ripard a écrit :
> Hi Thomas,
>
> Le 06/05/2013 16:30, Thomas Gleixner a écrit :
>> Proof of concept patch to demonstrate the new irqdomain support for
>> the generic irq chip. Untested !!
>>
>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> I just tested it, and with the minor patch I sent, it's working fine.
>
> You can add my
> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
After addressing the comments RobH already made that is.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 74+ messages in thread