root/drivers/target/iscsi/iscsi_target_seq_pdu_list.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iscsit_dump_seq_list
  2. iscsit_dump_pdu_list
  3. iscsit_dump_seq_list
  4. iscsit_dump_pdu_list
  5. iscsit_ordered_seq_lists
  6. iscsit_ordered_pdu_lists
  7. iscsit_create_random_array
  8. iscsit_randomize_pdu_lists
  9. iscsit_randomize_seq_lists
  10. iscsit_determine_counts_for_list
  11. iscsit_do_build_pdu_and_seq_lists
  12. iscsit_build_pdu_and_seq_lists
  13. iscsit_get_pdu_holder
  14. iscsit_get_pdu_holder_for_seq
  15. iscsit_get_seq_holder

   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
  21 static void iscsit_dump_seq_list(struct iscsi_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 
  39 static void iscsit_dump_pdu_list(struct iscsi_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
  55 static void iscsit_dump_seq_list(struct iscsi_cmd *cmd) {}
  56 static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd) {}
  57 #endif
  58 
  59 static void iscsit_ordered_seq_lists(
  60         struct iscsi_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 
  72 static void iscsit_ordered_pdu_lists(
  73         struct iscsi_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++) {
  79 redo:
  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  */
  94 static 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++) {
 104 redo:
 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 
 119 static int iscsit_randomize_pdu_lists(
 120         struct iscsi_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++) {
 127 redo:
 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 
 169 static int iscsit_randomize_seq_lists(
 170         struct iscsi_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 
 201 static void iscsit_determine_counts_for_list(
 202         struct iscsi_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 iscsi_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  */
 285 static int iscsit_do_build_pdu_and_seq_lists(
 286         struct iscsi_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 iscsi_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 
 486 int iscsit_build_pdu_and_seq_lists(
 487         struct iscsi_cmd *cmd,
 488         u32 immediate_data_length)
 489 {
 490         struct iscsi_build_list bl;
 491         u32 pdu_count = 0, seq_count = 1;
 492         struct iscsi_conn *conn = cmd->conn;
 493         struct iscsi_pdu *pdu = NULL;
 494         struct iscsi_seq *seq = NULL;
 495 
 496         struct iscsi_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 
 561 struct iscsi_pdu *iscsit_get_pdu_holder(
 562         struct iscsi_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 iscsi_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 
 585 struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
 586         struct iscsi_cmd *cmd,
 587         struct iscsi_seq *seq)
 588 {
 589         u32 i;
 590         struct iscsi_conn *conn = cmd->conn;
 591         struct iscsi_pdu *pdu = NULL;
 592 
 593         if (!cmd->pdu_list) {
 594                 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
 595                 return NULL;
 596         }
 597 
 598         if (conn->sess->sess_ops->DataSequenceInOrder) {
 599 redo:
 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 
 662 struct iscsi_seq *iscsit_get_seq_holder(
 663         struct iscsi_cmd *cmd,
 664         u32 offset,
 665         u32 length)
 666 {
 667         u32 i;
 668 
 669         if (!cmd->seq_list) {
 670                 pr_err("struct iscsi_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 }

/* [<][>][^][v][top][bottom][index][help] */