scsi: target: core: Add the VERSION DESCRIPTOR fields to the INQUIRY data
authorKonstantin Shelekhin <k.shelekhin@yadro.com>
Thu, 13 May 2021 19:28:04 +0000 (22:28 +0300)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 15 May 2021 18:34:26 +0000 (14:34 -0400)
Extend the standard INQUIRY data to 96 bytes and fill in the VERSION
DESCRIPTOR fields.

The layout follows SPC-4:

 - SCSI architecture standard
 - SCSI transport protocol standard
 - SCSI primary command set standard
 - SCSI device type command set standard

All version descriptor values are defined as "no version claimed" because
some initiators fail to recognize anything else.

[mkp: whitespace]

Link: https://lore.kernel.org/r/20210513192804.1252142-3-k.shelekhin@yadro.com
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
Signed-off-by: Konstantin Shelekhin <k.shelekhin@yadro.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/target/target_core_spc.c
include/scsi/scsi_proto.h

index 0f30b71f0acc844ccfe61ff260648d3be447325d..2cb141ed68f5e32622df7be66ec91e65ab935377 100644 (file)
@@ -47,10 +47,32 @@ static void spc_fill_alua_data(struct se_lun *lun, unsigned char *buf)
        spin_unlock(&lun->lun_tg_pt_gp_lock);
 }
 
+static u16
+spc_find_scsi_transport_vd(int proto_id)
+{
+       switch (proto_id) {
+       case SCSI_PROTOCOL_FCP:
+               return SCSI_VERSION_DESCRIPTOR_FCP4;
+       case SCSI_PROTOCOL_ISCSI:
+               return SCSI_VERSION_DESCRIPTOR_ISCSI;
+       case SCSI_PROTOCOL_SAS:
+               return SCSI_VERSION_DESCRIPTOR_SAS3;
+       case SCSI_PROTOCOL_SBP:
+               return SCSI_VERSION_DESCRIPTOR_SBP3;
+       case SCSI_PROTOCOL_SRP:
+               return SCSI_VERSION_DESCRIPTOR_SRP;
+       default:
+               pr_warn("Cannot find VERSION DESCRIPTOR value for unknown SCSI"
+                       " transport PROTOCOL IDENTIFIER %#x\n", proto_id);
+               return 0;
+       }
+}
+
 sense_reason_t
 spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
 {
        struct se_lun *lun = cmd->se_lun;
+       struct se_portal_group *tpg = lun->lun_tpg;
        struct se_device *dev = cmd->se_dev;
        struct se_session *sess = cmd->se_sess;
 
@@ -108,7 +130,17 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
               strnlen(dev->t10_wwn.model, INQUIRY_MODEL_LEN));
        memcpy(&buf[32], dev->t10_wwn.revision,
               strnlen(dev->t10_wwn.revision, INQUIRY_REVISION_LEN));
-       buf[4] = 31; /* Set additional length to 31 */
+
+       /*
+        * Set the VERSION DESCRIPTOR fields
+        */
+       put_unaligned_be16(SCSI_VERSION_DESCRIPTOR_SAM5, &buf[58]);
+       put_unaligned_be16(spc_find_scsi_transport_vd(tpg->proto_id), &buf[60]);
+       put_unaligned_be16(SCSI_VERSION_DESCRIPTOR_SPC4, &buf[62]);
+       if (cmd->se_dev->transport->get_device_type(dev) == TYPE_DISK)
+               put_unaligned_be16(SCSI_VERSION_DESCRIPTOR_SBC3, &buf[64]);
+
+       buf[4] = 91; /* Set additional length to 91 */
 
        return 0;
 }
index c3686011193224e7ace9093de0d13b2cecf5996d..5c106c4f249e2b41e43759c94528ff4188190ce1 100644 (file)
@@ -341,4 +341,16 @@ enum zbc_zone_cond {
        ZBC_ZONE_COND_OFFLINE           = 0xf,
 };
 
+/* Version descriptor values for INQUIRY */
+enum scsi_version_descriptor {
+       SCSI_VERSION_DESCRIPTOR_FCP4    = 0x0a40,
+       SCSI_VERSION_DESCRIPTOR_ISCSI   = 0x0960,
+       SCSI_VERSION_DESCRIPTOR_SAM5    = 0x00a0,
+       SCSI_VERSION_DESCRIPTOR_SAS3    = 0x0c60,
+       SCSI_VERSION_DESCRIPTOR_SBC3    = 0x04c0,
+       SCSI_VERSION_DESCRIPTOR_SBP3    = 0x0980,
+       SCSI_VERSION_DESCRIPTOR_SPC4    = 0x0460,
+       SCSI_VERSION_DESCRIPTOR_SRP     = 0x0940
+};
+
 #endif /* _SCSI_PROTO_H_ */