aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-01-12 13:41:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-01-12 13:41:20 -0500
commitcb38b45346f17f4b0a105b9315b030a2e24fb7e6 (patch)
treee91ecc715863928d8e3a33bf875423e19d1e7ba6
parent607ae5f26920b8dfedbbf882c0f9edd3b9aa6cf7 (diff)
parent7c9d8d0c41b3e24473ac7648a7fc2d644ccf08ff (diff)
Merge branch 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/bvanassche/linux
Pull scsi target fixes from Bart Van Assche: - a series of bug fixes for the XCOPY implementation from David Disseldorp - one bug fix for the ibmvscsis driver, a driver that is used for communication between partitions on IBM POWER systems. * 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/bvanassche/linux: ibmvscsis: Fix srp_transfer_data fail return code target: support XCOPY requests without parameters target: check for XCOPY parameter truncation target: use XCOPY segment descriptor CSCD IDs target: check XCOPY segment descriptor CSCD IDs target: simplify XCOPY wwn->se_dev lookup helper target: return UNSUPPORTED TARGET/SEGMENT DESC TYPE CODE sense target: bounds check XCOPY total descriptor list length target: bounds check XCOPY segment descriptor list target: use XCOPY TOO MANY TARGET DESCRIPTORS sense target: add XCOPY target/segment desc sense codes
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c2
-rw-r--r--drivers/target/target_core_transport.c24
-rw-r--r--drivers/target/target_core_xcopy.c157
-rw-r--r--drivers/target/target_core_xcopy.h7
-rw-r--r--include/target/target_core_base.h4
5 files changed, 142 insertions, 52 deletions
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index 3d3768aaab4f..8fb5c54c7dd3 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -3585,7 +3585,7 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
3585 1, 1); 3585 1, 1);
3586 if (rc) { 3586 if (rc) {
3587 pr_err("srp_transfer_data() failed: %d\n", rc); 3587 pr_err("srp_transfer_data() failed: %d\n", rc);
3588 return -EAGAIN; 3588 return -EIO;
3589 } 3589 }
3590 /* 3590 /*
3591 * We now tell TCM to add this WRITE CDB directly into the TCM storage 3591 * We now tell TCM to add this WRITE CDB directly into the TCM storage
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 7dfefd66df93..1cadc9eefa21 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1693,6 +1693,10 @@ void transport_generic_request_failure(struct se_cmd *cmd,
1693 case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: 1693 case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
1694 case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: 1694 case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
1695 case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE: 1695 case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
1696 case TCM_TOO_MANY_TARGET_DESCS:
1697 case TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE:
1698 case TCM_TOO_MANY_SEGMENT_DESCS:
1699 case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE:
1696 break; 1700 break;
1697 case TCM_OUT_OF_RESOURCES: 1701 case TCM_OUT_OF_RESOURCES:
1698 sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1702 sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -2808,6 +2812,26 @@ static const struct sense_info sense_info_table[] = {
2808 .key = ILLEGAL_REQUEST, 2812 .key = ILLEGAL_REQUEST,
2809 .asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */ 2813 .asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */
2810 }, 2814 },
2815 [TCM_TOO_MANY_TARGET_DESCS] = {
2816 .key = ILLEGAL_REQUEST,
2817 .asc = 0x26,
2818 .ascq = 0x06, /* TOO MANY TARGET DESCRIPTORS */
2819 },
2820 [TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE] = {
2821 .key = ILLEGAL_REQUEST,
2822 .asc = 0x26,
2823 .ascq = 0x07, /* UNSUPPORTED TARGET DESCRIPTOR TYPE CODE */
2824 },
2825 [TCM_TOO_MANY_SEGMENT_DESCS] = {
2826 .key = ILLEGAL_REQUEST,
2827 .asc = 0x26,
2828 .ascq = 0x08, /* TOO MANY SEGMENT DESCRIPTORS */
2829 },
2830 [TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE] = {
2831 .key = ILLEGAL_REQUEST,
2832 .asc = 0x26,
2833 .ascq = 0x09, /* UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE */
2834 },
2811 [TCM_PARAMETER_LIST_LENGTH_ERROR] = { 2835 [TCM_PARAMETER_LIST_LENGTH_ERROR] = {
2812 .key = ILLEGAL_REQUEST, 2836 .key = ILLEGAL_REQUEST,
2813 .asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */ 2837 .asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 37d5caebffa6..d828b3b5000b 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -53,18 +53,13 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
53 return 0; 53 return 0;
54} 54}
55 55
56static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, 56static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
57 bool src) 57 struct se_device **found_dev)
58{ 58{
59 struct se_device *se_dev; 59 struct se_device *se_dev;
60 unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn; 60 unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
61 int rc; 61 int rc;
62 62
63 if (src)
64 dev_wwn = &xop->dst_tid_wwn[0];
65 else
66 dev_wwn = &xop->src_tid_wwn[0];
67
68 mutex_lock(&g_device_mutex); 63 mutex_lock(&g_device_mutex);
69 list_for_each_entry(se_dev, &g_device_list, g_dev_node) { 64 list_for_each_entry(se_dev, &g_device_list, g_dev_node) {
70 65
@@ -78,15 +73,8 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
78 if (rc != 0) 73 if (rc != 0)
79 continue; 74 continue;
80 75
81 if (src) { 76 *found_dev = se_dev;
82 xop->dst_dev = se_dev; 77 pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
83 pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located"
84 " se_dev\n", xop->dst_dev);
85 } else {
86 xop->src_dev = se_dev;
87 pr_debug("XCOPY 0xe4: Setting xop->src_dev: %p from located"
88 " se_dev\n", xop->src_dev);
89 }
90 78
91 rc = target_depend_item(&se_dev->dev_group.cg_item); 79 rc = target_depend_item(&se_dev->dev_group.cg_item);
92 if (rc != 0) { 80 if (rc != 0) {
@@ -110,7 +98,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
110} 98}
111 99
112static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, 100static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
113 unsigned char *p, bool src) 101 unsigned char *p, unsigned short cscd_index)
114{ 102{
115 unsigned char *desc = p; 103 unsigned char *desc = p;
116 unsigned short ript; 104 unsigned short ript;
@@ -155,7 +143,13 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
155 return -EINVAL; 143 return -EINVAL;
156 } 144 }
157 145
158 if (src) { 146 if (cscd_index != xop->stdi && cscd_index != xop->dtdi) {
147 pr_debug("XCOPY 0xe4: ignoring CSCD entry %d - neither src nor "
148 "dest\n", cscd_index);
149 return 0;
150 }
151
152 if (cscd_index == xop->stdi) {
159 memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); 153 memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
160 /* 154 /*
161 * Determine if the source designator matches the local device 155 * Determine if the source designator matches the local device
@@ -167,10 +161,15 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
167 pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source" 161 pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source"
168 " received xop\n", xop->src_dev); 162 " received xop\n", xop->src_dev);
169 } 163 }
170 } else { 164 }
165
166 if (cscd_index == xop->dtdi) {
171 memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); 167 memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
172 /* 168 /*
173 * Determine if the destination designator matches the local device 169 * Determine if the destination designator matches the local
170 * device. If @cscd_index corresponds to both source (stdi) and
171 * destination (dtdi), or dtdi comes after stdi, then
172 * XCOL_DEST_RECV_OP wins.
174 */ 173 */
175 if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0], 174 if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0],
176 XCOPY_NAA_IEEE_REGEX_LEN)) { 175 XCOPY_NAA_IEEE_REGEX_LEN)) {
@@ -190,20 +189,23 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
190{ 189{
191 struct se_device *local_dev = se_cmd->se_dev; 190 struct se_device *local_dev = se_cmd->se_dev;
192 unsigned char *desc = p; 191 unsigned char *desc = p;
193 int offset = tdll % XCOPY_TARGET_DESC_LEN, rc, ret = 0; 192 int offset = tdll % XCOPY_TARGET_DESC_LEN, rc;
193 unsigned short cscd_index = 0;
194 unsigned short start = 0; 194 unsigned short start = 0;
195 bool src = true;
196 195
197 *sense_ret = TCM_INVALID_PARAMETER_LIST; 196 *sense_ret = TCM_INVALID_PARAMETER_LIST;
198 197
199 if (offset != 0) { 198 if (offset != 0) {
200 pr_err("XCOPY target descriptor list length is not" 199 pr_err("XCOPY target descriptor list length is not"
201 " multiple of %d\n", XCOPY_TARGET_DESC_LEN); 200 " multiple of %d\n", XCOPY_TARGET_DESC_LEN);
201 *sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
202 return -EINVAL; 202 return -EINVAL;
203 } 203 }
204 if (tdll > 64) { 204 if (tdll > RCR_OP_MAX_TARGET_DESC_COUNT * XCOPY_TARGET_DESC_LEN) {
205 pr_err("XCOPY target descriptor supports a maximum" 205 pr_err("XCOPY target descriptor supports a maximum"
206 " two src/dest descriptors, tdll: %hu too large..\n", tdll); 206 " two src/dest descriptors, tdll: %hu too large..\n", tdll);
207 /* spc4r37 6.4.3.4 CSCD DESCRIPTOR LIST LENGTH field */
208 *sense_ret = TCM_TOO_MANY_TARGET_DESCS;
207 return -EINVAL; 209 return -EINVAL;
208 } 210 }
209 /* 211 /*
@@ -215,37 +217,43 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
215 217
216 while (start < tdll) { 218 while (start < tdll) {
217 /* 219 /*
218 * Check target descriptor identification with 0xE4 type with 220 * Check target descriptor identification with 0xE4 type, and
219 * use VPD 0x83 WWPN matching .. 221 * compare the current index with the CSCD descriptor IDs in
222 * the segment descriptor. Use VPD 0x83 WWPN matching ..
220 */ 223 */
221 switch (desc[0]) { 224 switch (desc[0]) {
222 case 0xe4: 225 case 0xe4:
223 rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop, 226 rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop,
224 &desc[0], src); 227 &desc[0], cscd_index);
225 if (rc != 0) 228 if (rc != 0)
226 goto out; 229 goto out;
227 /*
228 * Assume target descriptors are in source -> destination order..
229 */
230 if (src)
231 src = false;
232 else
233 src = true;
234 start += XCOPY_TARGET_DESC_LEN; 230 start += XCOPY_TARGET_DESC_LEN;
235 desc += XCOPY_TARGET_DESC_LEN; 231 desc += XCOPY_TARGET_DESC_LEN;
236 ret++; 232 cscd_index++;
237 break; 233 break;
238 default: 234 default:
239 pr_err("XCOPY unsupported descriptor type code:" 235 pr_err("XCOPY unsupported descriptor type code:"
240 " 0x%02x\n", desc[0]); 236 " 0x%02x\n", desc[0]);
237 *sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
241 goto out; 238 goto out;
242 } 239 }
243 } 240 }
244 241
245 if (xop->op_origin == XCOL_SOURCE_RECV_OP) 242 switch (xop->op_origin) {
246 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); 243 case XCOL_SOURCE_RECV_OP:
247 else 244 rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
248 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); 245 &xop->dst_dev);
246 break;
247 case XCOL_DEST_RECV_OP:
248 rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
249 &xop->src_dev);
250 break;
251 default:
252 pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
253 "stdi: %hu dtdi: %hu\n", xop->stdi, xop->dtdi);
254 rc = -EINVAL;
255 break;
256 }
249 /* 257 /*
250 * If a matching IEEE NAA 0x83 descriptor for the requested device 258 * If a matching IEEE NAA 0x83 descriptor for the requested device
251 * is not located on this node, return COPY_ABORTED with ASQ/ASQC 259 * is not located on this node, return COPY_ABORTED with ASQ/ASQC
@@ -262,7 +270,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
262 pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n", 270 pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n",
263 xop->dst_dev, &xop->dst_tid_wwn[0]); 271 xop->dst_dev, &xop->dst_tid_wwn[0]);
264 272
265 return ret; 273 return cscd_index;
266 274
267out: 275out:
268 return -EINVAL; 276 return -EINVAL;
@@ -284,6 +292,14 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
284 292
285 xop->stdi = get_unaligned_be16(&desc[4]); 293 xop->stdi = get_unaligned_be16(&desc[4]);
286 xop->dtdi = get_unaligned_be16(&desc[6]); 294 xop->dtdi = get_unaligned_be16(&desc[6]);
295
296 if (xop->stdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX ||
297 xop->dtdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX) {
298 pr_err("XCOPY segment desc 0x02: unsupported CSCD ID > 0x%x; stdi: %hu dtdi: %hu\n",
299 XCOPY_CSCD_DESC_ID_LIST_OFF_MAX, xop->stdi, xop->dtdi);
300 return -EINVAL;
301 }
302
287 pr_debug("XCOPY seg desc 0x02: desc_len: %hu stdi: %hu dtdi: %hu, DC: %d\n", 303 pr_debug("XCOPY seg desc 0x02: desc_len: %hu stdi: %hu dtdi: %hu, DC: %d\n",
288 desc_len, xop->stdi, xop->dtdi, dc); 304 desc_len, xop->stdi, xop->dtdi, dc);
289 305
@@ -306,15 +322,25 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
306 322
307static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd, 323static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
308 struct xcopy_op *xop, unsigned char *p, 324 struct xcopy_op *xop, unsigned char *p,
309 unsigned int sdll) 325 unsigned int sdll, sense_reason_t *sense_ret)
310{ 326{
311 unsigned char *desc = p; 327 unsigned char *desc = p;
312 unsigned int start = 0; 328 unsigned int start = 0;
313 int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0; 329 int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
314 330
331 *sense_ret = TCM_INVALID_PARAMETER_LIST;
332
315 if (offset != 0) { 333 if (offset != 0) {
316 pr_err("XCOPY segment descriptor list length is not" 334 pr_err("XCOPY segment descriptor list length is not"
317 " multiple of %d\n", XCOPY_SEGMENT_DESC_LEN); 335 " multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
336 *sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
337 return -EINVAL;
338 }
339 if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) {
340 pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too"
341 " large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll);
342 /* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */
343 *sense_ret = TCM_TOO_MANY_SEGMENT_DESCS;
318 return -EINVAL; 344 return -EINVAL;
319 } 345 }
320 346
@@ -335,6 +361,7 @@ static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
335 default: 361 default:
336 pr_err("XCOPY unsupported segment descriptor" 362 pr_err("XCOPY unsupported segment descriptor"
337 "type: 0x%02x\n", desc[0]); 363 "type: 0x%02x\n", desc[0]);
364 *sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
338 goto out; 365 goto out;
339 } 366 }
340 } 367 }
@@ -861,6 +888,16 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
861 return TCM_UNSUPPORTED_SCSI_OPCODE; 888 return TCM_UNSUPPORTED_SCSI_OPCODE;
862 } 889 }
863 890
891 if (se_cmd->data_length == 0) {
892 target_complete_cmd(se_cmd, SAM_STAT_GOOD);
893 return TCM_NO_SENSE;
894 }
895 if (se_cmd->data_length < XCOPY_HDR_LEN) {
896 pr_err("XCOPY parameter truncation: length %u < hdr_len %u\n",
897 se_cmd->data_length, XCOPY_HDR_LEN);
898 return TCM_PARAMETER_LIST_LENGTH_ERROR;
899 }
900
864 xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL); 901 xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
865 if (!xop) { 902 if (!xop) {
866 pr_err("Unable to allocate xcopy_op\n"); 903 pr_err("Unable to allocate xcopy_op\n");
@@ -883,6 +920,12 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
883 */ 920 */
884 tdll = get_unaligned_be16(&p[2]); 921 tdll = get_unaligned_be16(&p[2]);
885 sdll = get_unaligned_be32(&p[8]); 922 sdll = get_unaligned_be32(&p[8]);
923 if (tdll + sdll > RCR_OP_MAX_DESC_LIST_LEN) {
924 pr_err("XCOPY descriptor list length %u exceeds maximum %u\n",
925 tdll + sdll, RCR_OP_MAX_DESC_LIST_LEN);
926 ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
927 goto out;
928 }
886 929
887 inline_dl = get_unaligned_be32(&p[12]); 930 inline_dl = get_unaligned_be32(&p[12]);
888 if (inline_dl != 0) { 931 if (inline_dl != 0) {
@@ -890,10 +933,32 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
890 goto out; 933 goto out;
891 } 934 }
892 935
936 if (se_cmd->data_length < (XCOPY_HDR_LEN + tdll + sdll + inline_dl)) {
937 pr_err("XCOPY parameter truncation: data length %u too small "
938 "for tdll: %hu sdll: %u inline_dl: %u\n",
939 se_cmd->data_length, tdll, sdll, inline_dl);
940 ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
941 goto out;
942 }
943
893 pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x" 944 pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"
894 " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, 945 " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
895 tdll, sdll, inline_dl); 946 tdll, sdll, inline_dl);
896 947
948 /*
949 * skip over the target descriptors until segment descriptors
950 * have been passed - CSCD ids are needed to determine src and dest.
951 */
952 seg_desc = &p[16] + tdll;
953
954 rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
955 sdll, &ret);
956 if (rc <= 0)
957 goto out;
958
959 pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
960 rc * XCOPY_SEGMENT_DESC_LEN);
961
897 rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret); 962 rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
898 if (rc <= 0) 963 if (rc <= 0)
899 goto out; 964 goto out;
@@ -911,18 +976,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
911 976
912 pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc, 977 pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
913 rc * XCOPY_TARGET_DESC_LEN); 978 rc * XCOPY_TARGET_DESC_LEN);
914 seg_desc = &p[16];
915 seg_desc += (rc * XCOPY_TARGET_DESC_LEN);
916
917 rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, sdll);
918 if (rc <= 0) {
919 xcopy_pt_undepend_remotedev(xop);
920 goto out;
921 }
922 transport_kunmap_data_sg(se_cmd); 979 transport_kunmap_data_sg(se_cmd);
923 980
924 pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
925 rc * XCOPY_SEGMENT_DESC_LEN);
926 INIT_WORK(&xop->xop_work, target_xcopy_do_work); 981 INIT_WORK(&xop->xop_work, target_xcopy_do_work);
927 queue_work(xcopy_wq, &xop->xop_work); 982 queue_work(xcopy_wq, &xop->xop_work);
928 return TCM_NO_SENSE; 983 return TCM_NO_SENSE;
diff --git a/drivers/target/target_core_xcopy.h b/drivers/target/target_core_xcopy.h
index 4d3d4dd060f2..7c0b105cbe1b 100644
--- a/drivers/target/target_core_xcopy.h
+++ b/drivers/target/target_core_xcopy.h
@@ -1,10 +1,17 @@
1#include <target/target_core_base.h> 1#include <target/target_core_base.h>
2 2
3#define XCOPY_HDR_LEN 16
3#define XCOPY_TARGET_DESC_LEN 32 4#define XCOPY_TARGET_DESC_LEN 32
4#define XCOPY_SEGMENT_DESC_LEN 28 5#define XCOPY_SEGMENT_DESC_LEN 28
5#define XCOPY_NAA_IEEE_REGEX_LEN 16 6#define XCOPY_NAA_IEEE_REGEX_LEN 16
6#define XCOPY_MAX_SECTORS 1024 7#define XCOPY_MAX_SECTORS 1024
7 8
9/*
10 * SPC4r37 6.4.6.1
11 * Table 150 — CSCD descriptor ID values
12 */
13#define XCOPY_CSCD_DESC_ID_LIST_OFF_MAX 0x07FF
14
8enum xcopy_origin_list { 15enum xcopy_origin_list {
9 XCOL_SOURCE_RECV_OP = 0x01, 16 XCOL_SOURCE_RECV_OP = 0x01,
10 XCOL_DEST_RECV_OP = 0x02, 17 XCOL_DEST_RECV_OP = 0x02,
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 29e6858bb164..43edf82e54ff 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -174,6 +174,10 @@ enum tcm_sense_reason_table {
174 TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), 174 TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16),
175 TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), 175 TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17),
176 TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18), 176 TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18),
177 TCM_TOO_MANY_TARGET_DESCS = R(0x19),
178 TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE = R(0x1a),
179 TCM_TOO_MANY_SEGMENT_DESCS = R(0x1b),
180 TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE = R(0x1c),
177#undef R 181#undef R
178}; 182};
179 183