Commit 4a2a0c0c authored by Bart Van Assche's avatar Bart Van Assche Committed by xia-bing1
Browse files

scsi: sd: Retry START STOP UNIT commands

mainline inclusion
from mainline-v6.12-rc1
commit a8598aefae31f3bf27bad1a4cebf2b04a4cdf220
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB5FF2
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/commit/?id=a8598aefae31f3bf27bad1a4cebf2b04a4cdf220



---------------------------------------------------------------------

During system resume, sd_start_stop_device() submits a START STOP UNIT
command to the SCSI device that is being resumed. That command is not
retried in case of a unit attention and hence may fail. An example:

[16575.983359] sd 0:0:0:3: [sdd] Starting disk
[16575.983693] sd 0:0:0:3: [sdd] Start/Stop Unit failed: Result: hostbyte=0x00 driverbyte=DRIVER_OK
[16575.983712] sd 0:0:0:3: [sdd] Sense Key : 0x6
[16575.983730] sd 0:0:0:3: [sdd] ASC=0x29 ASCQ=0x0
[16575.983738] sd 0:0:0:3: PM: dpm_run_callback(): scsi_bus_resume+0x0/0xa0 returns -5
[16575.983783] sd 0:0:0:3: PM: failed to resume async: error -5

Make the SCSI core retry the START STOP UNIT command if the device reports
that it has been powered on or that it has been reset.

Cc: Damien Le Moal <dlemoal@kernel.org>
Cc: Mike Christie <michael.christie@oracle.com>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240904210304.2947789-1-bvanassche@acm.org


Reviewed-by: default avatarDamien Le Moal <dlemoal@kernel.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent ebbc9589
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -3833,9 +3833,38 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
{
	unsigned char cmd[6] = { START_STOP };	/* START_VALID */
	struct scsi_sense_hdr sshdr;
	struct scsi_failure failure_defs[] = {
		{
			/* Power on, reset, or bus device reset occurred */
			.sense = UNIT_ATTENTION,
			.asc = 0x29,
			.ascq = 0,
			.result = SAM_STAT_CHECK_CONDITION,
		},
		{
			/* Power on occurred */
			.sense = UNIT_ATTENTION,
			.asc = 0x29,
			.ascq = 1,
			.result = SAM_STAT_CHECK_CONDITION,
		},
		{
			/* SCSI bus reset */
			.sense = UNIT_ATTENTION,
			.asc = 0x29,
			.ascq = 2,
			.result = SAM_STAT_CHECK_CONDITION,
		},
		{}
	};
	struct scsi_failures failures = {
		.total_allowed = 3,
		.failure_definitions = failure_defs,
	};
	const struct scsi_exec_args exec_args = {
		.sshdr = &sshdr,
		.req_flags = BLK_MQ_REQ_PM,
		.failures = &failures,
	};
	struct scsi_device *sdp = sdkp->device;
	int res;