aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-10-01 17:46:18 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-02 04:24:09 -0400
commit0c5d1eb77a8be917b638344a22afe1398236482b (patch)
tree57d57c9b270cc10428f818cfec9725a1344b78ce /kernel/irq/manage.c
parentd6d5aeb661fc14655c417f3582ae7ec52985d2a8 (diff)
genirq: record trigger type
Genirq hasn't previously recorded the trigger type used by any given IRQ, although some irq_chip support has done so. That data can be useful when troubleshooting. This patch records it in the relevant irq_desc.status bits, and improves consistency between the two driver-visible calls affected: - Make set_irq_type() usage match request_irq() usage: * IRQ_TYPE_NONE should be a NOP; succeed, so irq_chip methods won't have to handle that case any more (many do it wrong). * IRQ_TYPE_PROBE is ignored; any buggy out-of-tree callers might need to switch over to the real IRQ probing code. * emit the same diagnostics (from shared utility code) - Their kerneldoc now reflects usage: * request_irq() flags include IRQF_TRIGGER_* to specify active edge(s)/level ... docs previously omitted that * set_irq_type() is declared in <linux/irq.h> so callers should use the (bit-equivalent) IRQ_TYPE_* symbols there Also: adds a warning about shared IRQs that don't end up using the requested trigger mode; and fix an unrelated "sparse" warning. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index d62f69ba7453..e59157b591f8 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -216,7 +216,7 @@ void enable_irq(unsigned int irq)
216} 216}
217EXPORT_SYMBOL(enable_irq); 217EXPORT_SYMBOL(enable_irq);
218 218
219int set_irq_wake_real(unsigned int irq, unsigned int on) 219static int set_irq_wake_real(unsigned int irq, unsigned int on)
220{ 220{
221 struct irq_desc *desc = irq_desc + irq; 221 struct irq_desc *desc = irq_desc + irq;
222 int ret = -ENXIO; 222 int ret = -ENXIO;
@@ -305,10 +305,11 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
305 desc->handle_irq = NULL; 305 desc->handle_irq = NULL;
306} 306}
307 307
308static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq, 308int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
309 unsigned long flags) 309 unsigned long flags)
310{ 310{
311 int ret; 311 int ret;
312 struct irq_chip *chip = desc->chip;
312 313
313 if (!chip || !chip->set_type) { 314 if (!chip || !chip->set_type) {
314 /* 315 /*
@@ -326,6 +327,11 @@ static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
326 pr_err("setting trigger mode %d for irq %u failed (%pF)\n", 327 pr_err("setting trigger mode %d for irq %u failed (%pF)\n",
327 (int)(flags & IRQF_TRIGGER_MASK), 328 (int)(flags & IRQF_TRIGGER_MASK),
328 irq, chip->set_type); 329 irq, chip->set_type);
330 else {
331 /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
332 desc->status &= ~IRQ_TYPE_SENSE_MASK;
333 desc->status |= flags & IRQ_TYPE_SENSE_MASK;
334 }
329 335
330 return ret; 336 return ret;
331} 337}
@@ -404,7 +410,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
404 410
405 /* Setup the type (level, edge polarity) if configured: */ 411 /* Setup the type (level, edge polarity) if configured: */
406 if (new->flags & IRQF_TRIGGER_MASK) { 412 if (new->flags & IRQF_TRIGGER_MASK) {
407 ret = __irq_set_trigger(desc->chip, irq, new->flags); 413 ret = __irq_set_trigger(desc, irq, new->flags);
408 414
409 if (ret) { 415 if (ret) {
410 spin_unlock_irqrestore(&desc->lock, flags); 416 spin_unlock_irqrestore(&desc->lock, flags);
@@ -430,6 +436,14 @@ int setup_irq(unsigned int irq, struct irqaction *new)
430 436
431 /* Set default affinity mask once everything is setup */ 437 /* Set default affinity mask once everything is setup */
432 irq_select_affinity(irq); 438 irq_select_affinity(irq);
439
440 } else if ((new->flags & IRQF_TRIGGER_MASK)
441 && (new->flags & IRQF_TRIGGER_MASK)
442 != (desc->status & IRQ_TYPE_SENSE_MASK)) {
443 /* hope the handler works with the actual trigger mode... */
444 pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
445 irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),
446 (int)(new->flags & IRQF_TRIGGER_MASK));
433 } 447 }
434 448
435 *p = new; 449 *p = new;
@@ -586,6 +600,7 @@ EXPORT_SYMBOL(free_irq);
586 * IRQF_SHARED Interrupt is shared 600 * IRQF_SHARED Interrupt is shared
587 * IRQF_DISABLED Disable local interrupts while processing 601 * IRQF_DISABLED Disable local interrupts while processing
588 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy 602 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
603 * IRQF_TRIGGER_* Specify active edge(s) or level
589 * 604 *
590 */ 605 */
591int request_irq(unsigned int irq, irq_handler_t handler, 606int request_irq(unsigned int irq, irq_handler_t handler,