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);