Merge tag 'pm-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
[platform/adaptation/renesas_rcar/renesas_kernel.git] / kernel / irq / manage.c
index 89a3ea8..bb32326 100644 (file)
@@ -565,8 +565,8 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                 * IRQF_TRIGGER_* but the PIC does not support multiple
                 * flow-types?
                 */
-               pr_debug("No set_type function for IRQ %d (%s)\n", irq,
-                               chip ? (chip->name ? : "unknown") : "unknown");
+               pr_debug("genirq: No set_type function for IRQ %d (%s)\n", irq,
+                        chip ? (chip->name ? : "unknown") : "unknown");
                return 0;
        }
 
@@ -600,7 +600,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                ret = 0;
                break;
        default:
-               pr_err("setting trigger mode %lu for irq %u failed (%pF)\n",
+               pr_err("genirq: Setting trigger mode %lu for irq %u failed (%pF)\n",
                       flags, irq, chip->irq_set_type);
        }
        if (unmask)
@@ -837,8 +837,7 @@ void exit_irq_thread(void)
 
        action = kthread_data(tsk);
 
-       printk(KERN_ERR
-              "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
+       pr_err("genirq: exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
               tsk->comm ? tsk->comm : "", tsk->pid, action->irq);
 
        desc = irq_to_desc(action->irq);
@@ -878,7 +877,6 @@ static int
 __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 {
        struct irqaction *old, **old_ptr;
-       const char *old_name = NULL;
        unsigned long flags, thread_mask = 0;
        int ret, nested, shared = 0;
        cpumask_var_t mask;
@@ -972,10 +970,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                 */
                if (!((old->flags & new->flags) & IRQF_SHARED) ||
                    ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
-                   ((old->flags ^ new->flags) & IRQF_ONESHOT)) {
-                       old_name = old->name;
+                   ((old->flags ^ new->flags) & IRQF_ONESHOT))
                        goto mismatch;
-               }
 
                /* All handlers must agree on per-cpuness */
                if ((old->flags & IRQF_PERCPU) !=
@@ -1031,6 +1027,27 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                 * all existing action->thread_mask bits.
                 */
                new->thread_mask = 1 << ffz(thread_mask);
+
+       } else if (new->handler == irq_default_primary_handler) {
+               /*
+                * The interrupt was requested with handler = NULL, so
+                * we use the default primary handler for it. But it
+                * does not have the oneshot flag set. In combination
+                * with level interrupts this is deadly, because the
+                * default primary handler just wakes the thread, then
+                * the irq lines is reenabled, but the device still
+                * has the level irq asserted. Rinse and repeat....
+                *
+                * While this works for edge type interrupts, we play
+                * it safe and reject unconditionally because we can't
+                * say for sure which type this interrupt really
+                * has. The type flags are unreliable as the
+                * underlying chip implementation can override them.
+                */
+               pr_err("genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq %d\n",
+                      irq);
+               ret = -EINVAL;
+               goto out_mask;
        }
 
        if (!shared) {
@@ -1078,7 +1095,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 
                if (nmsk != omsk)
                        /* hope the handler works with current  trigger mode */
-                       pr_warning("IRQ %d uses trigger mode %u; requested %u\n",
+                       pr_warning("genirq: irq %d uses trigger mode %u; requested %u\n",
                                   irq, nmsk, omsk);
        }
 
@@ -1115,14 +1132,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
        return 0;
 
 mismatch:
-#ifdef CONFIG_DEBUG_SHIRQ
        if (!(new->flags & IRQF_PROBE_SHARED)) {
-               printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
-               if (old_name)
-                       printk(KERN_ERR "current handler: %s\n", old_name);
+               pr_err("genirq: Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n",
+                      irq, new->flags, new->name, old->flags, old->name);
+#ifdef CONFIG_DEBUG_SHIRQ
                dump_stack();
-       }
 #endif
+       }
        ret = -EBUSY;
 
 out_mask:
@@ -1204,12 +1220,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
        /* Found it - now remove it from the list of entries: */
        *action_ptr = action->next;
 
-       /* Currently used only by UML, might disappear one day: */
-#ifdef CONFIG_IRQ_RELEASE_METHOD
-       if (desc->irq_data.chip->release)
-               desc->irq_data.chip->release(irq, dev_id);
-#endif
-
        /* If this was the last handler, shut down the IRQ line: */
        if (!desc->action)
                irq_shutdown(desc);