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