[PATCH] ATA drive spin-down

From: Cliff L. Biffle <cbiffle_at_safety.net>
Date: Fri, 11 Apr 2003 17:07:39 -0700
Please find attached a kernel patch to enable ATA drive spin-down after a 
specified interval.  I'm using this on my laptop now with much success; I'm 
offering it primarily for testing purposes.  I'll toss it onto mobile if it 
seems okay.

This is simply an update of an earlier patch for 4.x; it's been updated to 
reflect the new ata_command syntax and some rearrangements in ata-disk.c.

The net effect of this patch is to provide a sysctl, hw.ata.suspend, that sets 
the disk auto-spindown delay in seconds.  This must be set at boot in 
loader.conf, and the value is sent to the drive on initialization, and again 
on reinit (such as after a suspend/resume cycle).  There -should- be no 
effect if hw.ata.suspend is not set.

The original patch was apparently to be superceded by code from Soren Schmidt, 
but I haven't been able to find any.  If anyone has any leads on what this 
real solution would be, drop me a line, I'll be happy to help test.

The one judgement I had to make when writing this was whether to place the 
suspend code before or after ATA_UNLOCK_CH.  I've placed it -after- the call.  
Anyone with more familiarity of the ATA subsystem, let me know if this was 
the right decision.

-Cliff L. Biffle

--- src/sys/dev/ata/ata-disk.c.orig	Fri Apr 11 12:50:37 2003
+++ src/sys/dev/ata/ata-disk.c	Fri Apr 11 13:05:54 2003
_at__at_ -70,9 +70,11 _at__at_
 static int ata_dma = 1;
 static int ata_wc = 1;
 static int ata_tags = 0; 
+static int ata_suspend = 0;
 TUNABLE_INT("hw.ata.ata_dma", &ata_dma);
 TUNABLE_INT("hw.ata.wc", &ata_wc);
 TUNABLE_INT("hw.ata.tags", &ata_tags);
+TUNABLE_INT("hw.ata.suspend", &ata_suspend);
 static MALLOC_DEFINE(M_AD, "AD driver", "ATA disk driver");
 
 /* sysctl vars */
_at__at_ -83,6 +85,8 _at__at_
 	   "ATA disk write caching");
 SYSCTL_INT(_hw_ata, OID_AUTO, tags, CTLFLAG_RD, &ata_tags, 0,
 	   "ATA disk tagged queuing support");
+SYSCTL_INT(_hw_ata, OID_AUTO, suspend, CTLFLAG_RD, &ata_suspend, 0,
+	   "ATA disk suspend timer");
 
 void
 ad_attach(struct ata_device *atadev)
_at__at_ -185,6 +189,12 _at__at_
 #endif
     ATA_UNLOCK_CH(atadev->channel);
 
+	 if(ata_suspend > 0) {
+		 /* attempt suspend mode.  The drive uses increments of ten seconds */
+		 if(ata_command(atadev, 0xe2, 0, ata_suspend/10, 0, ATA_WAIT_INTR))
+			 ata_prtdev(atadev, "suspend mode failed.");
+	 }
+
     adp->disk.d_open = adopen;
     adp->disk.d_close = adclose;
     adp->disk.d_strategy = adstrategy;
_at__at_ -856,6 +866,11 _at__at_
     ata_command(atadev, ATA_C_SET_MULTI, 0,
 		adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY);
     atadev->setmode(atadev, adp->device->mode);
+	 if(ata_suspend > 0) {
+		 /* attempt suspend mode.  The drive uses increments of ten seconds */
+		 if(ata_command(atadev, 0xe2, 0, ata_suspend/10, 0, ATA_WAIT_READY))
+			 ata_prtdev(atadev, "suspend mode failed.");
+	 }
 }
 
 void
Received on Fri Apr 11 2003 - 15:07:22 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:03 UTC