Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncqfixes]: src/sys/dev refactor shared parts of the SATA error ...
details: https://anonhg.NetBSD.org/src/rev/18413d6d6c00
branches: jdolecek-ncqfixes
changeset: 1025097:18413d6d6c00
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Thu Oct 11 20:57:51 2018 +0000
description:
refactor shared parts of the SATA error recovery into new function
ata_recovery_resume() and use for ahcisata/siisata/mvsata, also replace
per-controller hold/unhold with generic version
move the shared recovery code into separate file ata_recovery.c
diffstat:
sys/dev/ata/TODO.ncq | 3 +-
sys/dev/ata/ata.c | 96 +-----------------
sys/dev/ata/ata_recovery.c | 247 +++++++++++++++++++++++++++++++++++++++++++++
sys/dev/ata/ata_subr.c | 43 +++++++-
sys/dev/ata/atavar.h | 9 +-
sys/dev/ata/files.ata | 3 +-
sys/dev/ic/ahcisata_core.c | 162 +++++------------------------
sys/dev/ic/ahcisatavar.h | 5 +-
sys/dev/ic/mvsata.c | 177 +++++--------------------------
sys/dev/ic/mvsatavar.h | 8 +-
sys/dev/ic/siisata.c | 130 +++--------------------
sys/dev/ic/siisatavar.h | 6 +-
12 files changed, 386 insertions(+), 503 deletions(-)
diffs (truncated from 1466 to 300 lines):
diff -r ea9760aed674 -r 18413d6d6c00 sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq Sun Oct 07 15:44:47 2018 +0000
+++ b/sys/dev/ata/TODO.ncq Thu Oct 11 20:57:51 2018 +0000
@@ -4,7 +4,8 @@
- run recovery via atathread, move to new function and share ahci/siisata/mvsata
- maybe do device error handling in not-interrupt-context (maybe this should be
done on a mpata branch?)
-- remove controller-specific slot bitmaps (ic/siisata.c, ic/ahcisata_core.c)
+- adjust mvsata() intr code to accept tfd (instead of irq 0/1) so that
+ ata_recovery_resume() works properly for it
Bugs
----
diff -r ea9760aed674 -r 18413d6d6c00 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Sun Oct 07 15:44:47 2018 +0000
+++ b/sys/dev/ata/ata.c Thu Oct 11 20:57:51 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.141.6.15 2018/10/06 21:19:55 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.141.6.16 2018/10/11 20:57:51 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.6.15 2018/10/06 21:19:55 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141.6.16 2018/10/11 20:57:51 jdolecek Exp $");
#include "opt_ata.h"
@@ -933,98 +933,6 @@
return rv;
}
-int
-ata_read_log_ext_ncq(struct ata_drive_datas *drvp, uint8_t flags,
- uint8_t *slot, uint8_t *status, uint8_t *err)
-{
- struct ata_xfer *xfer = &drvp->recovery_xfer;
- int rv;
- struct ata_channel *chp = drvp->chnl_softc;
- struct atac_softc *atac = chp->ch_atac;
- uint8_t *tb, cksum, page;
-
- ATADEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
-
- /* Only NCQ ATA drives support/need this */
- if (drvp->drive_type != ATA_DRIVET_ATA ||
- (drvp->drive_flags & ATA_DRIVE_NCQ) == 0)
- return EOPNOTSUPP;
-
- memset(xfer, 0, sizeof(*xfer));
-
- tb = drvp->recovery_blk;
- memset(tb, 0, sizeof(drvp->recovery_blk));
-
- /*
- * We could use READ LOG DMA EXT if drive supports it (i.e.
- * when it supports Streaming feature) to avoid PIO command,
- * and to make this a little faster. Realistically, it
- * should not matter.
- */
- xfer->c_flags |= C_SKIP_QUEUE;
- xfer->c_ata_c.r_command = WDCC_READ_LOG_EXT;
- xfer->c_ata_c.r_lba = page = WDCC_LOG_PAGE_NCQ;
- xfer->c_ata_c.r_st_bmask = WDCS_DRDY;
- xfer->c_ata_c.r_st_pmask = WDCS_DRDY;
- xfer->c_ata_c.r_count = 1;
- xfer->c_ata_c.r_device = WDSD_LBA;
- xfer->c_ata_c.flags = AT_READ | AT_LBA | AT_LBA48 | flags;
- xfer->c_ata_c.timeout = 1000; /* 1s */
- xfer->c_ata_c.data = tb;
- xfer->c_ata_c.bcount = sizeof(drvp->recovery_blk);
-
- if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
- xfer) != ATACMD_COMPLETE) {
- rv = EAGAIN;
- goto out;
- }
- if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
- rv = EINVAL;
- goto out;
- }
-
- cksum = 0;
- for (int i = 0; i < sizeof(drvp->recovery_blk); i++)
- cksum += tb[i];
- if (cksum != 0) {
- device_printf(drvp->drv_softc,
- "invalid checksum %x for READ LOG EXT page %x\n",
- cksum, page);
- rv = EINVAL;
- goto out;
- }
-
- if (tb[0] & WDCC_LOG_NQ) {
- /* not queued command */
- rv = EOPNOTSUPP;
- goto out;
- }
-
- *slot = tb[0] & 0x1f;
- *status = tb[2];
- *err = tb[3];
-
- if ((*status & WDCS_ERR) == 0) {
- /*
- * We expect error here. Normal physical drives always
- * do, it's part of ATA standard. However, QEMU AHCI emulation
- * misehandles READ LOG EXT in a way that the command itself
- * returns without error, but no data is transferred.
- */
- device_printf(drvp->drv_softc,
- "READ LOG EXT page %x failed to report error: "
- "slot %d err %x status %x\n",
- page, *slot, *err, *status);
- rv = EOPNOTSUPP;
- goto out;
- }
-
- rv = 0;
-
-out:
- return rv;
-}
-
#if NATA_DMA
void
ata_dmaerr(struct ata_drive_datas *drvp, int flags)
diff -r ea9760aed674 -r 18413d6d6c00 sys/dev/ata/ata_recovery.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ata/ata_recovery.c Thu Oct 11 20:57:51 2018 +0000
@@ -0,0 +1,247 @@
+/* $NetBSD: ata_recovery.c,v 1.1.2.1 2018/10/11 20:57:51 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.1.2.1 2018/10/11 20:57:51 jdolecek Exp $");
+
+#include "opt_ata.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/kthread.h>
+#include <sys/errno.h>
+#include <sys/ataio.h>
+#include <sys/kmem.h>
+#include <sys/intr.h>
+#include <sys/bus.h>
+#include <sys/bitops.h>
+
+#include <dev/ata/ataconf.h>
+#include <dev/ata/atareg.h>
+#include <dev/ata/atavar.h>
+
+#define DEBUG_FUNCS 0x08
+#define DEBUG_PROBE 0x10
+#define DEBUG_DETACH 0x20
+#define DEBUG_XFERS 0x40
+#ifdef ATADEBUG
+extern int atadebug_mask;
+#define ATADEBUG_PRINT(args, level) \
+ if (atadebug_mask & (level)) \
+ printf args
+#else
+#define ATADEBUG_PRINT(args, level)
+#endif
+
+int
+ata_read_log_ext_ncq(struct ata_drive_datas *drvp, uint8_t flags,
+ uint8_t *slot, uint8_t *status, uint8_t *err)
+{
+ struct ata_xfer *xfer = &drvp->recovery_xfer;
+ int rv;
+ struct ata_channel *chp = drvp->chnl_softc;
+ struct atac_softc *atac = chp->ch_atac;
+ uint8_t *tb, cksum, page;
+
+ ATADEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
+
+ /* Only NCQ ATA drives support/need this */
+ if (drvp->drive_type != ATA_DRIVET_ATA ||
+ (drvp->drive_flags & ATA_DRIVE_NCQ) == 0)
+ return EOPNOTSUPP;
+
+ memset(xfer, 0, sizeof(*xfer));
+
+ tb = drvp->recovery_blk;
+ memset(tb, 0, sizeof(drvp->recovery_blk));
+
+ /*
+ * We could use READ LOG DMA EXT if drive supports it (i.e.
+ * when it supports Streaming feature) to avoid PIO command,
+ * and to make this a little faster. Realistically, it
+ * should not matter.
+ */
+ xfer->c_flags |= C_SKIP_QUEUE;
+ xfer->c_ata_c.r_command = WDCC_READ_LOG_EXT;
+ xfer->c_ata_c.r_lba = page = WDCC_LOG_PAGE_NCQ;
+ xfer->c_ata_c.r_st_bmask = WDCS_DRDY;
+ xfer->c_ata_c.r_st_pmask = WDCS_DRDY;
+ xfer->c_ata_c.r_count = 1;
+ xfer->c_ata_c.r_device = WDSD_LBA;
+ xfer->c_ata_c.flags = AT_READ | AT_LBA | AT_LBA48 | flags;
+ xfer->c_ata_c.timeout = 1000; /* 1s */
+ xfer->c_ata_c.data = tb;
+ xfer->c_ata_c.bcount = sizeof(drvp->recovery_blk);
+
+ if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
+ xfer) != ATACMD_COMPLETE) {
+ rv = EAGAIN;
+ goto out;
+ }
+ if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
+ rv = EINVAL;
+ goto out;
+ }
+
+ cksum = 0;
+ for (int i = 0; i < sizeof(drvp->recovery_blk); i++)
+ cksum += tb[i];
+ if (cksum != 0) {
+ device_printf(drvp->drv_softc,
+ "invalid checksum %x for READ LOG EXT page %x\n",
+ cksum, page);
+ rv = EINVAL;
+ goto out;
+ }
+
+ if (tb[0] & WDCC_LOG_NQ) {
+ /* not queued command */
+ rv = EOPNOTSUPP;
+ goto out;
+ }
+
+ *slot = tb[0] & 0x1f;
+ *status = tb[2];
+ *err = tb[3];
+
+ if ((*status & WDCS_ERR) == 0) {
+ /*
+ * We expect error here. Normal physical drives always
+ * do, it's part of ATA standard. However, QEMU AHCI emulation
+ * mishandles READ LOG EXT in a way that the command itself
+ * returns without error, but no data is transferred.
+ */
+ device_printf(drvp->drv_softc,
+ "READ LOG EXT page %x failed to report error: "
+ "slot %d err %x status %x\n",
+ page, *slot, *err, *status);
+ rv = EOPNOTSUPP;
+ goto out;
+ }
+
+ rv = 0;
+
+out:
+ return rv;
+}
+
+/*
+ * Must be called without channel lock, and with interrupts blocked.
+ */
+void
+ata_recovery_resume(struct ata_channel *chp, int drive, int tfd, int flags)
+{
+ struct ata_drive_datas *drvp;
+ uint8_t slot, eslot, st, err;
+ int error;
Home |
Main Index |
Thread Index |
Old Index