• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define OFFLOAD_BUF_SIZE	32768
29 
30 #ifdef DEBUG
iscsit_dump_seq_list(struct iscsi_cmd * cmd)31 static void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
32 {
33 	int i;
34 	struct iscsi_seq *seq;
35 
36 	pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
37 			cmd->init_task_tag);
38 
39 	for (i = 0; i < cmd->seq_count; i++) {
40 		seq = &cmd->seq_list[i];
41 		pr_debug("i: %d, pdu_start: %d, pdu_count: %d,"
42 			" offset: %d, xfer_len: %d, seq_send_order: %d,"
43 			" seq_no: %d\n", i, seq->pdu_start, seq->pdu_count,
44 			seq->offset, seq->xfer_len, seq->seq_send_order,
45 			seq->seq_no);
46 	}
47 }
48 
iscsit_dump_pdu_list(struct iscsi_cmd * cmd)49 static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
50 {
51 	int i;
52 	struct iscsi_pdu *pdu;
53 
54 	pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
55 			cmd->init_task_tag);
56 
57 	for (i = 0; i < cmd->pdu_count; i++) {
58 		pdu = &cmd->pdu_list[i];
59 		pr_debug("i: %d, offset: %d, length: %d,"
60 			" pdu_send_order: %d, seq_no: %d\n", i, pdu->offset,
61 			pdu->length, pdu->pdu_send_order, pdu->seq_no);
62 	}
63 }
64 #else
iscsit_dump_seq_list(struct iscsi_cmd * cmd)65 static void iscsit_dump_seq_list(struct iscsi_cmd *cmd) {}
iscsit_dump_pdu_list(struct iscsi_cmd * cmd)66 static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd) {}
67 #endif
68 
iscsit_ordered_seq_lists(struct iscsi_cmd * cmd,u8 type)69 static void iscsit_ordered_seq_lists(
70 	struct iscsi_cmd *cmd,
71 	u8 type)
72 {
73 	u32 i, seq_count = 0;
74 
75 	for (i = 0; i < cmd->seq_count; i++) {
76 		if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
77 			continue;
78 		cmd->seq_list[i].seq_send_order = seq_count++;
79 	}
80 }
81 
iscsit_ordered_pdu_lists(struct iscsi_cmd * cmd,u8 type)82 static void iscsit_ordered_pdu_lists(
83 	struct iscsi_cmd *cmd,
84 	u8 type)
85 {
86 	u32 i, pdu_send_order = 0, seq_no = 0;
87 
88 	for (i = 0; i < cmd->pdu_count; i++) {
89 redo:
90 		if (cmd->pdu_list[i].seq_no == seq_no) {
91 			cmd->pdu_list[i].pdu_send_order = pdu_send_order++;
92 			continue;
93 		}
94 		seq_no++;
95 		pdu_send_order = 0;
96 		goto redo;
97 	}
98 }
99 
100 /*
101  *	Generate count random values into array.
102  *	Use 0x80000000 to mark generates valued in array[].
103  */
iscsit_create_random_array(u32 * array,u32 count)104 static void iscsit_create_random_array(u32 *array, u32 count)
105 {
106 	int i, j, k;
107 
108 	if (count == 1) {
109 		array[0] = 0;
110 		return;
111 	}
112 
113 	for (i = 0; i < count; i++) {
114 redo:
115 		get_random_bytes(&j, sizeof(u32));
116 		j = (1 + (int) (9999 + 1) - j) % count;
117 		for (k = 0; k < i + 1; k++) {
118 			j |= 0x80000000;
119 			if ((array[k] & 0x80000000) && (array[k] == j))
120 				goto redo;
121 		}
122 		array[i] = j;
123 	}
124 
125 	for (i = 0; i < count; i++)
126 		array[i] &= ~0x80000000;
127 }
128 
iscsit_randomize_pdu_lists(struct iscsi_cmd * cmd,u8 type)129 static int iscsit_randomize_pdu_lists(
130 	struct iscsi_cmd *cmd,
131 	u8 type)
132 {
133 	int i = 0;
134 	u32 *array, pdu_count, seq_count = 0, seq_no = 0, seq_offset = 0;
135 
136 	for (pdu_count = 0; pdu_count < cmd->pdu_count; pdu_count++) {
137 redo:
138 		if (cmd->pdu_list[pdu_count].seq_no == seq_no) {
139 			seq_count++;
140 			continue;
141 		}
142 		array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
143 		if (!array) {
144 			pr_err("Unable to allocate memory"
145 				" for random array.\n");
146 			return -ENOMEM;
147 		}
148 		iscsit_create_random_array(array, seq_count);
149 
150 		for (i = 0; i < seq_count; i++)
151 			cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
152 
153 		kfree(array);
154 
155 		seq_offset += seq_count;
156 		seq_count = 0;
157 		seq_no++;
158 		goto redo;
159 	}
160 
161 	if (seq_count) {
162 		array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
163 		if (!array) {
164 			pr_err("Unable to allocate memory for"
165 				" random array.\n");
166 			return -ENOMEM;
167 		}
168 		iscsit_create_random_array(array, seq_count);
169 
170 		for (i = 0; i < seq_count; i++)
171 			cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
172 
173 		kfree(array);
174 	}
175 
176 	return 0;
177 }
178 
iscsit_randomize_seq_lists(struct iscsi_cmd * cmd,u8 type)179 static int iscsit_randomize_seq_lists(
180 	struct iscsi_cmd *cmd,
181 	u8 type)
182 {
183 	int i, j = 0;
184 	u32 *array, seq_count = cmd->seq_count;
185 
186 	if ((type == PDULIST_IMMEDIATE) || (type == PDULIST_UNSOLICITED))
187 		seq_count--;
188 	else if (type == PDULIST_IMMEDIATE_AND_UNSOLICITED)
189 		seq_count -= 2;
190 
191 	if (!seq_count)
192 		return 0;
193 
194 	array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
195 	if (!array) {
196 		pr_err("Unable to allocate memory for random array.\n");
197 		return -ENOMEM;
198 	}
199 	iscsit_create_random_array(array, seq_count);
200 
201 	for (i = 0; i < cmd->seq_count; i++) {
202 		if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
203 			continue;
204 		cmd->seq_list[i].seq_send_order = array[j++];
205 	}
206 
207 	kfree(array);
208 	return 0;
209 }
210 
iscsit_determine_counts_for_list(struct iscsi_cmd * cmd,struct iscsi_build_list * bl,u32 * seq_count,u32 * pdu_count)211 static void iscsit_determine_counts_for_list(
212 	struct iscsi_cmd *cmd,
213 	struct iscsi_build_list *bl,
214 	u32 *seq_count,
215 	u32 *pdu_count)
216 {
217 	int check_immediate = 0;
218 	u32 burstlength = 0, offset = 0;
219 	u32 unsolicited_data_length = 0;
220 	u32 mdsl;
221 	struct iscsi_conn *conn = cmd->conn;
222 
223 	if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
224 		mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
225 	else
226 		mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
227 
228 	if ((bl->type == PDULIST_IMMEDIATE) ||
229 	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
230 		check_immediate = 1;
231 
232 	if ((bl->type == PDULIST_UNSOLICITED) ||
233 	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
234 		unsolicited_data_length = min(cmd->se_cmd.data_length,
235 			conn->sess->sess_ops->FirstBurstLength);
236 
237 	while (offset < cmd->se_cmd.data_length) {
238 		*pdu_count += 1;
239 
240 		if (check_immediate) {
241 			check_immediate = 0;
242 			offset += bl->immediate_data_length;
243 			*seq_count += 1;
244 			if (unsolicited_data_length)
245 				unsolicited_data_length -=
246 					bl->immediate_data_length;
247 			continue;
248 		}
249 		if (unsolicited_data_length > 0) {
250 			if ((offset + mdsl) >= cmd->se_cmd.data_length) {
251 				unsolicited_data_length -=
252 					(cmd->se_cmd.data_length - offset);
253 				offset += (cmd->se_cmd.data_length - offset);
254 				continue;
255 			}
256 			if ((offset + mdsl)
257 					>= conn->sess->sess_ops->FirstBurstLength) {
258 				unsolicited_data_length -=
259 					(conn->sess->sess_ops->FirstBurstLength -
260 					offset);
261 				offset += (conn->sess->sess_ops->FirstBurstLength -
262 					offset);
263 				burstlength = 0;
264 				*seq_count += 1;
265 				continue;
266 			}
267 
268 			offset += mdsl;
269 			unsolicited_data_length -= mdsl;
270 			continue;
271 		}
272 		if ((offset + mdsl) >= cmd->se_cmd.data_length) {
273 			offset += (cmd->se_cmd.data_length - offset);
274 			continue;
275 		}
276 		if ((burstlength + mdsl) >=
277 		     conn->sess->sess_ops->MaxBurstLength) {
278 			offset += (conn->sess->sess_ops->MaxBurstLength -
279 					burstlength);
280 			burstlength = 0;
281 			*seq_count += 1;
282 			continue;
283 		}
284 
285 		burstlength += mdsl;
286 		offset += mdsl;
287 	}
288 }
289 
290 
291 /*
292  *	Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
293  *	or DataPDUInOrder=No.
294  */
iscsit_do_build_pdu_and_seq_lists(struct iscsi_cmd * cmd,struct iscsi_build_list * bl)295 static int iscsit_do_build_pdu_and_seq_lists(
296 	struct iscsi_cmd *cmd,
297 	struct iscsi_build_list *bl)
298 {
299 	int check_immediate = 0, datapduinorder, datasequenceinorder;
300 	u32 burstlength = 0, offset = 0, i = 0, mdsl;
301 	u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
302 	struct iscsi_conn *conn = cmd->conn;
303 	struct iscsi_pdu *pdu = cmd->pdu_list;
304 	struct iscsi_seq *seq = cmd->seq_list;
305 
306 	if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
307 		mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
308 	else
309 		mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
310 
311 	datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
312 	datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
313 
314 	if ((bl->type == PDULIST_IMMEDIATE) ||
315 	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
316 		check_immediate = 1;
317 
318 	if ((bl->type == PDULIST_UNSOLICITED) ||
319 	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
320 		unsolicited_data_length = min(cmd->se_cmd.data_length,
321 			conn->sess->sess_ops->FirstBurstLength);
322 
323 	while (offset < cmd->se_cmd.data_length) {
324 		pdu_count++;
325 		if (!datapduinorder) {
326 			pdu[i].offset = offset;
327 			pdu[i].seq_no = seq_no;
328 		}
329 		if (!datasequenceinorder && (pdu_count == 1)) {
330 			seq[seq_no].pdu_start = i;
331 			seq[seq_no].seq_no = seq_no;
332 			seq[seq_no].offset = offset;
333 			seq[seq_no].orig_offset = offset;
334 		}
335 
336 		if (check_immediate) {
337 			check_immediate = 0;
338 			if (!datapduinorder) {
339 				pdu[i].type = PDUTYPE_IMMEDIATE;
340 				pdu[i++].length = bl->immediate_data_length;
341 			}
342 			if (!datasequenceinorder) {
343 				seq[seq_no].type = SEQTYPE_IMMEDIATE;
344 				seq[seq_no].pdu_count = 1;
345 				seq[seq_no].xfer_len =
346 					bl->immediate_data_length;
347 			}
348 			offset += bl->immediate_data_length;
349 			pdu_count = 0;
350 			seq_no++;
351 			if (unsolicited_data_length)
352 				unsolicited_data_length -=
353 					bl->immediate_data_length;
354 			continue;
355 		}
356 		if (unsolicited_data_length > 0) {
357 			if ((offset + mdsl) >= cmd->se_cmd.data_length) {
358 				if (!datapduinorder) {
359 					pdu[i].type = PDUTYPE_UNSOLICITED;
360 					pdu[i].length =
361 						(cmd->se_cmd.data_length - offset);
362 				}
363 				if (!datasequenceinorder) {
364 					seq[seq_no].type = SEQTYPE_UNSOLICITED;
365 					seq[seq_no].pdu_count = pdu_count;
366 					seq[seq_no].xfer_len = (burstlength +
367 						(cmd->se_cmd.data_length - offset));
368 				}
369 				unsolicited_data_length -=
370 						(cmd->se_cmd.data_length - offset);
371 				offset += (cmd->se_cmd.data_length - offset);
372 				continue;
373 			}
374 			if ((offset + mdsl) >=
375 					conn->sess->sess_ops->FirstBurstLength) {
376 				if (!datapduinorder) {
377 					pdu[i].type = PDUTYPE_UNSOLICITED;
378 					pdu[i++].length =
379 					   (conn->sess->sess_ops->FirstBurstLength -
380 						offset);
381 				}
382 				if (!datasequenceinorder) {
383 					seq[seq_no].type = SEQTYPE_UNSOLICITED;
384 					seq[seq_no].pdu_count = pdu_count;
385 					seq[seq_no].xfer_len = (burstlength +
386 					   (conn->sess->sess_ops->FirstBurstLength -
387 						offset));
388 				}
389 				unsolicited_data_length -=
390 					(conn->sess->sess_ops->FirstBurstLength -
391 						offset);
392 				offset += (conn->sess->sess_ops->FirstBurstLength -
393 						offset);
394 				burstlength = 0;
395 				pdu_count = 0;
396 				seq_no++;
397 				continue;
398 			}
399 
400 			if (!datapduinorder) {
401 				pdu[i].type = PDUTYPE_UNSOLICITED;
402 				pdu[i++].length = mdsl;
403 			}
404 			burstlength += mdsl;
405 			offset += mdsl;
406 			unsolicited_data_length -= mdsl;
407 			continue;
408 		}
409 		if ((offset + mdsl) >= cmd->se_cmd.data_length) {
410 			if (!datapduinorder) {
411 				pdu[i].type = PDUTYPE_NORMAL;
412 				pdu[i].length = (cmd->se_cmd.data_length - offset);
413 			}
414 			if (!datasequenceinorder) {
415 				seq[seq_no].type = SEQTYPE_NORMAL;
416 				seq[seq_no].pdu_count = pdu_count;
417 				seq[seq_no].xfer_len = (burstlength +
418 					(cmd->se_cmd.data_length - offset));
419 			}
420 			offset += (cmd->se_cmd.data_length - offset);
421 			continue;
422 		}
423 		if ((burstlength + mdsl) >=
424 		     conn->sess->sess_ops->MaxBurstLength) {
425 			if (!datapduinorder) {
426 				pdu[i].type = PDUTYPE_NORMAL;
427 				pdu[i++].length =
428 					(conn->sess->sess_ops->MaxBurstLength -
429 						burstlength);
430 			}
431 			if (!datasequenceinorder) {
432 				seq[seq_no].type = SEQTYPE_NORMAL;
433 				seq[seq_no].pdu_count = pdu_count;
434 				seq[seq_no].xfer_len = (burstlength +
435 					(conn->sess->sess_ops->MaxBurstLength -
436 					burstlength));
437 			}
438 			offset += (conn->sess->sess_ops->MaxBurstLength -
439 					burstlength);
440 			burstlength = 0;
441 			pdu_count = 0;
442 			seq_no++;
443 			continue;
444 		}
445 
446 		if (!datapduinorder) {
447 			pdu[i].type = PDUTYPE_NORMAL;
448 			pdu[i++].length = mdsl;
449 		}
450 		burstlength += mdsl;
451 		offset += mdsl;
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 
iscsit_build_pdu_and_seq_lists(struct iscsi_cmd * cmd,u32 immediate_data_length)496 int iscsit_build_pdu_and_seq_lists(
497 	struct iscsi_cmd *cmd,
498 	u32 immediate_data_length)
499 {
500 	struct iscsi_build_list bl;
501 	u32 pdu_count = 0, seq_count = 1;
502 	struct iscsi_conn *conn = cmd->conn;
503 	struct iscsi_pdu *pdu = NULL;
504 	struct iscsi_seq *seq = NULL;
505 
506 	struct iscsi_session *sess = conn->sess;
507 	struct iscsi_node_attrib *na;
508 
509 	/*
510 	 * Do nothing if no OOO shenanigans
511 	 */
512 	if (sess->sess_ops->DataSequenceInOrder &&
513 	    sess->sess_ops->DataPDUInOrder)
514 		return 0;
515 
516 	if (cmd->data_direction == DMA_NONE)
517 		return 0;
518 
519 	na = iscsit_tpg_get_node_attrib(sess);
520 	memset(&bl, 0, sizeof(struct iscsi_build_list));
521 
522 	if (cmd->data_direction == DMA_FROM_DEVICE) {
523 		bl.data_direction = ISCSI_PDU_READ;
524 		bl.type = PDULIST_NORMAL;
525 		if (na->random_datain_pdu_offsets)
526 			bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
527 		if (na->random_datain_seq_offsets)
528 			bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
529 	} else {
530 		bl.data_direction = ISCSI_PDU_WRITE;
531 		bl.immediate_data_length = immediate_data_length;
532 		if (na->random_r2t_offsets)
533 			bl.randomize |= RANDOM_R2T_OFFSETS;
534 
535 		if (!cmd->immediate_data && !cmd->unsolicited_data)
536 			bl.type = PDULIST_NORMAL;
537 		else if (cmd->immediate_data && !cmd->unsolicited_data)
538 			bl.type = PDULIST_IMMEDIATE;
539 		else if (!cmd->immediate_data && cmd->unsolicited_data)
540 			bl.type = PDULIST_UNSOLICITED;
541 		else if (cmd->immediate_data && cmd->unsolicited_data)
542 			bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
543 	}
544 
545 	iscsit_determine_counts_for_list(cmd, &bl, &seq_count, &pdu_count);
546 
547 	if (!conn->sess->sess_ops->DataSequenceInOrder) {
548 		seq = kcalloc(seq_count, sizeof(struct iscsi_seq), GFP_ATOMIC);
549 		if (!seq) {
550 			pr_err("Unable to allocate struct iscsi_seq list\n");
551 			return -ENOMEM;
552 		}
553 		cmd->seq_list = seq;
554 		cmd->seq_count = seq_count;
555 	}
556 
557 	if (!conn->sess->sess_ops->DataPDUInOrder) {
558 		pdu = kcalloc(pdu_count, sizeof(struct iscsi_pdu), GFP_ATOMIC);
559 		if (!pdu) {
560 			pr_err("Unable to allocate struct iscsi_pdu list.\n");
561 			kfree(seq);
562 			return -ENOMEM;
563 		}
564 		cmd->pdu_list = pdu;
565 		cmd->pdu_count = pdu_count;
566 	}
567 
568 	return iscsit_do_build_pdu_and_seq_lists(cmd, &bl);
569 }
570 
iscsit_get_pdu_holder(struct iscsi_cmd * cmd,u32 offset,u32 length)571 struct iscsi_pdu *iscsit_get_pdu_holder(
572 	struct iscsi_cmd *cmd,
573 	u32 offset,
574 	u32 length)
575 {
576 	u32 i;
577 	struct iscsi_pdu *pdu = NULL;
578 
579 	if (!cmd->pdu_list) {
580 		pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
581 		return NULL;
582 	}
583 
584 	pdu = &cmd->pdu_list[0];
585 
586 	for (i = 0; i < cmd->pdu_count; i++)
587 		if ((pdu[i].offset == offset) && (pdu[i].length == length))
588 			return &pdu[i];
589 
590 	pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
591 		" %u, Length: %u\n", cmd->init_task_tag, offset, length);
592 	return NULL;
593 }
594 
iscsit_get_pdu_holder_for_seq(struct iscsi_cmd * cmd,struct iscsi_seq * seq)595 struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
596 	struct iscsi_cmd *cmd,
597 	struct iscsi_seq *seq)
598 {
599 	u32 i;
600 	struct iscsi_conn *conn = cmd->conn;
601 	struct iscsi_pdu *pdu = NULL;
602 
603 	if (!cmd->pdu_list) {
604 		pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
605 		return NULL;
606 	}
607 
608 	if (conn->sess->sess_ops->DataSequenceInOrder) {
609 redo:
610 		pdu = &cmd->pdu_list[cmd->pdu_start];
611 
612 		for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
613 			pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
614 				"_send_order: %d, pdu[i].offset: %d,"
615 				" pdu[i].length: %d\n", pdu[i].seq_no,
616 				pdu[i].pdu_send_order, pdu[i].offset,
617 				pdu[i].length);
618 
619 			if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
620 				cmd->pdu_send_order++;
621 				return &pdu[i];
622 			}
623 		}
624 
625 		cmd->pdu_start += cmd->pdu_send_order;
626 		cmd->pdu_send_order = 0;
627 		cmd->seq_no++;
628 
629 		if (cmd->pdu_start < cmd->pdu_count)
630 			goto redo;
631 
632 		pr_err("Command ITT: 0x%08x unable to locate"
633 			" struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
634 			cmd->init_task_tag, cmd->pdu_send_order);
635 		return NULL;
636 	} else {
637 		if (!seq) {
638 			pr_err("struct iscsi_seq is NULL!\n");
639 			return NULL;
640 		}
641 
642 		pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
643 			" seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
644 			seq->seq_no);
645 
646 		pdu = &cmd->pdu_list[seq->pdu_start];
647 
648 		if (seq->pdu_send_order == seq->pdu_count) {
649 			pr_err("Command ITT: 0x%08x seq->pdu_send"
650 				"_order: %u equals seq->pdu_count: %u\n",
651 				cmd->init_task_tag, seq->pdu_send_order,
652 				seq->pdu_count);
653 			return NULL;
654 		}
655 
656 		for (i = 0; i < seq->pdu_count; i++) {
657 			if (pdu[i].pdu_send_order == seq->pdu_send_order) {
658 				seq->pdu_send_order++;
659 				return &pdu[i];
660 			}
661 		}
662 
663 		pr_err("Command ITT: 0x%08x unable to locate iscsi"
664 			"_pdu_t for seq->pdu_send_order: %u.\n",
665 			cmd->init_task_tag, seq->pdu_send_order);
666 		return NULL;
667 	}
668 
669 	return NULL;
670 }
671 
iscsit_get_seq_holder(struct iscsi_cmd * cmd,u32 offset,u32 length)672 struct iscsi_seq *iscsit_get_seq_holder(
673 	struct iscsi_cmd *cmd,
674 	u32 offset,
675 	u32 length)
676 {
677 	u32 i;
678 
679 	if (!cmd->seq_list) {
680 		pr_err("struct iscsi_cmd->seq_list is NULL!\n");
681 		return NULL;
682 	}
683 
684 	for (i = 0; i < cmd->seq_count; i++) {
685 		pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
686 			"xfer_len: %d, seq_list[i].seq_no %u\n",
687 			cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
688 			cmd->seq_list[i].seq_no);
689 
690 		if ((cmd->seq_list[i].orig_offset +
691 				cmd->seq_list[i].xfer_len) >=
692 				(offset + length))
693 			return &cmd->seq_list[i];
694 	}
695 
696 	pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
697 		" Offset: %u, Length: %u\n", cmd->init_task_tag, offset,
698 		length);
699 	return NULL;
700 }
701