From nobody@FreeBSD.org  Sat Nov 21 11:41:12 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id D08E6106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 21 Nov 2009 11:41:12 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 89FBD8FC1E
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 21 Nov 2009 11:41:12 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id nALBfBKK081039
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 21 Nov 2009 11:41:11 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id nALBfBGj081013;
	Sat, 21 Nov 2009 11:41:11 GMT
	(envelope-from nobody)
Message-Id: <200911211141.nALBfBGj081013@www.freebsd.org>
Date: Sat, 21 Nov 2009 11:41:11 GMT
From: Denis <dynamic-wind@mail.ru>
To: freebsd-gnats-submit@FreeBSD.org
Subject: HDD power-off procedure is not clean
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         140752
>Category:       kern
>Synopsis:       [cam] [ata] [patch] [shutdown] HDD power-off procedure is not clean
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    brucec
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat Nov 21 11:50:01 UTC 2009
>Closed-Date:    Fri Nov 12 11:23:56 UTC 2010
>Last-Modified:  Fri Nov 12 11:30:10 UTC 2010
>Originator:     Denis
>Release:        7.2-production
>Organization:
>Environment:
Fujitsu-Siemens S6410 laptop
Hitachi HTS545016B9A300 SATA HDD (Travelstar 5K500.B family) 
>Description:
After power-down (halt -p) a loud enough "clink" sound is heard from the HDD suggesting it is performing emergency head unload. Such sound is NEVER heard when shutting down WinXP.
I am afraid that this causes excessive stress to a modern HDD.
The specification for Travelstar 5K500.B at

http://www.hitachigst.com/tech/techlib.nsf/techdocs/013B2CE7D7CBD07586257609007A40A3/$file/TS5K500.B_OEMSpecification_EAmodelRev10.pdf

declares that emergency head unload count is limited to 20,000.
Possibly there is no emergency unload, but the sound is very unpleasant.

P.S. my previous HDD died after 1 year of daily use of FreeBSD-6.3 on the same laptop.

>How-To-Repeat:

>Fix:
Could ata driver issue Sleep or Standby command at power-down as recommended in the above document?

>Release-Note:
>Audit-Trail:

From: Alexander Best <alexbestms@wwu.de>
To: <bug-followup@FreeBSD.org>,
 <dynamic-wind@mail.ru>
