Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncq]: src/sys/dev/ic move mvsata_quetag_get() to the start rout...
details: https://anonhg.NetBSD.org/src/rev/096a8a838c79
branches: jdolecek-ncq
changeset: 823032:096a8a838c79
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Mon Sep 25 22:50:20 2017 +0000
description:
move mvsata_quetag_get() to the start routines, so that it always matches
the active list of ata queue; important during error recovery, fixes
panics when calling
in mvsata_edma_handle() ignore events for non-active xfers
fix some missing ata_channel_unlock() on error path in mvsata_bio_intr()
and mvsata_atapi_intr(), fixes 'locking against myself' with LOCKDEBUG
with this, mvsata(4) finally survives full fio run with wdcdebug_wd_cnt == 200
diffstat:
sys/dev/ic/mvsata.c | 39 ++++++++++++++++++++++++++-------------
1 files changed, 26 insertions(+), 13 deletions(-)
diffs (154 lines):
diff -r 22c494f64cf5 -r 096a8a838c79 sys/dev/ic/mvsata.c
--- a/sys/dev/ic/mvsata.c Mon Sep 25 22:43:46 2017 +0000
+++ b/sys/dev/ic/mvsata.c Mon Sep 25 22:50:20 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mvsata.c,v 1.35.6.28 2017/09/22 20:19:08 jdolecek Exp $ */
+/* $NetBSD: mvsata.c,v 1.35.6.29 2017/09/25 22:50:20 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.35.6.28 2017/09/22 20:19:08 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.35.6.29 2017/09/25 22:50:20 jdolecek Exp $");
#include "opt_mvsata.h"
@@ -1086,7 +1086,6 @@
mvsata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
{
struct ata_channel *chp = drvp->chnl_softc;
- struct mvsata_port *mvport = (struct mvsata_port *)chp;
struct atac_softc *atac = chp->ch_atac;
struct ata_bio *ata_bio = &xfer->c_bio;
@@ -1095,8 +1094,6 @@
", bcount=%ld\n", device_xname(atac->atac_dev), chp->ch_channel,
drvp->drive, ata_bio->blkno, ata_bio->bcount));
- mvsata_quetag_get(mvport, xfer->c_slot);
-
if (atac->atac_cap & ATAC_CAP_NOIRQ)
ata_bio->flags |= ATA_POLL;
if (ata_bio->flags & ATA_POLL)
@@ -1135,6 +1132,8 @@
ata_channel_lock_owned(chp);
+ mvsata_quetag_get(mvport, xfer->c_slot);
+
if (xfer->c_flags & C_DMA)
if (drvp->n_xfers <= NXFER)
drvp->n_xfers++;
@@ -1410,8 +1409,10 @@
if (!(xfer->c_flags & C_DMA) &&
(wdc_wait_for_unbusy(chp, (irq == 0) ? ATA_DELAY : 0, AT_POLL, &tfd)
== WDCWAIT_TOUT)) {
- if (irq && (xfer->c_flags & C_TIMEOU) == 0)
+ if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
+ ata_channel_unlock(chp);
return 0; /* IRQ was not for us */
+ }
aprint_error_dev(atac->atac_dev,
"channel %d: drive %d timeout, c_bcount=%d, c_skip%d\n",
chp->ch_channel, xfer->c_drive, xfer->c_bcount,
@@ -1570,6 +1571,8 @@
flags |= AT_POLL; /* XXX */
+ ata_channel_lock_owned(chp);
+
/*
* disable interrupts, all commands here should be quick
* enough to be able to poll, and we don't go here that often
@@ -1682,8 +1685,6 @@
drvp->drive, ata_c->bcount, ata_c->r_lba, ata_c->r_count,
ata_c->r_features, ata_c->r_device, ata_c->r_command));
- mvsata_quetag_get(mvport, xfer->c_slot);
-
if (ata_c->flags & AT_POLL)
xfer->c_flags |= C_POLL;
if (ata_c->flags & AT_WAIT)
@@ -1736,6 +1737,8 @@
ata_channel_lock_owned(chp);
+ mvsata_quetag_get(mvport, xfer->c_slot);
+
/* First, EDMA disable, if enabled this channel. */
KASSERT((chp->ch_flags & ATACH_NCQ) == 0);
if (mvport->port_edmamode_curr != nodma)
@@ -2050,7 +2053,6 @@
struct atac_softc *atac = &sc->sc_wdcdev.sc_atac;
struct ata_channel *chp = atac->atac_channels[chan->chan_channel];
struct ata_xfer *xfer;
- struct mvsata_port *mvport = (struct mvsata_port *)chp;
int drive, s;
switch (req) {
@@ -2071,8 +2073,6 @@
return;
}
- mvsata_quetag_get(mvport, xfer->c_slot);
-
if (sc_xfer->xs_control & XS_CTL_POLL)
xfer->c_flags |= C_POLL;
xfer->c_drive = drive;
@@ -2122,6 +2122,8 @@
ata_channel_lock_owned(chp);
+ mvsata_quetag_get(mvport, xfer->c_slot);
+
KASSERT((chp->ch_flags & ATACH_NCQ) == 0);
if (mvport->port_edmamode_curr != nodma)
mvsata_edma_disable(mvport, 10 /* ms */, wait_flags);
@@ -2426,6 +2428,7 @@
if (xfer->c_flags & C_DMA)
ata_dmaerr(drvp,
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
+ ata_channel_unlock(chp);
sc_xfer->error = XS_TIMEOUT;
mvsata_atapi_reset(chp, xfer);
return 1;
@@ -2883,8 +2886,15 @@
mvsata_print_crpb(mvport, erpqop);
#endif
crpb = mvport->port_crpb + erpqop;
+ MVSATA_EDMAQ_INC(erpqop);
+
quetag = CRPB_CHOSTQUETAG(le16toh(crpb->id));
+ if ((mvport->port_quetagidx & __BIT(quetag)) == 0) {
+ /* not actually executing */
+ continue;
+ }
+
xfer = ata_queue_hwslot_to_xfer(chp, quetag);
bus_dmamap_sync(mvport->port_dmat, mvport->port_eprd_dmamap,
@@ -2905,7 +2915,6 @@
ata_bio->error = ERR_DMA;
mvsata_dma_bufunload(mvport, quetag, ata_bio->flags);
- MVSATA_EDMAQ_INC(erpqop);
#if 1 /* XXXX: flags clears here, because necessary the atabus layer. */
erqqip = (MVSATA_EDMA_READ_4(mvport, EDMA_REQQIP) &
@@ -3322,7 +3331,11 @@
mvsata_quetag_get(struct mvsata_port *mvport, uint8_t quetag)
{
KASSERT(quetag <= 32);
- KASSERT((mvport->port_quetagidx & __BIT(quetag)) == 0);
+
+ /*
+ * Do not check whether it's already set, can happen when
+ * postponing bio or atapi xfer to thread.
+ */
mvport->port_quetagidx |= __BIT(quetag);
}
Home |
Main Index |
Thread Index |
Old Index