[PATCH] ATA drive spin-down
Cliff L. Biffle
cbiffle at safety.net
Fri Apr 11 17:07:23 PDT 2003
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
@@ -70,9 +70,11 @@
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 */
@@ -83,6 +85,8 @@
"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)
@@ -185,6 +189,12 @@
#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;
@@ -856,6 +866,11 @@
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
More information about the freebsd-current
mailing list