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