Skip to content

Commit 2a1d3ab

Browse files
committed
genirq: Handle force threading of irqs with primary and thread handler
Force threading of interrupts does not really deal with interrupts which are requested with a primary and a threaded handler. The current policy is to leave them alone and let the primary handler run in interrupt context, but we set the ONESHOT flag for those interrupts as well. Kohji Okuno debugged a problem with the SDHCI driver where the interrupt thread waits for a hardware interrupt to trigger, which can't work well because the hardware interrupt is masked due to the ONESHOT flag being set. He proposed to set the ONESHOT flag only if the interrupt does not provide a thread handler. Though that does not work either because these interrupts can be shared. So the other interrupt would rightfully get the ONESHOT flag set and therefor the same situation would happen again. To deal with this proper, we need to force thread the primary handler of such interrupts as well. That means that the primary interrupt handler is treated as any other primary interrupt handler which is not marked IRQF_NO_THREAD. The threaded handler becomes a separate thread so the SDHCI flow logic can be handled gracefully. The same issue was reported against 4.1-rt. Reported-and-tested-by: Kohji Okuno <[email protected]> Reported-By: Michal Smucr <[email protected]> Reported-and-tested-by: Nathan Sullivan <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: Sebastian Andrzej Siewior <[email protected]> Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1509211058080.5606@nanos Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 1f93e4a commit 2a1d3ab

File tree

2 files changed

+119
-41
lines changed

2 files changed

+119
-41
lines changed

include/linux/interrupt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
102102
* @flags: flags (see IRQF_* above)
103103
* @thread_fn: interrupt handler function for threaded interrupts
104104
* @thread: thread pointer for threaded interrupts
105+
* @secondary: pointer to secondary irqaction (force threading)
105106
* @thread_flags: flags related to @thread
106107
* @thread_mask: bitmask for keeping track of @thread activity
107108
* @dir: pointer to the proc/irq/NN/name entry
@@ -113,6 +114,7 @@ struct irqaction {
113114
struct irqaction *next;
114115
irq_handler_t thread_fn;
115116
struct task_struct *thread;
117+
struct irqaction *secondary;
116118
unsigned int irq;
117119
unsigned int flags;
118120
unsigned long thread_flags;

kernel/irq/manage.c

Lines changed: 117 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,12 @@ static irqreturn_t irq_nested_primary_handler(int irq, void *dev_id)
730730
return IRQ_NONE;
731731
}
732732

733+
static irqreturn_t irq_forced_secondary_handler(int irq, void *dev_id)
734+
{
735+
WARN(1, "Secondary action handler called for irq %d\n", irq);
736+
return IRQ_NONE;
737+
}
738+
733739
static int irq_wait_for_interrupt(struct irqaction *action)
734740
{
735741
set_current_state(TASK_INTERRUPTIBLE);
@@ -756,7 +762,8 @@ static int irq_wait_for_interrupt(struct irqaction *action)
756762
static void irq_finalize_oneshot(struct irq_desc *desc,
757763
struct irqaction *action)
758764
{
759-
if (!(desc->istate & IRQS_ONESHOT))
765+
if (!(desc->istate & IRQS_ONESHOT) ||
766+
action->handler == irq_forced_secondary_handler)
760767
return;
761768
again:
762769
chip_bus_lock(desc);
@@ -910,6 +917,18 @@ static void irq_thread_dtor(struct callback_head *unused)
910917
irq_finalize_oneshot(desc, action);
911918
}
912919

920+
static void irq_wake_secondary(struct irq_desc *desc, struct irqaction *action)
921+
{
922+
struct irqaction *secondary = action->secondary;
923+
924+
if (WARN_ON_ONCE(!secondary))
925+
return;
926+
927+
raw_spin_lock_irq(&desc->lock);
928+
__irq_wake_thread(desc, secondary);
929+
raw_spin_unlock_irq(&desc->lock);
930+
}
931+
913932
/*
914933
* Interrupt handler thread
915934
*/
@@ -940,6 +959,8 @@ static int irq_thread(void *data)
940959
action_ret = handler_fn(desc, action);
941960
if (action_ret == IRQ_HANDLED)
942961
atomic_inc(&desc->threads_handled);
962+
if (action_ret == IRQ_WAKE_THREAD)
963+
irq_wake_secondary(desc, action);
943964

944965
wake_threads_waitq(desc);
945966
}
@@ -984,20 +1005,36 @@ void irq_wake_thread(unsigned int irq, void *dev_id)
9841005
}
9851006
EXPORT_SYMBOL_GPL(irq_wake_thread);
9861007

