Linux SCSI subsystem development
 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
  2026-10-29 11:12 ` sashiko-bot
  2026-10-29 17:19 ` Bart Van Assche
  0 siblings, 2 replies; 4+ 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 related	[flat|nested] 4+ messages in thread

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

Thread overview: 4+ 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
2026-10-29 11:12 ` sashiko-bot
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