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 */

Reply via email to