summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Winder <paul.winder@tegile.com>2018-06-01 13:56:28 +0000
committerDan McDonald <danmcd@joyent.com>2018-06-11 11:27:48 -0400
commitaf7c4cb5225cc98e505e165d8fe7b59f98595bbc (patch)
tree8d010f2fcb66b2c10972131a686bde294e568f12
parent52733287cd3e89957eb2a0c46360ce71b51a3070 (diff)
downloadillumos-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.c24
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;