Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncq]: src/sys/dev/ata sync with HEAD, remove the nonfunctional ...
details: https://anonhg.NetBSD.org/src/rev/67431b30521b
branches: jdolecek-ncq
changeset: 822903:67431b30521b
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Mon Apr 24 09:57:22 2017 +0000
description:
sync with HEAD, remove the nonfunctional Seagate 'mod15write' bug workaround
diffstat:
sys/dev/ata/wd.c | 141 +++---------------------------------------------------
1 files changed, 9 insertions(+), 132 deletions(-)
diffs (198 lines):
diff -r f2b6f1666c68 -r 67431b30521b sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c Mon Apr 24 08:48:45 2017 +0000
+++ b/sys/dev/ata/wd.c Mon Apr 24 09:57:22 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.428.2.11 2017/04/23 01:21:04 jakllsch Exp $ */
+/* $NetBSD: wd.c,v 1.428.2.12 2017/04/24 09:57:22 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.11 2017/04/23 01:21:04 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.428.2.12 2017/04/24 09:57:22 jdolecek Exp $");
#include "opt_ata.h"
@@ -186,11 +186,6 @@
struct wd_ioctl *wi_get(struct wd_softc *);
void wdioctlstrategy(struct buf *);
-struct wd_split_mod15_private {
- struct buf *bp;
- struct ata_xfer *xfer;
-};
-
void wdgetdefaultlabel(struct wd_softc *, struct disklabel *);
void wdgetdisklabel(struct wd_softc *);
void wdstart(struct wd_softc *);
@@ -349,6 +344,10 @@
char sbuf[sizeof(WD_QUIRK_FMT) + 64];
snprintb(sbuf, sizeof(sbuf), WD_QUIRK_FMT, wd->sc_quirks);
aprint_normal_dev(self, "quirks %s\n", sbuf);
+
+ if (wd->sc_quirks & WD_QUIRK_SPLIT_MOD15_WRITE) {
+ aprint_error_dev(self, "drive corrupts write transfers with certain controllers, consider replacing\n");
+ }
}
if ((wd->sc_params.atap_multi & 0xff) > 1) {
@@ -657,123 +656,12 @@
mutex_exit(&wd->sc_lock);
}
-static void
-wd_split_mod15_write(struct buf *bp)
-{
- struct wd_split_mod15_private *m = bp->b_private;
- struct buf *obp = m->bp;
- struct ata_xfer *xfer = m->xfer;
- struct wd_softc *wd =
- device_lookup_private(&wd_cd, DISKUNIT(obp->b_dev));
-
- free(m, sizeof *m);
-
- mutex_enter(&wd->sc_lock);
- if (__predict_false(bp->b_error != 0)) {
- /*
- * Propagate the error. If this was the first half of
- * the original transfer, make sure to account for that
- * in the residual.
- */
- if (bp->b_data == obp->b_data)
- bp->b_resid += bp->b_bcount;
- goto done;
- }
-
- /*
- * If this was the second half of the transfer, we're all done!
- */
- if (bp->b_data != obp->b_data)
- goto done;
-
- /*
- * Advance the pointer to the second half and issue that command
- * using the same xfer.
- */
- bp->b_flags = obp->b_flags;
- bp->b_oflags = obp->b_oflags;
- bp->b_cflags = obp->b_cflags;
- bp->b_data = (char *)bp->b_data + bp->b_bcount;
- bp->b_blkno += (bp->b_bcount / DEV_BSIZE);
- bp->b_rawblkno += (bp->b_bcount / wd->sc_blksize);
- memset(xfer, 0, sizeof(*xfer));
- wdstart1(wd, bp, xfer);
- mutex_exit(&wd->sc_lock);
- return;
-
- done:
- obp->b_error = bp->b_error;
- obp->b_resid = bp->b_resid;
- mutex_exit(&wd->sc_lock);
-
- putiobuf(bp);
- biodone(obp);
- /* wddone() will call wdstart() */
-}
-
void
wdstart1(struct wd_softc *wd, struct buf *bp, struct ata_xfer *xfer)
{
/* must be locked on entry */
KASSERT(mutex_owned(&wd->sc_lock));
- /*
- * Deal with the "split mod15 write" quirk. We just divide the
- * transfer in two, doing the first half and then then second half
- * with the same command opening.
- *
- * Note we MUST do this here, because we can't let insertion
- * into the bufq cause the transfers to be re-merged.
- */
- if (__predict_false((wd->sc_quirks & WD_QUIRK_SPLIT_MOD15_WRITE) != 0 &&
- (bp->b_flags & B_READ) == 0 &&
- bp->b_bcount > 512 &&
- ((bp->b_bcount / 512) % 15) == 1)) {
- struct buf *nbp;
- struct wd_split_mod15_private *m;
-
- m = malloc(sizeof *m, M_TEMP, M_NOWAIT);
- if (m == NULL)
- goto fail;
-
- nbp = getiobuf(NULL, false);
- if (__predict_false(nbp == NULL)) {
- free(m, sizeof *m);
-fail:
- /* No memory -- fail the iop. */
- bp->b_error = ENOMEM;
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- ata_free_xfer(wd->drvp->chnl_softc, xfer);
- return;
- }
-
- nbp->b_error = 0;
- nbp->b_proc = bp->b_proc;
- nbp->b_dev = bp->b_dev;
-
- nbp->b_bcount = bp->b_bcount / 2;
- nbp->b_bufsize = bp->b_bcount / 2;
- nbp->b_data = bp->b_data;
-
- nbp->b_blkno = bp->b_blkno;
- nbp->b_rawblkno = bp->b_rawblkno;
-
- nbp->b_flags = bp->b_flags;
- nbp->b_oflags = bp->b_oflags;
- nbp->b_cflags = bp->b_cflags;
- nbp->b_iodone = wd_split_mod15_write;
-
- /* Put ptr to orig buf in b_private and use new buf */
- m->bp = bp;
- m->xfer = xfer;
- nbp->b_private = m;
-
- BIO_COPYPRIO(nbp, bp);
-
- bp = nbp;
- }
-
xfer->c_bio.blkno = bp->b_rawblkno;
xfer->c_bio.bcount = bp->b_bcount;
xfer->c_bio.databuf = bp->b_data;
@@ -835,7 +723,7 @@
{
struct wd_softc *wd = device_private(v);
const char *errmsg;
- int do_perror = 0, finish;
+ int do_perror = 0;
struct buf *bp;
ATADEBUG_PRINT(("wddone %s\n", device_xname(wd->sc_dev)),
@@ -938,21 +826,10 @@
disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
(bp->b_flags & B_READ));
rnd_add_uint32(&wd->rnd_source, bp->b_blkno);
-
- /*
- * XXX Yuck, but we don't want to free the xfer in this case.
- * See wd_split_mod15_write() for details.
- */
- finish = (bp->b_iodone != wd_split_mod15_write);
-
mutex_exit(&wd->sc_lock);
-
biodone(bp);
-
- if (__predict_true(finish)) {
- ata_free_xfer(wd->drvp->chnl_softc, xfer);
- wdstart(wd);
- }
+ ata_free_xfer(wd->drvp->chnl_softc, xfer);
+ wdstart(wd);
}
void
Home |
Main Index |
Thread Index |
Old Index