987-
static void irq_setup_forced_threading(struct irqaction *new)
1008+
static int irq_setup_forced_threading(struct irqaction *new)
9881009
{
9891010
if (!force_irqthreads)
990-
return;
1011+
return 0;
9911012
if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
992-
return;
1013+
return 0;
9931014

9941015
new->flags |= IRQF_ONESHOT;
9951016

996-
if (!new->thread_fn) {
997-
set_bit(IRQTF_FORCED_THREAD, &new->thread_flags);
998-
new->thread_fn = new->handler;
999-
new->handler = irq_default_primary_handler;
1017+
/*
1018+
* Handle the case where we have a real primary handler and a
1019+
* thread handler. We force thread them as well by creating a
1020+
* secondary action.
1021+
*/
1022+
if (new->handler != irq_default_primary_handler && new->thread_fn) {
1023+
/* Allocate the secondary action */
1024+
new->secondary = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
1025+
if (!new->secondary)
1026+
return -ENOMEM;
1027+
new->secondary->handler = irq_forced_secondary_handler;
1028+
new->secondary->thread_fn = new->thread_fn;
1029+
new->secondary->dev_id = new->dev_id;
1030+
new->secondary->irq = new->irq;
1031+
new->secondary->name = new->name;
10001032
}
1033+
/* Deal with the primary handler */
1034+
set_bit(IRQTF_FORCED_THREAD, &new->thread_flags);
1035+
new->thread_fn = new->handler;
1036+
new->handler = irq_default_primary_handler;
1037+
return 0;
10011038
}
10021039

10031040
static int irq_request_resources(struct irq_desc *desc)
@@ -1017,6 +1054,48 @@ static void irq_release_resources(struct irq_desc *desc)
10171054
c->irq_release_resources(d);
10181055
}
10191056

1057+
static int
1058+
setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
1059+
{
1060+
struct task_struct *t;
1061+
struct sched_param param = {
1062+
.sched_priority = MAX_USER_RT_PRIO/2,
1063+
};
1064+
1065+
if (!secondary) {
1066+
t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
1067+
new->name);
1068+
} else {
1069+
t = kthread_create(irq_thread, new, "irq/%d-s-%s", irq,
1070+
new->name);
1071+
param.sched_priority -= 1;
1072+
}
1073+
1074+
if (IS_ERR(t))
1075+
return PTR_ERR(t);
1076+
1077+
sched_setscheduler_nocheck(t, SCHED_FIFO, &param);
1078+
1079+
/*
1080+
* We keep the reference to the task struct even if
1081+
* the thread dies to avoid that the interrupt code
1082+
* references an already freed task_struct.
1083+
*/
1084+
get_task_struct(t);
1085+
new->thread = t;
1086+
/*
1087+
* Tell the thread to set its affinity. This is
1088+
* important for shared interrupt handlers as we do
1089+
* not invoke setup_affinity() for the secondary
1090+
* handlers as everything is already set up. Even for
1091+
* interrupts marked with IRQF_NO_BALANCE this is
1092+
* correct as we want the thread to move to the cpu(s)
1093+
* on which the requesting code placed the interrupt.
1094+
*/
1095+
set_bit(IRQTF_AFFINITY, &new->thread_flags);
1096+
return 0;
1097+
}
1098+
10201099
/*
10211100
* Internal function to register an irqaction - typically used to
10221101
* allocate special interrupts that are part of the architecture.
@@ -1037,6 +1116,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
10371116
if (!try_module_get(desc->owner))
10381117
return -ENODEV;
10391118

1119+
new->irq = irq;
1120+
10401121
/*
10411122
* Check whether the interrupt nests into another interrupt
10421123
* thread.
@@ -1054,8 +1135,11 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
10541135
*/
10551136
new->handler = irq_nested_primary_handler;
10561137
} else {
1057-
if (irq_settings_can_thread(desc))
1058-
irq_setup_forced_threading(new);
1138+
if (irq_settings_can_thread(desc)) {
1139+
ret = irq_setup_forced_threading(new);
1140+
if (ret)
1141+
goto out_mput;
1142+
}
10591143
}
10601144

