Skip to content

Commit 2da4c5e

Browse files
committed
ata: libata-core: Improve ata_dev_power_set_active()
Improve the function ata_dev_power_set_active() by having it do nothing for a disk that is already in the active power state. To do that, introduce the function ata_dev_power_is_active() to test the current power state of the disk and return true if the disk is in the PM0: active or PM1: idle state (0xff value for the count field of the CHECK POWER MODE command output). To preserve the existing behavior, if the CHECK POWER MODE command issued in ata_dev_power_is_active() fails, the drive is assumed to be in standby mode and false is returned. With this change, issuing the VERIFY command to access the disk media to spin it up becomes unnecessary most of the time during system resume as the port reset done by libata-eh on resume often result in the drive to spin-up (this behavior is not clearly defined by the ACS specifications and may thus vary between disk models). Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
1 parent 54d7211 commit 2da4c5e

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

drivers/ata/libata-core.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,33 @@ void ata_dev_power_set_standby(struct ata_device *dev)
20422042
err_mask);
20432043
}
20442044

2045+
static bool ata_dev_power_is_active(struct ata_device *dev)
2046+
{
2047+
struct ata_taskfile tf;
2048+
unsigned int err_mask;
2049+
2050+
ata_tf_init(dev, &tf);
2051+
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
2052+
tf.protocol = ATA_PROT_NODATA;
2053+
tf.command = ATA_CMD_CHK_POWER;
2054+
2055+
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
2056+
if (err_mask) {
2057+
ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n",
2058+
err_mask);
2059+
/*
2060+
* Assume we are in standby mode so that we always force a
2061+
* spinup in ata_dev_power_set_active().
2062+
*/
2063+
return false;
2064+
}
2065+
2066+
ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect);
2067+
2068+
/* Active or idle */
2069+
return tf.nsect == 0xff;
2070+
}
2071+
20452072
/**
20462073
* ata_dev_power_set_active - Set a device power mode to active
20472074
* @dev: target device
@@ -2065,6 +2092,13 @@ void ata_dev_power_set_active(struct ata_device *dev)
20652092
if (!ata_dev_power_init_tf(dev, &tf, true))
20662093
return;
20672094

2095+
/*
2096+
* Check the device power state & condition and force a spinup with
2097+
* VERIFY command only if the drive is not already ACTIVE or IDLE.
2098+
*/
2099+
if (ata_dev_power_is_active(dev))
2100+
return;
2101+
20682102
ata_dev_notice(dev, "Entering active power mode\n");
20692103

20702104
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);

0 commit comments

Comments
 (0)