~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/target/iscsi/iscsi_target_seq_pdu_list.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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