]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: core: Query the Block Limits Extension VPD page
authorBart Van Assche <bvanassche@acm.org>
Tue, 30 Jan 2024 21:48:35 +0000 (13:48 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 27 Feb 2024 02:37:26 +0000 (21:37 -0500)
Parse the Reduced Stream Control Supported (RSCS) bit from the block limits
extension VPD page. The RSCS bit is defined in SBC-5 r05
(https://www.t10.org/cgi-bin/ac.pl?t=f&f=sbc5r05.pdf).

Reviewed-by: Avri Altman <avri.altman@wdc.com>
Reviewed-by: Daejun Park <daejun7.park@samsung.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240130214911.1863909-10-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
drivers/scsi/sd.h
include/scsi/scsi_device.h

index 76d369343c7a9c2457e7d7bc16aa518815cbfc8f..74cc3369dd8de76fcef2b457ec0894dbd8727a17 100644 (file)
@@ -499,6 +499,8 @@ void scsi_attach_vpd(struct scsi_device *sdev)
                        scsi_update_vpd_page(sdev, 0xb1, &sdev->vpd_pgb1);
                if (vpd_buf->data[i] == 0xb2)
                        scsi_update_vpd_page(sdev, 0xb2, &sdev->vpd_pgb2);
+               if (vpd_buf->data[i] == 0xb7)
+                       scsi_update_vpd_page(sdev, 0xb7, &sdev->vpd_pgb7);
        }
        kfree(vpd_buf);
 }
index 24f6eefb68030d39869934e6fbefc9fce11d640b..93652a786a4693dbf27d7f7ab32322d167d0193b 100644 (file)
@@ -449,6 +449,7 @@ static void scsi_device_dev_release(struct device *dev)
        struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
        struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL;
        struct scsi_vpd *vpd_pgb0 = NULL, *vpd_pgb1 = NULL, *vpd_pgb2 = NULL;
+       struct scsi_vpd *vpd_pgb7 = NULL;
        unsigned long flags;
 
        might_sleep();
@@ -494,6 +495,8 @@ static void scsi_device_dev_release(struct device *dev)
                                       lockdep_is_held(&sdev->inquiry_mutex));
        vpd_pgb2 = rcu_replace_pointer(sdev->vpd_pgb2, vpd_pgb2,
                                       lockdep_is_held(&sdev->inquiry_mutex));
+       vpd_pgb7 = rcu_replace_pointer(sdev->vpd_pgb7, vpd_pgb7,
+                                      lockdep_is_held(&sdev->inquiry_mutex));
        mutex_unlock(&sdev->inquiry_mutex);
 
        if (vpd_pg0)
@@ -510,6 +513,8 @@ static void scsi_device_dev_release(struct device *dev)
                kfree_rcu(vpd_pgb1, rcu);
        if (vpd_pgb2)
                kfree_rcu(vpd_pgb2, rcu);
+       if (vpd_pgb7)
+               kfree_rcu(vpd_pgb7, rcu);
        kfree(sdev->inquiry);
        kfree(sdev);
 
@@ -921,6 +926,7 @@ sdev_vpd_pg_attr(pg89);
 sdev_vpd_pg_attr(pgb0);
 sdev_vpd_pg_attr(pgb1);
 sdev_vpd_pg_attr(pgb2);
+sdev_vpd_pg_attr(pgb7);
 sdev_vpd_pg_attr(pg0);
 
 static ssize_t show_inquiry(struct file *filep, struct kobject *kobj,
@@ -1295,6 +1301,9 @@ static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj,
        if (attr == &dev_attr_vpd_pgb2 && !sdev->vpd_pgb2)
                return 0;
 
+       if (attr == &dev_attr_vpd_pgb7 && !sdev->vpd_pgb7)
+               return 0;
+
        return S_IRUGO;
 }
 
@@ -1347,6 +1356,7 @@ static struct bin_attribute *scsi_sdev_bin_attrs[] = {
        &dev_attr_vpd_pgb0,
        &dev_attr_vpd_pgb1,
        &dev_attr_vpd_pgb2,
+       &dev_attr_vpd_pgb7,
        &dev_attr_inquiry,
        NULL
 };
index 0833b3e6aa6e8f35b791d3f75fe208fb0f888914..86b819fa04d907520cac7169426f61c83e0a3869 100644 (file)
@@ -3108,6 +3108,18 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
        rcu_read_unlock();
 }
 
+/* Parse the Block Limits Extension VPD page (0xb7) */
+static void sd_read_block_limits_ext(struct scsi_disk *sdkp)
+{
+       struct scsi_vpd *vpd;
+
+       rcu_read_lock();
+       vpd = rcu_dereference(sdkp->device->vpd_pgb7);
+       if (vpd && vpd->len >= 2)
+               sdkp->rscs = vpd->data[5] & 1;
+       rcu_read_unlock();
+}
+
 /**
  * sd_read_block_characteristics - Query block dev. characteristics
  * @sdkp: disk to query
@@ -3459,6 +3471,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
                if (scsi_device_supports_vpd(sdp)) {
                        sd_read_block_provisioning(sdkp);
                        sd_read_block_limits(sdkp);
+                       sd_read_block_limits_ext(sdkp);
                        sd_read_block_characteristics(sdkp);
                        sd_zbc_read_zones(sdkp, buffer);
                        sd_read_cpr(sdkp);
index 409dda5350d10fb898b7bad49889ec165f257511..e4539122f2a24737da461cabe114bb2abdb2b575 100644 (file)
@@ -151,6 +151,7 @@ struct scsi_disk {
        unsigned        urswrz : 1;
        unsigned        security : 1;
        unsigned        ignore_medium_access_errors : 1;
+       bool            rscs : 1; /* reduced stream control support */
 };
 #define to_scsi_disk(obj) container_of(obj, struct scsi_disk, disk_dev)
 
index 5ec1e71a09de7698616dff799a935da15083deef..f670b55d803aa6b704b58eb143fb4bb5ec256510 100644 (file)
@@ -153,6 +153,7 @@ struct scsi_device {
        struct scsi_vpd __rcu *vpd_pgb0;
        struct scsi_vpd __rcu *vpd_pgb1;
        struct scsi_vpd __rcu *vpd_pgb2;
+       struct scsi_vpd __rcu *vpd_pgb7;
 
        struct scsi_target      *sdev_target;