summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorjdolecek <jdolecek@NetBSD.org>2017-10-15 18:02:33 +0000
committerjdolecek <jdolecek@NetBSD.org>2017-10-15 18:02:33 +0000
commit82cccface7d2f0efa0117052d13142482c35a5bf (patch)
tree3e98f5d4c49cf4d3571499f0e928f2784ec6bf22 /sys/dev/ic
parent18b862c68ebbbe44b8e11dec4b02c025846c7c7c (diff)
explicitely ignore polled xfers in wdcintr(), so it won't be processed
twice - seems setting WDSD_IBM actually has no effect at least on some PCI-IDE, and the interrupt ends up being triggered when we release the channel lock to call c_poll hook fixes PR kern/52605, and should also fix the 'New panic in wdc_ata_bio_intr' reported on current-users@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/wdc.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c
index 72706e16d27..cdbde2e09f3 100644
--- a/sys/dev/ic/wdc.c
+++ b/sys/dev/ic/wdc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.284 2017/10/07 16:05:32 jdolecek Exp $ */
+/* $NetBSD: wdc.c,v 1.285 2017/10/15 18:02:33 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.284 2017/10/07 16:05:32 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.285 2017/10/15 18:02:33 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -882,12 +882,24 @@ wdcintr(void *arg)
xfer = ata_queue_get_active_xfer(chp);
if (xfer == NULL) {
ATADEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR);
+ignore:
/* try to clear the pending interrupt anyway */
(void)bus_space_read_1(wdr->cmd_iot,
wdr->cmd_iohs[wd_status], 0);
return (0);
}
+ /*
+ * On some controllers (e.g. some PCI-IDE) setting the WDSD_IBM bit
+ * actually has no effect, and interrupt is triggered regardless.
+ * Ignore polled commands here, they are processed separately.
+ */
+ if (ISSET(xfer->c_flags, C_POLL)) {
+ ATADEBUG_PRINT(("%s: polled xfer ignored\n", __func__),
+ DEBUG_INTR);
+ goto ignore;
+ }
+
ATADEBUG_PRINT(("wdcintr\n"), DEBUG_INTR);
KASSERT(xfer != NULL);