summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2000-12-01 22:28:04 +0000
committergallatin <gallatin@FreeBSD.org>2000-12-01 22:28:04 +0000
commit537bde557a87f952713ab48b67eb60e8ab7cd9a7 (patch)
treebf3e3763c997522e702b4975340e7dc3a69b3b99
parentfe5dbadbbc9a5e5a9a1f005171380fadd6e16a02 (diff)
downloadFreeBSD-src-537bde557a87f952713ab48b67eb60e8ab7cd9a7.zip
FreeBSD-src-537bde557a87f952713ab48b67eb60e8ab7cd9a7.tar.gz
Alter isa interrupt behaviour on alpha. Rather than send a non-specific
EOI after the ithread runs, send the EOI when we get the interrupt and disable the source. After the ithread is run, the source is renabled. Also, add isa_handle_fast_intr() which handles fast interrupts by sending an EOI after the handler is run. This fixes the chronic missing interrupt problems under heavy NFS load on my UP1000 and should result in greater stability for alphas which route all irqs through an isa pic. Discussed with: jhb, bde (sending non-specific EOIs early was bde's idea)
-rw-r--r--sys/alpha/isa/isa.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/sys/alpha/isa/isa.c b/sys/alpha/isa/isa.c
index 961860c..d22f8b0 100644
--- a/sys/alpha/isa/isa.c
+++ b/sys/alpha/isa/isa.c
@@ -282,18 +282,50 @@ struct isa_intr {
*/
static void
-isa_handle_intr(void *arg)
+isa_handle_fast_intr(void *arg)
{
struct isa_intr *ii = arg;
int irq = ii->irq;
ii->intr(ii->arg);
- if (ii->irq > 7)
+ if (irq > 7)
outb(IO_ICU2, 0x20 | (irq & 7));
outb(IO_ICU1, 0x20 | (irq > 7 ? 2 : irq));
}
+static void
+isa_handle_intr(void *arg)
+{
+ struct isa_intr *ii = arg;
+
+ ii->intr(ii->arg);
+}
+
+/*
+ * Send a non-specific EIO early, then disable the source
+ */
+
+static void
+isa_disable_intr(int vector)
+{
+ int irq = (vector - 0x800) >> 4;
+
+ if (irq > 7)
+ outb(IO_ICU2, 0x20 | (irq & 7));
+ outb(IO_ICU1, 0x20 | (irq > 7 ? 2 : irq));
+
+ isa_intr_disable(irq);
+}
+
+static void
+isa_enable_intr(int vector)
+{
+ int irq = (vector - 0x800) >> 4;
+ isa_intr_enable(irq);
+}
+
+
int
isa_setup_intr(device_t dev, device_t child,
struct resource *irq, int flags,
@@ -319,10 +351,12 @@ isa_setup_intr(device_t dev, device_t child,
error = alpha_setup_intr(
device_get_nameunit(child ? child : dev),
- 0x800 + (irq->r_start << 4), isa_handle_intr, ii,
+ 0x800 + (irq->r_start << 4),
+ ((flags & INTR_FAST) ? isa_handle_fast_intr :
+ isa_handle_intr), ii,
ithread_priority(flags), flags, &ii->ih,
&intrcnt[INTRCNT_ISA_IRQ + irq->r_start],
- NULL, NULL);
+ isa_disable_intr, isa_enable_intr);
if (error) {
free(ii, M_DEVBUF);
return error;
OpenPOWER on IntegriCloud