diff options
Diffstat (limited to 'drivers/target/target_core_cdb.c')
-rw-r--r-- | drivers/target/target_core_cdb.c | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 8ae09a1bdf74..89ae923c5da6 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c | |||
@@ -67,6 +67,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd) | |||
67 | { | 67 | { |
68 | struct se_lun *lun = cmd->se_lun; | 68 | struct se_lun *lun = cmd->se_lun; |
69 | struct se_device *dev = cmd->se_dev; | 69 | struct se_device *dev = cmd->se_dev; |
70 | struct se_portal_group *tpg = lun->lun_sep->sep_tpg; | ||
70 | unsigned char *buf; | 71 | unsigned char *buf; |
71 | 72 | ||
72 | /* | 73 | /* |
@@ -81,9 +82,13 @@ target_emulate_inquiry_std(struct se_cmd *cmd) | |||
81 | 82 | ||
82 | buf = transport_kmap_first_data_page(cmd); | 83 | buf = transport_kmap_first_data_page(cmd); |
83 | 84 | ||
84 | buf[0] = dev->transport->get_device_type(dev); | 85 | if (dev == tpg->tpg_virt_lun0.lun_se_dev) { |
85 | if (buf[0] == TYPE_TAPE) | 86 | buf[0] = 0x3f; /* Not connected */ |
86 | buf[1] = 0x80; | 87 | } else { |
88 | buf[0] = dev->transport->get_device_type(dev); | ||
89 | if (buf[0] == TYPE_TAPE) | ||
90 | buf[1] = 0x80; | ||
91 | } | ||
87 | buf[2] = dev->transport->get_device_rev(dev); | 92 | buf[2] = dev->transport->get_device_rev(dev); |
88 | 93 | ||
89 | /* | 94 | /* |
@@ -915,8 +920,8 @@ target_emulate_modesense(struct se_cmd *cmd, int ten) | |||
915 | length += target_modesense_control(dev, &buf[offset+length]); | 920 | length += target_modesense_control(dev, &buf[offset+length]); |
916 | break; | 921 | break; |
917 | default: | 922 | default: |
918 | pr_err("Got Unknown Mode Page: 0x%02x\n", | 923 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", |
919 | cdb[2] & 0x3f); | 924 | cdb[2] & 0x3f, cdb[3]); |
920 | return PYX_TRANSPORT_UNKNOWN_MODE_PAGE; | 925 | return PYX_TRANSPORT_UNKNOWN_MODE_PAGE; |
921 | } | 926 | } |
922 | offset += length; | 927 | offset += length; |
@@ -1072,8 +1077,6 @@ target_emulate_unmap(struct se_task *task) | |||
1072 | size -= 16; | 1077 | size -= 16; |
1073 | } | 1078 | } |
1074 | 1079 | ||
1075 | task->task_scsi_status = GOOD; | ||
1076 | transport_complete_task(task, 1); | ||
1077 | err: | 1080 | err: |
1078 | transport_kunmap_first_data_page(cmd); | 1081 | transport_kunmap_first_data_page(cmd); |
1079 | 1082 | ||
@@ -1085,24 +1088,17 @@ err: | |||
1085 | * Note this is not used for TCM/pSCSI passthrough | 1088 | * Note this is not used for TCM/pSCSI passthrough |
1086 | */ | 1089 | */ |
1087 | static int | 1090 | static int |
1088 | target_emulate_write_same(struct se_task *task, int write_same32) | 1091 | target_emulate_write_same(struct se_task *task, u32 num_blocks) |
1089 | { | 1092 | { |
1090 | struct se_cmd *cmd = task->task_se_cmd; | 1093 | struct se_cmd *cmd = task->task_se_cmd; |
1091 | struct se_device *dev = cmd->se_dev; | 1094 | struct se_device *dev = cmd->se_dev; |
1092 | sector_t range; | 1095 | sector_t range; |
1093 | sector_t lba = cmd->t_task_lba; | 1096 | sector_t lba = cmd->t_task_lba; |
1094 | unsigned int num_blocks; | ||
1095 | int ret; | 1097 | int ret; |
1096 | /* | 1098 | /* |
1097 | * Extract num_blocks from the WRITE_SAME_* CDB. Then use the explict | 1099 | * Use the explicit range when non zero is supplied, otherwise calculate |
1098 | * range when non zero is supplied, otherwise calculate the remaining | 1100 | * the remaining range based on ->get_blocks() - starting LBA. |
1099 | * range based on ->get_blocks() - starting LBA. | ||
1100 | */ | 1101 | */ |
1101 | if (write_same32) | ||
1102 | num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]); | ||
1103 | else | ||
1104 | num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]); | ||
1105 | |||
1106 | if (num_blocks != 0) | 1102 | if (num_blocks != 0) |
1107 | range = num_blocks; | 1103 | range = num_blocks; |
1108 | else | 1104 | else |
@@ -1117,8 +1113,6 @@ target_emulate_write_same(struct se_task *task, int write_same32) | |||
1117 | return ret; | 1113 | return ret; |
1118 | } | 1114 | } |
1119 | 1115 | ||
1120 | task->task_scsi_status = GOOD; | ||
1121 | transport_complete_task(task, 1); | ||
1122 | return 0; | 1116 | return 0; |
1123 | } | 1117 | } |
1124 | 1118 | ||
@@ -1165,13 +1159,23 @@ transport_emulate_control_cdb(struct se_task *task) | |||
1165 | } | 1159 | } |
1166 | ret = target_emulate_unmap(task); | 1160 | ret = target_emulate_unmap(task); |
1167 | break; | 1161 | break; |
1162 | case WRITE_SAME: | ||
1163 | if (!dev->transport->do_discard) { | ||
1164 | pr_err("WRITE_SAME emulation not supported" | ||
1165 | " for: %s\n", dev->transport->name); | ||
1166 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1167 | } | ||
1168 | ret = target_emulate_write_same(task, | ||
1169 | get_unaligned_be16(&cmd->t_task_cdb[7])); | ||
1170 | break; | ||
1168 | case WRITE_SAME_16: | 1171 | case WRITE_SAME_16: |
1169 | if (!dev->transport->do_discard) { | 1172 | if (!dev->transport->do_discard) { |
1170 | pr_err("WRITE_SAME_16 emulation not supported" | 1173 | pr_err("WRITE_SAME_16 emulation not supported" |
1171 | " for: %s\n", dev->transport->name); | 1174 | " for: %s\n", dev->transport->name); |
1172 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | 1175 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; |
1173 | } | 1176 | } |
1174 | ret = target_emulate_write_same(task, 0); | 1177 | ret = target_emulate_write_same(task, |
1178 | get_unaligned_be32(&cmd->t_task_cdb[10])); | ||
1175 | break; | 1179 | break; |
1176 | case VARIABLE_LENGTH_CMD: | 1180 | case VARIABLE_LENGTH_CMD: |
1177 | service_action = | 1181 | service_action = |
@@ -1184,7 +1188,8 @@ transport_emulate_control_cdb(struct se_task *task) | |||
1184 | dev->transport->name); | 1188 | dev->transport->name); |
1185 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | 1189 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; |
1186 | } | 1190 | } |
1187 | ret = target_emulate_write_same(task, 1); | 1191 | ret = target_emulate_write_same(task, |
1192 | get_unaligned_be32(&cmd->t_task_cdb[28])); | ||
1188 | break; | 1193 | break; |
1189 | default: | 1194 | default: |
1190 | pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" | 1195 | pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" |
@@ -1219,8 +1224,14 @@ transport_emulate_control_cdb(struct se_task *task) | |||
1219 | 1224 | ||
1220 | if (ret < 0) | 1225 | if (ret < 0) |
1221 | return ret; | 1226 | return ret; |
1222 | task->task_scsi_status = GOOD; | 1227 | /* |
1223 | transport_complete_task(task, 1); | 1228 | * Handle the successful completion here unless a caller |
1229 | * has explictly requested an asychronous completion. | ||
1230 | */ | ||
1231 | if (!(cmd->se_cmd_flags & SCF_EMULATE_CDB_ASYNC)) { | ||
1232 | task->task_scsi_status = GOOD; | ||
1233 | transport_complete_task(task, 1); | ||
1234 | } | ||
1224 | 1235 | ||
1225 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | 1236 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; |
1226 | } | 1237 | } |