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