From: Linus Torvalds Date: Tue, 7 Apr 2009 21:07:52 +0000 (-0700) Subject: Merge branch 'irq/threaded' of git://git.kernel.org/pub/scm/linux/kernel/git/tip... X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=c61b79b6ef266890954213a701d8f6021d8c1289;hp=-c;p=linux-2.6-omap-h63xx.git Merge branch 'irq/threaded' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip * 'irq/threaded' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: genirq: fix devres.o build for GENERIC_HARDIRQS=n genirq: provide old request_irq() for CONFIG_GENERIC_HARDIRQ=n genirq: threaded irq handlers review fixups genirq: add support for threaded interrupts to devres genirq: add threaded interrupt handler support --- c61b79b6ef266890954213a701d8f6021d8c1289 diff --combined include/linux/interrupt.h index 8a9613d0c67,675727fb4b4..91bb76f44f1 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@@ -59,6 -59,18 +59,18 @@@ #define IRQF_NOBALANCING 0x00000800 #define IRQF_IRQPOLL 0x00001000 + /* + * 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 + */ + enum { + IRQTF_RUNTHREAD, + IRQTF_DIED, + IRQTF_WARNED, + }; + typedef irqreturn_t (*irq_handler_t)(int, void *); /** @@@ -71,6 -83,9 +83,9 @@@ * @next: pointer to the next irqaction for shared interrupts * @irq: interrupt number * @dir: pointer to the proc/irq/NN/name entry + * @thread_fn: interupt handler function for threaded interrupts + * @thread: thread pointer for threaded interrupts + * @thread_flags: flags related to @thread */ struct irqaction { irq_handler_t handler; @@@ -81,18 -96,68 +96,68 @@@ struct irqaction *next; int irq; struct proc_dir_entry *dir; + irq_handler_t thread_fn; + struct task_struct *thread; + unsigned long thread_flags; }; extern irqreturn_t no_action(int cpl, void *dev_id); - extern int __must_check request_irq(unsigned int, irq_handler_t handler, - unsigned long, const char *, void *); + + #ifdef CONFIG_GENERIC_HARDIRQS + extern int __must_check + request_threaded_irq(unsigned int irq, irq_handler_t handler, + irq_handler_t thread_fn, + unsigned long flags, const char *name, void *dev); + + static inline int __must_check + request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, + const char *name, void *dev) + { + return request_threaded_irq(irq, handler, NULL, flags, name, dev); + } + + extern void exit_irq_thread(void); + #else + + extern int __must_check + request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, + const char *name, void *dev); + + /* + * Special function to avoid ifdeffery in kernel/irq/devres.c which + * gets magically built by GENERIC_HARDIRQS=n architectures (sparc, + * m68k). I really love these $@%#!* obvious Makefile references: + * ../../../kernel/irq/devres.o + */ + static inline int __must_check + request_threaded_irq(unsigned int irq, irq_handler_t handler, + irq_handler_t thread_fn, + unsigned long flags, const char *name, void *dev) + { + return request_irq(irq, handler, flags, name, dev); + } + + static inline void exit_irq_thread(void) { } + #endif + extern void free_irq(unsigned int, void *); struct device; - extern int __must_check devm_request_irq(struct device *dev, unsigned int irq, - irq_handler_t handler, unsigned long irqflags, - const char *devname, void *dev_id); + extern int __must_check + devm_request_threaded_irq(struct device *dev, unsigned int irq, + irq_handler_t handler, irq_handler_t thread_fn, + unsigned long irqflags, const char *devname, + void *dev_id); + + static inline int __must_check + devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, + unsigned long irqflags, const char *devname, void *dev_id) + { + return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags, + devname, dev_id); + } + extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id); /* @@@ -299,7 -364,6 +364,7 @@@ extern void softirq_init(void) #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0) extern void raise_softirq_irqoff(unsigned int nr); extern void raise_softirq(unsigned int nr); +extern void wakeup_softirqd(void); /* This is the worklist that queues up per-cpu softirq work. * diff --combined kernel/exit.c index 32cbf2607cb,789b8862fe3..abf9cf3b95c --- a/kernel/exit.c +++ b/kernel/exit.c @@@ -837,7 -837,8 +837,7 @@@ static void exit_notify(struct task_str */ if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) && (tsk->parent_exec_id != tsk->real_parent->self_exec_id || - tsk->self_exec_id != tsk->parent_exec_id) && - !capable(CAP_KILL)) + tsk->self_exec_id != tsk->parent_exec_id)) tsk->exit_signal = SIGCHLD; signal = tracehook_notify_death(tsk, &cookie, group_dead); @@@ -923,6 -924,8 +923,8 @@@ NORET_TYPE 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