blob: c69c7577ad14e2cf1e1130d0c45d9ac82df6b1ca [file] [log] [blame]
Nicholas Bellingere48354c2011-07-23 06:43:04 +00001/*******************************************************************************
2 * This file contains main functions related to iSCSI DataSequenceInOrder=No
3 * and DataPDUInOrder=No.
4 *
5 \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
6 *
7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 *
9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 ******************************************************************************/
21
22#include <linux/slab.h>
23#include <linux/random.h>
24
25#include "iscsi_target_core.h"
26#include "iscsi_target_util.h"
27#include "iscsi_target_seq_pdu_list.h"
28
29#define OFFLOAD_BUF_SIZE 32768
30
Andy Grover8b1e1242012-04-03 15:51:12 -070031#ifdef DEBUG
32static void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
Nicholas Bellingere48354c2011-07-23 06:43:04 +000033{
34 int i;
35 struct iscsi_seq *seq;
36
37 pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
38 cmd->init_task_tag);
39
40 for (i = 0; i < cmd->seq_count; i++) {
41 seq = &cmd->seq_list[i];
42 pr_debug("i: %d, pdu_start: %d, pdu_count: %d,"
43 " offset: %d, xfer_len: %d, seq_send_order: %d,"
44 " seq_no: %d\n", i, seq->pdu_start, seq->pdu_count,
45 seq->offset, seq->xfer_len, seq->seq_send_order,
46 seq->seq_no);
47 }
48}
49
Andy Grover8b1e1242012-04-03 15:51:12 -070050static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
Nicholas Bellingere48354c2011-07-23 06:43:04 +000051{
52 int i;
53 struct iscsi_pdu *pdu;
54
55 pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
56 cmd->init_task_tag);
57
58 for (i = 0; i < cmd->pdu_count; i++) {
59 pdu = &cmd->pdu_list[i];
60 pr_debug("i: %d, offset: %d, length: %d,"
61 " pdu_send_order: %d, seq_no: %d\n", i, pdu->offset,
62 pdu->length, pdu->pdu_send_order, pdu->seq_no);
63 }
64}
Andy Grover8b1e1242012-04-03 15:51:12 -070065#else
66static void iscsit_dump_seq_list(struct iscsi_cmd *cmd) {}
67static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd) {}
68#endif
Nicholas Bellingere48354c2011-07-23 06:43:04 +000069
70static void iscsit_ordered_seq_lists(
71 struct iscsi_cmd *cmd,
72 u8 type)
73{
74 u32 i, seq_count = 0;
75
76 for (i = 0; i < cmd->seq_count; i++) {
77 if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
78 continue;
79 cmd->seq_list[i].seq_send_order = seq_count++;
80 }
81}
82
83static void iscsit_ordered_pdu_lists(
84 struct iscsi_cmd *cmd,
85 u8 type)
86{
87 u32 i, pdu_send_order = 0, seq_no = 0;
88
89 for (i = 0; i < cmd->pdu_count; i++) {
90redo:
91 if (cmd->pdu_list[i].seq_no == seq_no) {
92 cmd->pdu_list[i].pdu_send_order = pdu_send_order++;
93 continue;
94 }
95 seq_no++;
96 pdu_send_order = 0;
97 goto redo;
98 }
99}
100
101/*
102 * Generate count random values into array.
103 * Use 0x80000000 to mark generates valued in array[].
104 */
105static void iscsit_create_random_array(u32 *array, u32 count)
106{
107 int i, j, k;
108
109 if (count == 1) {
110 array[0] = 0;
111 return;
112 }
113
114 for (i = 0; i < count; i++) {
115redo:
116 get_random_bytes(&j, sizeof(u32));
117 j = (1 + (int) (9999 + 1) - j) % count;
118 for (k = 0; k < i + 1; k++) {
119 j |= 0x80000000;
120 if ((array[k] & 0x80000000) && (array[k] == j))
121 goto redo;
122 }
123 array[i] = j;
124 }
125
126 for (i = 0; i < count; i++)
127 array[i] &= ~0x80000000;
128}
129
130static int iscsit_randomize_pdu_lists(
131 struct iscsi_cmd *cmd,
132 u8 type)
133{
134 int i = 0;
135 u32 *array, pdu_count, seq_count = 0, seq_no = 0, seq_offset = 0;
136
137 for (pdu_count = 0; pdu_count < cmd->pdu_count; pdu_count++) {
138redo:
139 if (cmd->pdu_list[pdu_count].seq_no == seq_no) {
140 seq_count++;
141 continue;
142 }
143 array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
144 if (!array) {
145 pr_err("Unable to allocate memory"
146 " for random array.\n");
147 return -1;
148 }
149 iscsit_create_random_array(array, seq_count);
150
151 for (i = 0; i < seq_count; i++)
152 cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
153
154 kfree(array);
155
156 seq_offset += seq_count;
157 seq_count = 0;
158 seq_no++;
159 goto redo;
160 }
161
162 if (seq_count) {
163 array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
164 if (!array) {
165 pr_err("Unable to allocate memory for"
166 " random array.\n");
167 return -1;
168 }
169 iscsit_create_random_array(array, seq_count);
170
171 for (i = 0; i < seq_count; i++)
172 cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
173
174 kfree(array);
175 }
176
177 return 0;
178}
179
180static int iscsit_randomize_seq_lists(
181 struct iscsi_cmd *cmd,
182 u8 type)
183{
184 int i, j = 0;
185 u32 *array, seq_count = cmd->seq_count;
186
187 if ((type == PDULIST_IMMEDIATE) || (type == PDULIST_UNSOLICITED))
188 seq_count--;
189 else if (type == PDULIST_IMMEDIATE_AND_UNSOLICITED)
190 seq_count -= 2;
191
192 if (!seq_count)
193 return 0;
194
195 array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
196 if (!array) {
197 pr_err("Unable to allocate memory for random array.\n");
198 return -1;
199 }
200 iscsit_create_random_array(array, seq_count);
201
202 for (i = 0; i < cmd->seq_count; i++) {
203 if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
204 continue;
205 cmd->seq_list[i].seq_send_order = array[j++];
206 }
207
208 kfree(array);
209 return 0;
210}
211
212static void iscsit_determine_counts_for_list(
213 struct iscsi_cmd *cmd,
214 struct iscsi_build_list *bl,
215 u32 *seq_count,
216 u32 *pdu_count)
217{
218 int check_immediate = 0;
219 u32 burstlength = 0, offset = 0;
220 u32 unsolicited_data_length = 0;
221 struct iscsi_conn *conn = cmd->conn;
222
223 if ((bl->type == PDULIST_IMMEDIATE) ||
224 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
225 check_immediate = 1;
226
227 if ((bl->type == PDULIST_UNSOLICITED) ||
228 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
229 unsolicited_data_length = (cmd->data_length >
230 conn->sess->sess_ops->FirstBurstLength) ?
231 conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
232
233 while (offset < cmd->data_length) {
234 *pdu_count += 1;
235
236 if (check_immediate) {
237 check_immediate = 0;
238 offset += bl->immediate_data_length;
239 *seq_count += 1;
240 if (unsolicited_data_length)
241 unsolicited_data_length -=
242 bl->immediate_data_length;
243 continue;
244 }
245 if (unsolicited_data_length > 0) {
246 if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
247 >= cmd->data_length) {
248 unsolicited_data_length -=
249 (cmd->data_length - offset);
250 offset += (cmd->data_length - offset);
251 continue;
252 }
253 if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
254 >= conn->sess->sess_ops->FirstBurstLength) {
255 unsolicited_data_length -=
256 (conn->sess->sess_ops->FirstBurstLength -
257 offset);
258 offset += (conn->sess->sess_ops->FirstBurstLength -
259 offset);
260 burstlength = 0;
261 *seq_count += 1;
262 continue;
263 }
264
265 offset += conn->conn_ops->MaxRecvDataSegmentLength;
266 unsolicited_data_length -=
267 conn->conn_ops->MaxRecvDataSegmentLength;
268 continue;
269 }
270 if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
271 cmd->data_length) {
272 offset += (cmd->data_length - offset);
273 continue;
274 }
275 if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
276 conn->sess->sess_ops->MaxBurstLength) {
277 offset += (conn->sess->sess_ops->MaxBurstLength -
278 burstlength);
279 burstlength = 0;
280 *seq_count += 1;
281 continue;
282 }
283
284 burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
285 offset += conn->conn_ops->MaxRecvDataSegmentLength;
286 }
287}
288
289
290/*
291 * Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
292 * and DataPDUInOrder=No.
293 */
294static int iscsit_build_pdu_and_seq_list(
295 struct iscsi_cmd *cmd,
296 struct iscsi_build_list *bl)
297{
298 int check_immediate = 0, datapduinorder, datasequenceinorder;
299 u32 burstlength = 0, offset = 0, i = 0;
300 u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
301 struct iscsi_conn *conn = cmd->conn;
302 struct iscsi_pdu *pdu = cmd->pdu_list;
303 struct iscsi_seq *seq = cmd->seq_list;
304
305 datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
306 datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
307
308 if ((bl->type == PDULIST_IMMEDIATE) ||
309 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
310 check_immediate = 1;
311
312 if ((bl->type == PDULIST_UNSOLICITED) ||
313 (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
314 unsolicited_data_length = (cmd->data_length >
315 conn->sess->sess_ops->FirstBurstLength) ?
316 conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
317
318 while (offset < cmd->data_length) {
319 pdu_count++;
320 if (!datapduinorder) {
321 pdu[i].offset = offset;
322 pdu[i].seq_no = seq_no;
323 }
324 if (!datasequenceinorder && (pdu_count == 1)) {
325 seq[seq_no].pdu_start = i;
326 seq[seq_no].seq_no = seq_no;
327 seq[seq_no].offset = offset;
328 seq[seq_no].orig_offset = offset;
329 }
330
331 if (check_immediate) {
332 check_immediate = 0;
333 if (!datapduinorder) {
334 pdu[i].type = PDUTYPE_IMMEDIATE;
335 pdu[i++].length = bl->immediate_data_length;
336 }
337 if (!datasequenceinorder) {
338 seq[seq_no].type = SEQTYPE_IMMEDIATE;
339 seq[seq_no].pdu_count = 1;
340 seq[seq_no].xfer_len =
341 bl->immediate_data_length;
342 }
343 offset += bl->immediate_data_length;
344 pdu_count = 0;
345 seq_no++;
346 if (unsolicited_data_length)
347 unsolicited_data_length -=
348 bl->immediate_data_length;
349 continue;
350 }
351 if (unsolicited_data_length > 0) {
352 if ((offset +
353 conn->conn_ops->MaxRecvDataSegmentLength) >=
354 cmd->data_length) {
355 if (!datapduinorder) {
356 pdu[i].type = PDUTYPE_UNSOLICITED;
357 pdu[i].length =
358 (cmd->data_length - offset);
359 }
360 if (!datasequenceinorder) {
361 seq[seq_no].type = SEQTYPE_UNSOLICITED;
362 seq[seq_no].pdu_count = pdu_count;
363 seq[seq_no].xfer_len = (burstlength +
364 (cmd->data_length - offset));
365 }
366 unsolicited_data_length -=
367 (cmd->data_length - offset);
368 offset += (cmd->data_length - offset);
369 continue;
370 }
371 if ((offset +
372 conn->conn_ops->MaxRecvDataSegmentLength) >=
373 conn->sess->sess_ops->FirstBurstLength) {
374 if (!datapduinorder) {
375 pdu[i].type = PDUTYPE_UNSOLICITED;
376 pdu[i++].length =
377 (conn->sess->sess_ops->FirstBurstLength -
378 offset);
379 }
380 if (!datasequenceinorder) {
381 seq[seq_no].type = SEQTYPE_UNSOLICITED;
382 seq[seq_no].pdu_count = pdu_count;
383 seq[seq_no].xfer_len = (burstlength +
384 (conn->sess->sess_ops->FirstBurstLength -
385 offset));
386 }
387 unsolicited_data_length -=
388 (conn->sess->sess_ops->FirstBurstLength -
389 offset);
390 offset += (conn->sess->sess_ops->FirstBurstLength -
391 offset);
392 burstlength = 0;
393 pdu_count = 0;
394 seq_no++;
395 continue;
396 }
397
398 if (!datapduinorder) {
399 pdu[i].type = PDUTYPE_UNSOLICITED;
400 pdu[i++].length =
401 conn->conn_ops->MaxRecvDataSegmentLength;
402 }
403 burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
404 offset += conn->conn_ops->MaxRecvDataSegmentLength;
405 unsolicited_data_length -=
406 conn->conn_ops->MaxRecvDataSegmentLength;
407 continue;
408 }
409 if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
410 cmd->data_length) {
411 if (!datapduinorder) {
412 pdu[i].type = PDUTYPE_NORMAL;
413 pdu[i].length = (cmd->data_length - offset);
414 }
415 if (!datasequenceinorder) {
416 seq[seq_no].type = SEQTYPE_NORMAL;
417 seq[seq_no].pdu_count = pdu_count;
418 seq[seq_no].xfer_len = (burstlength +
419 (cmd->data_length - offset));
420 }
421 offset += (cmd->data_length - offset);
422 continue;
423 }
424 if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
425 conn->sess->sess_ops->MaxBurstLength) {
426 if (!datapduinorder) {
427 pdu[i].type = PDUTYPE_NORMAL;
428 pdu[i++].length =
429 (conn->sess->sess_ops->MaxBurstLength -
430 burstlength);
431 }
432 if (!datasequenceinorder) {
433 seq[seq_no].type = SEQTYPE_NORMAL;
434 seq[seq_no].pdu_count = pdu_count;
435 seq[seq_no].xfer_len = (burstlength +
436 (conn->sess->sess_ops->MaxBurstLength -
437 burstlength));
438 }
439 offset += (conn->sess->sess_ops->MaxBurstLength -
440 burstlength);
441 burstlength = 0;
442 pdu_count = 0;
443 seq_no++;
444 continue;
445 }
446
447 if (!datapduinorder) {
448 pdu[i].type = PDUTYPE_NORMAL;
449 pdu[i++].length =
450 conn->conn_ops->MaxRecvDataSegmentLength;
451 }
452 burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
453 offset += conn->conn_ops->MaxRecvDataSegmentLength;
454 }
455
456 if (!datasequenceinorder) {
457 if (bl->data_direction & ISCSI_PDU_WRITE) {
458 if (bl->randomize & RANDOM_R2T_OFFSETS) {
459 if (iscsit_randomize_seq_lists(cmd, bl->type)
460 < 0)
461 return -1;
462 } else
463 iscsit_ordered_seq_lists(cmd, bl->type);
464 } else if (bl->data_direction & ISCSI_PDU_READ) {
465 if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) {
466 if (iscsit_randomize_seq_lists(cmd, bl->type)
467 < 0)
468 return -1;
469 } else
470 iscsit_ordered_seq_lists(cmd, bl->type);
471 }
Andy Grover8b1e1242012-04-03 15:51:12 -0700472
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000473 iscsit_dump_seq_list(cmd);
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000474 }
475 if (!datapduinorder) {
476 if (bl->data_direction & ISCSI_PDU_WRITE) {
477 if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) {
478 if (iscsit_randomize_pdu_lists(cmd, bl->type)
479 < 0)
480 return -1;
481 } else
482 iscsit_ordered_pdu_lists(cmd, bl->type);
483 } else if (bl->data_direction & ISCSI_PDU_READ) {
484 if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) {
485 if (iscsit_randomize_pdu_lists(cmd, bl->type)
486 < 0)
487 return -1;
488 } else
489 iscsit_ordered_pdu_lists(cmd, bl->type);
490 }
Andy Grover8b1e1242012-04-03 15:51:12 -0700491
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000492 iscsit_dump_pdu_list(cmd);
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000493 }
494
495 return 0;
496}
497
498/*
499 * Only called while DataSequenceInOrder=No or DataPDUInOrder=No.
500 */
501int iscsit_do_build_list(
502 struct iscsi_cmd *cmd,
503 struct iscsi_build_list *bl)
504{
505 u32 pdu_count = 0, seq_count = 1;
506 struct iscsi_conn *conn = cmd->conn;
507 struct iscsi_pdu *pdu = NULL;
508 struct iscsi_seq *seq = NULL;
509
510 iscsit_determine_counts_for_list(cmd, bl, &seq_count, &pdu_count);
511
512 if (!conn->sess->sess_ops->DataSequenceInOrder) {
513 seq = kzalloc(seq_count * sizeof(struct iscsi_seq), GFP_ATOMIC);
514 if (!seq) {
515 pr_err("Unable to allocate struct iscsi_seq list\n");
516 return -1;
517 }
518 cmd->seq_list = seq;
519 cmd->seq_count = seq_count;
520 }
521
522 if (!conn->sess->sess_ops->DataPDUInOrder) {
523 pdu = kzalloc(pdu_count * sizeof(struct iscsi_pdu), GFP_ATOMIC);
524 if (!pdu) {
525 pr_err("Unable to allocate struct iscsi_pdu list.\n");
526 kfree(seq);
527 return -1;
528 }
529 cmd->pdu_list = pdu;
530 cmd->pdu_count = pdu_count;
531 }
532
533 return iscsit_build_pdu_and_seq_list(cmd, bl);
534}
535
536struct iscsi_pdu *iscsit_get_pdu_holder(
537 struct iscsi_cmd *cmd,
538 u32 offset,
539 u32 length)
540{
541 u32 i;
542 struct iscsi_pdu *pdu = NULL;
543
544 if (!cmd->pdu_list) {
545 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
546 return NULL;
547 }
548
549 pdu = &cmd->pdu_list[0];
550
551 for (i = 0; i < cmd->pdu_count; i++)
552 if ((pdu[i].offset == offset) && (pdu[i].length == length))
553 return &pdu[i];
554
555 pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
556 " %u, Length: %u\n", cmd->init_task_tag, offset, length);
557 return NULL;
558}
559
560struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
561 struct iscsi_cmd *cmd,
562 struct iscsi_seq *seq)
563{
564 u32 i;
565 struct iscsi_conn *conn = cmd->conn;
566 struct iscsi_pdu *pdu = NULL;
567
568 if (!cmd->pdu_list) {
569 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
570 return NULL;
571 }
572
573 if (conn->sess->sess_ops->DataSequenceInOrder) {
574redo:
575 pdu = &cmd->pdu_list[cmd->pdu_start];
576
577 for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000578 pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
579 "_send_order: %d, pdu[i].offset: %d,"
580 " pdu[i].length: %d\n", pdu[i].seq_no,
581 pdu[i].pdu_send_order, pdu[i].offset,
582 pdu[i].length);
Andy Grover8b1e1242012-04-03 15:51:12 -0700583
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000584 if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
585 cmd->pdu_send_order++;
586 return &pdu[i];
587 }
588 }
589
590 cmd->pdu_start += cmd->pdu_send_order;
591 cmd->pdu_send_order = 0;
592 cmd->seq_no++;
593
594 if (cmd->pdu_start < cmd->pdu_count)
595 goto redo;
596
597 pr_err("Command ITT: 0x%08x unable to locate"
598 " struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
599 cmd->init_task_tag, cmd->pdu_send_order);
600 return NULL;
601 } else {
602 if (!seq) {
603 pr_err("struct iscsi_seq is NULL!\n");
604 return NULL;
605 }
Andy Grover8b1e1242012-04-03 15:51:12 -0700606
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000607 pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
608 " seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
609 seq->seq_no);
Andy Grover8b1e1242012-04-03 15:51:12 -0700610
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000611 pdu = &cmd->pdu_list[seq->pdu_start];
612
613 if (seq->pdu_send_order == seq->pdu_count) {
614 pr_err("Command ITT: 0x%08x seq->pdu_send"
615 "_order: %u equals seq->pdu_count: %u\n",
616 cmd->init_task_tag, seq->pdu_send_order,
617 seq->pdu_count);
618 return NULL;
619 }
620
621 for (i = 0; i < seq->pdu_count; i++) {
622 if (pdu[i].pdu_send_order == seq->pdu_send_order) {
623 seq->pdu_send_order++;
624 return &pdu[i];
625 }
626 }
627
628 pr_err("Command ITT: 0x%08x unable to locate iscsi"
629 "_pdu_t for seq->pdu_send_order: %u.\n",
630 cmd->init_task_tag, seq->pdu_send_order);
631 return NULL;
632 }
633
634 return NULL;
635}
636
637struct iscsi_seq *iscsit_get_seq_holder(
638 struct iscsi_cmd *cmd,
639 u32 offset,
640 u32 length)
641{
642 u32 i;
643
644 if (!cmd->seq_list) {
645 pr_err("struct iscsi_cmd->seq_list is NULL!\n");
646 return NULL;
647 }
648
649 for (i = 0; i < cmd->seq_count; i++) {
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000650 pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
651 "xfer_len: %d, seq_list[i].seq_no %u\n",
652 cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
653 cmd->seq_list[i].seq_no);
Andy Grover8b1e1242012-04-03 15:51:12 -0700654
Nicholas Bellingere48354c2011-07-23 06:43:04 +0000655 if ((cmd->seq_list[i].orig_offset +
656 cmd->seq_list[i].xfer_len) >=
657 (offset + length))
658 return &cmd->seq_list[i];
659 }
660
661 pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
662 " Offset: %u, Length: %u\n", cmd->init_task_tag, offset,
663 length);
664 return NULL;
665}