From: Greg Kroah-Hartman Date: Wed, 17 Jun 2026 03:57:10 +0000 (+0530) Subject: 5.15-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4eab19381620c911be5de19d25a4eda5328aa7be;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: scsi-sd-revert-rework-asynchronous-resume-support.patch --- diff --git a/queue-5.15/ata-scsi-do-not-issue-start-stop-unit-on-resume.patch b/queue-5.15/ata-scsi-do-not-issue-start-stop-unit-on-resume.patch index f6aeaac8c0..8585d05bc3 100644 --- a/queue-5.15/ata-scsi-do-not-issue-start-stop-unit-on-resume.patch +++ b/queue-5.15/ata-scsi-do-not-issue-start-stop-unit-on-resume.patch @@ -78,7 +78,7 @@ Signed-off-by: Greg Kroah-Hartman /* --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c -@@ -3729,7 +3729,7 @@ static int sd_suspend_runtime(struct dev +@@ -3681,7 +3681,7 @@ static int sd_suspend_runtime(struct dev static int sd_resume(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); @@ -87,7 +87,7 @@ Signed-off-by: Greg Kroah-Hartman if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ return 0; -@@ -3737,8 +3737,11 @@ static int sd_resume(struct device *dev) +@@ -3689,8 +3689,11 @@ static int sd_resume(struct device *dev) if (!sdkp->device->manage_start_stop) return 0; diff --git a/queue-5.15/scsi-sd-revert-rework-asynchronous-resume-support.patch b/queue-5.15/scsi-sd-revert-rework-asynchronous-resume-support.patch new file mode 100644 index 0000000000..541177d026 --- /dev/null +++ b/queue-5.15/scsi-sd-revert-rework-asynchronous-resume-support.patch @@ -0,0 +1,196 @@ +From 785538bfdd682c8e962341d585f9b88262a0475e Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Tue, 16 Aug 2022 10:26:38 -0700 +Subject: scsi: sd: Revert "Rework asynchronous resume support" + +From: Bart Van Assche + +commit 785538bfdd682c8e962341d585f9b88262a0475e upstream. + +Although commit 88f1669019bd ("scsi: sd: Rework asynchronous resume support") +eliminates a delay for some ATA disks after resume, it causes resume of ATA +disks to fail on other setups. See also: + + * "Resume process hangs for 5-6 seconds starting sometime in 5.16" + (https://bugzilla.kernel.org/show_bug.cgi?id=215880). + + * Geert's regression report + (https://lore.kernel.org/linux-scsi/alpine.DEB.2.22.394.2207191125130.1006766@ramsan.of.borg/). + +This is what I understand about this issue: + + * During resume, ata_port_pm_resume() starts the SCSI error handler. This + changes the SCSI host state into SHOST_RECOVERY and causes + scsi_queue_rq() to return BLK_STS_RESOURCE. + + * sd_resume() calls sd_start_stop_device() for ATA devices. That function + in turn calls sd_submit_start() which tries to submit a START STOP UNIT + command. That command can only be submitted after the SCSI error handler + has changed the SCSI host state back to SHOST_RUNNING. + + * The SCSI error handler runs on its own thread and calls + schedule_work(&(ap->scsi_rescan_task)). That causes + ata_scsi_dev_rescan() to be called from the context of a kernel + workqueue. That call hangs in blk_mq_get_tag(). I'm not sure why - maybe + because all available tags have been allocated by sd_submit_start() + calls (this is a guess). + +Link: https://lore.kernel.org/r/20220816172638.538734-1-bvanassche@acm.org +Fixes: 88f1669019bd ("scsi: sd: Rework asynchronous resume support") +Cc: Damien Le Moal +Cc: Hannes Reinecke +Cc: Geert Uytterhoeven +Cc: gzhqyz@gmail.com +Reported-by: Geert Uytterhoeven +Reported-by: gzhqyz@gmail.com +Reported-and-tested-by: Vlastimil Babka +Tested-by: John Garry +Tested-by: Hans de Goede +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/sd.c | 84 +++++++++++------------------------------------------- + drivers/scsi/sd.h | 5 --- + 2 files changed, 18 insertions(+), 71 deletions(-) + +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -105,7 +105,6 @@ static void sd_config_discard(struct scs + static void sd_config_write_same(struct scsi_disk *); + static int sd_revalidate_disk(struct gendisk *); + static void sd_unlock_native_capacity(struct gendisk *disk); +-static void sd_start_done_work(struct work_struct *work); + static int sd_probe(struct device *); + static int sd_remove(struct device *); + static void sd_shutdown(struct device *); +@@ -3404,7 +3403,6 @@ static int sd_probe(struct device *dev) + sdkp->max_retries = SD_MAX_RETRIES; + atomic_set(&sdkp->openers, 0); + atomic_set(&sdkp->device->ioerr_cnt, 0); +- INIT_WORK(&sdkp->start_done_work, sd_start_done_work); + + if (!sdp->request_queue->rq_timeout) { + if (sdp->type != TYPE_MOD) +@@ -3565,69 +3563,12 @@ static void scsi_disk_release(struct dev + kfree(sdkp); + } + +-/* Process sense data after a START command finished. */ +-static void sd_start_done_work(struct work_struct *work) +-{ +- struct scsi_disk *sdkp = container_of(work, typeof(*sdkp), +- start_done_work); +- struct scsi_sense_hdr sshdr; +- int res = sdkp->start_result; +- +- if (res == 0) +- return; +- +- sd_print_result(sdkp, "Start/Stop Unit failed", res); +- +- if (res < 0) +- return; +- +- if (scsi_normalize_sense(sdkp->start_sense_buffer, +- sdkp->start_sense_len, &sshdr)) +- sd_print_sense_hdr(sdkp, &sshdr); +-} +- +-/* A START command finished. May be called from interrupt context. */ +-static void sd_start_done(struct request *req, blk_status_t status) +-{ +- const struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); +- struct scsi_disk *sdkp = scsi_disk(req->q->disk); +- +- sdkp->start_result = scmd->result; +- WARN_ON_ONCE(scmd->sense_len > SCSI_SENSE_BUFFERSIZE); +- sdkp->start_sense_len = scmd->sense_len; +- memcpy(sdkp->start_sense_buffer, scmd->sense_buffer, +- ARRAY_SIZE(sdkp->start_sense_buffer)); +- WARN_ON_ONCE(!schedule_work(&sdkp->start_done_work)); +-} +- +-/* Submit a START command asynchronously. */ +-static int sd_submit_start(struct scsi_disk *sdkp, u8 cmd[], u8 cmd_len) +-{ +- struct scsi_device *sdev = sdkp->device; +- struct request_queue *q = sdev->request_queue; +- struct request *req; +- struct scsi_cmnd *scmd; +- +- req = scsi_alloc_request(q, REQ_OP_DRV_IN, BLK_MQ_REQ_PM); +- if (IS_ERR(req)) +- return PTR_ERR(req); +- +- scmd = blk_mq_rq_to_pdu(req); +- scmd->cmd_len = cmd_len; +- memcpy(scmd->cmnd, cmd, cmd_len); +- scmd->allowed = sdkp->max_retries; +- req->timeout = SD_TIMEOUT; +- req->rq_flags |= RQF_PM | RQF_QUIET; +- req->end_io = sd_start_done; +- blk_execute_rq_nowait(req, /*at_head=*/true); +- +- return 0; +-} +- + 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_device *sdp = sdkp->device; ++ int res; + + if (start) + cmd[4] |= 1; /* START */ +@@ -3638,10 +3579,23 @@ static int sd_start_stop_device(struct s + if (!scsi_device_online(sdp)) + return -ENODEV; + +- /* Wait until processing of sense data has finished. */ +- flush_work(&sdkp->start_done_work); ++ res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, ++ SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL); ++ if (res) { ++ sd_print_result(sdkp, "Start/Stop Unit failed", res); ++ if (res > 0 && scsi_sense_valid(&sshdr)) { ++ sd_print_sense_hdr(sdkp, &sshdr); ++ /* 0x3a is medium not present */ ++ if (sshdr.asc == 0x3a) ++ res = 0; ++ } ++ } + +- return sd_submit_start(sdkp, cmd, sizeof(cmd)); ++ /* SCSI error codes must not go to the generic layer */ ++ if (res) ++ return -EIO; ++ ++ return 0; + } + + /* +@@ -3668,8 +3622,6 @@ static void sd_shutdown(struct device *d + sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); + sd_start_stop_device(sdkp, 0); + } +- +- flush_work(&sdkp->start_done_work); + } + + static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) +--- a/drivers/scsi/sd.h ++++ b/drivers/scsi/sd.h +@@ -130,11 +130,6 @@ struct scsi_disk { + unsigned urswrz : 1; + unsigned security : 1; + unsigned ignore_medium_access_errors : 1; +- +- int start_result; +- u32 start_sense_len; +- u8 start_sense_buffer[SCSI_SENSE_BUFFERSIZE]; +- struct work_struct start_done_work; + }; + #define to_scsi_disk(obj) container_of(obj, struct scsi_disk, disk_dev) + diff --git a/queue-5.15/scsi-sd-unregister-device-if-device_add_disk-failed-in-sd_probe.patch b/queue-5.15/scsi-sd-unregister-device-if-device_add_disk-failed-in-sd_probe.patch index f8afb1529a..e2e22742b2 100644 --- a/queue-5.15/scsi-sd-unregister-device-if-device_add_disk-failed-in-sd_probe.patch +++ b/queue-5.15/scsi-sd-unregister-device-if-device_add_disk-failed-in-sd_probe.patch @@ -27,7 +27,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c -@@ -3421,7 +3421,7 @@ static int sd_probe(struct device *dev) +@@ -3419,7 +3419,7 @@ static int sd_probe(struct device *dev) error = device_add(&sdkp->disk_dev); if (error) { diff --git a/queue-5.15/series b/queue-5.15/series index f0249eba7b..7f3923d6d9 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -416,6 +416,7 @@ media-rc-igorplugusb-fix-control-request-setup-packet.patch scsi-core-suppress-a-kernel-doc-warning.patch scsi-core-declare-scsi_scan_type-static.patch scsi-sd-rework-asynchronous-resume-support.patch +scsi-sd-revert-rework-asynchronous-resume-support.patch nvme-fix-discard-support-without-oncs.patch ata-libata-scsi-avoid-deadlock-on-rescan-after-device-resume.patch ata-scsi-do-not-issue-start-stop-unit-on-resume.patch