mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] scsi: core: Clear power-on UNIT ATTENTION on BIWIN UFS devices
@ 2026-10-29 10:41 Alexey Charkov
       [not found] ` <sashiko-outbox-189185@kernel.org>
  2026-10-29 17:19 ` Bart Van Assche
  0 siblings, 2 replies; 3+ messages in thread
From: Alexey Charkov @ 2026-10-29 10:41 UTC (permalink / raw)
  To: James E.J. Bottomley, Martin K. Petersen
  Cc: Bart Van Assche, linux-scsi, linux-kernel, Alexey Charkov

The SCSI core retries a command that receives a UNIT ATTENTION and relies
on the device to clear the condition once reported. The BIWIN
BWU2A0526B128G and BWU2A0516B064G UFS devices do not clear a power on or
reset UNIT ATTENTION when reporting it to a WRITE. After a device reset,
such as on resume with the UFS link off or in UFS error recovery, writes
then fail on every retry for the full 180s retry window and end in I/O
errors. A TEST UNIT READY or READ clears it.

Add BLIST_TUR_AFTER_RESET for such devices and set it for BIWIN models
starting with BWU2A05. Send them a TEST UNIT READY from the device event
worker, which already runs whenever a command reports a power on or reset
UNIT ATTENTION: that way the commands that fail with it are covered after
every reset, whoever performed it, and the TEST UNIT READY is sent from
process context once the device takes commands again.

Skip a device that is not runtime active by then rather than waking it up,
which would only reset it again. Until it is active, only PM requests can
reach it, and their senders handle the UNIT ATTENTION themselves. A
command that keeps failing with it holds a queue reference, which aborts a
runtime suspend, and reports it again on every retry, so the worker runs
again.

