Commit aa3998dbeb3a ("ata: libata-scsi: Disable scsi device manage_system_start_stop") change setting the manage_system_start_stop flag to false for libata managed disks to enable libata internal management of disk suspend/resume. However, a side effect of this change is that on system shutdown, disks are no longer being stopped (set to standby mode with the heads unloaded). While this is not a critical issue, this unclean shutdown is not recommended and shows up with increased smart counters (e.g. the unexpected power loss counter "Unexpect_Power_Loss_Ct"). Instead of defining a shutdown driver method for all ATA adapter drivers (not all of them define that operation), this patch resolves this issue by further refining the sd driver start/stop control of disks using the new flag manage_shutdown. If set to true, the function sd_shutdown() will issue a START STOP UNIT command with the start argument set to 0 when a disk is shutdown on system power off (system_state == SYSTEM_POWER_OFF). Fixes: aa3998dbeb3a ("ata: libata-scsi: Disable scsi device manage_system_start_stop") Cc: stable@xxxxxxxxxxxxxxx Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218038 Link: https://lore.kernel.org/all/cd397c88-bf53-4768-9ab8-9d107df9e613@xxxxxxxxx/ Signed-off-by: Damien Le Moal <dlemoal@xxxxxxxxxx> --- drivers/ata/libata-scsi.c | 5 +++-- drivers/firewire/sbp2.c | 1 + drivers/scsi/sd.c | 6 ++++-- include/scsi/scsi_device.h | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index a371b497035e..3a957c4da409 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1053,10 +1053,11 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) /* * Ask the sd driver to issue START STOP UNIT on runtime suspend - * and resume only. For system level suspend/resume, devices - * power state is handled directly by libata EH. + * and resume and shutdown only. For system level suspend/resume, + * devices power state is handled directly by libata EH. */ sdev->manage_runtime_start_stop = true; + sdev->manage_shutdown = true; } /* diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 749868b9e80d..7edf2c95282f 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -1521,6 +1521,7 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) if (sbp2_param_exclusive_login) { sdev->manage_system_start_stop = true; sdev->manage_runtime_start_stop = true; + sdev->manage_shutdown = true; } if (sdev->type == TYPE_ROM) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 83b6a3f3863b..52fa266d976f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3819,8 +3819,10 @@ static void sd_shutdown(struct device *dev) sd_sync_cache(sdkp, NULL); } - if (system_state != SYSTEM_RESTART && - sdkp->device->manage_system_start_stop) { + if ((system_state != SYSTEM_RESTART && + sdkp->device->manage_system_start_stop) || + (system_state == SYSTEM_POWER_OFF && + sdkp->device->manage_shutdown)) { sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); sd_start_stop_device(sdkp, 0); } diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index fd41fdac0a8e..7edefb73bf69 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -164,6 +164,7 @@ struct scsi_device { bool manage_system_start_stop; /* Let HLD (sd) manage system start/stop */ bool manage_runtime_start_stop; /* Let HLD (sd) manage runtime start/stop */ + bool manage_shutdown; /* Let HLD (sd) manage shutdown */ unsigned removable:1; unsigned changed:1; /* Data invalid due to media change */ -- 2.41.0