mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
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: 2da4c5e24e
("ata: libata-core: Improve ata_dev_power_set_active()")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
This commit is contained in:
parent
26c8404e16
commit
9cec467d05
@ -2001,51 +2001,6 @@ bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf,
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_standby - Set a device power mode to standby
|
||||
* @dev: target device
|
||||
*
|
||||
* Issue a STANDBY IMMEDIATE command to set a device power mode to standby.
|
||||
* For an HDD device, this spins down the disks.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
*/
|
||||
void ata_dev_power_set_standby(struct ata_device *dev)
|
||||
{
|
||||
unsigned long ap_flags = dev->link->ap->flags;
|
||||
struct ata_taskfile tf;
|
||||
unsigned int err_mask;
|
||||
|
||||
/* If the device is already sleeping, do nothing. */
|
||||
if (dev->flags & ATA_DFLAG_SLEEPING)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5)
|
||||
* causing some drives to spin up and down again. For these, do nothing
|
||||
* if we are being called on shutdown.
|
||||
*/
|
||||
if ((ap_flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
|
||||
system_state == SYSTEM_POWER_OFF)
|
||||
return;
|
||||
|
||||
if ((ap_flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
|
||||
system_entering_hibernation())
|
||||
return;
|
||||
|
||||
/* Issue STANDBY IMMEDIATE command only if supported by the device */
|
||||
if (!ata_dev_power_init_tf(dev, &tf, false))
|
||||
return;
|
||||
|
||||
ata_dev_notice(dev, "Entering standby power mode\n");
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
|
||||
if (err_mask)
|
||||
ata_dev_err(dev, "STANDBY IMMEDIATE failed (err_mask=0x%x)\n",
|
||||
err_mask);
|
||||
}
|
||||
|
||||
static bool ata_dev_power_is_active(struct ata_device *dev)
|
||||
{
|
||||
struct ata_taskfile tf;
|
||||
@ -2073,6 +2028,52 @@ static bool ata_dev_power_is_active(struct ata_device *dev)
|
||||
return tf.nsect == 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_standby - Set a device power mode to standby
|
||||
* @dev: target device
|
||||
*
|
||||
* Issue a STANDBY IMMEDIATE command to set a device power mode to standby.
|
||||
* For an HDD device, this spins down the disks.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
*/
|
||||
void ata_dev_power_set_standby(struct ata_device *dev)
|
||||
{
|
||||
unsigned long ap_flags = dev->link->ap->flags;
|
||||
struct ata_taskfile tf;
|
||||
unsigned int err_mask;
|
||||
|
||||
/* If the device is already sleeping or in standby, do nothing. */
|
||||
if ((dev->flags & ATA_DFLAG_SLEEPING) ||
|
||||
!ata_dev_power_is_active(dev))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5)
|
||||
* causing some drives to spin up and down again. For these, do nothing
|
||||
* if we are being called on shutdown.
|
||||
*/
|
||||
if ((ap_flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
|
||||
system_state == SYSTEM_POWER_OFF)
|
||||
return;
|
||||
|
||||
if ((ap_flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
|
||||
system_entering_hibernation())
|
||||
return;
|
||||
|
||||
/* Issue STANDBY IMMEDIATE command only if supported by the device */
|
||||
if (!ata_dev_power_init_tf(dev, &tf, false))
|
||||
return;
|
||||
|
||||
ata_dev_notice(dev, "Entering standby power mode\n");
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
|
||||
if (err_mask)
|
||||
ata_dev_err(dev, "STANDBY IMMEDIATE failed (err_mask=0x%x)\n",
|
||||
err_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_active - Set a device power mode to active
|
||||
* @dev: target device
|
||||
|
Loading…
Reference in New Issue
Block a user