Skip to content

Commit aa3998d

Browse files
committed
ata: libata-scsi: Disable scsi device manage_system_start_stop
The introduction of a device link to create a consumer/supplier relationship between the scsi device of an ATA device and the ATA port of that ATA device fixes the ordering of system suspend and resume operations. For suspend, the scsi device is suspended first and the ata port after it. This is fine as this allows the synchronize cache and START STOP UNIT commands issued by the scsi disk driver to be executed before the ata port is disabled. For resume operations, the ata port is resumed first, followed by the scsi device. This allows having the request queue of the scsi device to be unfrozen after the ata port resume is scheduled in EH, thus avoiding to see new requests prematurely issued to the ATA device. Since libata sets manage_system_start_stop to 1, the scsi disk resume operation also results in issuing a START STOP UNIT command to the device being resumed so that the device exits standby power mode. However, restoring the ATA device to the active power mode must be synchronized with libata EH processing of the port resume operation to avoid either 1) seeing the start stop unit command being received too early when the port is not yet resumed and ready to accept commands, or after the port resume process issues commands such as IDENTIFY to revalidate the device. In this last case, the risk is that the device revalidation fails with timeout errors as the drive is still spun down. Commit 0a85890 ("ata,scsi: do not issue START STOP UNIT on resume") disabled issuing the START STOP UNIT command to avoid issues with it. But this is incorrect as transitioning a device to the active power mode from the standby power mode set on suspend requires a media access command. The IDENTIFY, READ LOG and SET FEATURES commands executed in libata EH context triggered by the ata port resume operation may thus fail. Fix these synchronization issues is by handling a device power mode transitions for system suspend and resume directly in libata EH context, without relying on the scsi disk driver management triggered with the manage_system_start_stop flag. To do this, the following libata helper functions are introduced: 1) ata_dev_power_set_standby(): This function issues a STANDBY IMMEDIATE command to transitiom a device to the standby power mode. For HDDs, this spins down the disks. This function applies only to ATA and ZAC devices and does nothing otherwise. This function also does nothing for devices that have the ATA_FLAG_NO_POWEROFF_SPINDOWN or ATA_FLAG_NO_HIBERNATE_SPINDOWN flag set. For suspend, call ata_dev_power_set_standby() in ata_eh_handle_port_suspend() before the port is disabled and frozen. ata_eh_unload() is also modified to transition all enabled devices to the standby power mode when the system is shutdown or devices removed. 2) ata_dev_power_set_active() and This function applies to ATA or ZAC devices and issues a VERIFY command for 1 sector at LBA 0 to transition the device to the active power mode. For HDDs, since this function will complete only once the disk spin up. Its execution uses the same timeouts as for reset, to give the drive enough time to complete spinup without triggering a command timeout. For resume, call ata_dev_power_set_active() in ata_eh_revalidate_and_attach() after the port has been enabled and before any other command is issued to the device. With these changes, the manage_system_start_stop and no_start_on_resume scsi device flags do not need to be set in ata_scsi_dev_config(). The flag manage_runtime_start_stop is still set to allow the sd driver to spinup/spindown a disk through the sd runtime operations. Fixes: 0a85890 ("ata,scsi: do not issue START STOP UNIT on resume") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@suse.de> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 3cc2ffe commit aa3998d

File tree

5 files changed

+148
-12
lines changed

5 files changed

+148
-12
lines changed

drivers/ata/libata-core.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,96 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
19721972
return rc;
19731973
}
19741974

