In some particular cases (like in pccard and pccbb), the real device

handler is wrapped in a couple of functions - a filter wrapper and an
ithread wrapper. In this case (and just in this case), the filter
wrapper could ask the system to schedule the ithread and mask the
interrupt source if the wrapped handler is composed of just an ithread
handler: modify the "old" interrupt code to make it support
this situation, while the "new" interrupt code is already ok.

Discussed with: jhb
This commit is contained in:
Paolo Pisati 2007-05-31 19:25:35 +00:00
parent bba4862c64
commit 3401f2c1df
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=170162
8 changed files with 89 additions and 19 deletions

View file

@ -310,7 +310,7 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
struct thread *td;
struct intr_event *ie;
struct intr_handler *ih;
int error, vector, thread;
int error, vector, thread, ret;
td = curthread;
@ -356,6 +356,7 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
* a trapframe as its argument.
*/
td->td_intr_nesting_level++;
ret = 0;
thread = 0;
critical_enter();
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
@ -367,9 +368,17 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
ih->ih_filter, ih->ih_argument == NULL ? frame :
ih->ih_argument, ih->ih_name);
if (ih->ih_argument == NULL)
ih->ih_filter(frame);
ret = ih->ih_filter(frame);
else
ih->ih_filter(ih->ih_argument);
ret = ih->ih_filter(ih->ih_argument);
/*
* Wrapper handler special case: see
* i386/intr_machdep.c::intr_execute_handlers()
*/
if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD)
thread = 1;
}
}
/*

View file

@ -104,7 +104,7 @@ arm_handler_execute(struct trapframe *frame, int irqnb)
struct intr_event *event;
struct intr_handler *ih;
struct thread *td = curthread;
int i, thread;
int i, thread, ret;
PCPU_LAZY_INC(cnt.v_intr);
td->td_intr_nesting_level++;
@ -116,13 +116,22 @@ arm_handler_execute(struct trapframe *frame, int irqnb)
continue;
/* Execute fast handlers. */
ret = 0;
thread = 0;
TAILQ_FOREACH(ih, &event->ie_handlers, ih_next) {
if (ih->ih_filter == NULL)
thread = 1;
else
ih->ih_filter(ih->ih_argument ?
ret = ih->ih_filter(ih->ih_argument ?
ih->ih_argument : frame);
/*
* Wrapper handler special case: see
* i386/intr_machdep.c::intr_execute_handlers()
*/
if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD)
thread = 1;
}
}
/* Schedule thread if needed. */

View file

@ -301,7 +301,7 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
struct thread *td;
struct intr_event *ie;
struct intr_handler *ih;
int error, vector, thread;
int error, vector, thread, ret;
td = curthread;
@ -347,6 +347,7 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
* a trapframe as its argument.
*/
td->td_intr_nesting_level++;
ret = 0;
thread = 0;
critical_enter();
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
@ -358,9 +359,27 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
ih->ih_filter, ih->ih_argument == NULL ? frame :
ih->ih_argument, ih->ih_name);
if (ih->ih_argument == NULL)
ih->ih_filter(frame);
ret = ih->ih_filter(frame);
else
ih->ih_filter(ih->ih_argument);
ret = ih->ih_filter(ih->ih_argument);
/*
* Wrapper handler special handling:
*
* in some particular cases (like pccard and pccbb),
* the _real_ device handler is wrapped in a couple of
* functions - a filter wrapper and an ithread wrapper.
* In this case (and just in this case), the filter wrapper
* could ask the system to schedule the ithread and mask
* the interrupt source if the wrapped handler is composed
* of just an ithread handler.
*
* TODO: write a generic wrapper to avoid people rolling
* their own
*/
if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD)
thread = 1;
}
}
/*

View file

@ -353,7 +353,7 @@ ia64_dispatch_intr(void *frame, unsigned long vector)
struct ia64_intr *i;
struct intr_event *ie; /* our interrupt event */
struct intr_handler *ih;
int error, thread;
int error, thread, ret;
/*
* Find the interrupt thread for this vector.
@ -379,6 +379,7 @@ ia64_dispatch_intr(void *frame, unsigned long vector)
* Execute all fast interrupt handlers directly without Giant. Note
* that this means that any fast interrupt handler must be MP safe.
*/
ret = 0;
thread = 0;
critical_enter();
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
@ -388,7 +389,15 @@ ia64_dispatch_intr(void *frame, unsigned long vector)
}
CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
ih->ih_filter, ih->ih_argument, ih->ih_name);
ih->ih_filter(ih->ih_argument);
ret = ih->ih_filter(ih->ih_argument);
/*
* Wrapper handler special case: see
* i386/intr_machdep.c::intr_execute_handlers()
*/
if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD)
thread = 1;
}
}
critical_exit();

View file

@ -1264,9 +1264,6 @@ intr_filter_loop(struct intr_event *ie, struct trapframe *frame,
continue;
}
KASSERT(ret != FILTER_SCHEDULE_THREAD,
("intr_filter_loop: FILTER_SCHEDULE_THREAD from filter"));
if (ret & FILTER_STRAY)
continue;
else {

View file

@ -198,7 +198,7 @@ intr_handle(u_int irq)
struct ppc_intr *i;
struct intr_event *ie;
struct intr_handler *ih;
int error, sched;
int error, sched, ret;
i = ppc_intrs[irq];
if (i == NULL)
@ -216,6 +216,7 @@ intr_handle(u_int irq)
* Execute all fast interrupt handlers directly without Giant. Note
* that this means that any fast interrupt handler must be MP safe.
*/
ret = 0;
sched = 0;
critical_enter();
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
@ -225,7 +226,15 @@ intr_handle(u_int irq)
}
CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
ih->ih_filter, ih->ih_argument, ih->ih_name);
ih->ih_filter(ih->ih_argument);
ret = ih->ih_filter(ih->ih_argument);
/*
* Wrapper handler special case: see
* i386/intr_machdep.c::intr_execute_handlers()
*/
if (!sched) {
if (ret == FILTER_SCHEDULE_THREAD)
sched = 1;
}
}
critical_exit();

View file

@ -236,7 +236,7 @@ intr_execute_handlers(void *cookie)
struct intr_vector *iv;
struct intr_event *ie;
struct intr_handler *ih;
int error, thread;
int error, thread, ret;
iv = cookie;
ie = iv->iv_event;
@ -246,6 +246,7 @@ intr_execute_handlers(void *cookie)
}
/* Execute fast interrupt handlers directly. */
ret = 0;
thread = 0;
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (ih->ih_filter == NULL) {
@ -255,7 +256,15 @@ intr_execute_handlers(void *cookie)
MPASS(ih->ih_filter != NULL && ih->ih_argument != NULL);
CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__,
ih->ih_filter, ih->ih_argument);
ih->ih_filter(ih->ih_argument);
ret = ih->ih_filter(ih->ih_argument);
/*
* Wrapper handler special case: see
* i386/intr_machdep.c::intr_execute_handlers()
*/
if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD)
thread = 1;
}
}
/* Schedule a heavyweight interrupt process. */

View file

@ -283,7 +283,7 @@ intr_execute_handlers(void *cookie)
struct intr_vector *iv;
struct intr_event *ie;
struct intr_handler *ih;
int fast, thread;
int fast, thread, ret;
iv = cookie;
ie = iv->iv_event;
@ -292,6 +292,7 @@ intr_execute_handlers(void *cookie)
return;
}
ret = 0;
fast = thread = 0;
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (ih->ih_filter == NULL) {
@ -301,8 +302,16 @@ intr_execute_handlers(void *cookie)
MPASS(ih->ih_filter != NULL && ih->ih_argument != NULL);
CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__,
ih->ih_filter, ih->ih_argument);
ih->ih_filter(ih->ih_argument);
ret = ih->ih_filter(ih->ih_argument);
fast = 1;
/*
* Wrapper handler special case: see
* i386/intr_machdep.c::intr_execute_handlers()
*/
if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD)
thread = 1;
}
}
/* Schedule a heavyweight interrupt process. */