diff options
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.patch | 155 |
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 + |