Commit 9cec467d authored by Damien Le Moal's avatar Damien Le Moal Committed by Niklas Cassel

ata: libata-core: Do not call ata_dev_power_set_standby() twice

For regular system shutdown, ata_dev_power_set_standby() will be
executed twice: once the scsi device is removed and another when
ata_pci_shutdown_one() executes and EH completes unloading the devices.

Make the second call to ata_dev_power_set_standby() do nothing by using
ata_dev_power_is_active() and return if the device is already in
standby.

Fixes: 2da4c5e2 ("ata: libata-core: Improve ata_dev_power_set_active()")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDamien Le Moal <dlemoal@kernel.org>
Signed-off-by: default avatarNiklas Cassel <cassel@kernel.org>
parent 26c8404e
......@@ -2001,6 +2001,33 @@ bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf,
return true;
}
static bool ata_dev_power_is_active(struct ata_device *dev)
{
struct ata_taskfile tf;
unsigned int err_mask;
ata_tf_init(dev, &tf);
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
tf.protocol = ATA_PROT_NODATA;
tf.command = ATA_CMD_CHK_POWER;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) {
ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n",
err_mask);
/*
* Assume we are in standby mode so that we always force a
* spinup in ata_dev_power_set_active().
*/
return false;
}
ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect);
/* Active or idle */
return tf.nsect == 0xff;
}
/**
* ata_dev_power_set_standby - Set a device power mode to standby
* @dev: target device
......@@ -2017,8 +2044,9 @@ void ata_dev_power_set_standby(struct ata_device *dev)
struct ata_taskfile tf;
unsigned int err_mask;
/* If the device is already sleeping, do nothing. */
if (dev->flags & ATA_DFLAG_SLEEPING)
/* If the device is already sleeping or in standby, do nothing. */
if ((dev->flags & ATA_DFLAG_SLEEPING) ||
!ata_dev_power_is_active(dev))
return;
/*
......@@ -2046,33 +2074,6 @@ void ata_dev_power_set_standby(struct ata_device *dev)
err_mask);
}
static bool ata_dev_power_is_active(struct ata_device *dev)
{
struct ata_taskfile tf;
unsigned int err_mask;
ata_tf_init(dev, &tf);
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
tf.protocol = ATA_PROT_NODATA;
tf.command = ATA_CMD_CHK_POWER;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) {
ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n",
err_mask);
/*
* Assume we are in standby mode so that we always force a
* spinup in ata_dev_power_set_active().
*/
return false;
}
ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect);
/* Active or idle */
return tf.nsect == 0xff;
}
/**
* ata_dev_power_set_active - Set a device power mode to active
* @dev: target device
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment