diff options
Diffstat (limited to 'drivers/target/target_core_spc.c')
| -rw-r--r-- | drivers/target/target_core_spc.c | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 43c5ca9878b..6cd7222738f 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -71,6 +71,7 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf) { struct se_lun *lun = cmd->se_lun; struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; /* Set RMB (removable media) for tape devices */ if (dev->transport->get_device_type(dev) == TYPE_TAPE) @@ -101,10 +102,13 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf) if (dev->dev_attrib.emulate_3pc) buf[5] |= 0x8; /* - * Set Protection (PROTECT) bit when DIF has been enabled. + * Set Protection (PROTECT) bit when DIF has been enabled on the + * device, and the transport supports VERIFY + PASS. */ - if (dev->dev_attrib.pi_prot_type) - buf[5] |= 0x1; + if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) { + if (dev->dev_attrib.pi_prot_type) + buf[5] |= 0x1; + } buf[7] = 0x2; /* CmdQue=1 */ @@ -125,15 +129,10 @@ static sense_reason_t spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; - u16 len = 0; + u16 len; if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { - u32 unit_serial_len; - - unit_serial_len = strlen(dev->t10_wwn.unit_serial); - unit_serial_len++; /* For NULL Terminator */ - - len += sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial); + len = sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial); len++; /* Extra Byte for NULL Terminator */ buf[3] = len; } @@ -440,8 +439,8 @@ check_scsi_name: padding = ((-scsi_target_len) & 3); if (padding) scsi_target_len += padding; - if (scsi_name_len > 256) - scsi_name_len = 256; + if (scsi_target_len > 256) + scsi_target_len = 256; buf[off-1] = scsi_target_len; off += scsi_target_len; @@ -473,16 +472,19 @@ static sense_reason_t spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; buf[3] = 0x3c; /* * Set GRD_CHK + REF_CHK for TYPE1 protection, or GRD_CHK * only for TYPE3 protection. */ - if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT) - buf[4] = 0x5; - else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT) - buf[4] = 0x4; + if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) { + if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT) + buf[4] = 0x5; + else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT) + buf[4] = 0x4; + } /* Set HEADSUP, ORDSUP, SIMPSUP */ buf[5] = 0x07; @@ -714,6 +716,7 @@ spc_emulate_inquiry(struct se_cmd *cmd) unsigned char *buf; sense_reason_t ret; int p; + int len = 0; buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); if (!buf) { @@ -735,6 +738,7 @@ spc_emulate_inquiry(struct se_cmd *cmd) } ret = spc_emulate_inquiry_std(cmd, buf); + len = buf[4] + 5; goto out; } @@ -742,6 +746,7 @@ spc_emulate_inquiry(struct se_cmd *cmd) if (cdb[2] == evpd_handlers[p].page) { buf[1] = cdb[2]; ret = evpd_handlers[p].emulate(cmd, buf); + len = get_unaligned_be16(&buf[2]) + 4; goto out; } } @@ -758,11 +763,11 @@ out: kfree(buf); if (!ret) - target_complete_cmd(cmd, GOOD); + target_complete_cmd_with_length(cmd, GOOD, len); return ret; } -static int spc_modesense_rwrecovery(struct se_device *dev, u8 pc, u8 *p) +static int spc_modesense_rwrecovery(struct se_cmd *cmd, u8 pc, u8 *p) { p[0] = 0x01; p[1] = 0x0a; @@ -775,8 +780,11 @@ out: return 12; } -static int spc_modesense_control(struct se_device *dev, u8 pc, u8 *p) +static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p) { + struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; + p[0] = 0x0a; p[1] = 0x0a; @@ -868,8 +876,10 @@ static int spc_modesense_control(struct se_device *dev, u8 pc, u8 *p) * type, shall not modify the contents of the LOGICAL BLOCK REFERENCE * TAG field. */ - if (dev->dev_attrib.pi_prot_type) - p[5] |= 0x80; + if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) { + if (dev->dev_attrib.pi_prot_type) + p[5] |= 0x80; + } p[8] = 0xff; p[9] = 0xff; @@ -879,8 +889,10 @@ out: return 12; } -static int spc_modesense_caching(struct se_device *dev, u8 pc, u8 *p) +static int spc_modesense_caching(struct se_cmd *cmd, u8 pc, u8 *p) { + struct se_device *dev = cmd->se_dev; + p[0] = 0x08; p[1] = 0x12; @@ -896,7 +908,7 @@ out: return 20; } -static int spc_modesense_informational_exceptions(struct se_device *dev, u8 pc, unsigned char *p) +static int spc_modesense_informational_exceptions(struct se_cmd *cmd, u8 pc, unsigned char *p) { p[0] = 0x1c; p[1] = 0x0a; @@ -912,7 +924,7 @@ out: static struct { uint8_t page; uint8_t subpage; - int (*emulate)(struct se_device *, u8, unsigned char *); + int (*emulate)(struct se_cmd *, u8, unsigned char *); } modesense_handlers[] = { { .page = 0x01, .subpage = 0x00, .emulate = spc_modesense_rwrecovery }, { .page = 0x08, .subpage = 0x00, .emulate = spc_modesense_caching }, @@ -1050,7 +1062,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) * the only two possibilities). */ if ((modesense_handlers[i].subpage & ~subpage) == 0) { - ret = modesense_handlers[i].emulate(dev, pc, &buf[length]); + ret = modesense_handlers[i].emulate(cmd, pc, &buf[length]); if (!ten && length + ret >= 255) break; length += ret; @@ -1063,7 +1075,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) if (modesense_handlers[i].page == page && modesense_handlers[i].subpage == subpage) { - length += modesense_handlers[i].emulate(dev, pc, &buf[length]); + length += modesense_handlers[i].emulate(cmd, pc, &buf[length]); goto set_length; } @@ -1089,13 +1101,12 @@ set_length: transport_kunmap_data_sg(cmd); } - target_complete_cmd(cmd, GOOD); + target_complete_cmd_with_length(cmd, GOOD, length); return 0; } static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd) { - struct se_device *dev = cmd->se_dev; char *cdb = cmd->t_task_cdb; bool ten = cdb[0] == MODE_SELECT_10; int off = ten ? 8 : 4; @@ -1131,7 +1142,7 @@ static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd) if (modesense_handlers[i].page == page && modesense_handlers[i].subpage == subpage) { memset(tbuf, 0, SE_MODE_PAGE_BUF); - length = modesense_handlers[i].emulate(dev, 0, tbuf); + length = modesense_handlers[i].emulate(cmd, 0, tbuf); goto check_contents; } @@ -1266,7 +1277,7 @@ done: buf[3] = (lun_count & 0xff); transport_kunmap_data_sg(cmd); - target_complete_cmd(cmd, GOOD); + target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); return 0; } EXPORT_SYMBOL(spc_emulate_report_luns); |
