Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Sep 2010 23:43:14 +0200 (CEST)
From:      Oliver Fromme <olli@lurza.secnetix.de>
To:        freebsd-hackers@FreeBSD.ORG, wblock@wonkity.com, mav@FreeBSD.ORG
Subject:   Re: Summary: Re: Spin down HDD after disk sync or before power off
Message-ID:  <201009152143.o8FLhE9p022233@lurza.secnetix.de>
In-Reply-To: <alpine.BSF.2.00.1003051636030.2481@wonkity.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Warren Block <wblock@wonkity.com> wrote:
 > [...]
 > 8. Alexander Motin has an updated CAM version of the ATA system which 
 > will eventually replace the existing one.  In -CURRENT, anyway.  He was 
 > kind enough to look at my event handler.  My understanding is that he is 
 > looking at implementing the head parking/standby mechanism in that new 
 > code.

The patch below will work with the new CAM ATA driver
(i.e. ada(4) disks).  It adds a sysctl, so you can switch
the spin-down off if you're going to just reboot:
# sysctl kern.cam.ada.spindown_shutdown=0

This patch applies to stable/8, but I think it should
work with current, too (I haven't tried because I don't
have a machine running HEAD that has ada(4) disks).

Best regards
   Oliver


--- ata_da.c.orig	2010-05-23 18:16:33.000000000 +0200
+++ ata_da.c	2010-09-15 22:48:03.000000000 +0200
@@ -79,7 +79,8 @@
 	ADA_FLAG_CAN_TRIM	= 0x080,
 	ADA_FLAG_OPEN		= 0x100,
 	ADA_FLAG_SCTX_INIT	= 0x200,
-	ADA_FLAG_CAN_CFA        = 0x400
+	ADA_FLAG_CAN_CFA        = 0x400,
+	ADA_FLAG_CAN_POWERMGT   = 0x800
 } ada_flags;
 
 typedef enum {
@@ -180,6 +181,10 @@
 #define	ADA_DEFAULT_SEND_ORDERED	1
 #endif
 
+#ifndef	ADA_DEFAULT_SPINDOWN_SHUTDOWN
+#define	ADA_DEFAULT_SPINDOWN_SHUTDOWN	1
+#endif
+
 /*
  * Most platforms map firmware geometry to actual, but some don't.  If
  * not overridden, default to nothing.
@@ -191,6 +196,7 @@
 static int ada_retry_count = ADA_DEFAULT_RETRY;
 static int ada_default_timeout = ADA_DEFAULT_TIMEOUT;
 static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED;
+static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN;
 
 SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0,
             "CAM Direct Access Disk driver");
@@ -203,6 +209,9 @@
 SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW,
            &ada_send_ordered, 0, "Send Ordered Tags");
 TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered);
+SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW,
+           &ada_spindown_shutdown, 0, "Spin down upon shutdown");
+TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown);
 
 /*
  * ADA_ORDEREDTAG_INTERVAL determines how often, relative
@@ -665,6 +674,8 @@
 		softc->flags |= ADA_FLAG_CAN_48BIT;
 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
 		softc->flags |= ADA_FLAG_CAN_FLUSHCACHE;
+	if (cgd->ident_data.support.command2 & ATA_SUPPORT_POWERMGT)
+		softc->flags |= ADA_FLAG_CAN_POWERMGT;
 	if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ &&
 	    cgd->inq_flags & SID_CmdQue)
 		softc->flags |= ADA_FLAG_CAN_NCQ;
@@ -1222,6 +1233,57 @@
 					 /*getcount_only*/0);
 		cam_periph_unlock(periph);
 	}
+
+	if (ada_spindown_shutdown == 0)
+		return;
+
+	DELAY(500000);
+
+	TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
+		union ccb ccb;
+
+		/* If we paniced with lock held - not recurse here. */
+		if (cam_periph_owned(periph))
+			continue;
+		cam_periph_lock(periph);
+		softc = (struct ada_softc *)periph->softc;
+		/*
+		 * We only spin-down the drive if it is capable of it..
+		 */
+		if ((softc->flags & ADA_FLAG_CAN_POWERMGT) == 0) {
+			cam_periph_unlock(periph);
+			continue;
+		}
+
+		/* XXX Hide this behind bootverbose? */
+		xpt_print(periph->path, "spin-down\n");
+
+		xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+
+		ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
+		cam_fill_ataio(&ccb.ataio,
+				    1,
+				    adadone,
+				    CAM_DIR_NONE,
+				    0,
+				    NULL,
+				    0,
+				    ada_default_timeout*1000);
+
+		ata_28bit_cmd(&ccb.ataio, ATA_STANDBY_IMMEDIATE, 0, 0, 0);
+		xpt_polled_action(&ccb);
+
+		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+			xpt_print(periph->path, "Spin-down disk failed\n");
+
+		if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
+			cam_release_devq(ccb.ccb_h.path,
+					 /*relsim_flags*/0,
+					 /*reduction*/0,
+					 /*timeout*/0,
+					 /*getcount_only*/0);
+		cam_periph_unlock(periph);
+	}
 }
 
 #endif /* _KERNEL */



-- 
Oliver Fromme, secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing b. M.
Handelsregister: Registergericht Muenchen, HRA 74606,  Geschäftsfuehrung:
secnetix Verwaltungsgesellsch. mbH, Handelsregister: Registergericht Mün-
chen, HRB 125758,  Geschäftsführer: Maik Bachmann, Olaf Erb, Ralf Gebhart

FreeBSD-Dienstleistungen, -Produkte und mehr:  http://www.secnetix.de/bsd

Python is executable pseudocode.  Perl is executable line noise.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009152143.o8FLhE9p022233>