target/iscsi: Eliminate iscsi_cmd.data_length
[linux-2.6-microblaze.git] / drivers / target / iscsi / iscsi_target_seq_pdu_list.c
1 /*******************************************************************************
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
31 #ifdef DEBUG
32 static void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
33 {
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
50 static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
51 {
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 }
65 #else
66 static void iscsit_dump_seq_list(struct iscsi_cmd *cmd) {}
67 static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd) {}
68 #endif
69
70 static 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
83 static 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++) {
90 redo:
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  */
105 static 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++) {
115 redo:
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
130 static 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++) {
138 redo:
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
180 static 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
212 static 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 = min(cmd->se_cmd.data_length,
230                         conn->sess->sess_ops->FirstBurstLength);
231
232         while (offset < cmd->se_cmd.data_length) {
233                 *pdu_count += 1;
234
235                 if (check_immediate) {
236                         check_immediate = 0;
237                         offset += bl->immediate_data_length;
238                         *seq_count += 1;
239                         if (unsolicited_data_length)
240                                 unsolicited_data_length -=
241                                         bl->immediate_data_length;
242                         continue;
243                 }
244                 if (unsolicited_data_length > 0) {
245                         if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
246                                         >= cmd->se_cmd.data_length) {
247                                 unsolicited_data_length -=
248                                         (cmd->se_cmd.data_length - offset);
249                                 offset += (cmd->se_cmd.data_length - offset);
250                                 continue;
251                         }
252                         if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
253                                         >= conn->sess->sess_ops->FirstBurstLength) {
254                                 unsolicited_data_length -=
255                                         (conn->sess->sess_ops->FirstBurstLength -
256                                         offset);
257                                 offset += (conn->sess->sess_ops->FirstBurstLength -
258                                         offset);
259                                 burstlength = 0;
260                                 *seq_count += 1;
261                                 continue;
262                         }
263
264                         offset += conn->conn_ops->MaxRecvDataSegmentLength;
265                         unsolicited_data_length -=
266                                 conn->conn_ops->MaxRecvDataSegmentLength;
267                         continue;
268                 }
269                 if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
270                      cmd->se_cmd.data_length) {
271                         offset += (cmd->se_cmd.data_length - offset);
272                         continue;
273                 }
274                 if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
275                      conn->sess->sess_ops->MaxBurstLength) {
276                         offset += (conn->sess->sess_ops->MaxBurstLength -
277                                         burstlength);
278                         burstlength = 0;
279                         *seq_count += 1;
280                         continue;
281                 }
282
283                 burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
284                 offset += conn->conn_ops->MaxRecvDataSegmentLength;
285         }
286 }
287
288
289 /*
290  *      Builds PDU and/or Sequence list,  called while DataSequenceInOrder=No
291  *      and DataPDUInOrder=No.
292  */
293 static int iscsit_build_pdu_and_seq_list(
294         struct iscsi_cmd *cmd,
295         struct iscsi_build_list *bl)
296 {
297         int check_immediate = 0, datapduinorder, datasequenceinorder;
298         u32 burstlength = 0, offset = 0, i = 0;
299         u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
300         struct iscsi_conn *conn = cmd->conn;
301         struct iscsi_pdu *pdu = cmd->pdu_list;
302         struct iscsi_seq *seq = cmd->seq_list;
303
304         datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
305         datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
306
307         if ((bl->type == PDULIST_IMMEDIATE) ||
308             (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
309                 check_immediate = 1;
310
311         if ((bl->type == PDULIST_UNSOLICITED) ||
312             (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
313                 unsolicited_data_length = min(cmd->se_cmd.data_length,
314                         conn->sess->sess_ops->FirstBurstLength);
315
316         while (offset < cmd->se_cmd.data_length) {
317                 pdu_count++;
318                 if (!datapduinorder) {
319                         pdu[i].offset = offset;
320                         pdu[i].seq_no = seq_no;
321                 }
322                 if (!datasequenceinorder && (pdu_count == 1)) {
323                         seq[seq_no].pdu_start = i;
324                         seq[seq_no].seq_no = seq_no;
325                         seq[seq_no].offset = offset;
326                         seq[seq_no].orig_offset = offset;
327                 }
328
329                 if (check_immediate) {
330                         check_immediate = 0;
331                         if (!datapduinorder) {
332                                 pdu[i].type = PDUTYPE_IMMEDIATE;
333                                 pdu[i++].length = bl->immediate_data_length;
334                         }
335                         if (!datasequenceinorder) {
336                                 seq[seq_no].type = SEQTYPE_IMMEDIATE;
337                                 seq[seq_no].pdu_count = 1;
338                                 seq[seq_no].xfer_len =
339                                         bl->immediate_data_length;
340                         }
341                         offset += bl->immediate_data_length;
342                         pdu_count = 0;
343                         seq_no++;
344                         if (unsolicited_data_length)
345                                 unsolicited_data_length -=
346                                         bl->immediate_data_length;
347                         continue;
348                 }
349                 if (unsolicited_data_length > 0) {
350                         if ((offset +
351                              conn->conn_ops->MaxRecvDataSegmentLength) >=
352                              cmd->se_cmd.data_length) {
353                                 if (!datapduinorder) {
354                                         pdu[i].type = PDUTYPE_UNSOLICITED;
355                                         pdu[i].length =
356                                                 (cmd->se_cmd.data_length - offset);
357                                 }
358                                 if (!datasequenceinorder) {
359                                         seq[seq_no].type = SEQTYPE_UNSOLICITED;
360                                         seq[seq_no].pdu_count = pdu_count;
361                                         seq[seq_no].xfer_len = (burstlength +
362                                                 (cmd->se_cmd.data_length - offset));
363                                 }
364                                 unsolicited_data_length -=
365                                                 (cmd->se_cmd.data_length - offset);
366                                 offset += (cmd->se_cmd.data_length - offset);
367                                 continue;
368                         }
369                         if ((offset +
370                              conn->conn_ops->MaxRecvDataSegmentLength) >=
371                                         conn->sess->sess_ops->FirstBurstLength) {
372                                 if (!datapduinorder) {
373                                         pdu[i].type = PDUTYPE_UNSOLICITED;
374                                         pdu[i++].length =
375                                            (conn->sess->sess_ops->FirstBurstLength -
376                                                 offset);
377                                 }
378                                 if (!datasequenceinorder) {
379                                         seq[seq_no].type = SEQTYPE_UNSOLICITED;
380                                         seq[seq_no].pdu_count = pdu_count;
381                                         seq[seq_no].xfer_len = (burstlength +
382                                            (conn->sess->sess_ops->FirstBurstLength -
383                                                 offset));
384                                 }
385                                 unsolicited_data_length -=
386                                         (conn->sess->sess_ops->FirstBurstLength -
387                                                 offset);
388                                 offset += (conn->sess->sess_ops->FirstBurstLength -
389                                                 offset);
390                                 burstlength = 0;
391                                 pdu_count = 0;
392                                 seq_no++;
393                                 continue;
394                         }
395
396                         if (!datapduinorder) {
397                                 pdu[i].type = PDUTYPE_UNSOLICITED;
398                                 pdu[i++].length =
399                                      conn->conn_ops->MaxRecvDataSegmentLength;
400                         }
401                         burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
402                         offset += conn->conn_ops->MaxRecvDataSegmentLength;
403                         unsolicited_data_length -=
404                                 conn->conn_ops->MaxRecvDataSegmentLength;
405                         continue;
406                 }
407                 if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
408                      cmd->se_cmd.data_length) {
409                         if (!datapduinorder) {
410                                 pdu[i].type = PDUTYPE_NORMAL;
411                                 pdu[i].length = (cmd->se_cmd.data_length - offset);
412                         }
413                         if (!datasequenceinorder) {
414                                 seq[seq_no].type = SEQTYPE_NORMAL;
415                                 seq[seq_no].pdu_count = pdu_count;
416                                 seq[seq_no].xfer_len = (burstlength +
417                                         (cmd->se_cmd.data_length - offset));
418                         }
419                         offset += (cmd->se_cmd.data_length - offset);
420                         continue;
421                 }
422                 if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
423                      conn->sess->sess_ops->MaxBurstLength) {
424                         if (!datapduinorder) {
425                                 pdu[i].type = PDUTYPE_NORMAL;
426                                 pdu[i++].length =
427                                         (conn->sess->sess_ops->MaxBurstLength -
428                                                 burstlength);
429                         }
430                         if (!datasequenceinorder) {
431                                 seq[seq_no].type = SEQTYPE_NORMAL;
432                                 seq[seq_no].pdu_count = pdu_count;
433                                 seq[seq_no].xfer_len = (burstlength +
434                                         (conn->sess->sess_ops->MaxBurstLength -
435                                         burstlength));
436                         }
437                         offset += (conn->sess->sess_ops->MaxBurstLength -
438                                         burstlength);
439                         burstlength = 0;
440                         pdu_count = 0;
441                         seq_no++;
442                         continue;
443                 }
444
445                 if (!datapduinorder) {
446                         pdu[i].type = PDUTYPE_NORMAL;
447                         pdu[i++].length =
448                                 conn->conn_ops->MaxRecvDataSegmentLength;
449                 }
450                 burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
451                 offset += conn->conn_ops->MaxRecvDataSegmentLength;
452         }
453
454         if (!datasequenceinorder) {
455                 if (bl->data_direction & ISCSI_PDU_WRITE) {
456                         if (bl->randomize & RANDOM_R2T_OFFSETS) {
457                                 if (iscsit_randomize_seq_lists(cmd, bl->type)
458                                                 < 0)
459                                         return -1;
460                         } else
461                                 iscsit_ordered_seq_lists(cmd, bl->type);
462                 } else if (bl->data_direction & ISCSI_PDU_READ) {
463                         if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) {
464                                 if (iscsit_randomize_seq_lists(cmd, bl->type)
465                                                 < 0)
466                                         return -1;
467                         } else
468                                 iscsit_ordered_seq_lists(cmd, bl->type);
469                 }
470
471                 iscsit_dump_seq_list(cmd);
472         }
473         if (!datapduinorder) {
474                 if (bl->data_direction & ISCSI_PDU_WRITE) {
475                         if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) {
476                                 if (iscsit_randomize_pdu_lists(cmd, bl->type)
477                                                 < 0)
478                                         return -1;
479                         } else
480                                 iscsit_ordered_pdu_lists(cmd, bl->type);
481                 } else if (bl->data_direction & ISCSI_PDU_READ) {
482                         if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) {
483                                 if (iscsit_randomize_pdu_lists(cmd, bl->type)
484                                                 < 0)
485                                         return -1;
486                         } else
487                                 iscsit_ordered_pdu_lists(cmd, bl->type);
488                 }
489
490                 iscsit_dump_pdu_list(cmd);
491         }
492
493         return 0;
494 }
495
496 /*
497  *      Only called while DataSequenceInOrder=No or DataPDUInOrder=No.
498  */
499 int iscsit_do_build_list(
500         struct iscsi_cmd *cmd,
501         struct iscsi_build_list *bl)
502 {
503         u32 pdu_count = 0, seq_count = 1;
504         struct iscsi_conn *conn = cmd->conn;
505         struct iscsi_pdu *pdu = NULL;
506         struct iscsi_seq *seq = NULL;
507
508         iscsit_determine_counts_for_list(cmd, bl, &seq_count, &pdu_count);
509
510         if (!conn->sess->sess_ops->DataSequenceInOrder) {
511                 seq = kzalloc(seq_count * sizeof(struct iscsi_seq), GFP_ATOMIC);
512                 if (!seq) {
513                         pr_err("Unable to allocate struct iscsi_seq list\n");
514                         return -1;
515                 }
516                 cmd->seq_list = seq;
517                 cmd->seq_count = seq_count;
518         }
519
520         if (!conn->sess->sess_ops->DataPDUInOrder) {
521                 pdu = kzalloc(pdu_count * sizeof(struct iscsi_pdu), GFP_ATOMIC);
522                 if (!pdu) {
523                         pr_err("Unable to allocate struct iscsi_pdu list.\n");
524                         kfree(seq);
525                         return -1;
526                 }
527                 cmd->pdu_list = pdu;
528                 cmd->pdu_count = pdu_count;
529         }
530
531         return iscsit_build_pdu_and_seq_list(cmd, bl);
532 }
533
534 struct iscsi_pdu *iscsit_get_pdu_holder(
535         struct iscsi_cmd *cmd,
536         u32 offset,
537         u32 length)
538 {
539         u32 i;
540         struct iscsi_pdu *pdu = NULL;
541
542         if (!cmd->pdu_list) {
543                 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
544                 return NULL;
545         }
546
547         pdu = &cmd->pdu_list[0];
548
549         for (i = 0; i < cmd->pdu_count; i++)
550                 if ((pdu[i].offset == offset) && (pdu[i].length == length))
551                         return &pdu[i];
552
553         pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
554                 " %u, Length: %u\n", cmd->init_task_tag, offset, length);
555         return NULL;
556 }
557
558 struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
559         struct iscsi_cmd *cmd,
560         struct iscsi_seq *seq)
561 {
562         u32 i;
563         struct iscsi_conn *conn = cmd->conn;
564         struct iscsi_pdu *pdu = NULL;
565
566         if (!cmd->pdu_list) {
567                 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
568                 return NULL;
569         }
570
571         if (conn->sess->sess_ops->DataSequenceInOrder) {
572 redo:
573                 pdu = &cmd->pdu_list[cmd->pdu_start];
574
575                 for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
576                         pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
577                                 "_send_order: %d, pdu[i].offset: %d,"
578                                 " pdu[i].length: %d\n", pdu[i].seq_no,
579                                 pdu[i].pdu_send_order, pdu[i].offset,
580                                 pdu[i].length);
581
582                         if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
583                                 cmd->pdu_send_order++;
584                                 return &pdu[i];
585                         }
586                 }
587
588                 cmd->pdu_start += cmd->pdu_send_order;
589                 cmd->pdu_send_order = 0;
590                 cmd->seq_no++;
591
592                 if (cmd->pdu_start < cmd->pdu_count)
593                         goto redo;
594
595                 pr_err("Command ITT: 0x%08x unable to locate"
596                         " struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
597                         cmd->init_task_tag, cmd->pdu_send_order);
598                 return NULL;
599         } else {
600                 if (!seq) {
601                         pr_err("struct iscsi_seq is NULL!\n");
602                         return NULL;
603                 }
604
605                 pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
606                         " seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
607                         seq->seq_no);
608
609                 pdu = &cmd->pdu_list[seq->pdu_start];
610
611                 if (seq->pdu_send_order == seq->pdu_count) {
612                         pr_err("Command ITT: 0x%08x seq->pdu_send"
613                                 "_order: %u equals seq->pdu_count: %u\n",
614                                 cmd->init_task_tag, seq->pdu_send_order,
615                                 seq->pdu_count);
616                         return NULL;
617                 }
618
619                 for (i = 0; i < seq->pdu_count; i++) {
620                         if (pdu[i].pdu_send_order == seq->pdu_send_order) {
621                                 seq->pdu_send_order++;
622                                 return &pdu[i];
623                         }
624                 }
625
626                 pr_err("Command ITT: 0x%08x unable to locate iscsi"
627                         "_pdu_t for seq->pdu_send_order: %u.\n",
628                         cmd->init_task_tag, seq->pdu_send_order);
629                 return NULL;
630         }
631
632         return NULL;
633 }
634
635 struct iscsi_seq *iscsit_get_seq_holder(
636         struct iscsi_cmd *cmd,
637         u32 offset,
638         u32 length)
639 {
640         u32 i;
641
642         if (!cmd->seq_list) {
643                 pr_err("struct iscsi_cmd->seq_list is NULL!\n");
644                 return NULL;
645         }
646
647         for (i = 0; i < cmd->seq_count; i++) {
648                 pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
649                         "xfer_len: %d, seq_list[i].seq_no %u\n",
650                         cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
651                         cmd->seq_list[i].seq_no);
652
653                 if ((cmd->seq_list[i].orig_offset +
654                                 cmd->seq_list[i].xfer_len) >=
655                                 (offset + length))
656                         return &cmd->seq_list[i];
657         }
658
659         pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
660                 " Offset: %u, Length: %u\n", cmd->init_task_tag, offset,
661                 length);
662         return NULL;
663 }