Signed-off-by: Alexey Charkov <alchark@flipper.net>
---
Changes in v2:
- Rework the quirk to put it in the SCSI layer instead of UFS (thanks Bart)
- Link to v1: https://patch.msgid.link/20261028-biwin-tua-quirk-v1-1-767a12c9b9cc@flipper.net
---
 drivers/scsi/scsi_devinfo.c |  1 +
 drivers/scsi/scsi_lib.c     | 31 +++++++++++++++++++++++++++++++
 drivers/scsi/scsi_scan.c    |  3 +++
 include/scsi/scsi_device.h  |  1 +
 include/scsi/scsi_devinfo.h |  4 +++-
 5 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index cfc259fd0141..6dea39bf2f87 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -136,6 +136,7 @@ static struct {
 	{"AIX", "VDASD", NULL, BLIST_TRY_VPD_PAGES | BLIST_NO_VPD_SIZE},
 	{"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
 	{"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_FORCELUN | BLIST_INQUIRY_36},
+	{"BIWIN", "BWU2A05", NULL, BLIST_TUR_AFTER_RESET},
 	{"BROWNIE", "1200U3P", NULL, BLIST_NOREPORTLUN},
 	{"BROWNIE", "1600U3P", NULL, BLIST_NOREPORTLUN},
 	{"CANON", "IPUBJD", NULL, BLIST_SPARSELUN},
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ab39514cc0c6..863ae93f2618 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -20,6 +20,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/hardirq.h>
+#include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
 #include <linux/blk-mq.h>
 #include <linux/blk-integrity.h>
@@ -2713,6 +2714,32 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
 	kobject_uevent_env(&sdev->sdev_gendev.kobj, KOBJ_CHANGE, envp);
 }
 
+/*
+ * Some devices do not clear a power on or reset UNIT ATTENTION when reporting
+ * it to commands such as WRITE, which then keep failing on every retry. Send
+ * them a TEST UNIT READY, which does clear it.
+ *
+ * Leave a device that is not runtime active alone. Until it is, only PM
+ * requests can reach it, and their senders deal with the UNIT ATTENTION. Any
+ * other command that keeps failing with it holds a queue reference, which
+ * aborts a runtime suspend, and re-arms this event on every retry.
+ */
+static void scsi_clear_reset_ua(struct scsi_device *sdev)
+{
+	struct device *dev = &sdev->sdev_gendev;
+	struct scsi_sense_hdr sshdr;
+	int active;
+
+	active = pm_runtime_get_if_active(dev);
+	if (!active)
+		return;
+
+	scsi_test_unit_ready(sdev, sdev->request_queue->rq_timeout, 1, &sshdr);
+
+	if (active > 0)
+		pm_runtime_put(dev);
+}
+
 /**
  *	scsi_evt_thread - send a uevent for each scsi event
  *	@work: work struct for scsi_device
@@ -2728,6 +2755,10 @@ void scsi_evt_thread(struct work_struct *work)
 
 	sdev = container_of(work, struct scsi_device, event_work);
 
+	if (sdev->tur_after_reset &&
+	    test_bit(SDEV_EVT_POWER_ON_RESET_OCCURRED, sdev->pending_events))
+		scsi_clear_reset_ua(sdev);
+
 	for (evt_type = SDEV_EVT_FIRST; evt_type <= SDEV_EVT_LAST; evt_type++)
 		if (test_and_clear_bit(evt_type, sdev->pending_events))
 			sdev_evt_send_simple(sdev, evt_type, GFP_KERNEL);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 8aae12fd38f3..22a68fd9a57b 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1066,6 +1066,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
 	if (*bflags & BLIST_IGN_MEDIA_CHANGE)
 		sdev->ignore_media_change = 1;
 
+	if (*bflags & BLIST_TUR_AFTER_RESET)
+		sdev->tur_after_reset = 1;
+
 	sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT;
 
 	if (*bflags & BLIST_TRY_VPD_PAGES)
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index e6fd6bc30644..8433880cfc84 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -250,6 +250,7 @@ struct scsi_device {
 	unsigned rpm_autosuspend:1;	/* Enable runtime autosuspend at device
 					 * creation time */
 	unsigned ignore_media_change:1; /* Ignore MEDIA CHANGE on resume */
+	unsigned tur_after_reset:1;	/* TUR clears power on/reset UAs */
 	unsigned silence_suspend:1;	/* Do not print runtime PM related messages */
 	unsigned no_vpd_size:1;		/* No VPD size reported in header */
 
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index 1d79a3b536ce..12186f851270 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -71,8 +71,10 @@
 #define BLIST_RETRY_ASC_C1	((__force blist_flags_t)(1ULL << 33))
 /* Do not query the IO Advice Hints Grouping mode page */
 #define BLIST_SKIP_IO_HINTS	((__force blist_flags_t)(1ULL << 34))
+/* Send TEST UNIT READY to clear a power on or reset UNIT ATTENTION */
+#define BLIST_TUR_AFTER_RESET	((__force blist_flags_t)(1ULL << 35))
 
-#define __BLIST_LAST_USED BLIST_SKIP_IO_HINTS
+#define __BLIST_LAST_USED BLIST_TUR_AFTER_RESET
 
 #define __BLIST_HIGH_UNUSED (~(__BLIST_LAST_USED | \
 			       (__force blist_flags_t) \

---
base-commit: 151a134a4e6ec66f69db8750c66006f5207f7a9d
change-id: 20261028-biwin-tua-quirk-4f543fc96116

Best regards,
--  
Alexey Charkov <alchark@flipper.net>


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] scsi: core: Clear power-on UNIT ATTENTION on BIWIN UFS devices
       [not found] ` <sashiko-outbox-189185@kernel.org>
@ 2026-10-29 13:33   ` Alexey Charkov
  0 siblings, 0 replies; 3+ messages in thread
From: Alexey Charkov @ 2026-10-29 13:33 UTC (permalink / raw)
  To: sashiko-reviews, James E.J. Bottomley, Martin K. Petersen,
	Bart Van Assche
  Cc: linux-scsi, linux-kernel

On Thu, Oct 29, 2026 at 3:12 PM <sashiko-bot@kernel.org> wrote:
[...]
> [Severity: High]
> Can scsi_test_unit_ready() starve waiting for a request tag when retrying
> writes saturate the queue?
>
> scsi_test_unit_ready() calls scsi_execute_cmd() -> scsi_alloc_request() ->
> blk_mq_alloc_request() with flags == 0, which waits in blk_mq_get_tag() for a
> normal non-reserved tag from bitmap_tags.
>
> When write commands receive a power-on/reset unit attention,
> drivers/scsi/scsi_lib.c:scsi_io_completion_action() requeues them immediately:
>
>         case ACTION_RETRY:
>                 /* Retry the same command immediately */
>                 __scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY, false);
>                 break;
>
> In __scsi_queue_insert() -> blk_mq_requeue_request() ->
> __blk_mq_requeue_request() -> blk_mq_put_driver_tag():
>
>         if (rq->tag == BLK_MQ_NO_TAG || rq->internal_tag == BLK_MQ_NO_TAG)
>                 return;
>
>         __blk_mq_put_driver_tag(rq->mq_hctx, rq);
>
> When an I/O scheduler is attached (such as the default mq-deadline on UFS,
> where dd_init_sched() sets q->async_depth = q->nr_requests so writes can
> consume all tags in sched_tags->bitmap_tags), __blk_mq_requeue_request()
> releases rq->tag but keeps the scheduler tag (rq->internal_tag) across all
> retries. When no I/O scheduler is configured, blk_mq_limit_depth() imposes no
> limit on writes and blk_mq_put_driver_tag() does not release rq->tag on
> requeue because rq->internal_tag == BLK_MQ_NO_TAG.
>
> If enough write requests are queued to fill all non-reserved tags across a
> reset or runtime resume, won't those writes endlessly fail and requeue while
> pinning every tag, blocking scsi_test_unit_ready() in blk_mq_get_tag() until
> a write exceeds the 180s retry window and fails with an I/O error?

