Module Name: src Committed By: jdolecek Date: Fri Aug 31 19:08:03 UTC 2018
Modified Files: src/sys/dev/ata [jdolecek-ncqfixes]: ata.c ata_subr.c ata_wdc.c atavar.h wd.c wdvar.h src/sys/dev/ic [jdolecek-ncqfixes]: ahcisata_core.c mvsata.c siisata.c wdc.c src/sys/dev/scsipi [jdolecek-ncqfixes]: atapi_wdc.c Log Message: refactor ata_xfer to be just dumb structure; move all callouts/condvars out retry callout to wd(4); reset callout and the active/cmd finish condvars to channel queue; change code using the condvars so it works if there are multiple waiters simplify the async wait code for cmds, replace ata_wait_xfer()/ata_wake_xfer() with ata_wait_cmd() fix the callout_invoking/ack race handling code for timeouts to actually have chance to work; change mvsata(4) to use generic timeout func towards resolution of kern/52614 To generate a diff of this commit: cvs rdiff -u -r1.141 -r1.141.6.1 src/sys/dev/ata/ata.c cvs rdiff -u -r1.6 -r1.6.2.1 src/sys/dev/ata/ata_subr.c cvs rdiff -u -r1.110 -r1.110.4.1 src/sys/dev/ata/ata_wdc.c cvs rdiff -u -r1.99 -r1.99.2.1 src/sys/dev/ata/atavar.h cvs rdiff -u -r1.441 -r1.441.2.1 src/sys/dev/ata/wd.c cvs rdiff -u -r1.46 -r1.46.6.1 src/sys/dev/ata/wdvar.h cvs rdiff -u -r1.62 -r1.62.2.1 src/sys/dev/ic/ahcisata_core.c cvs rdiff -u -r1.41 -r1.41.2.1 src/sys/dev/ic/mvsata.c cvs rdiff -u -r1.35 -r1.35.6.1 src/sys/dev/ic/siisata.c cvs rdiff -u -r1.288 -r1.288.6.1 src/sys/dev/ic/wdc.c cvs rdiff -u -r1.129 -r1.129.6.1 src/sys/dev/scsipi/atapi_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/ata/ata.c diff -u src/sys/dev/ata/ata.c:1.141 src/sys/dev/ata/ata.c:1.141.6.1 --- src/sys/dev/ata/ata.c:1.141 Sat Oct 28 04:53:54 2017 +++ src/sys/dev/ata/ata.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ata.c,v 1.141 2017/10/28 04:53:54 riastradh Exp $ */ +/* $NetBSD: ata.c,v 1.141.6.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141 2017/10/28 04:53:54 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141.6.1 2018/08/31 19:08:03 jdolecek Exp $"); #include "opt_ata.h" @@ -1075,19 +1075,19 @@ ata_exec_xfer(struct ata_channel *chp, s while (chp->ch_queue->queue_active > 0 || TAILQ_FIRST(&chp->ch_queue->queue_xfer) != xfer) { xfer->c_flags |= C_WAITACT; - cv_wait(&xfer->c_active, &chp->ch_lock); + cv_wait(&chp->ch_queue->c_active, &chp->ch_lock); xfer->c_flags &= ~C_WAITACT; + } - /* - * Free xfer now if it there was attempt to free it - * while we were waiting. - */ - if ((xfer->c_flags & (C_FREE|C_WAITTIMO)) == C_FREE) { - ata_channel_unlock(chp); + /* + * Free xfer now if it there was attempt to free it + * while we were waiting. + */ + if ((xfer->c_flags & (C_FREE|C_WAITTIMO)) == C_FREE) { + ata_channel_unlock(chp); - ata_free_xfer(chp, xfer); - return; - } + ata_free_xfer(chp, xfer); + return; } } @@ -1187,7 +1187,7 @@ again: ATADEBUG_PRINT(("atastart: xfer %p channel %d drive %d " "wait active\n", xfer, chp->ch_channel, xfer->c_drive), DEBUG_XFERS); - cv_signal(&xfer->c_active); + cv_broadcast(&chp->ch_queue->c_active); goto out; } @@ -1300,15 +1300,20 @@ ata_deactivate_xfer(struct ata_channel * KASSERT(chq->queue_active > 0); KASSERT((chq->active_xfers_used & __BIT(xfer->c_slot)) != 0); - callout_stop(&xfer->c_timo_callout); + /* Stop only when this is last active xfer */ + if (chq->queue_active == 1) + callout_stop(&chp->c_timo_callout); - if (callout_invoking(&xfer->c_timo_callout)) + if (callout_invoking(&chp->c_timo_callout)) xfer->c_flags |= C_WAITTIMO; TAILQ_REMOVE(&chq->active_xfers, xfer, c_activechain); chq->active_xfers_used &= ~__BIT(xfer->c_slot); chq->queue_active--; + if (xfer->c_flags & C_WAIT) + cv_broadcast(&chq->c_cmd_finish); + ata_channel_unlock(chp); } @@ -1356,8 +1361,6 @@ ata_timo_xfer_check(struct ata_xfer *xfe ata_channel_lock(chp); - callout_ack(&xfer->c_timo_callout); - if (xfer->c_flags & C_WAITTIMO) { xfer->c_flags &= ~C_WAITTIMO; @@ -1389,30 +1392,6 @@ ata_timo_xfer_check(struct ata_xfer *xfe return false; } -void -ata_timeout(void *v) -{ - struct ata_xfer *xfer = v; - int s; - - ATADEBUG_PRINT(("%s: slot %d\n", __func__, xfer->c_slot), - DEBUG_FUNCS|DEBUG_XFERS); - - s = splbio(); /* XXX MPSAFE */ - - if (ata_timo_xfer_check(xfer)) { - /* Already logged */ - goto out; - } - - /* Mark as timed out. Do not print anything, wd(4) will. */ - xfer->c_flags |= C_TIMEOU; - xfer->c_intr(xfer->c_chp, xfer, 0); - -out: - splx(s); -} - /* * Kill off all active xfers for a ata_channel. * @@ -2304,17 +2283,17 @@ atacmd_toncq(struct ata_xfer *xfer, uint } void -ata_wait_xfer(struct ata_channel *chp, struct ata_xfer *xfer) +ata_wait_cmd(struct ata_channel *chp, struct ata_xfer *xfer) { - KASSERT(mutex_owned(&chp->ch_lock)); + struct ata_queue *chq = chp->ch_queue; + struct ata_command *ata_c = &xfer->c_ata_c; - cv_wait(&xfer->c_finish, &chp->ch_lock); -} + ata_channel_lock(chp); -void -ata_wake_xfer(struct ata_channel *chp, struct ata_xfer *xfer) -{ - KASSERT(mutex_owned(&chp->ch_lock)); + while ((ata_c->flags & AT_DONE) == 0) + cv_wait(&chq->c_cmd_finish, &chp->ch_lock); + + ata_channel_unlock(chp); - cv_signal(&xfer->c_finish); + KASSERT((ata_c->flags & AT_DONE) != 0); } Index: src/sys/dev/ata/ata_subr.c diff -u src/sys/dev/ata/ata_subr.c:1.6 src/sys/dev/ata/ata_subr.c:1.6.2.1 --- src/sys/dev/ata/ata_subr.c:1.6 Fri Aug 10 22:43:22 2018 +++ src/sys/dev/ata/ata_subr.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ata_subr.c,v 1.6 2018/08/10 22:43:22 jdolecek Exp $ */ +/* $NetBSD: ata_subr.c,v 1.6.2.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata_subr.c,v 1.6 2018/08/10 22:43:22 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_subr.c,v 1.6.2.1 2018/08/31 19:08:03 jdolecek Exp $"); #include "opt_ata.h" @@ -158,30 +158,6 @@ ata_queue_drive_active_xfer(struct ata_c return xfer; } -static void -ata_xfer_init(struct ata_xfer *xfer, uint8_t slot) -{ - memset(xfer, 0, sizeof(*xfer)); - - xfer->c_slot = slot; - - cv_init(&xfer->c_active, "ataact"); - cv_init(&xfer->c_finish, "atafin"); - callout_init(&xfer->c_timo_callout, 0); /* XXX MPSAFE */ - callout_init(&xfer->c_retry_callout, 0); /* XXX MPSAFE */ -} - -static void -ata_xfer_destroy(struct ata_xfer *xfer) -{ - callout_halt(&xfer->c_timo_callout, NULL); /* XXX MPSAFE */ - callout_destroy(&xfer->c_timo_callout); - callout_halt(&xfer->c_retry_callout, NULL); /* XXX MPSAFE */ - callout_destroy(&xfer->c_retry_callout); - cv_destroy(&xfer->c_active); - cv_destroy(&xfer->c_finish); -} - struct ata_queue * ata_queue_alloc(uint8_t openings) { @@ -201,8 +177,11 @@ ata_queue_alloc(uint8_t openings) cv_init(&chq->queue_drain, "atdrn"); cv_init(&chq->queue_idle, "qidl"); + cv_init(&chq->c_active, "ataact"); + cv_init(&chq->c_cmd_finish, "atafin"); + for (uint8_t i = 0; i < openings; i++) - ata_xfer_init(&chq->queue_xfers[i], i); + chq->queue_xfers[i].c_slot = i; return chq; } @@ -210,13 +189,13 @@ ata_queue_alloc(uint8_t openings) void ata_queue_free(struct ata_queue *chq) { - for (uint8_t i = 0; i < chq->queue_openings; i++) - ata_xfer_destroy(&chq->queue_xfers[i]); - cv_destroy(&chq->queue_busy); cv_destroy(&chq->queue_drain); cv_destroy(&chq->queue_idle); + cv_destroy(&chq->c_active); + cv_destroy(&chq->c_cmd_finish); + free(chq, M_DEVBUF); } @@ -226,6 +205,8 @@ ata_channel_init(struct ata_channel *chp mutex_init(&chp->ch_lock, MUTEX_DEFAULT, IPL_BIO); cv_init(&chp->ch_thr_idle, "atath"); + callout_init(&chp->c_timo_callout, 0); /* XXX MPSAFE */ + /* Optionally setup the queue, too */ if (chp->ch_queue == NULL) { chp->ch_queue = ata_queue_alloc(1); @@ -240,6 +221,11 @@ ata_channel_destroy(struct ata_channel * chp->ch_queue = NULL; } + mutex_enter(&chp->ch_lock); + callout_halt(&chp->c_timo_callout, &chp->ch_lock); + callout_destroy(&chp->c_timo_callout); + mutex_exit(&chp->ch_lock); + mutex_destroy(&chp->ch_lock); cv_destroy(&chp->ch_thr_idle); } @@ -336,7 +322,7 @@ ata_free_xfer(struct ata_channel *chp, s if (xfer->c_flags & (C_WAITACT|C_WAITTIMO)) { /* Someone is waiting for this xfer, so we can't free now */ xfer->c_flags |= C_FREE; - cv_signal(&xfer->c_active); + cv_broadcast(&chq->c_active); goto out; } @@ -372,6 +358,40 @@ out: DEBUG_XFERS); } +void +ata_timeout(void *v) +{ + struct ata_channel *chp = v; + struct ata_queue *chq = chp->ch_queue; + struct ata_xfer *xfer, *nxfer; + int s; + + s = splbio(); /* XXX MPSAFE */ + + callout_ack(&chp->c_timo_callout); + + /* + * If there is a timeout, means the last enqueued command + * timed out, and thus all commands timed out. + * XXX locking + */ + TAILQ_FOREACH_SAFE(xfer, &chq->active_xfers, c_activechain, nxfer) { + ATADEBUG_PRINT(("%s: slot %d\n", __func__, xfer->c_slot), + DEBUG_FUNCS|DEBUG_XFERS); + + if (ata_timo_xfer_check(xfer)) { + /* Already logged */ + continue; + } + + /* Mark as timed out. Do not print anything, wd(4) will. */ + xfer->c_flags |= C_TIMEOU; + xfer->c_intr(xfer->c_chp, xfer, 0); + } + + splx(s); +} + /* * Must be called without any locks, i.e. with both drive and channel locks * released. Index: src/sys/dev/ata/ata_wdc.c diff -u src/sys/dev/ata/ata_wdc.c:1.110 src/sys/dev/ata/ata_wdc.c:1.110.4.1 --- src/sys/dev/ata/ata_wdc.c:1.110 Fri Jun 1 18:13:30 2018 +++ src/sys/dev/ata/ata_wdc.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ata_wdc.c,v 1.110 2018/06/01 18:13:30 macallan Exp $ */ +/* $NetBSD: ata_wdc.c,v 1.110.4.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.110 2018/06/01 18:13:30 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.110.4.1 2018/08/31 19:08:03 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wdc.h" @@ -479,8 +479,8 @@ _wdc_ata_bio_start(struct ata_channel *c chp->ch_flags |= ATACH_DMA_WAIT; /* start timeout machinery */ if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&xfer->c_timo_callout, - ATA_DELAY / 1000 * hz, wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, + ATA_DELAY / 1000 * hz, wdctimeout, chp); /* wait for irq */ goto intr; } /* else not DMA */ @@ -550,8 +550,8 @@ _wdc_ata_bio_start(struct ata_channel *c } /* start timeout machinery */ if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&xfer->c_timo_callout, - ATA_DELAY / 1000 * hz, wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, + ATA_DELAY / 1000 * hz, wdctimeout, chp); } else if (ata_bio->nblks > 1) { /* The number of blocks in the last stretch may be smaller. */ nblks = xfer->c_bcount / drvp->lp->d_secsize; Index: src/sys/dev/ata/atavar.h diff -u src/sys/dev/ata/atavar.h:1.99 src/sys/dev/ata/atavar.h:1.99.2.1 --- src/sys/dev/ata/atavar.h:1.99 Fri Aug 10 22:43:22 2018 +++ src/sys/dev/ata/atavar.h Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: atavar.h,v 1.99 2018/08/10 22:43:22 jdolecek Exp $ */ +/* $NetBSD: atavar.h,v 1.99.2.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -131,10 +131,6 @@ struct scsipi_xfer; * commands are queued in a list. */ struct ata_xfer { - struct callout c_timo_callout; /* timeout callout handle */ - struct callout c_retry_callout; /* retry callout handle */ - kcondvar_t c_active; /* somebody actively waiting for xfer */ - kcondvar_t c_finish; /* somebody waiting for xfer finish */ int8_t c_slot; /* queue slot # */ #define c_startzero c_chp @@ -166,6 +162,9 @@ struct ata_xfer { TAILQ_ENTRY(ata_xfer) c_xferchain; TAILQ_ENTRY(ata_xfer) c_activechain; + /* Links for error handling */ + SLIST_ENTRY(ata_xfer) c_retrychain; + /* Low-level protocol handlers. */ int (*c_start)(struct ata_channel *, struct ata_xfer *); #define ATASTART_STARTED 0 /* xfer started, waiting for intr */ @@ -227,6 +226,8 @@ struct ata_queue { TAILQ_HEAD(, ata_xfer) active_xfers; /* active commands */ uint32_t active_xfers_used; /* mask of active commands */ uint32_t queue_xfers_avail; /* available xfers mask */ + kcondvar_t c_active; /* somebody actively waiting for xfer */ + kcondvar_t c_cmd_finish; /* somebody waiting for cmd finish */ struct ata_xfer queue_xfers[0]; /* xfers */ }; #endif @@ -412,6 +413,9 @@ struct ata_channel { /* for the reset callback */ int ch_reset_flags; + /* for the timeout callout */ + struct callout c_timo_callout; /* timeout callout handle */ + /* per-drive info */ int ch_ndrives; /* number of entries in ch_drive[] */ struct ata_drive_datas *ch_drive; /* array of ata_drive_datas */ @@ -528,8 +532,7 @@ void ata_free_xfer(struct ata_channel *, void ata_deactivate_xfer(struct ata_channel *, struct ata_xfer *); void ata_exec_xfer(struct ata_channel *, struct ata_xfer *); int ata_xfer_start(struct ata_xfer *xfer); -void ata_wait_xfer(struct ata_channel *, struct ata_xfer *xfer); -void ata_wake_xfer(struct ata_channel *, struct ata_xfer *xfer); +void ata_wait_cmd(struct ata_channel *, struct ata_xfer *xfer); void ata_timeout(void *); bool ata_timo_xfer_check(struct ata_xfer *); Index: src/sys/dev/ata/wd.c diff -u src/sys/dev/ata/wd.c:1.441 src/sys/dev/ata/wd.c:1.441.2.1 --- src/sys/dev/ata/wd.c:1.441 Fri Aug 10 22:43:22 2018 +++ src/sys/dev/ata/wd.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: wd.c,v 1.441 2018/08/10 22:43:22 jdolecek Exp $ */ +/* $NetBSD: wd.c,v 1.441.2.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.441 2018/08/10 22:43:22 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.441.2.1 2018/08/31 19:08:03 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wd.h" @@ -199,7 +199,8 @@ static int wd_diskstart(device_t, struct static int wd_dumpblocks(device_t, void *, daddr_t, int); static void wd_iosize(device_t, int *); static int wd_discard(device_t, off_t, off_t); -static void wdbiorestart(void *); +static void wdbioretry(void *); +static void wdbiorequeue(void *); static void wddone(device_t, struct ata_xfer *); static int wd_get_params(struct wd_softc *, uint8_t, struct ataparams *); static void wd_set_geometry(struct wd_softc *); @@ -329,6 +330,11 @@ wdattach(device_t parent, device_t self, wd->drvp->drv_softc = dksc->sc_dev; /* done in atabusconfig_thread() but too late */ + SLIST_INIT(&wd->sc_retry_list); + SLIST_INIT(&wd->sc_requeue_list); + callout_init(&wd->sc_retry_callout, 0); /* XXX MPSAFE */ + callout_init(&wd->sc_requeue_callout, 0); /* XXX MPSAFE */ + aprint_naive("\n"); aprint_normal("\n"); @@ -517,6 +523,12 @@ wddetach(device_t self, int flags) /* Kill off any pending commands. */ mutex_enter(&wd->sc_lock); wd->atabus->ata_killpending(wd->drvp); + + callout_halt(&wd->sc_retry_callout, &wd->sc_lock); + callout_destroy(&wd->sc_retry_callout); + callout_halt(&wd->sc_requeue_callout, &wd->sc_lock); + callout_destroy(&wd->sc_requeue_callout); + mutex_exit(&wd->sc_lock); bufq_free(dksc->sc_bufq); @@ -850,9 +862,17 @@ retry2: xfer->c_retries++; /* Rerun ASAP if just requeued */ - callout_reset(&xfer->c_retry_callout, - (xfer->c_bio.error == REQUEUE) ? 1 : RECOVERYTIME, - wdbiorestart, xfer); + if (xfer->c_bio.error == REQUEUE) { + SLIST_INSERT_HEAD(&wd->sc_requeue_list, xfer, + c_retrychain); + callout_reset(&wd->sc_requeue_callout, + 1, wdbiorequeue, wd); + } else { + SLIST_INSERT_HEAD(&wd->sc_retry_list, xfer, + c_retrychain); + callout_reset(&wd->sc_retry_callout, + RECOVERYTIME, wdbioretry, wd); + } mutex_exit(&wd->sc_lock); return; @@ -921,20 +941,36 @@ noerror: if ((xfer->c_bio.flags & ATA_CO } static void -wdbiorestart(void *v) +wdbioretry(void *v) { - struct ata_xfer *xfer = v; - struct buf *bp = xfer->c_bio.bp; - struct wd_softc *wd = device_lookup_private(&wd_cd, WDUNIT(bp->b_dev)); -#ifdef ATADEBUG - struct dk_softc *dksc = &wd->sc_dksc; -#endif + struct wd_softc *wd = v; + struct ata_xfer *xfer; - ATADEBUG_PRINT(("wdbiorestart %s\n", dksc->sc_xname), + ATADEBUG_PRINT(("%s %s\n", __func__, wd->sc_dksc.sc_xname), DEBUG_XFERS); mutex_enter(&wd->sc_lock); - wdstart1(wd, bp, xfer); + while ((xfer = SLIST_FIRST(&wd->sc_retry_list))) { + SLIST_REMOVE_HEAD(&wd->sc_retry_list, c_retrychain); + wdstart1(wd, xfer->c_bio.bp, xfer); + } + mutex_exit(&wd->sc_lock); +} + +static void +wdbiorequeue(void *v) +{ + struct wd_softc *wd = v; + struct ata_xfer *xfer; + + ATADEBUG_PRINT(("%s %s\n", __func__, wd->sc_dksc.sc_xname), + DEBUG_XFERS); + + mutex_enter(&wd->sc_lock); + while ((xfer = SLIST_FIRST(&wd->sc_requeue_list))) { + SLIST_REMOVE_HEAD(&wd->sc_requeue_list, c_retrychain); + wdstart1(wd, xfer->c_bio.bp, xfer); + } mutex_exit(&wd->sc_lock); } Index: src/sys/dev/ata/wdvar.h diff -u src/sys/dev/ata/wdvar.h:1.46 src/sys/dev/ata/wdvar.h:1.46.6.1 --- src/sys/dev/ata/wdvar.h:1.46 Fri Nov 3 13:01:26 2017 +++ src/sys/dev/ata/wdvar.h Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: wdvar.h,v 1.46 2017/11/03 13:01:26 mlelstv Exp $ */ +/* $NetBSD: wdvar.h,v 1.46.6.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -65,6 +65,13 @@ struct wd_softc { u_int sc_bscount; #endif + /* Retry/requeue failed transfers */ + SLIST_HEAD(, ata_xfer) sc_retry_list; + struct callout sc_retry_callout; /* retry callout handle */ + + SLIST_HEAD(, ata_xfer) sc_requeue_list; + struct callout sc_requeue_callout; /* requeue callout handle */ + /* Sysctl nodes specific for the disk */ struct sysctllog *nodelog; int drv_max_tags; Index: src/sys/dev/ic/ahcisata_core.c diff -u src/sys/dev/ic/ahcisata_core.c:1.62 src/sys/dev/ic/ahcisata_core.c:1.62.2.1 --- src/sys/dev/ic/ahcisata_core.c:1.62 Mon Jul 9 10:44:44 2018 +++ src/sys/dev/ic/ahcisata_core.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisata_core.c,v 1.62 2018/07/09 10:44:44 kamil Exp $ */ +/* $NetBSD: ahcisata_core.c,v 1.62.2.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.62 2018/07/09 10:44:44 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.62.2.1 2018/08/31 19:08:03 jdolecek Exp $"); #include <sys/types.h> #include <sys/malloc.h> @@ -1038,12 +1038,7 @@ ahci_exec_command(struct ata_drive_datas ret = ATACMD_COMPLETE; } else { if (ata_c->flags & AT_WAIT) { - ata_channel_lock(chp); - if ((ata_c->flags & AT_DONE) == 0) { - ata_wait_xfer(chp, xfer); - KASSERT((ata_c->flags & AT_DONE) != 0); - } - ata_channel_unlock(chp); + ata_wait_cmd(chp, xfer); ret = ATACMD_COMPLETE; } else { ret = ATACMD_QUEUED; @@ -1107,8 +1102,8 @@ ahci_cmd_start(struct ata_channel *chp, achp->ahcic_cmds_active |= 1U << slot; if ((ata_c->flags & AT_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, mstohz(ata_c->timeout), - ata_timeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(ata_c->timeout), + ata_timeout, chp); return ATASTART_STARTED; } else return ATASTART_POLL; @@ -1187,13 +1182,13 @@ ahci_cmd_kill_xfer(struct ata_channel *c panic("ahci_cmd_kill_xfer"); } + ahci_cmd_done_end(chp, xfer); + if (deactivate) { KASSERT((achp->ahcic_cmds_active & (1U << xfer->c_slot)) != 0); achp->ahcic_cmds_active &= ~(1U << xfer->c_slot); ata_deactivate_xfer(chp, xfer); } - - ahci_cmd_done_end(chp, xfer); } static int @@ -1213,7 +1208,6 @@ ahci_cmd_complete(struct ata_channel *ch KASSERT((achp->ahcic_cmds_active & (1U << xfer->c_slot)) != 0); achp->ahcic_cmds_active &= ~(1U << xfer->c_slot); - ata_deactivate_xfer(chp, xfer); if (xfer->c_flags & C_TIMEOU) { ata_c->flags |= AT_TIMEOU; @@ -1230,6 +1224,9 @@ ahci_cmd_complete(struct ata_channel *ch satafis_rdh_cmd_readreg(ata_c, achp->ahcic_rfis->rfis_rfis); ahci_cmd_done(chp, xfer); + + ata_deactivate_xfer(chp, xfer); + return 0; } @@ -1268,7 +1265,9 @@ ahci_cmd_done(struct ata_channel *chp, s if (achp->ahcic_cmdh[xfer->c_slot].cmdh_prdbc) ata_c->flags |= AT_XFDONE; + ahci_cmd_done_end(chp, xfer); + if ((flags & (AT_TIMEOU|AT_ERROR)) == 0) atastart(chp); } @@ -1278,15 +1277,7 @@ ahci_cmd_done_end(struct ata_channel *ch { struct ata_command *ata_c = &xfer->c_ata_c; - ata_channel_lock(chp); - ata_c->flags |= AT_DONE; - - if (ata_c->flags & AT_WAIT) - ata_wake_xfer(chp, xfer); - - ata_channel_unlock(chp); - return; } static int @@ -1363,8 +1354,8 @@ ahci_bio_start(struct ata_channel *chp, achp->ahcic_cmds_active |= 1U << xfer->c_slot; if ((xfer->c_flags & C_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, mstohz(ATA_DELAY), - ata_timeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(ATA_DELAY), + ata_timeout, chp); return ATASTART_STARTED; } else return ATASTART_POLL; @@ -1948,8 +1939,8 @@ ahci_atapi_start(struct ata_channel *chp achp->ahcic_cmds_active |= 1U << xfer->c_slot; if ((xfer->c_flags & C_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, mstohz(sc_xfer->timeout), - ata_timeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), + ata_timeout, chp); return ATASTART_STARTED; } else return ATASTART_POLL; Index: src/sys/dev/ic/mvsata.c diff -u src/sys/dev/ic/mvsata.c:1.41 src/sys/dev/ic/mvsata.c:1.41.2.1 --- src/sys/dev/ic/mvsata.c:1.41 Fri Aug 31 18:43:29 2018 +++ src/sys/dev/ic/mvsata.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: mvsata.c,v 1.41 2018/08/31 18:43:29 jdolecek Exp $ */ +/* $NetBSD: mvsata.c,v 1.41.2.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 2008 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.41 2018/08/31 18:43:29 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.41.2.1 2018/08/31 19:08:03 jdolecek Exp $"); #include "opt_mvsata.h" @@ -159,7 +159,6 @@ static void mvsata_atapi_polldsc(void *) static int mvsata_edma_enqueue(struct mvsata_port *, struct ata_xfer *); static int mvsata_edma_handle(struct mvsata_port *, struct ata_xfer *); static int mvsata_edma_wait(struct mvsata_port *, struct ata_xfer *, int); -static void mvsata_edma_timeout(void *); static void mvsata_edma_rqq_remove(struct mvsata_port *, struct ata_xfer *); #if NATAPIBUS > 0 static int mvsata_bdma_init(struct mvsata_port *, struct ata_xfer *); @@ -1214,9 +1213,8 @@ mvsata_bio_start(struct ata_channel *chp chp->ch_flags |= ATACH_DMA_WAIT; /* start timeout machinery */ if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&xfer->c_timo_callout, - mstohz(ATA_DELAY), - mvsata_edma_timeout, xfer); + callout_reset(&chp->c_timo_callout, + mstohz(ATA_DELAY), ata_timeout, chp); /* wait for irq */ goto intr; } /* else not DMA */ @@ -1300,8 +1298,8 @@ do_pio: /* start timeout machinery */ if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&xfer->c_timo_callout, - mstohz(ATA_DELAY), wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, + mstohz(ATA_DELAY), wdctimeout, chp); } else if (ata_bio->nblks > 1) { /* The number of blocks in the last stretch may be smaller. */ nblks = xfer->c_bcount / drvp->lp->d_secsize; @@ -1382,6 +1380,11 @@ mvsata_bio_intr(struct ata_channel *chp, device_xname(atac->atac_dev), chp->ch_channel, __func__, xfer->c_drive)); + if (xfer->c_flags & C_TIMEOU && !irq) { + /* Cleanup EDMA if invoked from timeout handler */ + mvsata_edma_rqq_remove((struct mvsata_port *)chp, xfer); + } + ata_channel_lock(chp); chp->ch_flags &= ~(ATACH_DMA_WAIT); @@ -1712,12 +1715,7 @@ mvsata_exec_command(struct ata_drive_dat rv = ATACMD_COMPLETE; else { if (ata_c->flags & AT_WAIT) { - ata_channel_lock(chp); - if ((ata_c->flags & AT_DONE) == 0) { - ata_wait_xfer(chp, xfer); - KASSERT((ata_c->flags & AT_DONE) != 0); - } - ata_channel_unlock(chp); + ata_wait_cmd(chp, xfer); rv = ATACMD_COMPLETE; } else rv = ATACMD_QUEUED; @@ -1779,8 +1777,8 @@ mvsata_wdc_cmd_start(struct ata_channel } if ((ata_c->flags & AT_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, ata_c->timeout / 1000 * hz, - wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz, + wdctimeout, chp); return ATASTART_STARTED; } @@ -1895,8 +1893,8 @@ again: wdc->dataout_pio(chp, drive_flags, data, bcount); ata_c->flags |= AT_XFDONE; if ((ata_c->flags & AT_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, - mstohz(ata_c->timeout), wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, + mstohz(ata_c->timeout), wdctimeout, chp); ata_channel_unlock(chp); return 1; } else @@ -1949,12 +1947,12 @@ mvsata_wdc_cmd_kill_xfer(struct ata_chan panic("mvsata_cmd_kill_xfer"); } + mvsata_wdc_cmd_done_end(chp, xfer); + if (deactivate) { mvsata_quetag_put(mvport, xfer->c_slot); ata_deactivate_xfer(chp, xfer); } - - mvsata_wdc_cmd_done_end(chp, xfer); } static void @@ -2015,7 +2013,6 @@ mvsata_wdc_cmd_done(struct ata_channel * } mvsata_quetag_put(mvport, xfer->c_slot); - ata_deactivate_xfer(chp, xfer); if (ata_c->flags & AT_POLL) { /* enable interrupts */ @@ -2024,6 +2021,8 @@ mvsata_wdc_cmd_done(struct ata_channel * } mvsata_wdc_cmd_done_end(chp, xfer); + + ata_deactivate_xfer(chp, xfer); } static void @@ -2038,11 +2037,7 @@ mvsata_wdc_cmd_done_end(struct ata_chann mvsata_edma_enable(mvport); } - ata_channel_lock(chp); ata_c->flags |= AT_DONE; - if (ata_c->flags & AT_WAIT) - ata_wake_xfer(chp, xfer); - ata_channel_unlock(chp); } #if NATAPIBUS > 0 @@ -2224,8 +2219,8 @@ ready: } /* start timeout machinery */ if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) - callout_reset(&xfer->c_timo_callout, mstohz(sc_xfer->timeout), - wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), + wdctimeout, chp); MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM); if (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags, &tfd) != 0) { @@ -2633,8 +2628,8 @@ mvsata_atapi_phase_complete(struct ata_x sc_xfer->error = XS_TIMEOUT; mvsata_atapi_reset(chp, xfer); } else { - callout_reset(&xfer->c_timo_callout, 1, - mvsata_atapi_polldsc, xfer); + callout_reset(&chp->c_timo_callout, 1, + mvsata_atapi_polldsc, chp); ata_channel_unlock(chp); } return; @@ -2727,8 +2722,10 @@ mvsata_atapi_done(struct ata_channel *ch static void mvsata_atapi_polldsc(void *arg) { - struct ata_xfer *xfer = arg; - struct ata_channel *chp = xfer->c_chp; + struct ata_channel *chp = arg; + struct ata_xfer *xfer = ata_queue_get_active_xfer(chp); + + KASSERT(xfer != NULL); ata_channel_lock(chp); @@ -2967,30 +2964,6 @@ mvsata_edma_wait(struct mvsata_port *mvp } static void -mvsata_edma_timeout(void *arg) -{ - struct ata_xfer *xfer = (struct ata_xfer *)arg; - struct ata_channel *chp = xfer->c_chp; - struct mvsata_port *mvport = (struct mvsata_port *)chp; - int s; - - s = splbio(); - DPRINTF(DEBUG_FUNCS, ("%s: %p\n", __func__, xfer)); - - if (ata_timo_xfer_check(xfer)) { - /* Already logged */ - goto out; - } - - mvsata_edma_rqq_remove(mvport, xfer); - xfer->c_flags |= C_TIMEOU; - mvsata_bio_intr(chp, xfer, 0); - -out: - splx(s); -} - -static void mvsata_edma_rqq_remove(struct mvsata_port *mvport, struct ata_xfer *xfer) { struct ata_channel *chp = &mvport->port_ata_channel; Index: src/sys/dev/ic/siisata.c diff -u src/sys/dev/ic/siisata.c:1.35 src/sys/dev/ic/siisata.c:1.35.6.1 --- src/sys/dev/ic/siisata.c:1.35 Fri Oct 20 07:06:07 2017 +++ src/sys/dev/ic/siisata.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: siisata.c,v 1.35 2017/10/20 07:06:07 jdolecek Exp $ */ +/* $NetBSD: siisata.c,v 1.35.6.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* from ahcisata_core.c */ @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35 2017/10/20 07:06:07 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35.6.1 2018/08/31 19:08:03 jdolecek Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -1005,16 +1005,7 @@ siisata_exec_command(struct ata_drive_da ret = ATACMD_COMPLETE; } else { if (ata_c->flags & AT_WAIT) { - ata_channel_lock(chp); - if ((ata_c->flags & AT_DONE) == 0) { - SIISATA_DEBUG_PRINT(("%s: %s: sleeping\n", - SIISATANAME( - (struct siisata_softc *)chp->ch_atac), - __func__), DEBUG_FUNCS); - ata_wait_xfer(chp, xfer); - KASSERT((ata_c->flags & AT_DONE) != 0); - } - ata_channel_unlock(chp); + ata_wait_cmd(chp, xfer); ret = ATACMD_COMPLETE; } else { ret = ATACMD_QUEUED; @@ -1071,8 +1062,8 @@ siisata_cmd_start(struct ata_channel *ch siisata_activate_prb(schp, xfer->c_slot); if ((ata_c->flags & AT_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, mstohz(ata_c->timeout), - ata_timeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(ata_c->timeout), + ata_timeout, chp); return ATASTART_STARTED; } else return ATASTART_POLL; @@ -1137,12 +1128,12 @@ siisata_cmd_kill_xfer(struct ata_channel __func__, chp->ch_channel, reason); } + siisata_cmd_done_end(chp, xfer); + if (deactivate) { siisata_deactivate_prb(schp, xfer->c_slot); ata_deactivate_xfer(chp, xfer); } - - siisata_cmd_done_end(chp, xfer); } int @@ -1164,7 +1155,6 @@ siisata_cmd_complete(struct ata_channel return 0; siisata_deactivate_prb(schp, xfer->c_slot); - ata_deactivate_xfer(chp, xfer); if (xfer->c_flags & C_TIMEOU) ata_c->flags |= AT_TIMEOU; @@ -1178,6 +1168,8 @@ siisata_cmd_complete(struct ata_channel siisata_cmd_done(chp, xfer, tfd); + ata_deactivate_xfer(chp, xfer); + return 0; } @@ -1229,15 +1221,7 @@ siisata_cmd_done_end(struct ata_channel { struct ata_command *ata_c = &xfer->c_ata_c; - ata_channel_lock(chp); - ata_c->flags |= AT_DONE; - - if (ata_c->flags & AT_WAIT) - ata_wake_xfer(chp, xfer); - - ata_channel_unlock(chp); - return; } int @@ -1303,8 +1287,8 @@ siisata_bio_start(struct ata_channel *ch siisata_activate_prb(schp, xfer->c_slot); if ((ata_bio->flags & ATA_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, mstohz(ATA_DELAY), - ata_timeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(ATA_DELAY), + ata_timeout, chp); return ATASTART_STARTED; } else return ATASTART_POLL; @@ -1913,8 +1897,8 @@ siisata_atapi_start(struct ata_channel * siisata_activate_prb(schp, xfer->c_slot); if ((xfer->c_flags & C_POLL) == 0) { - callout_reset(&xfer->c_timo_callout, mstohz(sc_xfer->timeout), - ata_timeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), + ata_timeout, chp); return ATASTART_STARTED; } else return ATASTART_POLL; Index: src/sys/dev/ic/wdc.c diff -u src/sys/dev/ic/wdc.c:1.288 src/sys/dev/ic/wdc.c:1.288.6.1 --- src/sys/dev/ic/wdc.c:1.288 Fri Oct 20 07:06:07 2017 +++ src/sys/dev/ic/wdc.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: wdc.c,v 1.288 2017/10/20 07:06:07 jdolecek Exp $ */ +/* $NetBSD: wdc.c,v 1.288.6.1 2018/08/31 19:08:03 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.288 2017/10/20 07:06:07 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.288.6.1 2018/08/31 19:08:03 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wdc.h" @@ -1324,8 +1324,8 @@ wdc_dmawait(struct ata_channel *chp, str void wdctimeout(void *arg) { - struct ata_xfer *xfer = arg; - struct ata_channel *chp = xfer->c_chp; + struct ata_xfer *xfer; + struct ata_channel *chp = arg; #if NATA_DMA || NATA_PIOBM struct wdc_softc *wdc = CHAN_TO_WDC(chp); #endif @@ -1334,6 +1334,10 @@ wdctimeout(void *arg) ATADEBUG_PRINT(("wdctimeout\n"), DEBUG_FUNCS); s = splbio(); + + callout_ack(&chp->c_timo_callout); + + xfer = ata_queue_get_active_xfer(chp); KASSERT(xfer != NULL); if (ata_timo_xfer_check(xfer)) { @@ -1361,7 +1365,7 @@ wdctimeout(void *arg) * in case it will miss another irq while in this transfer * We arbitray chose it to be 1s */ - callout_reset(&xfer->c_timo_callout, hz, wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, hz, wdctimeout, chp); xfer->c_flags |= C_TIMEOU; KASSERT(xfer->c_intr != NULL); xfer->c_intr(chp, xfer, 1); @@ -1408,12 +1412,7 @@ wdc_exec_command(struct ata_drive_datas ret = ATACMD_COMPLETE; } else { if (ata_c->flags & AT_WAIT) { - ata_channel_lock(chp); - if ((ata_c->flags & AT_DONE) == 0) { - ata_wait_xfer(chp, xfer); - KASSERT((ata_c->flags & AT_DONE) != 0); - } - ata_channel_unlock(chp); + ata_wait_cmd(chp, xfer); ret = ATACMD_COMPLETE; } else { ret = ATACMD_QUEUED; @@ -1474,8 +1473,8 @@ __wdccommand_start(struct ata_channel *c if ((ata_c->flags & AT_POLL) == 0) { chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */ - callout_reset(&xfer->c_timo_callout, ata_c->timeout / 1000 * hz, - wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz, + wdctimeout, chp); return ATASTART_STARTED; } @@ -1597,8 +1596,8 @@ again: ata_c->flags |= AT_XFDONE; if ((ata_c->flags & AT_POLL) == 0) { chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */ - callout_reset(&xfer->c_timo_callout, - mstohz(ata_c->timeout), wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, + mstohz(ata_c->timeout), wdctimeout, chp); ata_channel_unlock(chp); return 1; } else { @@ -1691,10 +1690,10 @@ __wdccommand_done(struct ata_channel *ch ata_c->r_device &= 0xf0; } - ata_deactivate_xfer(chp, xfer); - __wdccommand_done_end(chp, xfer); + ata_deactivate_xfer(chp, xfer); + out: if (ata_c->flags & AT_POLL) { /* enable interrupts */ @@ -1713,11 +1712,7 @@ __wdccommand_done_end(struct ata_channel { struct ata_command *ata_c = &xfer->c_ata_c; - ata_channel_lock(chp); ata_c->flags |= AT_DONE; - if (ata_c->flags & AT_WAIT) - ata_wake_xfer(chp, xfer); - ata_channel_unlock(chp); } static void @@ -1743,10 +1738,10 @@ __wdccommand_kill_xfer(struct ata_channe panic("__wdccommand_kill_xfer"); } + __wdccommand_done_end(chp, xfer); + if (deactivate) ata_deactivate_xfer(chp, xfer); - - __wdccommand_done_end(chp, xfer); } /* Index: src/sys/dev/scsipi/atapi_wdc.c diff -u src/sys/dev/scsipi/atapi_wdc.c:1.129 src/sys/dev/scsipi/atapi_wdc.c:1.129.6.1 --- src/sys/dev/scsipi/atapi_wdc.c:1.129 Tue Oct 17 18:52:51 2017 +++ src/sys/dev/scsipi/atapi_wdc.c Fri Aug 31 19:08:03 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: atapi_wdc.c,v 1.129 2017/10/17 18:52:51 jdolecek Exp $ */ +/* $NetBSD: atapi_wdc.c,v 1.129.6.1 2018/08/31 19:08:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.129 2017/10/17 18:52:51 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.129.6.1 2018/08/31 19:08:03 jdolecek Exp $"); #ifndef ATADEBUG #define ATADEBUG @@ -595,8 +595,8 @@ ready: } /* start timeout machinery */ if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) - callout_reset(&xfer->c_timo_callout, mstohz(sc_xfer->timeout), - wdctimeout, xfer); + callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), + wdctimeout, chp); if (wdc->select) wdc->select(chp, xfer->c_drive); @@ -1087,8 +1087,8 @@ wdc_atapi_phase_complete(struct ata_xfer sc_xfer->error = XS_TIMEOUT; wdc_atapi_reset(chp, xfer); } else { - callout_reset(&xfer->c_timo_callout, 1, - wdc_atapi_polldsc, xfer); + callout_reset(&chp->c_timo_callout, 1, + wdc_atapi_polldsc, chp); ata_channel_unlock(chp); } return; @@ -1192,8 +1192,10 @@ wdc_atapi_reset(struct ata_channel *chp, static void wdc_atapi_polldsc(void *arg) { - struct ata_xfer *xfer = arg; - struct ata_channel *chp = xfer->c_chp; + struct ata_channel *chp = arg; + struct ata_xfer *xfer = ata_queue_get_active_xfer(chp); + + KASSERT(xfer != NULL); ata_channel_lock(chp);