aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Frias <sf84@laposte.net>2016-08-16 10:05:08 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-09-02 14:20:59 -0400
commitf88eecfe2f22b2790e7527c0aaec14ea175919de (patch)
tree057a63155ecd74e71451f13efed04f2184940593
parent0c228919e04ddec195402296e7ebf2472ed6caef (diff)
genirq/generic_chip: Verify irqs_per_chip <= 32
Most (if not all) code here implicitly assumes that the maximum number of IRQs per chip will be 32, and thus uses 'u32' or 'unsigned long' for many tasks (for example "struct irq_data" declares its 'mask' field as 'u32', and "struct irq_chip_generic" declares its 'installed' field as 'unsigned long') However, there is no check to verify that irqs_per_chip is <= 32. Hence, calling irq_alloc_domain_generic_chips() with a bigger value will result in unexpected results. Provide a wrapper with a MAYBE_BUILD_BUG_ON(nrirqs >= 32) to catch such cases. [ tglx: Reduced changelog to the essential information ] Signed-off-by: Sebastian Frias <sf84@laposte.net> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Mason <slash.tmp@free.fr> Cc: Jason Cooper <jason@lakedaemon.net> Link: http://lkml.kernel.org/r/57B31D94.5040701@laposte.net Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--include/linux/irq.h18
-rw-r--r--kernel/irq/generic-chip.c16
2 files changed, 21 insertions, 13 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index b52424eaa0ed..603986741f2c 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -916,12 +916,20 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
916 unsigned int clr, unsigned int set); 916 unsigned int clr, unsigned int set);
917 917
918struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq); 918struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq);
919int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
920 int num_ct, const char *name,
921 irq_flow_handler_t handler,
922 unsigned int clr, unsigned int set,
923 enum irq_gc_flags flags);
924 919
920int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
921 int num_ct, const char *name,
922 irq_flow_handler_t handler,
923 unsigned int clr, unsigned int set,
924 enum irq_gc_flags flags);
925
926#define irq_alloc_domain_generic_chips(d, irqs_per_chip, num_ct, name, \
927 handler, clr, set, flags) \
928({ \
929 MAYBE_BUILD_BUG_ON(irqs_per_chip > 32); \
930 __irq_alloc_domain_generic_chips(d, irqs_per_chip, num_ct, name,\
931 handler, clr, set, flags); \
932})
925 933
926static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d) 934static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
927{ 935{
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
index a3a392097804..ee32870079c9 100644
--- a/kernel/irq/generic-chip.c
+++ b/kernel/irq/generic-chip.c
@@ -260,9 +260,9 @@ irq_gc_init_mask_cache(struct irq_chip_generic *gc, enum irq_gc_flags flags)
260} 260}
261 261
262/** 262/**
263 * irq_alloc_domain_generic_chip - Allocate generic chips for an irq domain 263 * __irq_alloc_domain_generic_chip - Allocate generic chips for an irq domain
264 * @d: irq domain for which to allocate chips 264 * @d: irq domain for which to allocate chips
265 * @irqs_per_chip: Number of interrupts each chip handles 265 * @irqs_per_chip: Number of interrupts each chip handles (max 32)
266 * @num_ct: Number of irq_chip_type instances associated with this 266 * @num_ct: Number of irq_chip_type instances associated with this
267 * @name: Name of the irq chip 267 * @name: Name of the irq chip
268 * @handler: Default flow handler associated with these chips 268 * @handler: Default flow handler associated with these chips
@@ -270,11 +270,11 @@ irq_gc_init_mask_cache(struct irq_chip_generic *gc, enum irq_gc_flags flags)
270 * @set: IRQ_* bits to set in the mapping function 270 * @set: IRQ_* bits to set in the mapping function
271 * @gcflags: Generic chip specific setup flags 271 * @gcflags: Generic chip specific setup flags
272 */ 272 */
273int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, 273int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
274 int num_ct, const char *name, 274 int num_ct, const char *name,
275 irq_flow_handler_t handler, 275 irq_flow_handler_t handler,
276 unsigned int clr, unsigned int set, 276 unsigned int clr, unsigned int set,
277 enum irq_gc_flags gcflags) 277 enum irq_gc_flags gcflags)
278{ 278{
279 struct irq_domain_chip_generic *dgc; 279 struct irq_domain_chip_generic *dgc;
280 struct irq_chip_generic *gc; 280 struct irq_chip_generic *gc;
@@ -326,7 +326,7 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
326 d->name = name; 326 d->name = name;
327 return 0; 327 return 0;
328} 328}
329EXPORT_SYMBOL_GPL(irq_alloc_domain_generic_chips); 329EXPORT_SYMBOL_GPL(__irq_alloc_domain_generic_chips);
330 330
331static struct irq_chip_generic * 331static struct irq_chip_generic *
332__irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq) 332__irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq)