Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncq]: src/sys/dev adjust reset channel and dump paths
details: https://anonhg.NetBSD.org/src/rev/2ae4f97bb5a3
branches: jdolecek-ncq
changeset: 822924:2ae4f97bb5a3
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Fri Jun 16 20:40:49 2017 +0000
description:
adjust reset channel and dump paths
- channel reset now always kills active transfer, even on dump path, but
now doesn't touch the queued waiting transfers; also kill_xfer hook is
always called, so that HBA can free any private xfer resources and thus
the dump request has chance to work
- kill_xfer routines now always call ata_deactivate_xfer(); added KASSERT()s
to ata_free_xfer() to expect deactivated xfer
- when called during channel reset before dump, ata_kill_active() drops
any queued waiting transfers without processing
- do not (re)queue any transfers in wddone() when dumping
- kill AT_RST_NOCMD flag
This should also hopefully fix the 'polled command has been queued' panic
as reported in:
PR kern/11811 by John Hawkinson
PR kern/47041 by Taylor R Campbell
PR kern/51979 by Martin Husemann
dump tested working with piixide(4) and ahci(4). mvsata(4) dump times out,
but otherwise tested working, will be fixed separately. siisata(4) mechanically
changed and not tested.
diffstat:
sys/dev/ata/ata.c | 35 ++++++++++++++++----
sys/dev/ata/ata_wdc.c | 6 ++-
sys/dev/ata/atavar.h | 9 ++--
sys/dev/ata/wd.c | 21 ++++++-----
sys/dev/ic/ahcisata_core.c | 43 +++++++++---------------
sys/dev/ic/mvsata.c | 31 +++++++----------
sys/dev/ic/siisata.c | 14 ++++----
sys/dev/ic/wdc.c | 80 +++++++++++++++------------------------------
sys/dev/scsipi/atapi_wdc.c | 6 ++-
9 files changed, 116 insertions(+), 129 deletions(-)
diffs (truncated from 739 to 300 lines):
diff -r 01f19f60d2be -r 2ae4f97bb5a3 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Fri Jun 16 18:01:10 2017 +0000
+++ b/sys/dev/ata/ata.c Fri Jun 16 20:40:49 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.132.8.8 2017/04/24 22:20:23 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.132.8.9 2017/06/16 20:40:49 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.132.8.8 2017/04/24 22:20:23 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132.8.9 2017/06/16 20:40:49 jdolecek Exp $");
#include "opt_ata.h"
@@ -187,6 +187,8 @@
TAILQ_INIT(&chq->active_xfers);
chq->queue_freeze = 0;
chq->queue_active = 0;
+ chq->active_xfers_used = 0;
+ chq->queue_xfers_avail = (1 << chq->queue_openings) - 1;
}
struct ata_xfer *
@@ -207,6 +209,18 @@
chq->active_xfers_used);
}
+/*
+ * This interface is supposed only to be used when there is exactly
+ * one outstanding command, and there is no information about the slot,
+ * which triggered the command. ata_queue_hwslot_to_xfer() interface
+ * is preferred in all standard cases.
+ */
+struct ata_xfer *
+ata_queue_active_xfer_peek(struct ata_queue *chq)
+{
+ return TAILQ_FIRST(&chq->active_xfers);
+}
+
void
ata_xfer_init(struct ata_xfer *xfer, bool zero)
{
@@ -241,7 +255,6 @@
M_DEVBUF, M_WAITOK | M_ZERO);
chq->queue_openings = openings;
- chq->queue_xfers_avail = (1 << openings) - 1;
ata_queue_reset(chq);
for (uint8_t i = 0; i < openings; i++)
@@ -258,7 +271,6 @@
KASSERT(openings < chq->queue_openings);
chq->queue_openings = openings;
- chq->queue_xfers_avail = (1 << openings) - 1;
ata_queue_reset(chq);
}
@@ -1136,6 +1148,8 @@
xfer = &chq->queue_xfers[slot];
chq->queue_xfers_avail &= ~__BIT(slot);
+ KASSERT((chq->active_xfers_used & __BIT(slot)) == 0);
+
/* zero everything after the callout member */
memset(&xfer->c_startzero, 0,
sizeof(struct ata_xfer) - offsetof(struct ata_xfer, c_startzero));
@@ -1146,6 +1160,9 @@
return xfer;
}
+/*
+ * ata_deactivate_xfer() must be always called prior to ata_free_xfer()
+ */
void
ata_free_xfer(struct ata_channel *chp, struct ata_xfer *xfer)
{
@@ -1171,6 +1188,7 @@
#endif
s = splbio();
+ KASSERT((chq->active_xfers_used & __BIT(xfer->c_slot)) == 0);
KASSERT((chq->queue_xfers_avail & __BIT(xfer->c_slot)) == 0);
chq->queue_xfers_avail |= __BIT(xfer->c_slot);
splx(s);
@@ -1236,7 +1254,7 @@
* Must be called at splbio().
*/
void
-ata_kill_active(struct ata_channel *chp, int reason)
+ata_kill_active(struct ata_channel *chp, int reason, int flags)
{
struct ata_queue * const chq = chp->ch_queue;
struct ata_xfer *xfer, *xfernext;
@@ -1244,6 +1262,9 @@
TAILQ_FOREACH_SAFE(xfer, &chq->active_xfers, c_activechain, xfernext) {
(*xfer->c_kill_xfer)(xfer->c_chp, xfer, reason);
}
+
+ if (flags & AT_RST_EMERG)
+ ata_queue_reset(chq);
}
/*
@@ -1322,7 +1343,7 @@
return;
}
chp->ch_flags |= ATACH_TH_RESET;
- chp->ch_reset_flags = flags & (AT_RST_EMERG | AT_RST_NOCMD);
+ chp->ch_reset_flags = flags & AT_RST_EMERG;
wakeup(&chp->ch_thread);
return;
}
@@ -1486,7 +1507,7 @@
(*atac->atac_set_modes)(chp);
ata_print_modes(chp);
/* reset the channel, which will schedule all drives for setup */
- ata_reset_channel(chp, flags | AT_RST_NOCMD);
+ ata_reset_channel(chp, flags);
return 1;
}
#endif /* NATA_DMA */
diff -r 01f19f60d2be -r 2ae4f97bb5a3 sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c Fri Jun 16 18:01:10 2017 +0000
+++ b/sys/dev/ata/ata_wdc.c Fri Jun 16 20:40:49 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_wdc.c,v 1.105.6.3 2017/04/19 20:49:17 jdolecek Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.105.6.4 2017/06/16 20:40:49 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.105.6.3 2017/04/19 20:49:17 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.105.6.4 2017/06/16 20:40:49 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -775,6 +775,8 @@
struct ata_bio *ata_bio = &xfer->c_bio;
int drive = xfer->c_drive;
+ ata_deactivate_xfer(chp, xfer);
+
ata_bio->flags |= ATA_ITSDONE;
switch (reason) {
case KILL_GONE:
diff -r 01f19f60d2be -r 2ae4f97bb5a3 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h Fri Jun 16 18:01:10 2017 +0000
+++ b/sys/dev/ata/atavar.h Fri Jun 16 20:40:49 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.92.8.8 2017/04/24 22:20:23 jdolecek Exp $ */
+/* $NetBSD: atavar.h,v 1.92.8.9 2017/06/16 20:40:49 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -185,7 +185,7 @@
/* Per-channel queue of ata_xfers */
struct ata_queue {
- TAILQ_HEAD(, ata_xfer) queue_xfer; /* queue of pending commands */
+ TAILQ_HEAD(, ata_xfer) queue_xfer; /* queue of pending commands */
int queue_freeze; /* freeze count for the queue */
int queue_flags; /* flags for this queue */
#define QF_IDLE_WAIT 0x01 /* someone wants the controller idle */
@@ -322,7 +322,6 @@
void (*ata_reset_channel)(struct ata_channel *, int);
/* extra flags for ata_reset_*(), in addition to AT_* */
#define AT_RST_EMERG 0x10000 /* emergency - e.g. for a dump */
-#define AT_RST_NOCMD 0x20000 /* XXX has to go - temporary until we have tagged queuing */
int (*ata_exec_command)(struct ata_drive_datas *,
struct ata_xfer *);
@@ -482,7 +481,7 @@
void ata_exec_xfer(struct ata_channel *, struct ata_xfer *);
void ata_kill_pending(struct ata_drive_datas *);
-void ata_kill_active(struct ata_channel *, int);
+void ata_kill_active(struct ata_channel *, int, int);
void ata_reset_channel(struct ata_channel *, int);
int ata_addref(struct ata_channel *);
@@ -505,6 +504,8 @@
void ata_queue_free(struct ata_queue *);
struct ata_xfer *
ata_queue_hwslot_to_xfer(struct ata_queue *, int);
+struct ata_xfer *
+ ata_queue_active_xfer_peek(struct ata_queue *);
void ata_delay(int, const char *, int);
diff -r 01f19f60d2be -r 2ae4f97bb5a3 sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c Fri Jun 16 18:01:10 2017 +0000
+++ b/sys/dev/ata/wd.c Fri Jun 16 20:40:49 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.428.2.15 2017/06/14 20:17:46 jdolecek Exp $ */
+/* $NetBSD: wd.c,v 1.428.2.16 2017/06/16 20:40:49 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.428.2.15 2017/06/14 20:17:46 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.428.2.16 2017/06/16 20:40:49 jdolecek Exp $");
#include "opt_ata.h"
@@ -168,6 +168,10 @@
.d_flag = D_DISK | D_MPSAFE
};
+/* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
+static int wddoingadump = 0;
+static int wddumprecalibrated = 0;
+
/*
* Glue necessary to hook WDCIOCCOMMAND into physio
*/
@@ -742,6 +746,11 @@
ATADEBUG_PRINT(("wddone %s\n", device_xname(wd->sc_dev)),
DEBUG_XFERS);
+ if (wddoingadump) {
+ /* just drop it to the floor */
+ ata_free_xfer(wd->drvp->chnl_softc, xfer);
+ return;
+ }
mutex_enter(&wd->sc_lock);
@@ -770,7 +779,7 @@
errmsg = "error";
do_perror = 1;
retry: /* Just reset and retry. Can we do more ? */
- (*wd->atabus->ata_reset_drive)(wd->drvp, AT_RST_NOCMD, NULL);
+ (*wd->atabus->ata_reset_drive)(wd->drvp, 0, NULL);
retry2:
diskerr(bp, "wd", errmsg, LOG_PRINTF,
xfer->c_bio.blkdone, wd->sc_dk.dk_label);
@@ -1583,10 +1592,6 @@
return (size);
}
-/* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
-static int wddoingadump = 0;
-static int wddumprecalibrated = 0;
-
/*
* Dump core after a system crash.
*/
@@ -1683,8 +1688,6 @@
panic("wddump: unknown error type %d", err);
}
- ata_free_xfer(wd->drvp->chnl_softc, xfer);
-
if (err != 0) {
printf("\n");
return err;
diff -r 01f19f60d2be -r 2ae4f97bb5a3 sys/dev/ic/ahcisata_core.c
--- a/sys/dev/ic/ahcisata_core.c Fri Jun 16 18:01:10 2017 +0000
+++ b/sys/dev/ic/ahcisata_core.c Fri Jun 16 20:40:49 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_core.c,v 1.57.6.12 2017/04/25 20:55:05 jdolecek Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.57.6.13 2017/06/16 20:40:49 jdolecek Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.57.6.12 2017/04/25 20:55:05 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.57.6.13 2017/06/16 20:40:49 jdolecek Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -673,10 +673,7 @@
AHCINAME(sc), chp->ch_channel, is);
return ERR_DF;
}
- if (flags & AT_WAIT)
- tsleep(&sc, PRIBIO, "ahcifis", 1);
- else
- delay(10000);
+ ata_delay(10, "ahcifis", flags);
}
aprint_debug("%s channel %d: timeout sending FIS\n",
@@ -779,10 +776,7 @@
sig = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
if ((__SHIFTOUT(sig, AHCI_P_TFD_ST) & WDCS_BSY) == 0)
Home |
Main Index |
Thread Index |
Old Index