lkml.org 
[lkml]   [2016]   [Jun]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 2/5] genirq: add flags for controlling the default threaded irq behavior
Date
A threadable irq can benefit from irq_set_affinity when running
in non threaded mode and prefer running unbounded to cpu when in
threaded mode. Setting the IRQF_TH_NO_AFFINITY flag on irq
registration allow the irq to achieve both behaviors.

A long running threaded irq can starve the system if scheduled under
SCHED_FIFO. Setting the IRQF_TH_SCHED_NORMAL flag on irq will cause
the irq thread to run by default under the SCHED_NORMAL scheduler.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
include/linux/interrupt.h | 6 ++++++
kernel/irq/manage.c | 17 +++++++++++------
2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 85d3738..33c3033 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -61,6 +61,10 @@
* interrupt handler after suspending interrupts. For system
* wakeup devices users need to implement wakeup detection in
* their interrupt handlers.
+ * IRQF_TH_SCHED_NORMAL - If the IRQ is threaded, it will use SCHED_NORMAL,
+ * instead the default SCHED_FIFO scheduler
+ * IRQF_TH_NO_AFFINITY - If the IRQ is threaded, the affinity hint will not be
+ * enforced in the IRQ thread
*/
#define IRQF_SHARED 0x00000080
#define IRQF_PROBE_SHARED 0x00000100
@@ -74,6 +78,8 @@
#define IRQF_NO_THREAD 0x00010000
#define IRQF_EARLY_RESUME 0x00020000
#define IRQF_COND_SUSPEND 0x00040000
+#define IRQF_TH_SCHED_NORMAL 0x00080000
+#define IRQF_TH_NO_AFFINITY 0x00100000

#define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index cce4efd..d695e12 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1055,9 +1055,7 @@ static struct task_struct *
create_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
{
struct task_struct *t;
- struct sched_param param = {
- .sched_priority = MAX_USER_RT_PRIO/2,
- };
+ struct sched_param param;

if (!secondary) {
t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
@@ -1071,7 +1069,12 @@ create_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
if (IS_ERR(t))
return t;

- sched_setscheduler_nocheck(t, SCHED_FIFO, &param);
+ if (new->flags & IRQF_TH_SCHED_NORMAL) {
+ sched_setscheduler_nocheck(t, SCHED_NORMAL, &param);
+ } else {
+ param.sched_priority = MAX_USER_RT_PRIO/2;
+ sched_setscheduler_nocheck(t, SCHED_FIFO, &param);
+ }

/*
* We keep the reference to the task struct even if
@@ -1100,7 +1103,8 @@ setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
* correct as we want the thread to move to the cpu(s)
* on which the requesting code placed the interrupt.
*/
- set_bit(IRQTF_AFFINITY, &new->thread_flags);
+ if (!(new->flags & IRQF_TH_NO_AFFINITY))
+ set_bit(IRQTF_AFFINITY, &new->thread_flags);
return 0;
}

@@ -1549,7 +1553,8 @@ void __irq_reconfigure_action(struct irq_desc *desc, struct irqaction *action,

action->thread = t;
set_bit(IRQTF_FORCED_THREAD, &action->thread_flags);
- set_bit(IRQTF_AFFINITY, &action->thread_flags);
+ if (!(action->flags & IRQF_TH_NO_AFFINITY))
+ set_bit(IRQTF_AFFINITY, &action->thread_flags);

if (!(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) {
/*
--
1.8.3.1
\
 
 \ /
  Last update: 2016-06-15 16:21    [W:0.080 / U:0.276 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site