1975+
/**
1976+
* ata_dev_power_set_standby - Set a device power mode to standby
1977+
* @dev: target device
1978+
*
1979+
* Issue a STANDBY IMMEDIATE command to set a device power mode to standby.
1980+
* For an HDD device, this spins down the disks.
1981+
*
1982+
* LOCKING:
1983+
* Kernel thread context (may sleep).
1984+
*/
1985+
void ata_dev_power_set_standby(struct ata_device *dev)
1986+
{
1987+
unsigned long ap_flags = dev->link->ap->flags;
1988+
struct ata_taskfile tf;
1989+
unsigned int err_mask;
1990+
1991+
/* Issue STANDBY IMMEDIATE command only if supported by the device */
1992+
if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
1993+
return;
1994+
1995+
/*
1996+
* Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5)
1997+
* causing some drives to spin up and down again. For these, do nothing
1998+
* if we are being called on shutdown.
1999+
*/
2000+
if ((ap_flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
2001+
system_state == SYSTEM_POWER_OFF)
2002+
return;
2003+
2004+
if ((ap_flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
2005+
system_entering_hibernation())
2006+
return;
2007+
2008+
ata_tf_init(dev, &tf);
2009+
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
2010+
tf.protocol = ATA_PROT_NODATA;
2011+
tf.command = ATA_CMD_STANDBYNOW1;
2012+
2013+
ata_dev_notice(dev, "Entering standby power mode\n");
2014+
2015+
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
2016+
if (err_mask)
2017+
ata_dev_err(dev, "STANDBY IMMEDIATE failed (err_mask=0x%x)\n",
2018+
err_mask);
2019+
}
2020+
2021+
/**
2022+
* ata_dev_power_set_active - Set a device power mode to active
2023+
* @dev: target device
2024+
*
2025+
* Issue a VERIFY command to enter to ensure that the device is in the
2026+
* active power mode. For a spun-down HDD (standby or idle power mode),
2027+
* the VERIFY command will complete after the disk spins up.
2028+
*
2029+
* LOCKING:
2030+
* Kernel thread context (may sleep).
2031+
*/
2032+
void ata_dev_power_set_active(struct ata_device *dev)
2033+
{
2034+
struct ata_taskfile tf;
2035+
unsigned int err_mask;
2036+
2037+
/*
2038+
* Issue READ VERIFY SECTORS command for 1 sector at lba=0 only
2039+
* if supported by the device.
2040+
*/
2041+
if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
2042+
return;
2043+
2044+
ata_tf_init(dev, &tf);
2045+
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
2046+
tf.protocol = ATA_PROT_NODATA;
2047+
tf.command = ATA_CMD_VERIFY;
2048+
tf.nsect = 1;
2049+
if (dev->flags & ATA_DFLAG_LBA) {
2050+
tf.flags |= ATA_TFLAG_LBA;
2051+
tf.device |= ATA_LBA;
2052+
} else {
2053+
/* CHS */
2054+
tf.lbal = 0x1; /* sect */
2055+
}
2056+
2057+
ata_dev_notice(dev, "Entering active power mode\n");
2058+
2059+
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
2060+
if (err_mask)
2061+
ata_dev_err(dev, "VERIFY failed (err_mask=0x%x)\n",
2062+
err_mask);
2063+
}
2064+
19752065
/**
19762066
* ata_read_log_page - read a specific log page
19772067
* @dev: target device

drivers/ata/libata-eh.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
147147
.timeouts = ata_eh_other_timeouts, },
148148
{ .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT),
149149
.timeouts = ata_eh_flush_timeouts },
150+
{ .commands = CMDS(ATA_CMD_VERIFY),
151+
.timeouts = ata_eh_reset_timeouts },
150152
};
151153
#undef CMDS
152154

@@ -498,7 +500,19 @@ static void ata_eh_unload(struct ata_port *ap)
498500
struct ata_device *dev;
499501
unsigned long flags;
500502

501-
/* Restore SControl IPM and SPD for the next driver and
503+
/*
504+
* Unless we are restarting, transition all enabled devices to
505+
* standby power mode.
506+
*/
507+
if (system_state != SYSTEM_RESTART) {
508+
ata_for_each_link(link, ap, PMP_FIRST) {
509+
ata_for_each_dev(dev, link, ENABLED)
510+
ata_dev_power_set_standby(dev);
511+
}
512+
}
513+
514+
/*
515+
* Restore SControl IPM and SPD for the next driver and
502516
* disable attached devices.
503517
*/
504518
ata_for_each_link(link, ap, PMP_FIRST) {
@@ -684,6 +698,10 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
684698
ehc->saved_xfer_mode[devno] = dev->xfer_mode;
685699
if (ata_ncq_enabled(dev))
686700
ehc->saved_ncq_enabled |= 1 << devno;
701+
702+
/* If we are resuming, wake up the device */
703+
if (ap->pflags & ATA_PFLAG_RESUMING)
704+
ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE;
687705
}
688706
}
689707

@@ -743,6 +761,8 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
743761
/* clean up */
744762
spin_lock_irqsave(ap->lock, flags);
745763

764+
ap->pflags &= ~ATA_PFLAG_RESUMING;
765+
746766
if (ap->pflags & ATA_PFLAG_LOADING)
747767
ap->pflags &= ~ATA_PFLAG_LOADING;
748768
else if ((ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) &&
@@ -1218,6 +1238,13 @@ void ata_eh_detach_dev(struct ata_device *dev)
12181238
struct ata_eh_context *ehc = &link->eh_context;
12191239
unsigned long flags;
12201240

1241+
/*
1242+
* If the device is still enabled, transition it to standby power mode
1243+
* (i.e. spin down HDDs).
1244+
*/
1245+
if (ata_dev_enabled(dev))
1246+
ata_dev_power_set_standby(dev);
1247+
12211248
ata_dev_disable(dev);
12221249

12231250
spin_lock_irqsave(ap->lock, flags);
@@ -3016,6 +3043,15 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
30163043
if (ehc->i.flags & ATA_EHI_DID_RESET)
30173044
readid_flags |= ATA_READID_POSTRESET;
30183045

3046+
/*
3047+
* When resuming, before executing any command, make sure to
3048+
* transition the device to the active power mode.
3049+
*/
3050+
if ((action & ATA_EH_SET_ACTIVE) && ata_dev_enabled(dev)) {
3051+
ata_dev_power_set_active(dev);
3052+
ata_eh_done(link, dev, ATA_EH_SET_ACTIVE);
3053+
}
3054+
30193055
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
30203056
WARN_ON(dev->class == ATA_DEV_PMP);
30213057

@@ -3989,6 +4025,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
39894025
unsigned long flags;
39904026
int rc = 0;
39914027
struct ata_device *dev;
4028+
struct ata_link *link;
39924029

39934030
/* are we suspending? */
39944031
spin_lock_irqsave(ap->lock, flags);
@@ -4001,6 +4038,12 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
40014038

40024039
WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
40034040

4041+
/* Set all devices attached to the port in standby mode */
4042+
ata_for_each_link(link, ap, HOST_FIRST) {
4043+
ata_for_each_dev(dev, link, ENABLED)
4044+
ata_dev_power_set_standby(dev);
4045+
}
4046+
40044047
/*
40054048
* If we have a ZPODD attached, check its zero
40064049
* power ready status before the port is frozen.
@@ -4083,6 +4126,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
40834126
/* update the flags */
40844127
spin_lock_irqsave(ap->lock, flags);
40854128
ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
4129+
ap->pflags |= ATA_PFLAG_RESUMING;
40864130
spin_unlock_irqrestore(ap->lock, flags);
40874131
}
40884132
#endif /* CONFIG_PM */

drivers/ata/libata-scsi.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,15 +1050,13 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
10501050
}
10511051
} else {
10521052
sdev->sector_size = ata_id_logical_sector_size(dev->id);
1053+
10531054
/*
1054-
* Stop the drive on suspend but do not issue START STOP UNIT
1055-
* on resume as this is not necessary and may fail: the device
1056-
* will be woken up by ata_port_pm_resume() with a port reset
1057-
* and device revalidation.
1055+
* Ask the sd driver to issue START STOP UNIT on runtime suspend
1056+
* and resume only. For system level suspend/resume, devices
1057+
* power state is handled directly by libata EH.
10581058
*/
1059-
sdev->manage_system_start_stop = true;
10601059
sdev->manage_runtime_start_stop = true;
1061-
sdev->no_start_on_resume = 1;
10621060
}
10631061

