Merge branch 'linus' into irq/core
authorThomas Gleixner <tglx@linutronix.de>
Tue, 13 Mar 2012 15:34:48 +0000 (16:34 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 13 Mar 2012 15:35:16 +0000 (16:35 +0100)
Reason: Get upstream fixes integrated before further modifications.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/kernel/irq_32.c
include/linux/sched.h
kernel/exit.c
kernel/irq/chip.c
kernel/irq/handle.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/softirq.c

index 40fc861..58b7f27 100644 (file)
@@ -100,13 +100,8 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
        irqctx->tinfo.task = curctx->tinfo.task;
        irqctx->tinfo.previous_esp = current_stack_pointer;
 
-       /*
-        * Copy the softirq bits in preempt_count so that the
-        * softirq checks work in the hardirq context.
-        */
-       irqctx->tinfo.preempt_count =
-               (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
-               (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+       /* Copy the preempt_count so that the [soft]irq checks work. */
+       irqctx->tinfo.preempt_count = curctx->tinfo.preempt_count;
 
        if (unlikely(overflow))
                call_on_stack(print_stack_overflow, isp);
@@ -196,7 +191,7 @@ bool handle_irq(unsigned irq, struct pt_regs *regs)
        if (unlikely(!desc))
                return false;
 
-       if (!execute_on_irq_stack(overflow, desc, irq)) {
+       if (user_mode_vm(regs) || !execute_on_irq_stack(overflow, desc, irq)) {
                if (unlikely(overflow))
                        print_stack_overflow();
                desc->handle_irq(irq, desc);
index 0657368..abb67cf 100644 (file)
@@ -1319,6 +1319,11 @@ struct task_struct {
        unsigned sched_reset_on_fork:1;
        unsigned sched_contributes_to_load:1;
 
+#ifdef CONFIG_GENERIC_HARDIRQS
+       /* IRQ handler threads */
+       unsigned irq_thread:1;
+#endif
+
        pid_t pid;
        pid_t tgid;
 
@@ -1427,11 +1432,6 @@ struct task_struct {
  * mempolicy */
        spinlock_t alloc_lock;
 
-#ifdef CONFIG_GENERIC_HARDIRQS
-       /* IRQ handler threads */
-       struct irqaction *irqaction;
-#endif
-
        /* Protection of the PI data structures: */
        raw_spinlock_t pi_lock;
 
index 4b4042f..752d2c0 100644 (file)
@@ -935,8 +935,6 @@ void do_exit(long code)
                schedule();
        }
 
-       exit_irq_thread();
-
        exit_signals(tsk);  /* sets PF_EXITING */
        /*
         * tsk->flags are checked in the futex code to protect against
@@ -945,6 +943,8 @@ void do_exit(long code)
        smp_mb();
        raw_spin_unlock_wait(&tsk->pi_lock);
 
+       exit_irq_thread();
+
        if (unlikely(in_atomic()))
                printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
                                current->comm, task_pid_nr(current),
index fb7db75..25784d6 100644 (file)
@@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, unsigned int type)
                return -EINVAL;
 
        type &= IRQ_TYPE_SENSE_MASK;
-       if (type != IRQ_TYPE_NONE)
-               ret = __irq_set_trigger(desc, irq, type);
+       ret = __irq_set_trigger(desc, irq, type);
        irq_put_desc_busunlock(desc, flags);
        return ret;
 }
index 470d08c..500aaf6 100644 (file)
@@ -60,7 +60,7 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
         * device interrupt, so no irq storm is lurking. If the
         * RUNTHREAD bit is already set, nothing to do.
         */
-       if (test_bit(IRQTF_DIED, &action->thread_flags) ||
+       if ((action->thread->flags & PF_EXITING) ||
            test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags))
                return;
 
index 40378ff..8e5c56b 100644 (file)
@@ -20,14 +20,12 @@ extern bool noirqdebug;
 /*
  * Bits used by threaded handlers:
  * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
- * IRQTF_DIED      - handler thread died
  * IRQTF_WARNED    - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
  * IRQTF_AFFINITY  - irq thread is requested to adjust affinity
  * IRQTF_FORCED_THREAD  - irq action is force threaded
  */
 enum {
        IRQTF_RUNTHREAD,
-       IRQTF_DIED,
        IRQTF_WARNED,
        IRQTF_AFFINITY,
        IRQTF_FORCED_THREAD,
index 0f0d470..1786cf7 100644 (file)
@@ -773,14 +773,14 @@ static int irq_thread(void *data)
                        struct irqaction *action);
        int wake;
 
-       if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
+       if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD,
                                        &action->thread_flags))
                handler_fn = irq_forced_thread_fn;
        else
                handler_fn = irq_thread_fn;
 
        sched_setscheduler(current, SCHED_FIFO, &param);
-       current->irqaction = action;
+       current->irq_thread = 1;
 
        while (!irq_wait_for_interrupt(action)) {
 
@@ -818,10 +818,10 @@ static int irq_thread(void *data)
        irq_finalize_oneshot(desc, action, true);
 
        /*
-        * Clear irqaction. Otherwise exit_irq_thread() would make
+        * Clear irq_thread. Otherwise exit_irq_thread() would make
         * fuzz about an active irq thread going into nirvana.
         */
-       current->irqaction = NULL;
+       current->irq_thread = 0;
        return 0;
 }
 
@@ -832,27 +832,21 @@ void exit_irq_thread(void)
 {
        struct task_struct *tsk = current;
        struct irq_desc *desc;
+       struct irqaction *action;
 
-       if (!tsk->irqaction)
+       if (!tsk->irq_thread)
                return;
 
+       action = kthread_data(tsk);
+
        printk(KERN_ERR
               "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
-              tsk->comm ? tsk->comm : "", tsk->pid, tsk->irqaction->irq);
-
-       desc = irq_to_desc(tsk->irqaction->irq);
+              tsk->comm ? tsk->comm : "", tsk->pid, action->irq);
 
-       /*
-        * Prevent a stale desc->threads_oneshot. Must be called
-        * before setting the IRQTF_DIED flag.
-        */
-       irq_finalize_oneshot(desc, tsk->irqaction, true);
+       desc = irq_to_desc(action->irq);
 
-       /*
-        * Set the THREAD DIED flag to prevent further wakeups of the
-        * soon to be gone threaded handler.
-        */
-       set_bit(IRQTF_DIED, &tsk->irqaction->flags);
+       /* Prevent a stale desc->threads_oneshot */
+       irq_finalize_oneshot(desc, action, true);
 }
 
 static void irq_setup_forced_threading(struct irqaction *new)
@@ -1135,8 +1129,7 @@ out_thread:
                struct task_struct *t = new->thread;
 
                new->thread = NULL;
-               if (likely(!test_bit(IRQTF_DIED, &new->thread_flags)))
-                       kthread_stop(t);
+               kthread_stop(t);
                put_task_struct(t);
        }
 out_mput:
@@ -1246,8 +1239,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 #endif
 
        if (action->thread) {
-               if (!test_bit(IRQTF_DIED, &action->thread_flags))
-                       kthread_stop(action->thread);
+               kthread_stop(action->thread);
                put_task_struct(action->thread);
        }
 
index 4eb3a0f..c82d95a 100644 (file)
@@ -310,31 +310,21 @@ void irq_enter(void)
        __irq_enter();
 }
 
-#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
 static inline void invoke_softirq(void)
 {
-       if (!force_irqthreads)
+       if (!force_irqthreads) {
+#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
                __do_softirq();
-       else {
-               __local_bh_disable((unsigned long)__builtin_return_address(0),
-                               SOFTIRQ_OFFSET);
-               wakeup_softirqd();
-               __local_bh_enable(SOFTIRQ_OFFSET);
-       }
-}
 #else
-static inline void invoke_softirq(void)
-{
-       if (!force_irqthreads)
                do_softirq();
-       else {
+#endif
+       } else {
                __local_bh_disable((unsigned long)__builtin_return_address(0),
                                SOFTIRQ_OFFSET);
                wakeup_softirqd();
                __local_bh_enable(SOFTIRQ_OFFSET);
        }
 }
-#endif
 
 /*
  * Exit an interrupt context. Process softirqs if needed and possible: