iscsi_target_seq_pdu_list.c 17 KB

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