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