Cc:  
Subject: Re: kern/140752: [ata] HDD power-off procedure is not clean
Date: Sun, 06 Dec 2009 03:58:14 +0100 (CET)

   This is a MIME encoded multipart message.
 
 --+permail-2009120602581480e26a0b000071f6-a_best01+
 Content-Type: text/plain; charset=us-ascii
 Content-Transfer-Encoding: 7bit
 
 this issue has been discussed in a few threads already, but i don't think an
 agreement about how to handle the issue was made. see
 http://lists.freebsd.org/pipermail/freebsd-hackers/2009-March/027879.html
 
 attached is a small patch against HEAD which should set any hdd into standby
 immediate state (if supported) before shutdown. before that however hdds get
 their cache flushed which isn't recommended by the document you refer to in
 your pr. so you might want to remove that code from ad_shutdown().
 
 this issue needs to finally get solved imo. the technical part is quite simple
 actually. however discussing this issue has always led to bikesheds. :(
 
 cheers.
 alex
 
 --+permail-2009120602581480e26a0b000071f6-a_best01+
 Content-Type: text/plain
 Content-Transfer-Encoding: Base64
 Content-Disposition: attachment; filename="atadisk.c.patch.txt"
 
 SW5kZXg6IHN5cy9kZXYvYXRhL2F0YS1kaXNrLmMKPT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0gc3lzL2Rldi9hdGEv
 YXRhLWRpc2suYwkocmV2aXNpb24gMjAwMTc2KQorKysgc3lzL2Rldi9hdGEvYXRhLWRpc2suYwko
 d29ya2luZyBjb3B5KQpAQCAtMTg5LDYgKzE4OSwxMCBAQAogCiAgICAgaWYgKGF0YWRldi0+cGFy
 YW0uc3VwcG9ydC5jb21tYW5kMiAmIEFUQV9TVVBQT1JUX0ZMVVNIQ0FDSEUpCiAJYXRhX2NvbnRy
 b2xjbWQoZGV2LCBBVEFfRkxVU0hDQUNIRSwgMCwgMCwgMCk7CisKKyAgICBpZiAoYXRhZGV2LT5w
 YXJhbS5zdXBwb3J0LmNvbW1hbmQyICYgQVRBX1NVUFBPUlRfU1RBTkRCWSkKKwlhdGFfY29udHJv
 bGNtZChkZXYsIEFUQV9TVEFOREJZX0lNTUVESUFURSwgMCwgMCwgMCk7CisKICAgICByZXR1cm4g
 MDsKIH0KIAo=
 
 --+permail-2009120602581480e26a0b000071f6-a_best01+--

From: Alexander Best <alexbestms@wwu.de>
To: <bug-followup@FreeBSD.org>
Cc: Denis <dynamic-wind@mail.ru>
Subject: Re: kern/140752: [ata] HDD power-off procedure is not clean
Date: Sun, 31 Jan 2010 22:02:58 +0100 (CET)

   This is a MIME encoded multipart message.
 
 --+permail-20100131210258f0889e8400000bf0-a_best01+
 Content-Type: text/plain; charset=us-ascii
 Content-Transfer-Encoding: quoted-printable
 
 this patch was suggested by Warren Block on freebsd-hackers@. after applyin=
 g
 the patch the hdd heads get properly parked during shutdown.
 
 =2E..looking for a committer to put this into HEAD.
 
 cheers.
 alex
 
 --+permail-20100131210258f0889e8400000bf0-a_best01+
 Content-Type: text/plain
 Content-Transfer-Encoding: Base64
 Content-Disposition: attachment; filename="patchatadisk.c.txt"
 
 LS0tIHN5cy9kZXYvYXRhL2F0YS1kaXNrLmMub3JpZwkyMDEwLTAxLTI5IDE4OjE1OjQ5LjAwMDAw
 MDAwMCAtMDcwMAorKysgc3lzL2Rldi9hdGEvYXRhLWRpc2suYwkyMDEwLTAxLTI5IDE4OjE2OjQ3
 LjAwMDAwMDAwMCAtMDcwMApAQCAtMTkzLDcgKzE5MywxMCBAQAogCiAgICAgaWYgKGF0YWRldi0+
 cGFyYW0uc3VwcG9ydC5jb21tYW5kMiAmIEFUQV9TVVBQT1JUX0ZMVVNIQ0FDSEUpCiAJYXRhX2Nv
 bnRyb2xjbWQoZGV2LCBBVEFfRkxVU0hDQUNIRSwgMCwgMCwgMCk7Ci0gICAgcmV0dXJuIDA7CisK
 KyAgICBpZiAoYXRhZGV2LT5wYXJhbS5zdXBwb3J0LmNvbW1hbmQyICYgQVRBX1NVUFBPUlRfUE9X
 RVJNR1QpCisJYXRhX2NvbnRyb2xjbWQoZGV2LCBBVEFfU1RBTkRCWV9JTU1FRElBVEUsIDAsIDAs
 IDApOworICAgIHJldHVybiAwOyAgICAKIH0KIAogc3RhdGljIGludAo=
 
 --+permail-20100131210258f0889e8400000bf0-a_best01+--

From: Alexander Best <arundel@freebsd.org>
To: bug-followup@freebsd.org
Cc:  
Subject: Re: kern/140752: [ata] [patch] HDD power-off procedure is not clean
Date: Thu, 29 Jul 2010 23:03:14 +0000

 i'm forwarding this message i got from warren which might be helpful to anybody
 working on this pr in the future.
 
 cheers.
 alex
 
 ---------- Forwarded message ----------  
 From: Warren Block <wblock@wonkity.com>
 Date: 2010/3/6
 Subject: Summary: Re: Spin down HDD after disk sync or before power off
 To: Oliver Fromme <olli@lurza.secnetix.de>
 Cc: freebsd-hackers@freebsd.org, alexbestms@wwu.de, jkim@freebsd.org
 
 
 Just wanted to followup with a summary before all vestiges of what I learned evaporate from my memory.  My apologies for the lateness.
 
 1. Existing FreeBSD ata-disk code does not explicitly park the hard drive heads on shutdown.  So the power loss causes an emergency park, which sounds bad and is bad for the heads.
 
 2. There are a limited number of powerup/powerdown or maybe spinup/spindown cycles for a drive.  Not sure what causes the wear.
 
 3. FreeBSD doesn't park heads at reboot, either, but that's good because of #2.
 
 4. FreeBSD's suspend code does call STANDBY_IMMEDIATE to park heads.
 
 5. I couldn't tell if the STANDBY_IMMEDIATE in a reboot actually spun the drive down.  It may be that the hardware reset happens so quickly after the standby that it doesn't matter.  Or maybe it brakes very quietly.  Possibly different brands do different things.  I can think of ways to check, like measuring motor current, but don't have the equipment to try that.
 
 6. Ond?ej Majerech suggested checking NetBSD's method of spinning the drive down.  I did, and they have a direct way of telling the difference between reboot and shutdown, somewhat differently from FreeBSD.
 
 7. I actually waded hip-deep through magic C code and made a powerdown event handler for ata-disk.c.  It compiled and even seemed to work, although I don't trust it.
 
 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.
 
 Conclusions:
 
 If you rarely power down a system with FreeBSD, it may not matter, and reboots with the existing code should not be a problem.
 
 If you power down a system from FreeBSD often, the patch in http://docs.freebsd.org/cgi/getmsg.cgi?fetch=233916+0+archive/2010/freebsd-hackers/20100131.freebsd-hackers is still the lowest-impact version, although it calls STANDBY_IMMEDIATE for both reboot and shutdown.
 
 I don't have evidence either way as to whether the standby followed by a reboot causes as much wear as a cold spinup/spindown cycle, or whether that is more of a problem than emergency head parks.
 
 -Warren Block * Rapid City, South Dakota USA
 
State-Changed-From-To: open->analyzed 
State-Changed-By: arundel 
State-Changed-When: Wed Sep 22 01:20:19 UTC 2010 
State-Changed-Why:  
Oliver Fromme submitted a patch for CAM(4) which takes care of the issue. 
A patch for ATA(4) is also available, however since no distinction between 
reboots and shutdowns can be made in ATA(4) it is uncertain if the issue is 
fully fixable here, too. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140752 

From: Alexander Best <arundel@freebsd.org>
To: bug-followup@freebsd.org
Cc:  
Subject: Re: kern/140752: [ata] [patch] HDD power-off procedure is not clean
Date: Wed, 22 Sep 2010 01:18:44 +0000

 a new patch has been submitted [1].
 
 cheers.
 alex
 
 [1] http://www.freebsd.org/cgi/getmsg.cgi?fetch=144160+0+/usr/local/www/db/text/2010/freebsd-hackers/20100919.freebsd-hackers
 
 -- 
 a13x

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/140752: commit references a PR
Date: Sun, 24 Oct 2010 16:32:04 +0000 (UTC)

 Author: brucec
 Date: Sun Oct 24 16:31:57 2010
 New Revision: 214279
 URL: http://svn.freebsd.org/changeset/base/214279
 
 Log:
   Mostly revert r203420, and add similar functionality into ada(4) since the
   existing code caused problems with some SCSI controllers.
   
   A new sysctl kern.cam.ada.spindown_shutdown has been added that controls
   whether or not to spin-down disks when shutting down.
   Spinning down the disks unloads/parks the heads - this is
   much better than removing power when the disk is still
   spinning because otherwise an Emergency Unload occurs which may cause damage
   to the actuator.
   
   PR:	kern/140752
   Submitted by:   olli
   Reviewed by:	arundel
   Discussed with: mav
   MFC after:	2 weeks
 
 Modified:
   head/share/man/man4/ada.4
   head/sys/cam/ata/ata_da.c
   head/sys/cam/cam_xpt.c
   head/sys/kern/kern_shutdown.c
 
 Modified: head/share/man/man4/ada.4
 ==============================================================================
 --- head/share/man/man4/ada.4	Sun Oct 24 16:10:32 2010	(r214278)
 +++ head/share/man/man4/ada.4	Sun Oct 24 16:31:57 2010	(r214279)
 @@ -118,6 +118,9 @@ This variable determines how long the
  driver will wait before timing out an outstanding command.
  The units for this value are seconds, and the default is currently 30
  seconds.
 +.It kern.cam.ada.spindown_shutdown
 +.Pp
 +This variable determines whether to spin-down disks when shutting down.
  .El
  .Sh FILES
  .Bl -tag -width ".Pa /dev/ada*" -compact
 
 Modified: head/sys/cam/ata/ata_da.c
 ==============================================================================
 --- head/sys/cam/ata/ata_da.c	Sun Oct 24 16:10:32 2010	(r214278)
 +++ head/sys/cam/ata/ata_da.c	Sun Oct 24 16:31:57 2010	(r214279)
 @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/eventhandler.h>
  #include <sys/malloc.h>
  #include <sys/cons.h>
 +#include <sys/reboot.h>
  #include <geom/geom_disk.h>
  #endif /* _KERNEL */
  
 @@ -79,7 +80,8 @@ typedef enum {
  	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 +182,10 @@ static void		adashutdown(void *arg, int 
  #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 +197,7 @@ static void		adashutdown(void *arg, int 
  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 +210,9 @@ TUNABLE_INT("kern.cam.ada.default_timeou
  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 +675,8 @@ adaregister(struct cam_periph *periph, v
  		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.command1 & 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;
 @@ -1227,6 +1239,56 @@ adashutdown(void * arg, int howto)
  					 /*getcount_only*/0);
  		cam_periph_unlock(periph);
  	}
 +
 +	if (ada_spindown_shutdown == 0 ||
 +	    (howto & (RB_HALT | RB_POWEROFF)) == 0)
 +		return;
 +
 +	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;
 +		}
 +
 +		if (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 */
 
 Modified: head/sys/cam/cam_xpt.c
 ==============================================================================
 --- head/sys/cam/cam_xpt.c	Sun Oct 24 16:10:32 2010	(r214278)
 +++ head/sys/cam/cam_xpt.c	Sun Oct 24 16:31:57 2010	(r214279)
 @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
  #include <sys/time.h>
  #include <sys/conf.h>
  #include <sys/fcntl.h>
 -#include <sys/reboot.h>
  #include <sys/interrupt.h>
  #include <sys/sbuf.h>
  #include <sys/taskqueue.h>
 @@ -153,10 +152,6 @@ static struct xpt_softc xsoftc;
  TUNABLE_INT("kern.cam.boot_delay", &xsoftc.boot_delay);
  SYSCTL_INT(_kern_cam, OID_AUTO, boot_delay, CTLFLAG_RDTUN,
             &xsoftc.boot_delay, 0, "Bus registration wait time");
 -static int	xpt_power_down = 0;
 -TUNABLE_INT("kern.cam.power_down", &xpt_power_down);
 -SYSCTL_INT(_kern_cam, OID_AUTO, power_down, CTLFLAG_RW,
 -           &xpt_power_down, 0, "Power down devices on shutdown");
  
  /* Queues for our software interrupt handler */
  typedef TAILQ_HEAD(cam_isrq, ccb_hdr) cam_isrq_t;
 @@ -250,7 +245,6 @@ static struct cam_ed*
  		 xpt_find_device(struct cam_et *target, lun_id_t lun_id);
  static void	 xpt_config(void *arg);
  static xpt_devicefunc_t xptpassannouncefunc;
 -static void	 xpt_shutdown(void *arg, int howto);
  static void	 xptaction(struct cam_sim *sim, union ccb *work_ccb);
  static void	 xptpoll(struct cam_sim *sim);
  static void	 camisr(void *);
 @@ -4538,12 +4532,6 @@ xpt_config(void *arg)
  #endif /* CAM_DEBUG_BUS */
  #endif /* CAMDEBUG */
  
 -	/* Register our shutdown event handler */
 -	if ((EVENTHANDLER_REGISTER(shutdown_final, xpt_shutdown, 
 -				   NULL, SHUTDOWN_PRI_FIRST)) == NULL) {
 -		printf("xpt_config: failed to register shutdown event.\n");
 -	}
 -
  	periphdriver_init(1);
  	xpt_hold_boot();
  	callout_init(&xsoftc.boot_callout, 1);
 @@ -4625,87 +4613,6 @@ xpt_finishconfig_task(void *context, int
  	free(context, M_CAMXPT);
  }
  
 -/*
 - * Power down all devices when we are going to power down the system.
 - */
 -static void
 -xpt_shutdown_dev_done(struct cam_periph *periph, union ccb *done_ccb)
 -{
 -
 -	/* No-op. We're polling. */
 -	return;
 -}
 -
 -static int
 -xpt_shutdown_dev(struct cam_ed *device, void *arg)
 -{
 -	union ccb ccb;
 -	struct cam_path path;
 -
 -	if (device->flags & CAM_DEV_UNCONFIGURED)
 -		return (1);
 -
 -	if (device->protocol == PROTO_ATA) {
 -		/* Only power down device if it supports power management. */
 -		if ((device->ident_data.support.command1 &
 -		    ATA_SUPPORT_POWERMGT) == 0)
 -			return (1);
 -	} else if (device->protocol != PROTO_SCSI)
 -		return (1);
 -
 -	xpt_compile_path(&path,
 -			 NULL,
 -			 device->target->bus->path_id,
 -			 device->target->target_id,
 -			 device->lun_id);
 -	xpt_setup_ccb(&ccb.ccb_h, &path, CAM_PRIORITY_NORMAL);
 -	if (device->protocol == PROTO_ATA) {
 -		cam_fill_ataio(&ccb.ataio,
 -				    1,
 -				    xpt_shutdown_dev_done,
 -				    CAM_DIR_NONE,
 -				    0,
 -				    NULL,
 -				    0,
 -				    30*1000);
 -		ata_28bit_cmd(&ccb.ataio, ATA_SLEEP, 0, 0, 0);
 -	} else {
 -		scsi_start_stop(&ccb.csio,
 -				/*retries*/1,
 -				xpt_shutdown_dev_done,
 -				MSG_SIMPLE_Q_TAG,
 -				/*start*/FALSE,
 -				/*load/eject*/FALSE,
 -				/*immediate*/TRUE,
 -				SSD_FULL_SIZE,
 -				/*timeout*/50*1000);
 -	}
 -	xpt_polled_action(&ccb);
 -
 -	if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
 -		xpt_print(&path, "Device power down 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);
 -	xpt_release_path(&path);
 -	return (1);
 -}
 -
 -static void
 -xpt_shutdown(void * arg, int howto)
 -{
 -
 -	if (!xpt_power_down)
 -		return;
 -	if ((howto & RB_POWEROFF) == 0)
 -		return;
 -
 -	xpt_for_all_devices(xpt_shutdown_dev, NULL);
 -}
 -
  cam_status
  xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg,
  		   struct cam_path *path)
 
 Modified: head/sys/kern/kern_shutdown.c
 ==============================================================================
 --- head/sys/kern/kern_shutdown.c	Sun Oct 24 16:10:32 2010	(r214278)
 +++ head/sys/kern/kern_shutdown.c	Sun Oct 24 16:31:57 2010	(r214279)
 @@ -144,7 +144,7 @@ shutdown_conf(void *unused)
  {
  
  	EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL,
 -	    SHUTDOWN_PRI_FIRST + 100);
 +	    SHUTDOWN_PRI_FIRST);
  	EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL,
  	    SHUTDOWN_PRI_LAST + 100);
  	EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL,
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: analyzed->patched 
State-Changed-By: arundel 
State-Changed-When: Mon Oct 25 20:44:55 UTC 2010 
State-Changed-Why:  
Patched in HEAD (r214279). 

Please note: This fixes the spindown issue only for ATA devices running under 
CAM with ATA_CAM enabled. Fixing it for the ATA subsystem will require much more 
work, since ATA in general has problems with power management. Since the ATA 
subsystem will very likely become legacy software in the near future there are 
no plans porting these changes to it. 

There are plans of reworking mavs original spindown patch (r203420) at some 
point in the future so non-ATA devices will benefit from it too. However for 
this to happen the CAM subsystem needs some intensive improvement. 
For now this commit poses an efficient way of preventing ATA hdds from dying 
early due to exessive emergency head unloads/parks. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140752 
Responsible-Changed-From-To: freebsd-bugs->brucec 
Responsible-Changed-By: arundel 
Responsible-Changed-When: Tue Oct 26 23:30:50 UTC 2010 
Responsible-Changed-Why:  
Assign to Bruce as MFC reminder. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140752 
State-Changed-From-To: patched->closed 
State-Changed-By: brucec 
State-Changed-When: Fri Nov 12 11:23:31 UTC 2010 
State-Changed-Why:  
Committed to HEAD and stable/8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140752 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/140752: commit references a PR
Date: Fri, 12 Nov 2010 11:23:08 +0000 (UTC)

 Author: brucec
 Date: Fri Nov 12 11:22:59 2010
 New Revision: 215173
 URL: http://svn.freebsd.org/changeset/base/215173
 
 Log:
   MFC r214279:
   
   Mostly revert r203420, and add similar functionality into ada(4) since the
   existing code caused problems with some SCSI controllers.
   
   A new sysctl kern.cam.ada.spindown_shutdown has been added that controls
   whether or not to spin-down disks when shutting down.
   Spinning down the disks unloads/parks the heads - this is much better than
   removing power when the disk is still spinning because otherwise an
   Emergency Unload occurs which may cause damage to the actuator.
   
   The FLUSH_CACHE + STANDBY_IMMEDIATE commands are issued following the
   procedure documented in Fujitsu's MHW series product documentation under
   section 1.10.1, "Recommended power-off sequence".
   
   PR:	kern/140752
   Submitted by: olli
 
 Modified:
   stable/8/share/man/man4/ada.4
   stable/8/sys/cam/ata/ata_da.c
   stable/8/sys/cam/cam_xpt.c
 Directory Properties:
   stable/8/share/man/man4/   (props changed)
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
   stable/8/sys/dev/xen/xenpci/   (props changed)
 
 Modified: stable/8/share/man/man4/ada.4
 ==============================================================================
 --- stable/8/share/man/man4/ada.4	Fri Nov 12 09:52:56 2010	(r215172)
 +++ stable/8/share/man/man4/ada.4	Fri Nov 12 11:22:59 2010	(r215173)
 @@ -118,6 +118,9 @@ This variable determines how long the
  driver will wait before timing out an outstanding command.
  The units for this value are seconds, and the default is currently 30
  seconds.
 +.It kern.cam.ada.spindown_shutdown
 +.Pp
 +This variable determines whether to spin-down disks when shutting down.
  .El
  .Sh FILES
  .Bl -tag -width ".Pa /dev/ada*" -compact
 
 Modified: stable/8/sys/cam/ata/ata_da.c
 ==============================================================================
 --- stable/8/sys/cam/ata/ata_da.c	Fri Nov 12 09:52:56 2010	(r215172)
 +++ stable/8/sys/cam/ata/ata_da.c	Fri Nov 12 11:22:59 2010	(r215173)
 @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/eventhandler.h>
  #include <sys/malloc.h>
  #include <sys/cons.h>
 +#include <sys/reboot.h>
  #include <geom/geom_disk.h>
  #endif /* _KERNEL */
  
 @@ -79,7 +80,8 @@ typedef enum {
  	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 +182,10 @@ static void		adashutdown(void *arg, int 
  #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 +197,7 @@ static void		adashutdown(void *arg, int 
  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 +210,9 @@ TUNABLE_INT("kern.cam.ada.default_timeou
  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 +675,8 @@ adaregister(struct cam_periph *periph, v
  		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.command1 & 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;
 @@ -1223,6 +1235,56 @@ adashutdown(void * arg, int howto)
  					 /*getcount_only*/0);
  		cam_periph_unlock(periph);
  	}
 +
 +	if (ada_spindown_shutdown == 0 ||
 +	    (howto & (RB_HALT | RB_POWEROFF)) == 0)
 +		return;
 +
 +	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;
 +		}
 +
 +		if (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 */
 
 Modified: stable/8/sys/cam/cam_xpt.c
 ==============================================================================
 --- stable/8/sys/cam/cam_xpt.c	Fri Nov 12 09:52:56 2010	(r215172)
 +++ stable/8/sys/cam/cam_xpt.c	Fri Nov 12 11:22:59 2010	(r215173)
 @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/time.h>
  #include <sys/conf.h>
  #include <sys/fcntl.h>
 -#include <sys/md5.h>
 +#include <sys/reboot.h>
  #include <sys/interrupt.h>
  #include <sys/sbuf.h>
  #include <sys/taskqueue.h>
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
