summaryrefslogtreecommitdiffstats
path: root/debian/patches/bugfix/all/scsi-sd-usb_storage-uas-Access-media-prior-to-queryi.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/bugfix/all/scsi-sd-usb_storage-uas-Access-media-prior-to-queryi.patch')
-rw-r--r--debian/patches/bugfix/all/scsi-sd-usb_storage-uas-Access-media-prior-to-queryi.patch155
1 files changed, 155 insertions, 0 deletions
diff --git a/debian/patches/bugfix/all/scsi-sd-usb_storage-uas-Access-media-prior-to-queryi.patch b/debian/patches/bugfix/all/scsi-sd-usb_storage-uas-Access-media-prior-to-queryi.patch
new file mode 100644
index 000000000..c59abc9f8
--- /dev/null
+++ b/debian/patches/bugfix/all/scsi-sd-usb_storage-uas-Access-media-prior-to-queryi.patch
@@ -0,0 +1,155 @@
+From: "Martin K. Petersen" <martin.petersen@oracle.com>
+Date: Tue, 13 Feb 2024 09:33:06 -0500
+Subject: scsi: sd: usb_storage: uas: Access media prior to querying device
+ properties
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/commit?id=46e587855c060a0fdcbb4349accb62b31e9ce70f
+
+[ Upstream commit 321da3dc1f3c92a12e3c5da934090d2992a8814c ]
+
+It has been observed that some USB/UAS devices return generic properties
+hardcoded in firmware for mode pages for a period of time after a device
+has been discovered. The reported properties are either garbage or they do
+not accurately reflect the characteristics of the physical storage device
+attached in the case of a bridge.
+
+Prior to commit 1e029397d12f ("scsi: sd: Reorganize DIF/DIX code to
+avoid calling revalidate twice") we would call revalidate several
+times during device discovery. As a result, incorrect values would
+eventually get replaced with ones accurately describing the attached
+storage. When we did away with the redundant revalidate pass, several
+cases were reported where devices reported nonsensical values or would
+end up in write-protected state.
+
+An initial attempt at addressing this issue involved introducing a
+delayed second revalidate invocation. However, this approach still
+left some devices reporting incorrect characteristics.
+
+Tasos Sahanidis debugged the problem further and identified that
+introducing a READ operation prior to MODE SENSE fixed the problem and that
+it wasn't a timing issue. Issuing a READ appears to cause the devices to
+update their state to reflect the actual properties of the storage
+media. Device properties like vendor, model, and storage capacity appear to
+be correctly reported from the get-go. It is unclear why these devices
+defer populating the remaining characteristics.
+
+Match the behavior of a well known commercial operating system and
+trigger a READ operation prior to querying device characteristics to
+force the device to populate the mode pages.
+
+The additional READ is triggered by a flag set in the USB storage and
+UAS drivers. We avoid issuing the READ for other transport classes
+since some storage devices identify Linux through our particular
+discovery command sequence.
+
+Link: https://lore.kernel.org/r/20240213143306.2194237-1-martin.petersen@oracle.com
+Fixes: 1e029397d12f ("scsi: sd: Reorganize DIF/DIX code to avoid calling revalidate twice")
+Cc: stable@vger.kernel.org
+Reported-by: Tasos Sahanidis <tasos@tasossah.com>
+Reviewed-by: Ewan D. Milne <emilne@redhat.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Tested-by: Tasos Sahanidis <tasos@tasossah.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/sd.c | 26 +++++++++++++++++++++++++-
+ drivers/usb/storage/scsiglue.c | 7 +++++++
+ drivers/usb/storage/uas.c | 7 +++++++
+ include/scsi/scsi_device.h | 1 +
+ 4 files changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index ad619f7c7418..3ec9b324fdcf 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -3286,6 +3286,24 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
+ return true;
+ }
+
++static void sd_read_block_zero(struct scsi_disk *sdkp)
++{
++ unsigned int buf_len = sdkp->device->sector_size;
++ char *buffer, cmd[10] = { };
++
++ buffer = kmalloc(buf_len, GFP_KERNEL);
++ if (!buffer)
++ return;
++
++ cmd[0] = READ_10;
++ put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */
++ put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */
++
++ scsi_execute_req(sdkp->device, cmd, DMA_FROM_DEVICE, buffer, buf_len,
++ NULL, SD_TIMEOUT, sdkp->max_retries, NULL);
++ kfree(buffer);
++}
++
+ /**
+ * sd_revalidate_disk - called the first time a new disk is seen,
+ * performs disk spin up, read_capacity, etc.
+@@ -3325,7 +3343,13 @@ static int sd_revalidate_disk(struct gendisk *disk)
+ */
+ if (sdkp->media_present) {
+ sd_read_capacity(sdkp, buffer);
+-
++ /*
++ * Some USB/UAS devices return generic values for mode pages
++ * until the media has been accessed. Trigger a READ operation
++ * to force the device to populate mode pages.
++ */
++ if (sdp->read_before_ms)
++ sd_read_block_zero(sdkp);
+ /*
+ * set the default to rotational. All non-rotational devices
+ * support the block characteristics VPD page, which will
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index c54e9805da53..12cf9940e5b6 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -179,6 +179,13 @@ static int slave_configure(struct scsi_device *sdev)
+ */
+ sdev->use_192_bytes_for_3f = 1;
+
++ /*
++ * Some devices report generic values until the media has been
++ * accessed. Force a READ(10) prior to querying device
++ * characteristics.
++ */
++ sdev->read_before_ms = 1;
++
+ /*
+ * Some devices don't like MODE SENSE with page=0x3f,
+ * which is the command used for checking if a device
+diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
+index ee5621bdb11e..af619efe8eab 100644
+--- a/drivers/usb/storage/uas.c
++++ b/drivers/usb/storage/uas.c
+@@ -876,6 +876,13 @@ static int uas_slave_configure(struct scsi_device *sdev)
+ if (devinfo->flags & US_FL_CAPACITY_HEURISTICS)
+ sdev->guess_capacity = 1;
+
++ /*
++ * Some devices report generic values until the media has been
++ * accessed. Force a READ(10) prior to querying device
++ * characteristics.
++ */
++ sdev->read_before_ms = 1;
++
+ /*
+ * Some devices don't like MODE SENSE with page=0x3f,
+ * which is the command used for checking if a device
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index d2751ed536df..1504d3137cc6 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -204,6 +204,7 @@ struct scsi_device {
+ unsigned use_10_for_rw:1; /* first try 10-byte read / write */
+ unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+ unsigned set_dbd_for_ms:1; /* Set "DBD" field in mode sense */
++ unsigned read_before_ms:1; /* perform a READ before MODE SENSE */
+ unsigned no_report_opcodes:1; /* no REPORT SUPPORTED OPERATION CODES */
+ unsigned no_write_same:1; /* no WRITE SAME command */
+ unsigned use_16_for_rw:1; /* Use read/write(16) over read/write(10) */
+--
+2.43.0
+