# [AHCI] Spinning down ada(4) disks



## Tzim (Nov 30, 2009)

With Freebsd 7 appeared the atacontrol spindown command, with the ata hard drive spindown timeout in the kernel ata driver.

Is there similar feature for ahci and ada drives ? 
Or a way to achieve similar behavior ?

I've been told of a script, but I can't find it anywhere.


----------



## trev (Nov 30, 2009)

"atacontrol spindown" works with my SATA drives in AHCI mode (FreeBSD 7.2-STABLE amd64).


----------



## aragon (Nov 30, 2009)

Have you tried the idle and standby commands in camcontrol(8)?


----------



## Tzim (Nov 30, 2009)

trev said:
			
		

> "atacontrol spindown" works with my SATA drives in AHCI mode (FreeBSD 7.2-STABLE amd64).



Freebsd 7.2 has not the new ahci(4) driver present in 8.0.



			
				aragon said:
			
		

> Have you tried the idle and standby commands in camcontrol(8)?



How to use them ? 
camcontrol spindown ada0 does not works.
camcontrol idle ada0 does not works either.

I tried camcontrol stop, but then, subsequent disk access doesn't return from kernel.


----------



## aragon (Dec 6, 2009)

Tzim said:
			
		

> camcontrol spindown ada0 does not works.
> camcontrol idle ada0 does not works either.



Try:


```
camcontrol standby ada0 -t 10
```

Should spin the drive down after 10 seconds of idle...


----------



## embeddedbob (Apr 1, 2010)

Nope theres no standby option in camcontrol. Not on FreeBSD 8.0 RELEASE P2 system. 

I know ive dug this thread up but does anyone know how todo this in FreeBSD 8 with AHCI*?

I previously used the command `# atacontrol spindown <disk> <time in seconds>`

Edited to add - AHCI added into the kernel so the disks use the new cam layer and appear as 'adaX'.


----------



## sub_mesa (Apr 17, 2010)

Same issue here - it appears the manpage also doesn't list a standby command.

I did manage to enable APM (Advanced Power Management) on the drives; which drives use to spindown themselves after inactivity. I successfully used these commands under FreeBSD 8-STABLE (march 2010):

`camcontrol cmd ada1 -a "EF 05 00 00 00 00 00 00 00 00 60 00"`

note: the 60 is the actual value in hex; 00 is lowest APM FF is highest value. I'm assuming the lower the value the sooner the drive will spindown.

To see if it worked:

`camcontrol identify ada1`

To disable APM:

`camcontrol cmd ada1 -a "EF 85 00 00 00 00 00 00 00 00 00 00"`

I'm not sure why the standby commands don't work anymore; hope they'll get introduced back to camcontrol before 8.1 releases.


----------



## kdemidofff (May 9, 2010)

I get this error on stable/8 while sending above command


```
camcontrol cmd ada1 -a "EF 05 00 00 00 00 00 00 00 00 60 00"
camcontrol: error sending command

camcontrol identify ada1
pass1: <ST31000528AS CC35> ATA-8 SATA 2.x device
pass1: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
...
```


```
camcontrol cmd ada0 -a "EF 05 00 00 00 00 00 00 00 00 60 00"
camcontrol: error sending command

camcontrol identify ada0
pass0: <MAXTOR STM3750330AS MX15> ATA-8 SATA 2.x device
pass0: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
...
```


----------



## sub_mesa (May 9, 2010)

Does your drive support APM? If not, this will not work.


----------



## kdemidofff (May 10, 2010)

well ataidle was working fine


----------



## kdemidofff (May 10, 2010)

"power management" doesnt work? need "advanced power management"?
is any quick hack to make ataidle work again?