Hmm, I've simulated this scenario and it is indeed the case. When a
lot of writes are in-flight at the moment of an injected UFS
error-handler reset, they end up holding every scheduler tag upon
resume, meaning the TUR queues behind them, and the recovery doesn't
happen until after the writes time out with an I/O error (which is
pretty much the original broken behavior this was meant to fix).

Given that, I'm wondering if dealing with this via the UFS devman
interface (as was done in v1) is a better option after all. Bart, what
would you say?

- sd.c looks like a wrong place, because sd never sees resets the UFS
layer does on its own, such as UFS error recovery
- The midlayer (like this version) doesn't seem to work either,
because it only learns about the reset under the host lock, where it
can't issue commands, and queuing them in a process context means they
wait for a tag from the same pool as the offending writes are holding
- The devman path in UFS, on the other hand, knows when UFS does all
of its resets, and has its own reserved tag, so the TUR can go out
inside the reset before LU queues restart (thus no deadlock of the
sorts referenced in edc0596cc04b)

I've run the same test on v1 (TUR through the devman slot): the TUR
went out inside the reset, before ufshcd_err_handler finished, and all
399599 WRITEs in the same window succeeded, with no UNIT ATTENTIONs,
stalls or I/O errors. If we go that way, v3 would be v1 plus setting
lrbp->lun from the request UPIU, as pointed out by Sashiko during the
review of v1.

Best regards,
Alexey

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] scsi: core: Clear power-on UNIT ATTENTION on BIWIN UFS devices
  2026-10-29 10:41 [PATCH v2] scsi: core: Clear power-on UNIT ATTENTION on BIWIN UFS devices Alexey Charkov
       [not found] ` <sashiko-outbox-189185@kernel.org>
@ 2026-10-29 17:19 ` Bart Van Assche
  1 sibling, 0 replies; 3+ messages in thread
From: Bart Van Assche @ 2026-10-29 17:19 UTC (permalink / raw)
  To: Alexey Charkov, James E.J. Bottomley, Martin K. Petersen
  Cc: linux-scsi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 583 bytes --]