10611145
/*
@@ -1064,37 +1148,14 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
10641148
* thread.
10651149
*/
10661150
if (new->thread_fn && !nested) {
1067-
struct task_struct *t;
1068-
static const struct sched_param param = {
1069-
.sched_priority = MAX_USER_RT_PRIO/2,
1070-
};
1071-
1072-
t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
1073-
new->name);
1074-
if (IS_ERR(t)) {
1075-
ret = PTR_ERR(t);
1151+
ret = setup_irq_thread(new, irq, false);
1152+
if (ret)
10761153
goto out_mput;
1154+
if (new->secondary) {
1155+
ret = setup_irq_thread(new->secondary, irq, true);
1156+
if (ret)
1157+
goto out_thread;
10771158
}
1078-
1079-
sched_setscheduler_nocheck(t, SCHED_FIFO, &param);
1080-
1081-
/*
1082-
* We keep the reference to the task struct even if
1083-
* the thread dies to avoid that the interrupt code
1084-
* references an already freed task_struct.
1085-
*/
1086-
get_task_struct(t);
1087-
new->thread = t;
1088-
/*
1089-
* Tell the thread to set its affinity. This is
1090-
* important for shared interrupt handlers as we do
1091-
* not invoke setup_affinity() for the secondary
1092-
* handlers as everything is already set up. Even for
1093-
* interrupts marked with IRQF_NO_BALANCE this is
1094-
* correct as we want the thread to move to the cpu(s)
1095-
* on which the requesting code placed the interrupt.
1096-
*/
1097-
set_bit(IRQTF_AFFINITY, &new->thread_flags);
10981159
}
10991160

11001161
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
@@ -1267,7 +1328,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
12671328
irq, nmsk, omsk);
12681329
}
12691330

1270-
new->irq = irq;
12711331
*old_ptr = new;
12721332

12731333
irq_pm_install_action(desc, new);
@@ -1293,6 +1353,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
12931353
*/
12941354
if (new->thread)
12951355
wake_up_process(new->thread);
1356+
if (new->secondary)
1357+
wake_up_process(new->secondary->thread);
12961358

12971359
register_irq_proc(irq, desc);
12981360
new->dir = NULL;
@@ -1323,6 +1385,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
13231385
kthread_stop(t);
13241386
put_task_struct(t);
13251387
}
1388+
if (new->secondary && new->secondary->thread) {
1389+
struct task_struct *t = new->secondary->thread;
1390+
1391+
new->secondary->thread = NULL;
1392+
kthread_stop(t);
1393+
put_task_struct(t);
1394+
}
13261395
out_mput:
13271396
module_put(desc->owner);
13281397
return ret;
@@ -1430,9 +1499,14 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
14301499
if (action->thread) {
14311500
kthread_stop(action->thread);
14321501
put_task_struct(action->thread);
1502+
if (action->secondary && action->secondary->thread) {
1503+
kthread_stop(action->secondary->thread);
1504+
put_task_struct(action->secondary->thread);
1505+
}
14331506
}
14341507

14351508
module_put(desc->owner);
1509+
kfree(action->secondary);
14361510
return action;
14371511
}
14381512

@@ -1576,8 +1650,10 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
15761650
retval = __setup_irq(irq, desc, action);
15771651
chip_bus_sync_unlock(desc);
15781652

1579-
if (retval)
1653+
if (retval) {
1654+
kfree(action->secondary);
15801655
kfree(action);
1656+
}
15811657

15821658
#ifdef CONFIG_DEBUG_SHIRQ_FIXME
15831659
if (!retval && (irqflags & IRQF_SHARED)) {

0 commit comments

Comments
 (0)