```
camcontrol identify ada1
pass1: <ST31000528AS CC35> ATA-8 SATA 2.x device
pass1: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)

protocol              ATA/ATAPI-8 SATA 2.x
device model          ST31000528AS
firmware revision     CC35
serial number         9VP0VXQK
WWN                   5000c5001532e420
cylinders             16383
heads                 16
sectors/track         63
sector size           logical 512, physical 512, offset 0
LBA supported         268435455 sectors
LBA48 supported       1953525168 sectors
PIO supported         PIO4
DMA supported         WDMA2 UDMA6
media RPM             7200

Feature                      Support  Enable    Value           Vendor
read ahead                     yes      yes
write cache                    yes      yes
flush cache                    yes      yes
overlap                        no
Tagged Command Queuing (TCQ)   no       no
Native Command Queuing (NCQ)   yes              32 tags
SMART                          yes      yes
microcode download             yes      yes
security                       yes      no
power management               yes      yes
advanced power management      no       no      0/0x00
automatic acoustic management  yes      yes     254/0xFE        254/0xFE
media status notification      no       no
power-up in Standby            yes      no
write-read-verify              yes      no      0/0x0
unload                         no       no
free-fall                      no       no
data set management (TRIM)     no
```


----------



## mav@ (May 11, 2010)

Your drive seems doesn't support Advanced Power Management. You may just use simple Power Management via [cmd=]camcontrol standby ada0 -t XXX[/cmd]


----------



## kdemidofff (May 14, 2010)

I'm switched back to ata driver.. so ataidle make spin down disks again on inactivity timer...

  Is there any way to make system aware of sleeping drive? AFAIK system doesn't make account when drive sleeping for its access. Because when drive in power saving mode system gets ugly DMA transfer error message when it tries to access the fs on drive and makes queries again and again ("making request directly" message) like bad sector error... can be it short paused to access just-spinned-up drive?


----------



## mav@ (May 14, 2010)

What's wrong with 'camcontrol standby ...' that I have mentioned? Old ata(4) has too low timeout values that may cause timeouts on long spin-up.


----------



## kdemidofff (May 19, 2010)

getting timeouts on one of my drives (cable brand new from Asus mobo kit)
but after issuing it again it executes..

yes brand new camcontrol has better timeouts xD


```
camcontrol standby ada1 -t 3600
(pass1:ahcich1:0:0:0): STANDBY. ACB: e2 00 00 00 00 40 00 00 00 00 f3 00
(pass1:ahcich1:0:0:0): CAM status: Command timeout
```


```
ahcich1: Timeout on slot 0
ahcich1: is 00000000 cs 00000001 ss 00000000 rs 00000001 tfd c0 serr 00000000
ahcich1: Timeout on slot 0
ahcich1: is 00000000 cs 00000001 ss 00000000 rs 00000001 tfd c0 serr 00000000
```


```
camcontrol identify ada1
pass1: <ST31000528AS CC35> ATA-8 SATA 2.x device
pass1: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)

protocol              ATA/ATAPI-8 SATA 2.x
device model          ST31000528AS
firmware revision     CC35
```


----------



## rft (May 26, 2010)

I'm unable to disable power management feature on the HDD.
Doing:


```
% camcontrol cmd ada0 -a "EF 85 00 00 00 00 00 00 00 00 00 00"
camcontrol: error sending command
```

Drive info:

```
camcontrol identify ada0
pass0: <WDC WD10EARS-00Y5B1 80.00A80> ATA-8 SATA 2.x device
pass0: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)

protocol              ATA/ATAPI-8 SATA 2.x
device model          WDC WD10EARS-00Y5B1
firmware revision     80.00A80
cylinders             16383
heads                 16
sectors/track         63
sector size           logical 512, physical 512, offset 0
LBA supported         268435455 sectors
LBA48 supported       1953525168 sectors
PIO supported         PIO4
DMA supported         WDMA2 UDMA6

Feature                      Support  Enable    Value           Vendor
read ahead                     yes      yes
write cache                    yes      yes
flush cache                    yes      yes
overlap                        no
Tagged Command Queuing (TCQ)   no       no
Native Command Queuing (NCQ)   yes              32 tags
SMART                          yes      yes
microcode download             yes      yes
security                       yes      no
power management               yes      yes
advanced power management      no       no      0/0x00
automatic acoustic management  yes      no      254/0xFE        128/0x80
media status notification      no       no
power-up in Standby            yes      no
write-read-verify              no       no      0/0x0
unload                         no       no
free-fall                      no       no
data set management (TRIM)     no
```

Please suggest how to disable power management.

Thanks


----------



## kdemidofff (May 27, 2010)

IMHO it's works only in stable kernel, u need compile world from sources


----------



## rft (May 27, 2010)

kdulep,
Yes I'm using 8.1-PRERELEASE right now.


----------



## mcj (Jun 3, 2010)

rft said:
			
		

> I'm unable to disable power management feature on the HDD.
> 
> ```
> camcontrol identify ada0
> ...



In my experience, the only way to disable the power management on these WD Green drives is to use the wdidle3.exe utility provided by Western Digital.  It's a DOS utility, which sucks, but there's instructions on how to make a boot CD for this at http://forum.synology.com/enu/viewtopic.php?f=124&t=20907 - I used it on my WD15EARS, and it worked fine.


----------



## fronclynne (Jul 18, 2010)

*Something meaning a fix to ataidle or something equally acceptable*



			
				sub_mesa said:
			
		

> To disable APM:
> 
> `camcontrol cmd ada1 -a "EF 85 00 00 00 00 00 00 00 00 00 00"`
> 
> I'm not sure why the standby commands don't work anymore; hope they'll get introduced back to camcontrol before 8.1 releases.



Just for notational purposes, my drive is 
	
	



```
ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
ada0: <WDC WD5000BEVT-22A0RT0 01.01A01> ATA-8 SATA 2.x device
ada0: Serial Number WD-WX70AA9L4426
ada0: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada0: Command Queueing enabled
ada0: 476940MB (976773168 512 byte sectors: 16H 63S/T 16383C)
pass0: Command Queueing enabledGEOM: new disk ada0
```
`# ataidle /dev/ada0` gives 
	
	



```
could not get device information: is a device attached?
ataidle: an error occurred identifying the device /dev/ada0
```
Which makes me feel squishy as my "193 Load_Cycle_Count" is (or was) going up at about 1/min, even under heavy HDD use.

Anyway, hopefully something comes of all of this.


----------



## bugboy (Jul 25, 2010)

*FreeBSD 8.1-RELEASE has additional options*

I just found out that camcontrol(8) in FreeBSD 8.1-RELEASE now supports the following commands:

*idle:* Put ATA device into IDLE state. Optional parameter specifies automatic idle timer value in seconds.
*standby:* Put ATA device into STANDBY state. Optional parameter specifies automatic standby timer value in seconds.
*sleep:* Put ATA device into SLEEP state. Note that the only way get device out of this state may be reset.
I haven't had the time to investigate if we can use these commands to spin down disks when the system is idle, but I will look into it soon. I someone else has more info, then please post the information in this thread.


----------



## soobaerodude (Aug 1, 2010)

bugboy said:
			
		

> I just found out that camcontrol(8) in FreeBSD 8.1-RELEASE now supports the following commands:
> 
> *idle:* Put ATA device into IDLE state. Optional parameter specifies automatic idle timer value in seconds.
> *standby:* Put ATA device into STANDBY state. Optional parameter specifies automatic standby timer value in seconds.
> ...



I tried camcontrol standby in the 8.1-RELEASE, and it did spin down my SATA disks using the AHCI driver.  I tried to set a 15 minute timer for standby using:


```
camcontrol standby ada0 -t 900
```
but my drives spun down immediately.  However after disk access caused them to spin up, they did spin down on their own after 15 minutes.


----------



## mav@ (Aug 1, 2010)

Man page was not completely correct. It is already corrected in 8-STABLE. There is no idle timer in drive, only one standby timer. If you don't need to spin-down drive immediately, but after timeout, use

```
camcontrol idle ada0 -t 900
```


----------



## soobaerodude (Aug 1, 2010)

Hmm, when I initially tried *camcontrol idle ada0* (without -t), it did not seem to spin-down my drive.  It did not bring down power usage when measured with a Kill A Watt meter.  I guess my drives were already in the idle state.  However, *camcontrol standby ada0* did bring down power usage, and I could hear my drive spin down.

I'd like to set up spin-down after 15 minutes of inactivity by issuing camcontrol commands to a /usr/local/etc/rc.d/ shell script.  Trying to follow the advice above, how about this for a theoretical /usr/local/etc/rc.d/spindown.sh script?


