diff options
Diffstat (limited to 'drivers/target/target_core_spc.c')
-rw-r--r-- | drivers/target/target_core_spc.c | 97 |
1 files changed, 64 insertions, 33 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 70a661801cb9..22703a0dbd07 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -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; @@ -58,7 +80,7 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf) if (dev->transport->get_device_type(dev) == TYPE_TAPE) buf[1] = 0x80; - buf[2] = 0x05; /* SPC-3 */ + buf[2] = 0x06; /* SPC-4 */ /* * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2 @@ -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; } @@ -129,14 +161,29 @@ spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) return 0; } -void spc_parse_naa_6h_vendor_specific(struct se_device *dev, - unsigned char *buf) +/* + * Generate NAA IEEE Registered Extended designator + */ +void spc_gen_naa_6h_vendor_specific(struct se_device *dev, + unsigned char *buf) { unsigned char *p = &dev->t10_wwn.unit_serial[0]; - int cnt; + u32 company_id = dev->t10_wwn.company_id; + int cnt, off = 0; bool next = true; /* + * Start NAA IEEE Registered Extended Identifier/Designator + */ + buf[off] = 0x6 << 4; + + /* IEEE COMPANY_ID */ + buf[off++] |= (company_id >> 20) & 0xf; + buf[off++] = (company_id >> 12) & 0xff; + buf[off++] = (company_id >> 4) & 0xff; + buf[off] = (company_id & 0xf) << 4; + + /* * Generate up to 36 bits of VENDOR SPECIFIC IDENTIFIER starting on * byte 3 bit 3-0 for NAA IEEE Registered Extended DESIGNATOR field * format, followed by 64 bits of VENDOR SPECIFIC IDENTIFIER EXTENSION @@ -144,7 +191,7 @@ void spc_parse_naa_6h_vendor_specific(struct se_device *dev, * NUMBER set via vpd_unit_serial in target_core_configfs.c to ensure * per device uniqeness. */ - for (cnt = 0; *p && cnt < 13; p++) { + for (cnt = off + 13; *p && off < cnt; p++) { int val = hex_to_bin(*p); if (val < 0) @@ -152,10 +199,10 @@ void spc_parse_naa_6h_vendor_specific(struct se_device *dev, if (next) { next = false; - buf[cnt++] |= val; + buf[off++] |= val; } else { next = true; - buf[cnt] = val << 4; + buf[off] = val << 4; } } } @@ -203,24 +250,8 @@ spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) /* Identifier/Designator length */ buf[off++] = 0x10; - /* - * Start NAA IEEE Registered Extended Identifier/Designator - */ - buf[off++] = (0x6 << 4); - - /* - * Use OpenFabrics IEEE Company ID: 00 14 05 - */ - buf[off++] = 0x01; - buf[off++] = 0x40; - buf[off] = (0x5 << 4); - - /* - * Return ConfigFS Unit Serial Number information for - * VENDOR_SPECIFIC_IDENTIFIER and - * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION - */ - spc_parse_naa_6h_vendor_specific(dev, &buf[off]); + /* NAA IEEE Registered Extended designator */ + spc_gen_naa_6h_vendor_specific(dev, &buf[off]); len = 20; off = (len + 4); @@ -750,7 +781,7 @@ out: kfree(buf); if (!ret) - target_complete_cmd_with_length(cmd, GOOD, len); + target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, len); return ret; } @@ -1104,7 +1135,7 @@ set_length: transport_kunmap_data_sg(cmd); } - target_complete_cmd_with_length(cmd, GOOD, length); + target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, length); return 0; } @@ -1122,7 +1153,7 @@ static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd) int i; if (!cmd->data_length) { - target_complete_cmd(cmd, GOOD); + target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; } @@ -1165,7 +1196,7 @@ out: transport_kunmap_data_sg(cmd); if (!ret) - target_complete_cmd(cmd, GOOD); + target_complete_cmd(cmd, SAM_STAT_GOOD); return ret; } @@ -1198,7 +1229,7 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); transport_kunmap_data_sg(cmd); - target_complete_cmd(cmd, GOOD); + target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; } @@ -1265,7 +1296,7 @@ done: transport_kunmap_data_sg(cmd); } - target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); + target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, 8 + lun_count * 8); return 0; } EXPORT_SYMBOL(spc_emulate_report_luns); @@ -1273,7 +1304,7 @@ EXPORT_SYMBOL(spc_emulate_report_luns); static sense_reason_t spc_emulate_testunitready(struct se_cmd *cmd) { - target_complete_cmd(cmd, GOOD); + target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; } |