Module Name: src
Committed By: jdolecek
Date: Sun Oct 15 18:02:33 UTC 2017
Modified Files:
src/sys/dev/ic: wdc.c
Log Message:
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@
To generate a diff of this commit:
cvs rdiff -u -r1.284 -r1.285 src/sys/dev/ic/wdc.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/wdc.c
diff -u src/sys/dev/ic/wdc.c:1.284 src/sys/dev/ic/wdc.c:1.285
--- src/sys/dev/ic/wdc.c:1.284 Sat Oct 7 16:05:32 2017
+++ src/sys/dev/ic/wdc.c Sun Oct 15 18:02:33 2017
@@ -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);