10641062
/*
@@ -1231,7 +1229,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
12311229
}
12321230

12331231
if (cdb[4] & 0x1) {
1234-
tf->nsect = 1; /* 1 sector, lba=0 */
1232+
tf->nsect = 1; /* 1 sector, lba=0 */
12351233

12361234
if (qc->dev->flags & ATA_DFLAG_LBA) {
12371235
tf->flags |= ATA_TFLAG_LBA;
@@ -1247,7 +1245,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
12471245
tf->lbah = 0x0; /* cyl high */
12481246
}
12491247

1250-
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
1248+
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
12511249
} else {
12521250
/* Some odd clown BIOSen issue spindown on power off (ACPI S4
12531251
* or S5) causing some drives to spin up and down again.
@@ -1257,7 +1255,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
12571255
goto skip;
12581256

12591257
if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
1260-
system_entering_hibernation())
1258+
system_entering_hibernation())
12611259
goto skip;
12621260

12631261
/* Issue ATA STANDBY IMMEDIATE command */

drivers/ata/libata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
6060
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
6161
unsigned int readid_flags);
6262
extern int ata_dev_configure(struct ata_device *dev);
63+
extern void ata_dev_power_set_standby(struct ata_device *dev);
64+
extern void ata_dev_power_set_active(struct ata_device *dev);
6365
extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
6466
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
6567
extern unsigned int ata_dev_set_feature(struct ata_device *dev,

include/linux/libata.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ enum {
192192
ATA_PFLAG_UNLOADING = (1 << 9), /* driver is being unloaded */
193193
ATA_PFLAG_UNLOADED = (1 << 10), /* driver is unloaded */
194194

195+
ATA_PFLAG_RESUMING = (1 << 16), /* port is being resumed */
195196
ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */
196197
ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */
197198
ATA_PFLAG_INIT_GTM_VALID = (1 << 19), /* initial gtm data valid */
@@ -318,9 +319,10 @@ enum {
318319
ATA_EH_ENABLE_LINK = (1 << 3),
319320
ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */
320321
ATA_EH_GET_SUCCESS_SENSE = (1 << 6), /* Get sense data for successful cmd */
322+
ATA_EH_SET_ACTIVE = (1 << 7), /* Set a device to active power mode */
321323

322324
ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK |
323-
ATA_EH_GET_SUCCESS_SENSE,
325+
ATA_EH_GET_SUCCESS_SENSE | ATA_EH_SET_ACTIVE,
324326
ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET |
325327
ATA_EH_ENABLE_LINK,
326328

@@ -357,7 +359,7 @@ enum {
357359
/* This should match the actual table size of
358360
* ata_eh_cmd_timeout_table in libata-eh.c.
359361
*/
360-
ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 7,
362+
ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 8,
361363

362364
/* Horkage types. May be set by libata or controller on drives
363365
(some horkage may be drive/controller pair dependent */

0 commit comments

Comments
 (0)