Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 234772
b: refs/heads/master
c: 8d32a30
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Gleixner committed Feb 26, 2011
1 parent 5351c54 commit 44234d5
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8eb90c30e0e815a1308828352eabd03ca04229dd
refs/heads/master: 8d32a307e4faa8b123dc8a9cd56d1a7525f69ad3
4 changes: 4 additions & 0 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2436,6 +2436,10 @@ and is between 256 and 4096 characters. It is defined in the file
<deci-seconds>: poll all this frequency
0: no polling (default)

threadirqs [KNL]
Force threading of all interrupt handlers except those
marked explicitely IRQF_NO_THREAD.

topology= [S390]
Format: {off | on}
Specify if the kernel should make use of the cpu
Expand Down
7 changes: 7 additions & 0 deletions trunk/include/linux/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,13 @@ static inline int disable_irq_wake(unsigned int irq)
}
#endif /* CONFIG_GENERIC_HARDIRQS */


#ifdef CONFIG_IRQ_FORCED_THREADING
extern bool force_irqthreads;
#else
#define force_irqthreads (0)
#endif

#ifndef __ARCH_SET_SOFTIRQ_PENDING
#define set_softirq_pending(x) (local_softirq_pending() = (x))
#define or_softirq_pending(x) (local_softirq_pending() |= (x))
Expand Down
3 changes: 3 additions & 0 deletions trunk/kernel/irq/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ config HARDIRQS_SW_RESEND
config IRQ_PREFLOW_FASTEOI
bool

config IRQ_FORCED_THREADING
bool

config SPARSE_IRQ
bool "Support sparse irq numbering"
depends on HAVE_SPARSE_IRQ
Expand Down
2 changes: 2 additions & 0 deletions trunk/kernel/irq/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ extern int noirqdebug;
* 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,
};

/*
Expand Down
67 changes: 63 additions & 4 deletions trunk/kernel/irq/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@

#include "internals.h"

#ifdef CONFIG_IRQ_FORCED_THREADING
__read_mostly bool force_irqthreads;

static int __init setup_forced_irqthreads(char *arg)
{
force_irqthreads = true;
return 0;
}
early_param("threadirqs", setup_forced_irqthreads);
#endif

/**
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
* @irq: interrupt number to wait for
Expand Down Expand Up @@ -701,6 +712,32 @@ static inline void
irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
#endif

/*
* Interrupts which are not explicitely requested as threaded
* interrupts rely on the implicit bh/preempt disable of the hard irq
* context. So we need to disable bh here to avoid deadlocks and other
* side effects.
*/
static void
irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
{
local_bh_disable();
action->thread_fn(action->irq, action->dev_id);
irq_finalize_oneshot(desc, action, false);
local_bh_enable();
}

/*
* Interrupts explicitely requested as threaded interupts want to be
* preemtible - many of them need to sleep and wait for slow busses to
* complete.
*/
static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action)
{
action->thread_fn(action->irq, action->dev_id);
irq_finalize_oneshot(desc, action, false);
}

/*
* Interrupt handler thread
*/
Expand All @@ -711,8 +748,15 @@ static int irq_thread(void *data)
};
struct irqaction *action = data;
struct irq_desc *desc = irq_to_desc(action->irq);
void (*handler_fn)(struct irq_desc *desc, struct irqaction *action);
int wake;

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;

Expand All @@ -736,10 +780,7 @@ static int irq_thread(void *data)
raw_spin_unlock_irq(&desc->lock);
} else {
raw_spin_unlock_irq(&desc->lock);

action->thread_fn(action->irq, action->dev_id);

irq_finalize_oneshot(desc, action, false);
handler_fn(desc, action);
}

wake = atomic_dec_and_test(&desc->threads_active);
Expand Down Expand Up @@ -789,6 +830,22 @@ void exit_irq_thread(void)
set_bit(IRQTF_DIED, &tsk->irqaction->flags);
}

static void irq_setup_forced_threading(struct irqaction *new)
{
if (!force_irqthreads)
return;
if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
return;

new->flags |= IRQF_ONESHOT;

if (!new->thread_fn) {
set_bit(IRQTF_FORCED_THREAD, &new->thread_flags);
new->thread_fn = new->handler;
new->handler = irq_default_primary_handler;
}
}

/*
* Internal function to register an irqaction - typically used to
* allocate special interrupts that are part of the architecture.
Expand Down Expand Up @@ -838,6 +895,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
* dummy function which warns when called.
*/
new->handler = irq_nested_primary_handler;
} else {
irq_setup_forced_threading(new);
}

/*
Expand Down
16 changes: 14 additions & 2 deletions trunk/kernel/softirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,21 @@ void irq_enter(void)
}

#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
# define invoke_softirq() __do_softirq()
static inline void invoke_softirq(void)
{
if (!force_irqthreads)
__do_softirq();
else
wakeup_softirqd();
}
#else
# define invoke_softirq() do_softirq()
static inline void invoke_softirq(void)
{
if (!force_irqthreads)
do_softirq();
else
wakeup_softirqd();
}
#endif

/*
Expand Down

0 comments on commit 44234d5

Please sign in to comment.