scsi: core: Support retrieving sub-pages of mode pages
authorDamien Le Moal <dlemoal@kernel.org>
Thu, 11 May 2023 01:13:39 +0000 (03:13 +0200)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 22 May 2023 21:05:19 +0000 (17:05 -0400)
Allow scsi_mode_sense() to retrieve sub-pages of mode pages by adding the
subpage argument. Change all the current caller sites to specify the
subpage 0.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
Link: https://lore.kernel.org/r/20230511011356.227789-7-nks@flawful.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/sd.c
drivers/scsi/sr.c
include/scsi/scsi_device.h

index fac9c31161d29dfe2c5b386763d98c08bff9ae73..633c4e8af8307041b13e7c48d6a9a2379b5be55d 100644 (file)
@@ -2144,6 +2144,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
  *     @sdev:  SCSI device to be queried
  *     @dbd:   set to prevent mode sense from returning block descriptors
  *     @modepage: mode page being requested
+ *     @subpage: sub-page of the mode page being requested
  *     @buffer: request buffer (may not be smaller than eight bytes)
  *     @len:   length of request buffer.
  *     @timeout: command timeout
@@ -2155,7 +2156,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
  *     Returns zero if successful, or a negative error number on failure
  */
 int
-scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
+scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, int subpage,
                  unsigned char *buffer, int len, int timeout, int retries,
                  struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr)
 {
@@ -2175,6 +2176,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
        dbd = sdev->set_dbd_for_ms ? 8 : dbd;
        cmd[1] = dbd & 0x18;    /* allows DBD and LLBA bits */
        cmd[2] = modepage;
+       cmd[3] = subpage;
 
        sshdr = exec_args.sshdr;
 
index 74b99f2b0b74ac5c32ef00fe6ca698b4f5f7f0ae..d704c484a251c5d3ebf112a4b9b68e32a3822d4a 100644 (file)
@@ -1245,7 +1245,7 @@ int sas_read_port_mode_page(struct scsi_device *sdev)
        if (!buffer)
                return -ENOMEM;
 
-       error = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3,
+       error = scsi_mode_sense(sdev, 1, 0x19, 0, buffer, BUF_SIZE, 30*HZ, 3,
                                &mode_data, NULL);
 
        if (error)
index 1624d528aa1f9c5f525aa704b22314029f73af60..cdcef1b651c1ed5bf71465abf46abd44c86dc076 100644 (file)
@@ -183,7 +183,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
                return count;
        }
 
-       if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
+       if (scsi_mode_sense(sdp, 0x08, 8, 0, buffer, sizeof(buffer), SD_TIMEOUT,
                            sdkp->max_retries, &data, NULL))
                return -EINVAL;
        len = min_t(size_t, sizeof(buffer), data.length - data.header_length -
@@ -2609,9 +2609,8 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage,
        if (sdkp->device->use_10_for_ms && len < 8)
                len = 8;
 
-       return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len,
-                              SD_TIMEOUT, sdkp->max_retries, data,
-                              sshdr);
+       return scsi_mode_sense(sdkp->device, dbd, modepage, 0, buffer, len,
+                              SD_TIMEOUT, sdkp->max_retries, data, sshdr);
 }
 
 /*
@@ -2868,7 +2867,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
        if (sdkp->protection_type == 0)
                return;
 
-       res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT,
+       res = scsi_mode_sense(sdp, 1, 0x0a, 0, buffer, 36, SD_TIMEOUT,
                              sdkp->max_retries, &data, &sshdr);
 
        if (res < 0 || !data.header_length ||
index 12869e6d4ebda8d6b74a0b562ce51adf81ee2cc1..cd5b08689c1a14b4fc0062b401534f9d8371d8ab 100644 (file)
@@ -825,7 +825,7 @@ static int get_capabilities(struct scsi_cd *cd)
        scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
 
        /* ask for mode page 0x2a */
-       rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len,
+       rc = scsi_mode_sense(cd->device, 0, 0x2a, 0, buffer, ms_len,
                             SR_TIMEOUT, 3, &data, NULL);
 
        if (rc < 0 || data.length > ms_len ||
index f10a008e5bfa1408b4836465015c9c3ac984cb32..c146cc807d4470db92620933254c789f25c923b4 100644 (file)
@@ -421,10 +421,10 @@ extern int scsi_track_queue_full(struct scsi_device *, int);
 
 extern int scsi_set_medium_removal(struct scsi_device *, char);
 
-extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
-                          unsigned char *buffer, int len, int timeout,
-                          int retries, struct scsi_mode_data *data,
-                          struct scsi_sense_hdr *);
+int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
+                   int subpage, unsigned char *buffer, int len, int timeout,
+                   int retries, struct scsi_mode_data *data,
+                   struct scsi_sense_hdr *);
 extern int scsi_mode_select(struct scsi_device *sdev, int pf, int sp,
                            unsigned char *buffer, int len, int timeout,
                            int retries, struct scsi_mode_data *data,