diff options
author | Paul Winder <paul.winder@tegile.com> | 2018-06-01 13:56:28 +0000 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2018-06-11 11:27:48 -0400 |
commit | af7c4cb5225cc98e505e165d8fe7b59f98595bbc (patch) | |
tree | 8d010f2fcb66b2c10972131a686bde294e568f12 | |
parent | 52733287cd3e89957eb2a0c46360ce71b51a3070 (diff) | |
download | illumos-joyent-af7c4cb5225cc98e505e165d8fe7b59f98595bbc.tar.gz |
9575 apix can lose interrupts after interrupt thread blocks
Reviewed by: Igor Kozhukhov <igor@dilos.org>
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Reviewed by: Ken Mays <kmays2000@gmail.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r-- | usr/src/uts/i86pc/io/apix/apix_intr.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/usr/src/uts/i86pc/io/apix/apix_intr.c b/usr/src/uts/i86pc/io/apix/apix_intr.c index 752a4045da..227ce0c991 100644 --- a/usr/src/uts/i86pc/io/apix/apix_intr.c +++ b/usr/src/uts/i86pc/io/apix/apix_intr.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018 Western Digital Corporation. All rights reserved. */ #include <sys/cpuvar.h> @@ -330,6 +331,13 @@ apix_do_softint_epilog(struct cpu *cpu, uint_t oldpil) set_base_spl(); /* mcpu->mcpu_pri = cpu->cpu_base_spl; */ + /* + * If there are pending interrupts, send a softint to + * re-enter apix_do_interrupt() and get them processed. + */ + if (apixs[cpu->cpu_id]->x_intr_pending) + siron(); + it->t_state = TS_FREE; it->t_link = cpu->cpu_intr_thread; cpu->cpu_intr_thread = it; @@ -720,6 +728,13 @@ apix_intr_thread_epilog(struct cpu *cpu, uint_t oldpil) mcpu->mcpu_pri = basespl; (*setlvlx)(basespl, 0); + /* + * If there are pending interrupts, send a softint to + * re-enter apix_do_interrupt() and get them processed. + */ + if (apixs[cpu->cpu_id]->x_intr_pending) + siron(); + it->t_state = TS_FREE; /* * Return interrupt thread to pool @@ -937,7 +952,14 @@ apix_do_interrupt(struct regs *rp, trap_trace_rec_t *ttp) newipl > MAX(oldipl, cpu->cpu_base_spl)) { caddr_t newsp; - if (newipl > LOCK_LEVEL) { + if (INTR_PENDING(apixs[cpu->cpu_id], newipl)) { + /* + * There are already vectors pending at newipl, + * queue this one and fall through to process + * all pending. + */ + apix_add_pending_hardint(vector); + } else if (newipl > LOCK_LEVEL) { if (apix_hilevel_intr_prolog(cpu, newipl, oldipl, rp) == 0) { newsp = cpu->cpu_intr_stack; |