```
#!/bin/sh

case "$1" in
start)
        /sbin/camcontrol idle ada0 -t 900
        /sbin/camcontrol idle ada1 -t 900
        /sbin/camcontrol idle ada2 -t 900
        /sbin/camcontrol idle ada3 -t 900
        /sbin/camcontrol idle ada4 -t 900
        /sbin/camcontrol idle ada5 -t 900
 
        /sbin/camcontrol standby ada0 -t 900
        /sbin/camcontrol standby ada1 -t 900
        /sbin/camcontrol standby ada2 -t 900
        /sbin/camcontrol standby ada3 -t 900
        /sbin/camcontrol standby ada4 -t 900
        /sbin/camcontrol standby ada5 -t 900
        echo "Set sata spindown to 900 seconds"
        exit 0
        ;;
stop)
        exit 0
        ;;
*)
        echo "Usage: `basename $0` {start|stop}" >&2
        exit 64
        ;;
esac
```


----------



## mav@ (Aug 1, 2010)

If you need spin down immediately - use `camcontrol standby adaX`. If you need standby after 15 minutes - use `camcontrol idle adaX -t 900` (it means: idle now, but set standby timer for 900 seconds). If you need both - `camcontrol standby adaX -t 900`. If device is already in standby - `camcontrol idle adaX -t 0` will spin it up and stop standby timer.


----------



## soobaerodude (Aug 1, 2010)

Thanks for the clarification.  I'll adjust my script accordingly.


----------



## Dr_Sweety (Aug 23, 2010)

I've stumbled upon this interesting thread while looking for information on how to replace "atacontrol spindown" with the corresponding equivalent when AHCI is used. As mentioned before if you're looking to replace "atacontrol spindown 900 ad4" the replacement would be "camcontrol idle ada4 -t 900" which means "Idle now, spin down in 900 seconds".

A very interesting read is the "AT Attachment 8 - ATA/ATAPI Command Set" specification. It helps you in mapping the various "camcontrol" idle/standby options:

From camcontrol.c:

```
if (strcmp(argv[1], "idle") == 0) {
                if (t == -1)
                        cmd = ATA_IDLE_IMMEDIATE;
                else
                        cmd = ATA_IDLE_CMD;
        } else if (strcmp(argv[1], "standby") == 0) {
                if (t == -1)
                        cmd = ATA_STANDBY_IMMEDIATE;
                else
                        cmd = ATA_STANDBY_CMD;
        } else {
                cmd = ATA_SLEEP;
                t = -1;
        }
```

The corresponding mapping (Freebsd Command vs ATA Command):


*camcontrol idle adaX: IDLE IMMEDIATE* (page 154 in the ATA8 specs): _The IDLE IMMEDIATE command allows the host to immediately place the device in the Idle mode.  Command completion may occur even though the device has not fully transitioned into the Idle mode._ -> Bottom line: the drive will immediately be put into idle mode, the platters won't spin down.
*camcontrol idle adaX -t XXX: IDLE* (p153): _The IDLE command allows the host to place the device in the Idle mode and also set the Standby timer. If the Count field is non-zero then the Standby timer shall be enabled.  The value in the Count field shall be used to determine the time programmed into the Standby timer (see 4.18).  If the Count field is zero then the Standby timer is disabled._ -> Bottom line: Same as above but in addition the standby timer will be armed which will cause the platters to spin down XXX seconds after the last request. *This is most probably what most users want!*
*camcontrol standby adaX: STANDBY IMMEDIATE* (p247): _This command causes the device to immediately enter the Standby mode._ -> Bottom line: the platters will spin down immediately.
*camcontrol standby adaX -t XXX: STANDBY* (p246): _This command causes the device to enter the Standby mode. If the Count field is non-zero then the Standby timer shall be enabled.  The value in the Count field shall be used to determine the time programmed into the Standby timer (see table 27). If the Count field is zero then the Standby timer is disabled._ Bottom line: same as above but in addition the standby timer will be activated.

The only question left for me is how to check whether the disks are currently spun down or active. The nice thing about "atacontrol" is that it will log both spin down and up of disks to syslog:


```
Aug 10 18:13:16 DrSweety-Server kernel: ad8: Idle, spin down
Aug 10 18:13:16 DrSweety-Server kernel: ad8: drive spun down.
Aug 10 20:20:09 DrSweety-Server kernel: ad8: request while spun down, starting.
```

So you'll get immediate feedback if something caused the disks to spin up. Obviously the nice thing is that you can then use a script etc. to immediately catch e.g. the "ps aux" output and - with a little bit of luck - catch the corresponding process which accessed the sleeping disks (e.g. a cron job which runs every 3 hours and causes the disks to wake up). Unfortunately, this is no longer possible with AHCI as - as opposed to atacontrol - it's no longer FreeBSD who tells the disks "go and sleep now". Instead, as we are now sending one of the ATA commandes mentioned above to the disk, the disk itself will decided that "it is now time to spin down as the last request was 900 seconds ago". I do not think that it will give the OS feedback about this. The only thing you can do is to regularly poll the current mode of the drive:


```
camcontrol cmd adaX -a "E5 00 00 00 00 00 00 00 00 00 00 00" -r -
```

This will send the ATA command *"CHECK POWER MODE"* (p86) to the drive: _The CHECK POWER MODE command allows the host to determine the current power mode of the device.  The 
CHECK POWER MODE command shall not cause the device to change power or affect the operation of the Standby timer._. Important is the last paragraph: you can safely issue the above command no matter if the drive is operating or in standby mode. It shouldn't cause the platters to spin up.

The output of the above command can be read as follows (p311):

*Value of the next to last hex code: Description*
_00h:_ Device is in Standby mode.
_40h:_ Device is in NV Cache Power Mode and the spindle is spun down or spinning down.
_41h:_ device is in NV Cache Power Mode and the spindle is spun up or spinning up.
_80h:_ Device is in Idle mode.
_FFh:_ Device is in Active mode or Idle mode.

An example:


```
# sh -c 'for drive in `camcontrol devlist -v | grep ada | cut -d , -f 2 | cut -d ")" -f 1`; do camcontrol cmd $drive  -a "E5 00 00 00 00 00 00 00 00 00 00 00" -r -; done'
50 00 00 00 00 00 00 00 00 FF 00
50 00 00 00 00 40 00 00 00 00 00
50 00 00 00 00 40 00 00 00 00 00
50 00 00 00 00 40 00 00 00 00 00
```

-> The first disk is active whereas the last 3 are currently in standby mode.

It would probably be possible to - with a little bit of effort - emulate atacontrol's behaviour regarding the logging of spin ups/downs to syslog with CAM too by using CAM internal timers etc. But as I do not have much knowledge of the FreeBSD internals I'm unfortunately not up for the task ...

I hope this post helps whomever is seeking more information regarding the topic. If you're looking for a way to keep your disks spun down as much as possible I would suggest to first disable AHCI and use the following script at startup:


```
#!/bin/sh
# /usr/local/etc/rc.d/disks.sh

DEVLIST=`ls /dev/ | egrep '^ad[0-9]+$'`

for drive in ${DEVLIST}; do
  atacontrol spindown ${drive} 900
done

wait-spinup() {
  while true; do
  read l
  l=`echo $l | grep 'request while spun down'`
   if [ -n "$l" -a "`date +%H%M%S`" != "$d" ]; then
     d=`date +%H%M%S`
     for drive in ${DEVLIST}; do
       dd if=/dev/${drive} of=/dev/null count=1 2> /dev/null &
     done
     ps axo pid,user,command | mail -s "Disks spun up" root
   fi
  done
}
tail -n 0 -F /var/log/messages | wait-spinup
```

This will send root an email with the current process table. You may use the output of that email to figure out which process caused the disks to spun up. As soon as you have tweaked your system accordingly (e.g. I'm using one script which starts a bunch of other scripts in a row which all would cause the disks to spin up) you may then enable AHCI and use the following script (at startup) to set the standby timer:


```
#!/bin/sh

DEVLIST=`camcontrol devlist -v | grep ada | cut -d , -f 2 | cut -d ')' -f 1`

for drive in ${DEVLIST}; do
  /sbin/camcontrol idle ${drive} -t 900
done
```


----------

