Patch "scsi: sd: usb_storage: uas: Access media prior to querying device properties" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    scsi: sd: usb_storage: uas: Access media prior to querying device properties

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     scsi-sd-usb_storage-uas-access-media-prior-to-queryi.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit c3a450f19d741d9a79f5e41aa39e16c25076a093
Author: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
Date:   Tue Feb 13 09:33:06 2024 -0500

    scsi: sd: usb_storage: uas: Access media prior to querying device properties
    
    [ 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@xxxxxxxxxx
    Fixes: 1e029397d12f ("scsi: sd: Reorganize DIF/DIX code to avoid calling revalidate twice")
    Cc: stable@xxxxxxxxxxxxxxx
    Reported-by: Tasos Sahanidis <tasos@xxxxxxxxxxxx>
    Reviewed-by: Ewan D. Milne <emilne@xxxxxxxxxx>
    Reviewed-by: Bart Van Assche <bvanassche@xxxxxxx>
    Tested-by: Tasos Sahanidis <tasos@xxxxxxxxxxxx>
    Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 31b5273f43a71..4433b02c8935f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3284,6 +3284,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_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len,
+			 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.
@@ -3323,7 +3341,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 c54e9805da536..12cf9940e5b67 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 de3836412bf32..ed22053b3252f 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -878,6 +878,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 b407807cc6695..a64713fe52640 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) */




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux