irq/core changes for v3.4
Linus,
Please pull the latest irq-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-core-for-linus
HEAD: e04268b0effc0ceea366c50b3107baad9edadafa genirq: Remove paranoid warnons and bogus fixups
Thanks,
Ingo
------------------>
Alexander Gordeev (4):
genirq: Fix incorrect check for forced IRQ thread handler
genirq: Get rid of unnecessary irqaction field in task_struct
genirq: No need to check IRQTF_DIED before stopping a thread handler
genirq: Get rid of unnecessary IRQTF_DIED flag
Heiko Carstens (1):
softirq: Reduce invoke_softirq() code duplication
Ido Yariv (1):
genirq: Flush the irq thread on synchronization
Linus Torvalds (1):
x86-32/irq: Don't switch to irq stack for a user-mode irq
Russell King (1):
genirq: Fix long-term regression in genirq irq_set_irq_type() handling
Thomas Gleixner (1):
genirq: Remove paranoid warnons and bogus fixups
arch/x86/kernel/irq_32.c | 11 ++---- include/linux/sched.h | 10 +++--- kernel/exit.c | 4 +- kernel/irq/chip.c | 3 +- kernel/irq/handle.c | 14 +++++++- kernel/irq/internals.h | 2 - kernel/irq/manage.c | 86 ++++++++++++++++++++------------------------- kernel/softirq.c | 18 ++------- 8 files changed, 66 insertions(+), 82 deletions(-)
arch/x86/kernel/irq_32.c +3 -8
@@ -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);
include/linux/sched.h +5 -5
@@ -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;
kernel/exit.c +2 -2
@@ -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),
kernel/irq/chip.c +1 -2
@@ -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; }
kernel/irq/handle.c +13 -1
@@ -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 ;
@@ -110,6 +110,18 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)* threads_oneshot untouched and runs the thread another time. */ desc->threads_oneshot |= action->thread_mask; + +/* +* We increment the threads_active counter in case we wake up +* the irq thread. The irq thread decrements the counter when +* it returns from the handler or in the exit path and wakes +* up waiters which are stuck in synchronize_irq() when the +* active count becomes zero. synchronize_irq() is serialized +* against this code (hard irq handler) via IRQS_INPROGRESS +* like the finalize_oneshot() code. See comment above. +*/ +atomic_inc (&desc->threads_active); +wake_up_process (action->thread); }
kernel/irq/internals.h +0 -2
@@ -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 ,
kernel/irq/manage.c +38 -48
144 lines not on this page · raw message
kernel/softirq.c +4 -14
@@ -310,31 +310,21 @@ void irq_enter(void)__irq_enter (); } -#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLEDstatic 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: