Module Name: src
Committed By: bouyer
Date: Fri Apr 5 18:23:45 UTC 2019
Modified Files:
src/sys/dev/ata: wd.c wdvar.h
Log Message:
Implement a DIRTY flag (copied from sd(4)) so avoid flushing the cache if
there has been no write. This avoids a (long) timeout on the flush cache
command triggered by atactl sleep, when the device is open only by the atactl
command itself.
If a drive has no partition open and goes to sleep, the WDF_LOADED
flag is clear, and the next open will issue wd_get_params() command.
But to wake up the drive a reset is required, and wd_get_params() doens't
issue a reset on timeout, so there's no way to wake up the disk.
Add a retry after reset to wd_get_params().
Tested by Hauke Fath; fixes PR kern/49457
To generate a diff of this commit:
cvs rdiff -u -r1.446 -r1.447 src/sys/dev/ata/wd.c
cvs rdiff -u -r1.48 -r1.49 src/sys/dev/ata/wdvar.h
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/wd.c
diff -u src/sys/dev/ata/wd.c:1.446 src/sys/dev/ata/wd.c:1.447
--- src/sys/dev/ata/wd.c:1.446 Tue Mar 19 16:56:29 2019
+++ src/sys/dev/ata/wd.c Fri Apr 5 18:23:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.446 2019/03/19 16:56:29 mlelstv Exp $ */
+/* $NetBSD: wd.c,v 1.447 2019/04/05 18:23:45 bouyer 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.446 2019/03/19 16:56:29 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.447 2019/04/05 18:23:45 bouyer Exp $");
#include "opt_ata.h"
#include "opt_wd.h"
@@ -1638,11 +1638,20 @@ wd_set_geometry(struct wd_softc *wd)
int
wd_get_params(struct wd_softc *wd, uint8_t flags, struct ataparams *params)
{
+ int retry = 0;
+again:
switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) {
case CMD_AGAIN:
return 1;
case CMD_ERR:
+ if (retry == 0) {
+ retry++;
+ (*wd->atabus->ata_reset_drive)(wd->drvp,
+ flags | AT_RST_NOCMD, NULL);
+ goto again;
+ }
+
if (wd->drvp->drive_type != ATA_DRIVET_OLD)
return 1;
/*
@@ -2227,6 +2236,7 @@ wddebug(void)
atachannel_debug(wd->drvp->chnl_softc);
}
+ wd->sc_flags &= ~WDF_DIRTY;
return 0;
}
#endif /* ATADEBUG */
Index: src/sys/dev/ata/wdvar.h
diff -u src/sys/dev/ata/wdvar.h:1.48 src/sys/dev/ata/wdvar.h:1.49
--- src/sys/dev/ata/wdvar.h:1.48 Tue Mar 19 06:51:05 2019
+++ src/sys/dev/ata/wdvar.h Fri Apr 5 18:23:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: wdvar.h,v 1.48 2019/03/19 06:51:05 mlelstv Exp $ */
+/* $NetBSD: wdvar.h,v 1.49 2019/04/05 18:23:45 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -53,6 +53,7 @@ struct wd_softc {
#define WDF_WAIT 0x020 /* waiting for resources */
#define WDF_LBA 0x040 /* using LBA mode */
#define WDF_LBA48 0x100 /* using 48-bit LBA mode */
+#define WDF_DIRTY 0x200 /* disk cache dirty */
#define WDF_OPEN 0x400 /* device is open */
uint64_t sc_capacity; /* full capacity of the device */
uint64_t sc_capacity512; /* ... in DEV_BSIZE blocks */