On 10/29/26 3:41 AM, Alexey Charkov wrote:
> The SCSI core retries a command that receives a UNIT ATTENTION and relies
> on the device to clear the condition once reported. The BIWIN
> BWU2A0526B128G and BWU2A0516B064G UFS devices do not clear a power on or
> reset UNIT ATTENTION when reporting it to a WRITE. After a device reset,
> such as on resume with the UFS link off or in UFS error recovery, writes
> then fail on every retry for the full 180s retry window and end in I/O
> errors. A TEST UNIT READY or READ clears it.

Does the attached untested patch help?

Thanks,

Bart.

[-- Attachment #2: 0001-scsi-core-Clear-persistent-UNIT-ATTENTION-with-TEST-.patch --]
[-- Type: text/x-patch, Size: 9153 bytes --]

From a81dfc5b9d1ae8d77c0ef4ea70322c937767a8f2 Mon Sep 17 00:00:00 2001
From: Bart Van Assche <bvanassche@acm.org>
Date: Thu, 29 Oct 2026 10:11:42 -0700
Subject: [PATCH] scsi: core: Clear persistent UNIT ATTENTION with TEST UNIT
 READY

Recover from persistent UNIT ATTENTION conditions in the SCSI midlayer
instead of maintaining a per-device quirk list for targets such as
BIWIN BWU2A05* UFS devices that fail to clear power-on UNIT ATTENTION
on WRITE commands after a reset and only clear it on TEST UNIT READY.

Retry UNIT ATTENTION up to twice on the normal completion path in
scsi_check_sense() for non-removable block requests by returning
NEEDS_RETRY while scmd->retries < 2 and FAILED thereafter, instead of
letting scsi_io_completion_action() retry uncounted until the command
runtime limit is exceeded.

Add scsi_eh_clear_ua() to scsi_eh_ready_devs() ahead of device reset
so that the error handler sends TEST UNIT READY to consume a stuck
UNIT ATTENTION and verifies with a follow-up TEST UNIT READY that the
condition cleared before requeueing affected commands. Save and
restore scmd->sense_buffer across scsi_send_eh_cmnd() so that the
original sense data remains intact while filtering work_q and if
retries are later exhausted.

Introduce scsi_cmd_needs_stu() and use it in scsi_eh_stu() instead of
testing scsi_check_sense(scmd) == FAILED so that scsi_eh_stu() only
sends START_UNIT for LU_NOT_READY_INITIALIZING_COMMAND_REQUIRED and
not for persistent UNIT ATTENTION when sdev->allow_restart is set.

Fail non-removable commands in scsi_io_completion_action() on UNIT
ATTENTION when scsi_noretry_cmd() is true or retries exceed
max(cmd->allowed, 3) to honor failfast flags and prevent infinite
retry loops if a target continues to report UNIT ATTENTION after
recovery.

Reported-by: Alexey Charkov <alchark@flipper.net>
Closes: https://lore.kernel.org/linux-scsi/20261028-biwin-tua-quirk-v1-1-767a12c9b9cc@flipper.net/
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/scsi/scsi_error.c | 167 ++++++++++++++++++++++++++++++++++++--
 drivers/scsi/scsi_lib.c   |   4 +
 2 files changed, 162 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 75442d60c30e..e7899c86d171 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -716,6 +716,20 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
 		    sshdr.sense_code ==
 		    LU_NOT_READY_INITIALIZING_COMMAND_REQUIRED)
 			return FAILED;
