0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/slab.h>
0013 #include <linux/random.h>
0014
0015 #include <target/iscsi/iscsi_target_core.h>
0016 #include "iscsi_target_util.h"
0017 #include "iscsi_target_tpg.h"
0018 #include "iscsi_target_seq_pdu_list.h"
0019
0020 #ifdef DEBUG
0021 static void iscsit_dump_seq_list(struct iscsit_cmd *cmd)
0022 {
0023 int i;
0024 struct iscsi_seq *seq;
0025
0026 pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
0027 cmd->init_task_tag);
0028
0029 for (i = 0; i < cmd->seq_count; i++) {
0030 seq = &cmd->seq_list[i];
0031 pr_debug("i: %d, pdu_start: %d, pdu_count: %d,"
0032 " offset: %d, xfer_len: %d, seq_send_order: %d,"
0033 " seq_no: %d\n", i, seq->pdu_start, seq->pdu_count,
0034 seq->offset, seq->xfer_len, seq->seq_send_order,
0035 seq->seq_no);
0036 }
0037 }
0038
0039 static void iscsit_dump_pdu_list(struct iscsit_cmd *cmd)
0040 {
0041 int i;
0042 struct iscsi_pdu *pdu;
0043
0044 pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
0045 cmd->init_task_tag);
0046
0047 for (i = 0; i < cmd->pdu_count; i++) {
0048 pdu = &cmd->pdu_list[i];
0049 pr_debug("i: %d, offset: %d, length: %d,"
0050 " pdu_send_order: %d, seq_no: %d\n", i, pdu->offset,
0051 pdu->length, pdu->pdu_send_order, pdu->seq_no);
0052 }
0053 }
0054 #else
0055 static void iscsit_dump_seq_list(struct iscsit_cmd *cmd) {}
0056 static void iscsit_dump_pdu_list(struct iscsit_cmd *cmd) {}
0057 #endif
0058
0059 static void iscsit_ordered_seq_lists(
0060 struct iscsit_cmd *cmd,
0061 u8 type)
0062 {
0063 u32 i, seq_count = 0;
0064
0065 for (i = 0; i < cmd->seq_count; i++) {
0066 if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
0067 continue;
0068 cmd->seq_list[i].seq_send_order = seq_count++;
0069 }
0070 }
0071
0072 static void iscsit_ordered_pdu_lists(
0073 struct iscsit_cmd *cmd,
0074 u8 type)
0075 {
0076 u32 i, pdu_send_order = 0, seq_no = 0;
0077
0078 for (i = 0; i < cmd->pdu_count; i++) {
0079 redo:
0080 if (cmd->pdu_list[i].seq_no == seq_no) {
0081 cmd->pdu_list[i].pdu_send_order = pdu_send_order++;
0082 continue;
0083 }
0084 seq_no++;
0085 pdu_send_order = 0;
0086 goto redo;
0087 }
0088 }
0089
0090
0091
0092
0093
0094 static void iscsit_create_random_array(u32 *array, u32 count)
0095 {
0096 int i, j, k;
0097
0098 if (count == 1) {
0099 array[0] = 0;
0100 return;
0101 }
0102
0103 for (i = 0; i < count; i++) {
0104 redo:
0105 get_random_bytes(&j, sizeof(u32));
0106 j = (1 + (int) (9999 + 1) - j) % count;
0107 for (k = 0; k < i + 1; k++) {
0108 j |= 0x80000000;
0109 if ((array[k] & 0x80000000) && (array[k] == j))
0110 goto redo;
0111 }
0112 array[i] = j;
0113 }
0114
0115 for (i = 0; i < count; i++)
0116 array[i] &= ~0x80000000;
0117 }
0118
0119 static int iscsit_randomize_pdu_lists(
0120 struct iscsit_cmd *cmd,
0121 u8 type)
0122 {
0123 int i = 0;
0124 u32 *array, pdu_count, seq_count = 0, seq_no = 0, seq_offset = 0;
0125
0126 for (pdu_count = 0; pdu_count < cmd->pdu_count; pdu_count++) {
0127 redo:
0128 if (cmd->pdu_list[pdu_count].seq_no == seq_no) {
0129 seq_count++;
0130 continue;
0131 }
0132 array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
0133 if (!array) {
0134 pr_err("Unable to allocate memory"
0135 " for random array.\n");
0136 return -ENOMEM;
0137 }
0138 iscsit_create_random_array(array, seq_count);
0139
0140 for (i = 0; i < seq_count; i++)
0141 cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
0142
0143 kfree(array);
0144
0145 seq_offset += seq_count;
0146 seq_count = 0;
0147 seq_no++;
0148 goto redo;
0149 }
0150
0151 if (seq_count) {
0152 array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
0153 if (!array) {
0154 pr_err("Unable to allocate memory for"
0155 " random array.\n");
0156 return -ENOMEM;
0157 }
0158 iscsit_create_random_array(array, seq_count);
0159
0160 for (i = 0; i < seq_count; i++)
0161 cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
0162
0163 kfree(array);
0164 }
0165
0166 return 0;
0167 }
0168
0169 static int iscsit_randomize_seq_lists(
0170 struct iscsit_cmd *cmd,
0171 u8 type)
0172 {
0173 int i, j = 0;
0174 u32 *array, seq_count = cmd->seq_count;
0175
0176 if ((type == PDULIST_IMMEDIATE) || (type == PDULIST_UNSOLICITED))
0177 seq_count--;
0178 else if (type == PDULIST_IMMEDIATE_AND_UNSOLICITED)
0179 seq_count -= 2;
0180
0181 if (!seq_count)
0182 return 0;
0183
0184 array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
0185 if (!array) {
0186 pr_err("Unable to allocate memory for random array.\n");
0187 return -ENOMEM;
0188 }
0189 iscsit_create_random_array(array, seq_count);
0190
0191 for (i = 0; i < cmd->seq_count; i++) {
0192 if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
0193 continue;
0194 cmd->seq_list[i].seq_send_order = array[j++];
0195 }
0196
0197 kfree(array);
0198 return 0;
0199 }
0200
0201 static void iscsit_determine_counts_for_list(
0202 struct iscsit_cmd *cmd,
0203 struct iscsi_build_list *bl,
0204 u32 *seq_count,
0205 u32 *pdu_count)
0206 {
0207 int check_immediate = 0;
0208 u32 burstlength = 0, offset = 0;
0209 u32 unsolicited_data_length = 0;
0210 u32 mdsl;
0211 struct iscsit_conn *conn = cmd->conn;
0212
0213 if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
0214 mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
0215 else
0216 mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
0217
0218 if ((bl->type == PDULIST_IMMEDIATE) ||
0219 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0220 check_immediate = 1;
0221
0222 if ((bl->type == PDULIST_UNSOLICITED) ||
0223 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0224 unsolicited_data_length = min(cmd->se_cmd.data_length,
0225 conn->sess->sess_ops->FirstBurstLength);
0226
0227 while (offset < cmd->se_cmd.data_length) {
0228 *pdu_count += 1;
0229
0230 if (check_immediate) {
0231 check_immediate = 0;
0232 offset += bl->immediate_data_length;
0233 *seq_count += 1;
0234 if (unsolicited_data_length)
0235 unsolicited_data_length -=
0236 bl->immediate_data_length;
0237 continue;
0238 }
0239 if (unsolicited_data_length > 0) {
0240 if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0241 unsolicited_data_length -=
0242 (cmd->se_cmd.data_length - offset);
0243 offset += (cmd->se_cmd.data_length - offset);
0244 continue;
0245 }
0246 if ((offset + mdsl)
0247 >= conn->sess->sess_ops->FirstBurstLength) {
0248 unsolicited_data_length -=
0249 (conn->sess->sess_ops->FirstBurstLength -
0250 offset);
0251 offset += (conn->sess->sess_ops->FirstBurstLength -
0252 offset);
0253 burstlength = 0;
0254 *seq_count += 1;
0255 continue;
0256 }
0257
0258 offset += mdsl;
0259 unsolicited_data_length -= mdsl;
0260 continue;
0261 }
0262 if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0263 offset += (cmd->se_cmd.data_length - offset);
0264 continue;
0265 }
0266 if ((burstlength + mdsl) >=
0267 conn->sess->sess_ops->MaxBurstLength) {
0268 offset += (conn->sess->sess_ops->MaxBurstLength -
0269 burstlength);
0270 burstlength = 0;
0271 *seq_count += 1;
0272 continue;
0273 }
0274
0275 burstlength += mdsl;
0276 offset += mdsl;
0277 }
0278 }
0279
0280
0281
0282
0283
0284
0285 static int iscsit_do_build_pdu_and_seq_lists(
0286 struct iscsit_cmd *cmd,
0287 struct iscsi_build_list *bl)
0288 {
0289 int check_immediate = 0, datapduinorder, datasequenceinorder;
0290 u32 burstlength = 0, offset = 0, i = 0, mdsl;
0291 u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
0292 struct iscsit_conn *conn = cmd->conn;
0293 struct iscsi_pdu *pdu = cmd->pdu_list;
0294 struct iscsi_seq *seq = cmd->seq_list;
0295
0296 if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
0297 mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
0298 else
0299 mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
0300
0301 datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
0302 datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
0303
0304 if ((bl->type == PDULIST_IMMEDIATE) ||
0305 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0306 check_immediate = 1;
0307
0308 if ((bl->type == PDULIST_UNSOLICITED) ||
0309 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0310 unsolicited_data_length = min(cmd->se_cmd.data_length,
0311 conn->sess->sess_ops->FirstBurstLength);
0312
0313 while (offset < cmd->se_cmd.data_length) {
0314 pdu_count++;
0315 if (!datapduinorder) {
0316 pdu[i].offset = offset;
0317 pdu[i].seq_no = seq_no;
0318 }
0319 if (!datasequenceinorder && (pdu_count == 1)) {
0320 seq[seq_no].pdu_start = i;
0321 seq[seq_no].seq_no = seq_no;
0322 seq[seq_no].offset = offset;
0323 seq[seq_no].orig_offset = offset;
0324 }
0325
0326 if (check_immediate) {
0327 check_immediate = 0;
0328 if (!datapduinorder) {
0329 pdu[i].type = PDUTYPE_IMMEDIATE;
0330 pdu[i++].length = bl->immediate_data_length;
0331 }
0332 if (!datasequenceinorder) {
0333 seq[seq_no].type = SEQTYPE_IMMEDIATE;
0334 seq[seq_no].pdu_count = 1;
0335 seq[seq_no].xfer_len =
0336 bl->immediate_data_length;
0337 }
0338 offset += bl->immediate_data_length;
0339 pdu_count = 0;
0340 seq_no++;
0341 if (unsolicited_data_length)
0342 unsolicited_data_length -=
0343 bl->immediate_data_length;
0344 continue;
0345 }
0346 if (unsolicited_data_length > 0) {
0347 if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0348 if (!datapduinorder) {
0349 pdu[i].type = PDUTYPE_UNSOLICITED;
0350 pdu[i].length =
0351 (cmd->se_cmd.data_length - offset);
0352 }
0353 if (!datasequenceinorder) {
0354 seq[seq_no].type = SEQTYPE_UNSOLICITED;
0355 seq[seq_no].pdu_count = pdu_count;
0356 seq[seq_no].xfer_len = (burstlength +
0357 (cmd->se_cmd.data_length - offset));
0358 }
0359 unsolicited_data_length -=
0360 (cmd->se_cmd.data_length - offset);
0361 offset += (cmd->se_cmd.data_length - offset);
0362 continue;
0363 }
0364 if ((offset + mdsl) >=
0365 conn->sess->sess_ops->FirstBurstLength) {
0366 if (!datapduinorder) {
0367 pdu[i].type = PDUTYPE_UNSOLICITED;
0368 pdu[i++].length =
0369 (conn->sess->sess_ops->FirstBurstLength -
0370 offset);
0371 }
0372 if (!datasequenceinorder) {
0373 seq[seq_no].type = SEQTYPE_UNSOLICITED;
0374 seq[seq_no].pdu_count = pdu_count;
0375 seq[seq_no].xfer_len = (burstlength +
0376 (conn->sess->sess_ops->FirstBurstLength -
0377 offset));
0378 }
0379 unsolicited_data_length -=
0380 (conn->sess->sess_ops->FirstBurstLength -
0381 offset);
0382 offset += (conn->sess->sess_ops->FirstBurstLength -
0383 offset);
0384 burstlength = 0;
0385 pdu_count = 0;
0386 seq_no++;
0387 continue;
0388 }
0389
0390 if (!datapduinorder) {
0391 pdu[i].type = PDUTYPE_UNSOLICITED;
0392 pdu[i++].length = mdsl;
0393 }
0394 burstlength += mdsl;
0395 offset += mdsl;
0396 unsolicited_data_length -= mdsl;
0397 continue;
0398 }
0399 if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0400 if (!datapduinorder) {
0401 pdu[i].type = PDUTYPE_NORMAL;
0402 pdu[i].length = (cmd->se_cmd.data_length - offset);
0403 }
0404 if (!datasequenceinorder) {
0405 seq[seq_no].type = SEQTYPE_NORMAL;
0406 seq[seq_no].pdu_count = pdu_count;
0407 seq[seq_no].xfer_len = (burstlength +
0408 (cmd->se_cmd.data_length - offset));
0409 }
0410 offset += (cmd->se_cmd.data_length - offset);
0411 continue;
0412 }
0413 if ((burstlength + mdsl) >=
0414 conn->sess->sess_ops->MaxBurstLength) {
0415 if (!datapduinorder) {
0416 pdu[i].type = PDUTYPE_NORMAL;
0417 pdu[i++].length =
0418 (conn->sess->sess_ops->MaxBurstLength -
0419 burstlength);
0420 }
0421 if (!datasequenceinorder) {
0422 seq[seq_no].type = SEQTYPE_NORMAL;
0423 seq[seq_no].pdu_count = pdu_count;
0424 seq[seq_no].xfer_len = (burstlength +
0425 (conn->sess->sess_ops->MaxBurstLength -
0426 burstlength));
0427 }
0428 offset += (conn->sess->sess_ops->MaxBurstLength -
0429 burstlength);
0430 burstlength = 0;
0431 pdu_count = 0;
0432 seq_no++;
0433 continue;
0434 }
0435
0436 if (!datapduinorder) {
0437 pdu[i].type = PDUTYPE_NORMAL;
0438 pdu[i++].length = mdsl;
0439 }
0440 burstlength += mdsl;
0441 offset += mdsl;
0442 }
0443
0444 if (!datasequenceinorder) {
0445 if (bl->data_direction & ISCSI_PDU_WRITE) {
0446 if (bl->randomize & RANDOM_R2T_OFFSETS) {
0447 if (iscsit_randomize_seq_lists(cmd, bl->type)
0448 < 0)
0449 return -1;
0450 } else
0451 iscsit_ordered_seq_lists(cmd, bl->type);
0452 } else if (bl->data_direction & ISCSI_PDU_READ) {
0453 if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) {
0454 if (iscsit_randomize_seq_lists(cmd, bl->type)
0455 < 0)
0456 return -1;
0457 } else
0458 iscsit_ordered_seq_lists(cmd, bl->type);
0459 }
0460
0461 iscsit_dump_seq_list(cmd);
0462 }
0463 if (!datapduinorder) {
0464 if (bl->data_direction & ISCSI_PDU_WRITE) {
0465 if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) {
0466 if (iscsit_randomize_pdu_lists(cmd, bl->type)
0467 < 0)
0468 return -1;
0469 } else
0470 iscsit_ordered_pdu_lists(cmd, bl->type);
0471 } else if (bl->data_direction & ISCSI_PDU_READ) {
0472 if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) {
0473 if (iscsit_randomize_pdu_lists(cmd, bl->type)
0474 < 0)
0475 return -1;
0476 } else
0477 iscsit_ordered_pdu_lists(cmd, bl->type);
0478 }
0479
0480 iscsit_dump_pdu_list(cmd);
0481 }
0482
0483 return 0;
0484 }
0485
0486 int iscsit_build_pdu_and_seq_lists(
0487 struct iscsit_cmd *cmd,
0488 u32 immediate_data_length)
0489 {
0490 struct iscsi_build_list bl;
0491 u32 pdu_count = 0, seq_count = 1;
0492 struct iscsit_conn *conn = cmd->conn;
0493 struct iscsi_pdu *pdu = NULL;
0494 struct iscsi_seq *seq = NULL;
0495
0496 struct iscsit_session *sess = conn->sess;
0497 struct iscsi_node_attrib *na;
0498
0499
0500
0501
0502 if (sess->sess_ops->DataSequenceInOrder &&
0503 sess->sess_ops->DataPDUInOrder)
0504 return 0;
0505
0506 if (cmd->data_direction == DMA_NONE)
0507 return 0;
0508
0509 na = iscsit_tpg_get_node_attrib(sess);
0510 memset(&bl, 0, sizeof(struct iscsi_build_list));
0511
0512 if (cmd->data_direction == DMA_FROM_DEVICE) {
0513 bl.data_direction = ISCSI_PDU_READ;
0514 bl.type = PDULIST_NORMAL;
0515 if (na->random_datain_pdu_offsets)
0516 bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
0517 if (na->random_datain_seq_offsets)
0518 bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
0519 } else {
0520 bl.data_direction = ISCSI_PDU_WRITE;
0521 bl.immediate_data_length = immediate_data_length;
0522 if (na->random_r2t_offsets)
0523 bl.randomize |= RANDOM_R2T_OFFSETS;
0524
0525 if (!cmd->immediate_data && !cmd->unsolicited_data)
0526 bl.type = PDULIST_NORMAL;
0527 else if (cmd->immediate_data && !cmd->unsolicited_data)
0528 bl.type = PDULIST_IMMEDIATE;
0529 else if (!cmd->immediate_data && cmd->unsolicited_data)
0530 bl.type = PDULIST_UNSOLICITED;
0531 else if (cmd->immediate_data && cmd->unsolicited_data)
0532 bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
0533 }
0534
0535 iscsit_determine_counts_for_list(cmd, &bl, &seq_count, &pdu_count);
0536
0537 if (!conn->sess->sess_ops->DataSequenceInOrder) {
0538 seq = kcalloc(seq_count, sizeof(struct iscsi_seq), GFP_ATOMIC);
0539 if (!seq) {
0540 pr_err("Unable to allocate struct iscsi_seq list\n");
0541 return -ENOMEM;
0542 }
0543 cmd->seq_list = seq;
0544 cmd->seq_count = seq_count;
0545 }
0546
0547 if (!conn->sess->sess_ops->DataPDUInOrder) {
0548 pdu = kcalloc(pdu_count, sizeof(struct iscsi_pdu), GFP_ATOMIC);
0549 if (!pdu) {
0550 pr_err("Unable to allocate struct iscsi_pdu list.\n");
0551 kfree(seq);
0552 return -ENOMEM;
0553 }
0554 cmd->pdu_list = pdu;
0555 cmd->pdu_count = pdu_count;
0556 }
0557
0558 return iscsit_do_build_pdu_and_seq_lists(cmd, &bl);
0559 }
0560
0561 struct iscsi_pdu *iscsit_get_pdu_holder(
0562 struct iscsit_cmd *cmd,
0563 u32 offset,
0564 u32 length)
0565 {
0566 u32 i;
0567 struct iscsi_pdu *pdu = NULL;
0568
0569 if (!cmd->pdu_list) {
0570 pr_err("struct iscsit_cmd->pdu_list is NULL!\n");
0571 return NULL;
0572 }
0573
0574 pdu = &cmd->pdu_list[0];
0575
0576 for (i = 0; i < cmd->pdu_count; i++)
0577 if ((pdu[i].offset == offset) && (pdu[i].length == length))
0578 return &pdu[i];
0579
0580 pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
0581 " %u, Length: %u\n", cmd->init_task_tag, offset, length);
0582 return NULL;
0583 }
0584
0585 struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
0586 struct iscsit_cmd *cmd,
0587 struct iscsi_seq *seq)
0588 {
0589 u32 i;
0590 struct iscsit_conn *conn = cmd->conn;
0591 struct iscsi_pdu *pdu = NULL;
0592
0593 if (!cmd->pdu_list) {
0594 pr_err("struct iscsit_cmd->pdu_list is NULL!\n");
0595 return NULL;
0596 }
0597
0598 if (conn->sess->sess_ops->DataSequenceInOrder) {
0599 redo:
0600 pdu = &cmd->pdu_list[cmd->pdu_start];
0601
0602 for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
0603 pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
0604 "_send_order: %d, pdu[i].offset: %d,"
0605 " pdu[i].length: %d\n", pdu[i].seq_no,
0606 pdu[i].pdu_send_order, pdu[i].offset,
0607 pdu[i].length);
0608
0609 if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
0610 cmd->pdu_send_order++;
0611 return &pdu[i];
0612 }
0613 }
0614
0615 cmd->pdu_start += cmd->pdu_send_order;
0616 cmd->pdu_send_order = 0;
0617 cmd->seq_no++;
0618
0619 if (cmd->pdu_start < cmd->pdu_count)
0620 goto redo;
0621
0622 pr_err("Command ITT: 0x%08x unable to locate"
0623 " struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
0624 cmd->init_task_tag, cmd->pdu_send_order);
0625 return NULL;
0626 } else {
0627 if (!seq) {
0628 pr_err("struct iscsi_seq is NULL!\n");
0629 return NULL;
0630 }
0631
0632 pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
0633 " seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
0634 seq->seq_no);
0635
0636 pdu = &cmd->pdu_list[seq->pdu_start];
0637
0638 if (seq->pdu_send_order == seq->pdu_count) {
0639 pr_err("Command ITT: 0x%08x seq->pdu_send"
0640 "_order: %u equals seq->pdu_count: %u\n",
0641 cmd->init_task_tag, seq->pdu_send_order,
0642 seq->pdu_count);
0643 return NULL;
0644 }
0645
0646 for (i = 0; i < seq->pdu_count; i++) {
0647 if (pdu[i].pdu_send_order == seq->pdu_send_order) {
0648 seq->pdu_send_order++;
0649 return &pdu[i];
0650 }
0651 }
0652
0653 pr_err("Command ITT: 0x%08x unable to locate iscsi"
0654 "_pdu_t for seq->pdu_send_order: %u.\n",
0655 cmd->init_task_tag, seq->pdu_send_order);
0656 return NULL;
0657 }
0658
0659 return NULL;
0660 }
0661
0662 struct iscsi_seq *iscsit_get_seq_holder(
0663 struct iscsit_cmd *cmd,
0664 u32 offset,
0665 u32 length)
0666 {
0667 u32 i;
0668
0669 if (!cmd->seq_list) {
0670 pr_err("struct iscsit_cmd->seq_list is NULL!\n");
0671 return NULL;
0672 }
0673
0674 for (i = 0; i < cmd->seq_count; i++) {
0675 pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
0676 "xfer_len: %d, seq_list[i].seq_no %u\n",
0677 cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
0678 cmd->seq_list[i].seq_no);
0679
0680 if ((cmd->seq_list[i].orig_offset +
0681 cmd->seq_list[i].xfer_len) >=
0682 (offset + length))
0683 return &cmd->seq_list[i];
0684 }
0685
0686 pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
0687 " Offset: %u, Length: %u\n", cmd->init_task_tag, offset,
0688 length);
0689 return NULL;
0690 }