1275970Scy// SPDX-License-Identifier: GPL-2.0-or-later 2275970Scy/******************************************************************************* 3275970Scy * This file contains main functions related to iSCSI DataSequenceInOrder=No 4275970Scy * and DataPDUInOrder=No. 5275970Scy * 6275970Scy * (c) Copyright 2007-2013 Datera, Inc. 7275970Scy * 8275970Scy * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 9275970Scy * 10275970Scy ******************************************************************************/ 11275970Scy 12275970Scy#include <linux/slab.h> 13275970Scy#include <linux/random.h> 14275970Scy 15275970Scy#include <target/iscsi/iscsi_target_core.h> 16275970Scy#include "iscsi_target_util.h" 17275970Scy#include "iscsi_target_tpg.h" 18275970Scy#include "iscsi_target_seq_pdu_list.h" 19275970Scy 20275970Scy#ifdef DEBUG 21275970Scystatic void iscsit_dump_seq_list(struct iscsit_cmd *cmd) 22275970Scy{ 23275970Scy int i; 24275970Scy struct iscsi_seq *seq; 25275970Scy 26275970Scy pr_debug("Dumping Sequence List for ITT: 0x%08x:\n", 27275970Scy cmd->init_task_tag); 28275970Scy 29275970Scy for (i = 0; i < cmd->seq_count; i++) { 30275970Scy seq = &cmd->seq_list[i]; 31275970Scy pr_debug("i: %d, pdu_start: %d, pdu_count: %d," 32275970Scy " offset: %d, xfer_len: %d, seq_send_order: %d," 33275970Scy " seq_no: %d\n", i, seq->pdu_start, seq->pdu_count, 34275970Scy seq->offset, seq->xfer_len, seq->seq_send_order, 35275970Scy seq->seq_no); 36275970Scy } 37275970Scy} 38275970Scy 39275970Scystatic void iscsit_dump_pdu_list(struct iscsit_cmd *cmd) 40275970Scy{ 41275970Scy int i; 42275970Scy struct iscsi_pdu *pdu; 43275970Scy 44275970Scy pr_debug("Dumping PDU List for ITT: 0x%08x:\n", 45275970Scy cmd->init_task_tag); 46275970Scy 47275970Scy for (i = 0; i < cmd->pdu_count; i++) { 48275970Scy pdu = &cmd->pdu_list[i]; 49275970Scy pr_debug("i: %d, offset: %d, length: %d," 50275970Scy " pdu_send_order: %d, seq_no: %d\n", i, pdu->offset, 51275970Scy pdu->length, pdu->pdu_send_order, pdu->seq_no); 52275970Scy } 53275970Scy} 54275970Scy#else 55275970Scystatic void iscsit_dump_seq_list(struct iscsit_cmd *cmd) {} 56275970Scystatic void iscsit_dump_pdu_list(struct iscsit_cmd *cmd) {} 57275970Scy#endif 58275970Scy 59275970Scystatic void iscsit_ordered_seq_lists( 60275970Scy struct iscsit_cmd *cmd, 61275970Scy u8 type) 62275970Scy{ 63275970Scy u32 i, seq_count = 0; 64275970Scy 65275970Scy for (i = 0; i < cmd->seq_count; i++) { 66275970Scy if (cmd->seq_list[i].type != SEQTYPE_NORMAL) 67275970Scy continue; 68275970Scy cmd->seq_list[i].seq_send_order = seq_count++; 69275970Scy } 70275970Scy} 71275970Scy 72275970Scystatic void iscsit_ordered_pdu_lists( 73275970Scy struct iscsit_cmd *cmd, 74275970Scy u8 type) 75275970Scy{ 76275970Scy u32 i, pdu_send_order = 0, seq_no = 0; 77275970Scy 78275970Scy for (i = 0; i < cmd->pdu_count; i++) { 79275970Scyredo: 80275970Scy if (cmd->pdu_list[i].seq_no == seq_no) { 81275970Scy cmd->pdu_list[i].pdu_send_order = pdu_send_order++; 82275970Scy continue; 83275970Scy } 84275970Scy seq_no++; 85275970Scy pdu_send_order = 0; 86275970Scy goto redo; 87275970Scy } 88275970Scy} 89275970Scy 90275970Scy/* 91275970Scy * Generate count random values into array. 92275970Scy * Use 0x80000000 to mark generates valued in array[]. 93275970Scy */ 94275970Scystatic void iscsit_create_random_array(u32 *array, u32 count) 95275970Scy{ 96275970Scy int i, j, k; 97275970Scy 98275970Scy if (count == 1) { 99275970Scy array[0] = 0; 100275970Scy return; 101275970Scy } 102275970Scy 103275970Scy for (i = 0; i < count; i++) { 104275970Scyredo: 105275970Scy get_random_bytes(&j, sizeof(u32)); 106275970Scy j = (1 + (int) (9999 + 1) - j) % count; 107275970Scy for (k = 0; k < i + 1; k++) { 108275970Scy j |= 0x80000000; 109275970Scy if ((array[k] & 0x80000000) && (array[k] == j)) 110275970Scy goto redo; 111275970Scy } 112275970Scy array[i] = j; 113275970Scy } 114275970Scy 115275970Scy for (i = 0; i < count; i++) 116275970Scy array[i] &= ~0x80000000; 117275970Scy} 118275970Scy 119275970Scystatic int iscsit_randomize_pdu_lists( 120275970Scy struct iscsit_cmd *cmd, 121275970Scy u8 type) 122275970Scy{ 123275970Scy int i = 0; 124275970Scy u32 *array, pdu_count, seq_count = 0, seq_no = 0, seq_offset = 0; 125275970Scy 126275970Scy for (pdu_count = 0; pdu_count < cmd->pdu_count; pdu_count++) { 127275970Scyredo: 128275970Scy if (cmd->pdu_list[pdu_count].seq_no == seq_no) { 129275970Scy seq_count++; 130275970Scy continue; 131275970Scy } 132275970Scy array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL); 133275970Scy if (!array) { 134275970Scy pr_err("Unable to allocate memory" 135275970Scy " for random array.\n"); 136275970Scy return -ENOMEM; 137275970Scy } 138275970Scy iscsit_create_random_array(array, seq_count); 139275970Scy 140275970Scy for (i = 0; i < seq_count; i++) 141275970Scy cmd->pdu_list[seq_offset+i].pdu_send_order = array[i]; 142275970Scy 143275970Scy kfree(array); 144275970Scy 145275970Scy seq_offset += seq_count; 146275970Scy seq_count = 0; 147275970Scy seq_no++; 148275970Scy goto redo; 149275970Scy } 150275970Scy 151275970Scy if (seq_count) { 152275970Scy array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL); 153275970Scy if (!array) { 154275970Scy pr_err("Unable to allocate memory for" 155275970Scy " random array.\n"); 156275970Scy return -ENOMEM; 157275970Scy } 158275970Scy iscsit_create_random_array(array, seq_count); 159275970Scy 160275970Scy for (i = 0; i < seq_count; i++) 161275970Scy cmd->pdu_list[seq_offset+i].pdu_send_order = array[i]; 162275970Scy 163275970Scy kfree(array); 164275970Scy } 165275970Scy 166275970Scy return 0; 167275970Scy} 168275970Scy 169275970Scystatic int iscsit_randomize_seq_lists( 170275970Scy struct iscsit_cmd *cmd, 171275970Scy u8 type) 172275970Scy{ 173275970Scy int i, j = 0; 174275970Scy u32 *array, seq_count = cmd->seq_count; 175275970Scy 176275970Scy if ((type == PDULIST_IMMEDIATE) || (type == PDULIST_UNSOLICITED)) 177275970Scy seq_count--; 178275970Scy else if (type == PDULIST_IMMEDIATE_AND_UNSOLICITED) 179275970Scy seq_count -= 2; 180275970Scy 181275970Scy if (!seq_count) 182275970Scy return 0; 183275970Scy 184275970Scy array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL); 185275970Scy if (!array) { 186275970Scy pr_err("Unable to allocate memory for random array.\n"); 187275970Scy return -ENOMEM; 188275970Scy } 189275970Scy iscsit_create_random_array(array, seq_count); 190275970Scy 191275970Scy for (i = 0; i < cmd->seq_count; i++) { 192275970Scy if (cmd->seq_list[i].type != SEQTYPE_NORMAL) 193275970Scy continue; 194275970Scy cmd->seq_list[i].seq_send_order = array[j++]; 195275970Scy } 196275970Scy 197275970Scy kfree(array); 198275970Scy return 0; 199275970Scy} 200275970Scy 201275970Scystatic void iscsit_determine_counts_for_list( 202275970Scy struct iscsit_cmd *cmd, 203275970Scy struct iscsi_build_list *bl, 204275970Scy u32 *seq_count, 205275970Scy u32 *pdu_count) 206275970Scy{ 207275970Scy int check_immediate = 0; 208275970Scy u32 burstlength = 0, offset = 0; 209275970Scy u32 unsolicited_data_length = 0; 210275970Scy u32 mdsl; 211275970Scy struct iscsit_conn *conn = cmd->conn; 212275970Scy 213275970Scy if (cmd->se_cmd.data_direction == DMA_TO_DEVICE) 214275970Scy mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength; 215275970Scy else 216275970Scy mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength; 217275970Scy 218275970Scy if ((bl->type == PDULIST_IMMEDIATE) || 219275970Scy (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED)) 220275970Scy check_immediate = 1; 221275970Scy 222275970Scy if ((bl->type == PDULIST_UNSOLICITED) || 223275970Scy (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED)) 224275970Scy unsolicited_data_length = min(cmd->se_cmd.data_length, 225275970Scy conn->sess->sess_ops->FirstBurstLength); 226275970Scy 227275970Scy while (offset < cmd->se_cmd.data_length) { 228275970Scy *pdu_count += 1; 229275970Scy 230275970Scy if (check_immediate) { 231275970Scy check_immediate = 0; 232275970Scy offset += bl->immediate_data_length; 233275970Scy *seq_count += 1; 234275970Scy if (unsolicited_data_length) 235275970Scy unsolicited_data_length -= 236275970Scy bl->immediate_data_length; 237275970Scy continue; 238275970Scy } 239275970Scy if (unsolicited_data_length > 0) { 240275970Scy if ((offset + mdsl) >= cmd->se_cmd.data_length) { 241275970Scy unsolicited_data_length -= 242275970Scy (cmd->se_cmd.data_length - offset); 243275970Scy offset += (cmd->se_cmd.data_length - offset); 244275970Scy continue; 245275970Scy } 246275970Scy if ((offset + mdsl) 247275970Scy >= conn->sess->sess_ops->FirstBurstLength) { 248275970Scy unsolicited_data_length -= 249275970Scy (conn->sess->sess_ops->FirstBurstLength - 250275970Scy offset); 251275970Scy offset += (conn->sess->sess_ops->FirstBurstLength - 252275970Scy offset); 253275970Scy burstlength = 0; 254275970Scy *seq_count += 1; 255275970Scy continue; 256275970Scy } 257275970Scy 258275970Scy offset += mdsl; 259275970Scy unsolicited_data_length -= mdsl; 260275970Scy continue; 261275970Scy } 262275970Scy if ((offset + mdsl) >= cmd->se_cmd.data_length) { 263275970Scy offset += (cmd->se_cmd.data_length - offset); 264275970Scy continue; 265275970Scy } 266275970Scy if ((burstlength + mdsl) >= 267275970Scy conn->sess->sess_ops->MaxBurstLength) { 268275970Scy offset += (conn->sess->sess_ops->MaxBurstLength - 269275970Scy burstlength); 270275970Scy burstlength = 0; 271275970Scy *seq_count += 1; 272275970Scy continue; 273275970Scy } 274275970Scy 275275970Scy burstlength += mdsl; 276275970Scy offset += mdsl; 277275970Scy } 278275970Scy} 279275970Scy 280275970Scy 281275970Scy/* 282275970Scy * Builds PDU and/or Sequence list, called while DataSequenceInOrder=No 283275970Scy * or DataPDUInOrder=No. 284275970Scy */ 285275970Scystatic int iscsit_do_build_pdu_and_seq_lists( 286275970Scy struct iscsit_cmd *cmd, 287275970Scy struct iscsi_build_list *bl) 288275970Scy{ 289275970Scy int check_immediate = 0, datapduinorder, datasequenceinorder; 290275970Scy u32 burstlength = 0, offset = 0, i = 0, mdsl; 291275970Scy u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0; 292275970Scy struct iscsit_conn *conn = cmd->conn; 293275970Scy struct iscsi_pdu *pdu = cmd->pdu_list; 294275970Scy struct iscsi_seq *seq = cmd->seq_list; 295275970Scy 296275970Scy if (cmd->se_cmd.data_direction == DMA_TO_DEVICE) 297275970Scy mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength; 298275970Scy else 299275970Scy mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength; 300275970Scy 301275970Scy datapduinorder = conn->sess->sess_ops->DataPDUInOrder; 302275970Scy datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder; 303275970Scy 304275970Scy if ((bl->type == PDULIST_IMMEDIATE) || 305275970Scy (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED)) 306275970Scy check_immediate = 1; 307275970Scy 308275970Scy if ((bl->type == PDULIST_UNSOLICITED) || 309275970Scy (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED)) 310275970Scy unsolicited_data_length = min(cmd->se_cmd.data_length, 311275970Scy conn->sess->sess_ops->FirstBurstLength); 312275970Scy 313275970Scy while (offset < cmd->se_cmd.data_length) { 314275970Scy pdu_count++; 315275970Scy if (!datapduinorder) { 316275970Scy pdu[i].offset = offset; 317275970Scy pdu[i].seq_no = seq_no; 318275970Scy } 319275970Scy if (!datasequenceinorder && (pdu_count == 1)) { 320275970Scy seq[seq_no].pdu_start = i; 321275970Scy seq[seq_no].seq_no = seq_no; 322275970Scy seq[seq_no].offset = offset; 323275970Scy seq[seq_no].orig_offset = offset; 324275970Scy } 325275970Scy 326275970Scy if (check_immediate) { 327275970Scy check_immediate = 0; 328275970Scy if (!datapduinorder) { 329275970Scy pdu[i].type = PDUTYPE_IMMEDIATE; 330275970Scy pdu[i++].length = bl->immediate_data_length; 331275970Scy } 332275970Scy if (!datasequenceinorder) { 333275970Scy seq[seq_no].type = SEQTYPE_IMMEDIATE; 334275970Scy seq[seq_no].pdu_count = 1; 335275970Scy seq[seq_no].xfer_len = 336275970Scy bl->immediate_data_length; 337275970Scy } 338275970Scy offset += bl->immediate_data_length; 339275970Scy pdu_count = 0; 340275970Scy seq_no++; 341275970Scy if (unsolicited_data_length) 342275970Scy unsolicited_data_length -= 343275970Scy bl->immediate_data_length; 344275970Scy continue; 345275970Scy } 346275970Scy if (unsolicited_data_length > 0) { 347275970Scy if ((offset + mdsl) >= cmd->se_cmd.data_length) { 348275970Scy if (!datapduinorder) { 349275970Scy pdu[i].type = PDUTYPE_UNSOLICITED; 350275970Scy pdu[i].length = 351275970Scy (cmd->se_cmd.data_length - offset); 352275970Scy } 353275970Scy if (!datasequenceinorder) { 354275970Scy seq[seq_no].type = SEQTYPE_UNSOLICITED; 355275970Scy seq[seq_no].pdu_count = pdu_count; 356275970Scy seq[seq_no].xfer_len = (burstlength + 357275970Scy (cmd->se_cmd.data_length - offset)); 358275970Scy } 359275970Scy unsolicited_data_length -= 360275970Scy (cmd->se_cmd.data_length - offset); 361275970Scy offset += (cmd->se_cmd.data_length - offset); 362275970Scy continue; 363275970Scy } 364275970Scy if ((offset + mdsl) >= 365275970Scy conn->sess->sess_ops->FirstBurstLength) { 366275970Scy if (!datapduinorder) { 367275970Scy pdu[i].type = PDUTYPE_UNSOLICITED; 368275970Scy pdu[i++].length = 369275970Scy (conn->sess->sess_ops->FirstBurstLength - 370275970Scy offset); 371275970Scy } 372275970Scy if (!datasequenceinorder) { 373275970Scy seq[seq_no].type = SEQTYPE_UNSOLICITED; 374275970Scy seq[seq_no].pdu_count = pdu_count; 375275970Scy seq[seq_no].xfer_len = (burstlength + 376275970Scy (conn->sess->sess_ops->FirstBurstLength - 377275970Scy offset)); 378275970Scy } 379275970Scy unsolicited_data_length -= 380275970Scy (conn->sess->sess_ops->FirstBurstLength - 381275970Scy offset); 382275970Scy offset += (conn->sess->sess_ops->FirstBurstLength - 383275970Scy offset); 384275970Scy burstlength = 0; 385275970Scy pdu_count = 0; 386275970Scy seq_no++; 387275970Scy continue; 388275970Scy } 389275970Scy 390275970Scy if (!datapduinorder) { 391275970Scy pdu[i].type = PDUTYPE_UNSOLICITED; 392275970Scy pdu[i++].length = mdsl; 393275970Scy } 394275970Scy burstlength += mdsl; 395275970Scy offset += mdsl; 396275970Scy unsolicited_data_length -= mdsl; 397275970Scy continue; 398275970Scy } 399275970Scy if ((offset + mdsl) >= cmd->se_cmd.data_length) { 400275970Scy if (!datapduinorder) { 401275970Scy pdu[i].type = PDUTYPE_NORMAL; 402275970Scy pdu[i].length = (cmd->se_cmd.data_length - offset); 403275970Scy } 404275970Scy if (!datasequenceinorder) { 405275970Scy seq[seq_no].type = SEQTYPE_NORMAL; 406275970Scy seq[seq_no].pdu_count = pdu_count; 407275970Scy seq[seq_no].xfer_len = (burstlength + 408275970Scy (cmd->se_cmd.data_length - offset)); 409275970Scy } 410275970Scy offset += (cmd->se_cmd.data_length - offset); 411275970Scy continue; 412275970Scy } 413275970Scy if ((burstlength + mdsl) >= 414275970Scy conn->sess->sess_ops->MaxBurstLength) { 415275970Scy if (!datapduinorder) { 416275970Scy pdu[i].type = PDUTYPE_NORMAL; 417275970Scy pdu[i++].length = 418275970Scy (conn->sess->sess_ops->MaxBurstLength - 419275970Scy burstlength); 420275970Scy } 421275970Scy if (!datasequenceinorder) { 422275970Scy seq[seq_no].type = SEQTYPE_NORMAL; 423275970Scy seq[seq_no].pdu_count = pdu_count; 424275970Scy seq[seq_no].xfer_len = (burstlength + 425275970Scy (conn->sess->sess_ops->MaxBurstLength - 426275970Scy burstlength)); 427275970Scy } 428275970Scy offset += (conn->sess->sess_ops->MaxBurstLength - 429275970Scy burstlength); 430275970Scy burstlength = 0; 431275970Scy pdu_count = 0; 432275970Scy seq_no++; 433275970Scy continue; 434275970Scy } 435275970Scy 436275970Scy if (!datapduinorder) { 437275970Scy pdu[i].type = PDUTYPE_NORMAL; 438275970Scy pdu[i++].length = mdsl; 439275970Scy } 440275970Scy burstlength += mdsl; 441275970Scy offset += mdsl; 442275970Scy } 443275970Scy 444275970Scy if (!datasequenceinorder) { 445275970Scy if (bl->data_direction & ISCSI_PDU_WRITE) { 446275970Scy if (bl->randomize & RANDOM_R2T_OFFSETS) { 447275970Scy if (iscsit_randomize_seq_lists(cmd, bl->type) 448275970Scy < 0) 449275970Scy return -1; 450275970Scy } else 451275970Scy iscsit_ordered_seq_lists(cmd, bl->type); 452275970Scy } else if (bl->data_direction & ISCSI_PDU_READ) { 453275970Scy if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) { 454275970Scy if (iscsit_randomize_seq_lists(cmd, bl->type) 455275970Scy < 0) 456275970Scy return -1; 457275970Scy } else 458275970Scy iscsit_ordered_seq_lists(cmd, bl->type); 459275970Scy } 460275970Scy 461275970Scy iscsit_dump_seq_list(cmd); 462275970Scy } 463275970Scy if (!datapduinorder) { 464275970Scy if (bl->data_direction & ISCSI_PDU_WRITE) { 465275970Scy if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) { 466275970Scy if (iscsit_randomize_pdu_lists(cmd, bl->type) 467275970Scy < 0) 468275970Scy return -1; 469275970Scy } else 470275970Scy iscsit_ordered_pdu_lists(cmd, bl->type); 471275970Scy } else if (bl->data_direction & ISCSI_PDU_READ) { 472275970Scy if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) { 473275970Scy if (iscsit_randomize_pdu_lists(cmd, bl->type) 474275970Scy < 0) 475275970Scy return -1; 476275970Scy } else 477275970Scy iscsit_ordered_pdu_lists(cmd, bl->type); 478275970Scy } 479275970Scy 480275970Scy iscsit_dump_pdu_list(cmd); 481275970Scy } 482275970Scy 483275970Scy return 0; 484275970Scy} 485275970Scy 486275970Scyint iscsit_build_pdu_and_seq_lists( 487275970Scy struct iscsit_cmd *cmd, 488275970Scy 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} 691