+		/*
+		 * Retry UNIT ATTENTION up to twice on the normal completion
+		 * path for non-removable block requests, then invoke the error
+		 * handler so TEST UNIT READY can clear a stuck UNIT ATTENTION.
+		 */
+		if (sshdr.sense_key == UNIT_ATTENTION &&
+		    !sdev->removable &&
+		    !blk_rq_is_passthrough(req) &&
+		    scmd->submitter != SUBMITTED_BY_SCSI_ERROR_HANDLER &&
+		    !scsi_noretry_cmd(scmd)) {
+			if (scmd->retries < 2)
+				return NEEDS_RETRY;
+			return FAILED;
+		}
 		/*
 		 * Pass the UA upwards for a determination in the completion
 		 * functions.
@@ -1582,6 +1596,24 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
 	return 1;
 }
 
+static bool scsi_cmd_needs_stu(const struct scsi_cmnd *scmd)
+{
+	struct scsi_sense_hdr sshdr;
+
+	if (!scmd->device->allow_restart ||
+	    (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) ||
+	    host_byte(scmd->result) != DID_OK ||
+	    !scsi_status_is_check_condition(scmd->result) ||
+	    !SCSI_SENSE_VALID(scmd))
+		return false;
+
+	return scsi_command_normalize_sense(scmd, &sshdr) &&
+		!scsi_sense_is_deferred(&sshdr) &&
+		(sshdr.sense_key == NOT_READY ||
+		 sshdr.sense_key == UNIT_ATTENTION) &&
+		sshdr.sense_code == LU_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
+}
+
  /**
  * scsi_eh_stu - send START_UNIT if needed
  * @shost:	&scsi host being recovered.
@@ -1610,8 +1642,7 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
 		}
 		stu_scmd = NULL;
 		list_for_each_entry(scmd, work_q, eh_entry)
-			if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) &&
-			    scsi_check_sense(scmd) == FAILED ) {
+			if (scmd->device == sdev && scsi_cmd_needs_stu(scmd)) {
 				stu_scmd = scmd;
 				break;
 			}
@@ -1645,6 +1676,124 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
 	return list_empty(work_q);
 }
 
+static bool scsi_cmd_has_ua(const struct scsi_cmnd *scmd)
+{
+	struct scsi_sense_hdr sshdr;
+
+	if ((scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) ||
+	    host_byte(scmd->result) != DID_OK ||
+	    !scsi_status_is_check_condition(scmd->result) ||
+	    !SCSI_SENSE_VALID(scmd))
+		return false;
+
+	return scsi_command_normalize_sense(scmd, &sshdr) &&
+		!scsi_sense_is_deferred(&sshdr) &&
+		sshdr.sense_key == UNIT_ATTENTION;
+}
+
+static bool scsi_eh_send_tur_clear_ua(struct scsi_cmnd *scmd)
+{
+	static unsigned char tur_command[6] = { TEST_UNIT_READY };
+	u8 sense_buf[SCSI_SENSE_BUFFERSIZE];
+	struct scsi_sense_hdr sshdr;
+	enum scsi_disposition rtn;
+	bool cleared = false;
+	int i;
+
+	memcpy(sense_buf, scmd->sense_buffer, sizeof(sense_buf));
+
+	/*
+	 * Send TEST UNIT READY to consume the pending UNIT ATTENTION, then
+	 * send a follow-up TEST UNIT READY to verify that the condition
+	 * cleared rather than remaining stuck.
+	 */
+	for (i = 0; i < 4; i++) {
+		rtn = scsi_send_eh_cmnd(scmd, tur_command, sizeof(tur_command),
+					scmd->device->eh_timeout, 0);
+		if (rtn == NEEDS_RETRY)
+			continue;
+		if (rtn != SUCCESS)
+			break;
+		if (!scsi_command_normalize_sense(scmd, &sshdr) ||
+		    sshdr.sense_key == NO_SENSE ||
+		    sshdr.sense_key == RECOVERED_ERROR) {
+			cleared = true;
+			break;
+		}
+		if (sshdr.sense_key != UNIT_ATTENTION)
+			break;
+	}
+
+	memcpy(scmd->sense_buffer, sense_buf, sizeof(sense_buf));
+	return cleared;
+}
+
+/**
+ * scsi_eh_clear_ua - clear pending UNIT ATTENTION conditions if needed
+ * @shost:	SCSI host being recovered.
+ * @work_q:	&list_head for pending commands.
+ * @done_q:	&list_head for processed commands.
+ *
+ * If commands fail repeatedly with UNIT ATTENTION because a target does not
+ * clear the condition for those commands (for example, WRITE), send
+ * TEST UNIT READY to clear the UNIT ATTENTION before escalating to a reset.
+ *
+ * Return: 1 if @work_q is empty, 0 otherwise.
+ */
+static int scsi_eh_clear_ua(struct Scsi_Host *shost,
+			    struct list_head *work_q,
+			    struct list_head *done_q)
+{
+	struct scsi_cmnd *scmd, *ua_scmd, *next;
+	struct scsi_device *sdev;
+
+	shost_for_each_device(sdev, shost) {
+		if (scsi_host_eh_past_deadline(shost)) {
+			SCSI_LOG_ERROR_RECOVERY(3,
+						sdev_printk(KERN_INFO, sdev,
+							    "%s: skip clear UA, past eh deadline\n",
+							    current->comm));
+			scsi_device_put(sdev);
+			break;
+		}
+
+		ua_scmd = NULL;
+		list_for_each_entry(scmd, work_q, eh_entry) {
+			if (scmd->device == sdev && scsi_cmd_has_ua(scmd)) {
+				ua_scmd = scmd;
+				break;
+			}
+		}
+
+		if (!ua_scmd)
+			continue;
+
+		SCSI_LOG_ERROR_RECOVERY(3,
+					sdev_printk(KERN_INFO, sdev,
+						    "%s: Sending TEST_UNIT_READY to clear UA\n",
+						    current->comm));
+
+		if (!scsi_device_online(sdev) ||
+		    scsi_eh_send_tur_clear_ua(ua_scmd)) {
+			if (sdev->expecting_cc_ua)
+				sdev->expecting_cc_ua = 0;
+			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
+				if (scmd->device == sdev &&
+				    scsi_cmd_has_ua(scmd) &&
+				    scsi_eh_action(scmd, SUCCESS) == SUCCESS)
+					scsi_eh_finish_cmd(scmd, done_q);
+			}
+		} else {
+			SCSI_LOG_ERROR_RECOVERY(3,
+						sdev_printk(KERN_INFO, sdev,
+							    "%s: Failed to clear UA\n",
+							    current->comm));
+		}
+	}
+
+	return list_empty(work_q);
+}
+
 
 /**
  * scsi_eh_bus_device_reset - send bdr if needed
@@ -2275,13 +2424,13 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
 			struct list_head *work_q,
 			struct list_head *done_q)
 {
-	if (!scsi_eh_stu(shost, work_q, done_q))
-		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
-			if (!scsi_eh_target_reset(shost, work_q, done_q))
-				if (!scsi_eh_bus_reset(shost, work_q, done_q))
-					if (!scsi_eh_host_reset(shost, work_q, done_q))
-						scsi_eh_offline_sdevs(work_q,
-								      done_q);
+	if (!scsi_eh_stu(shost, work_q, done_q) &&
+	    !scsi_eh_clear_ua(shost, work_q, done_q) &&
+	    !scsi_eh_bus_device_reset(shost, work_q, done_q) &&
+	    !scsi_eh_target_reset(shost, work_q, done_q) &&
+	    !scsi_eh_bus_reset(shost, work_q, done_q) &&
+	    !scsi_eh_host_reset(shost, work_q, done_q))
+		scsi_eh_offline_sdevs(work_q, done_q);
 }
 EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ab39514cc0c6..28fcfc6de117 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -849,6 +849,10 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
 				 */
 				cmd->device->changed = 1;
 				action = ACTION_FAIL;
+			} else if (scsi_noretry_cmd(cmd) ||
+				   (cmd->allowed != SCSI_CMD_RETRIES_NO_LIMIT &&
+				    cmd->retries > max(cmd->allowed, 3))) {
+				action = ACTION_FAIL;
 			} else {
 				/* Must have been a power glitch, or a
 				 * bus reset.  Could not have been a

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-29 17:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 10:41 [PATCH v2] scsi: core: Clear power-on UNIT ATTENTION on BIWIN UFS devices Alexey Charkov
     [not found] ` <sashiko-outbox-189185@kernel.org>
2026-10-29 13:33   ` Alexey Charkov
2026-10-29 17:19 ` Bart Van Assche

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®