xtensa: fix syscall_set_return_value
[linux/fpc-iii.git] / drivers / target / iscsi / iscsi_target_erl0.c
blobb4abd7b68e6da3de03b4a0eee8c47e42d7276ea1
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /******************************************************************************
3 * This file contains error recovery level zero functions used by
4 * the iSCSI Target driver.
6 * (c) Copyright 2007-2013 Datera, Inc.
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 ******************************************************************************/
12 #include <linux/sched/signal.h>
14 #include <scsi/iscsi_proto.h>
15 #include <target/target_core_base.h>
16 #include <target/target_core_fabric.h>
18 #include <target/iscsi/iscsi_target_core.h>
19 #include "iscsi_target_seq_pdu_list.h"
20 #include "iscsi_target_erl0.h"
21 #include "iscsi_target_erl1.h"
22 #include "iscsi_target_erl2.h"
23 #include "iscsi_target_util.h"
24 #include "iscsi_target.h"
27 * Used to set values in struct iscsi_cmd that iscsit_dataout_check_sequence()
28 * checks against to determine a PDU's Offset+Length is within the current
29 * DataOUT Sequence. Used for DataSequenceInOrder=Yes only.
31 void iscsit_set_dataout_sequence_values(
32 struct iscsi_cmd *cmd)
34 struct iscsi_conn *conn = cmd->conn;
36 * Still set seq_start_offset and seq_end_offset for Unsolicited
37 * DataOUT, even if DataSequenceInOrder=No.
39 if (cmd->unsolicited_data) {
40 cmd->seq_start_offset = cmd->write_data_done;
41 cmd->seq_end_offset = min(cmd->se_cmd.data_length,
42 conn->sess->sess_ops->FirstBurstLength);
43 return;
46 if (!conn->sess->sess_ops->DataSequenceInOrder)
47 return;
49 if (!cmd->seq_start_offset && !cmd->seq_end_offset) {
50 cmd->seq_start_offset = cmd->write_data_done;
51 cmd->seq_end_offset = (cmd->se_cmd.data_length >
52 conn->sess->sess_ops->MaxBurstLength) ?
53 (cmd->write_data_done +
54 conn->sess->sess_ops->MaxBurstLength) : cmd->se_cmd.data_length;
55 } else {
56 cmd->seq_start_offset = cmd->seq_end_offset;
57 cmd->seq_end_offset = ((cmd->seq_end_offset +
58 conn->sess->sess_ops->MaxBurstLength) >=
59 cmd->se_cmd.data_length) ? cmd->se_cmd.data_length :
60 (cmd->seq_end_offset +
61 conn->sess->sess_ops->MaxBurstLength);
65 static int iscsit_dataout_within_command_recovery_check(
66 struct iscsi_cmd *cmd,
67 unsigned char *buf)
69 struct iscsi_conn *conn = cmd->conn;
70 struct iscsi_data *hdr = (struct iscsi_data *) buf;
71 u32 payload_length = ntoh24(hdr->dlength);
74 * We do the within-command recovery checks here as it is
75 * the first function called in iscsi_check_pre_dataout().
76 * Basically, if we are in within-command recovery and
77 * the PDU does not contain the offset the sequence needs,
78 * dump the payload.
80 * This only applies to DataPDUInOrder=Yes, for
81 * DataPDUInOrder=No we only re-request the failed PDU
82 * and check that all PDUs in a sequence are received
83 * upon end of sequence.
85 if (conn->sess->sess_ops->DataSequenceInOrder) {
86 if ((cmd->cmd_flags & ICF_WITHIN_COMMAND_RECOVERY) &&
87 cmd->write_data_done != be32_to_cpu(hdr->offset))
88 goto dump;
90 cmd->cmd_flags &= ~ICF_WITHIN_COMMAND_RECOVERY;
91 } else {
92 struct iscsi_seq *seq;
94 seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
95 payload_length);
96 if (!seq)
97 return DATAOUT_CANNOT_RECOVER;
99 * Set the struct iscsi_seq pointer to reuse later.
101 cmd->seq_ptr = seq;
103 if (conn->sess->sess_ops->DataPDUInOrder) {
104 if (seq->status ==
105 DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
106 (seq->offset != be32_to_cpu(hdr->offset) ||
107 seq->data_sn != be32_to_cpu(hdr->datasn)))
108 goto dump;
109 } else {
110 if (seq->status ==
111 DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
112 seq->data_sn != be32_to_cpu(hdr->datasn))
113 goto dump;
116 if (seq->status == DATAOUT_SEQUENCE_COMPLETE)
117 goto dump;
119 if (seq->status != DATAOUT_SEQUENCE_COMPLETE)
120 seq->status = 0;
123 return DATAOUT_NORMAL;
125 dump:
126 pr_err("Dumping DataOUT PDU Offset: %u Length: %d DataSN:"
127 " 0x%08x\n", hdr->offset, payload_length, hdr->datasn);
128 return iscsit_dump_data_payload(conn, payload_length, 1);
131 static int iscsit_dataout_check_unsolicited_sequence(
132 struct iscsi_cmd *cmd,
133 unsigned char *buf)
135 u32 first_burst_len;
136 struct iscsi_conn *conn = cmd->conn;
137 struct iscsi_data *hdr = (struct iscsi_data *) buf;
138 u32 payload_length = ntoh24(hdr->dlength);
141 if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
142 ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
143 pr_err("Command ITT: 0x%08x with Offset: %u,"
144 " Length: %u outside of Unsolicited Sequence %u:%u while"
145 " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
146 be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
147 cmd->seq_end_offset);
148 return DATAOUT_CANNOT_RECOVER;
151 first_burst_len = (cmd->first_burst_len + payload_length);
153 if (first_burst_len > conn->sess->sess_ops->FirstBurstLength) {
154 pr_err("Total %u bytes exceeds FirstBurstLength: %u"
155 " for this Unsolicited DataOut Burst.\n",
156 first_burst_len, conn->sess->sess_ops->FirstBurstLength);
157 transport_send_check_condition_and_sense(&cmd->se_cmd,
158 TCM_INCORRECT_AMOUNT_OF_DATA, 0);
159 return DATAOUT_CANNOT_RECOVER;
163 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
164 * checks for the current Unsolicited DataOUT Sequence.
166 if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
168 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
169 * sequence checks are handled in
170 * iscsit_dataout_datapduinorder_no_fbit().
172 if (!conn->sess->sess_ops->DataPDUInOrder)
173 goto out;
175 if ((first_burst_len != cmd->se_cmd.data_length) &&
176 (first_burst_len != conn->sess->sess_ops->FirstBurstLength)) {
177 pr_err("Unsolicited non-immediate data"
178 " received %u does not equal FirstBurstLength: %u, and"
179 " does not equal ExpXferLen %u.\n", first_burst_len,
180 conn->sess->sess_ops->FirstBurstLength,
181 cmd->se_cmd.data_length);
182 transport_send_check_condition_and_sense(&cmd->se_cmd,
183 TCM_INCORRECT_AMOUNT_OF_DATA, 0);
184 return DATAOUT_CANNOT_RECOVER;
186 } else {
187 if (first_burst_len == conn->sess->sess_ops->FirstBurstLength) {
188 pr_err("Command ITT: 0x%08x reached"
189 " FirstBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
190 " error.\n", cmd->init_task_tag,
191 conn->sess->sess_ops->FirstBurstLength);
192 return DATAOUT_CANNOT_RECOVER;
194 if (first_burst_len == cmd->se_cmd.data_length) {
195 pr_err("Command ITT: 0x%08x reached"
196 " ExpXferLen: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
197 " error.\n", cmd->init_task_tag, cmd->se_cmd.data_length);
198 return DATAOUT_CANNOT_RECOVER;
202 out:
203 return DATAOUT_NORMAL;
206 static int iscsit_dataout_check_sequence(
207 struct iscsi_cmd *cmd,
208 unsigned char *buf)
210 u32 next_burst_len;
211 struct iscsi_conn *conn = cmd->conn;
212 struct iscsi_seq *seq = NULL;
213 struct iscsi_data *hdr = (struct iscsi_data *) buf;
214 u32 payload_length = ntoh24(hdr->dlength);
217 * For DataSequenceInOrder=Yes: Check that the offset and offset+length
218 * is within range as defined by iscsi_set_dataout_sequence_values().
220 * For DataSequenceInOrder=No: Check that an struct iscsi_seq exists for
221 * offset+length tuple.
223 if (conn->sess->sess_ops->DataSequenceInOrder) {
225 * Due to possibility of recovery DataOUT sent by the initiator
226 * fullfilling an Recovery R2T, it's best to just dump the
227 * payload here, instead of erroring out.
229 if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
230 ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
231 pr_err("Command ITT: 0x%08x with Offset: %u,"
232 " Length: %u outside of Sequence %u:%u while"
233 " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
234 be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
235 cmd->seq_end_offset);
237 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
238 return DATAOUT_CANNOT_RECOVER;
239 return DATAOUT_WITHIN_COMMAND_RECOVERY;
242 next_burst_len = (cmd->next_burst_len + payload_length);
243 } else {
244 seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
245 payload_length);
246 if (!seq)
247 return DATAOUT_CANNOT_RECOVER;
249 * Set the struct iscsi_seq pointer to reuse later.
251 cmd->seq_ptr = seq;
253 if (seq->status == DATAOUT_SEQUENCE_COMPLETE) {
254 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
255 return DATAOUT_CANNOT_RECOVER;
256 return DATAOUT_WITHIN_COMMAND_RECOVERY;
259 next_burst_len = (seq->next_burst_len + payload_length);
262 if (next_burst_len > conn->sess->sess_ops->MaxBurstLength) {
263 pr_err("Command ITT: 0x%08x, NextBurstLength: %u and"
264 " Length: %u exceeds MaxBurstLength: %u. protocol"
265 " error.\n", cmd->init_task_tag,
266 (next_burst_len - payload_length),
267 payload_length, conn->sess->sess_ops->MaxBurstLength);
268 return DATAOUT_CANNOT_RECOVER;
272 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
273 * checks for the current DataOUT Sequence.
275 if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
277 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
278 * sequence checks are handled in
279 * iscsit_dataout_datapduinorder_no_fbit().
281 if (!conn->sess->sess_ops->DataPDUInOrder)
282 goto out;
284 if (conn->sess->sess_ops->DataSequenceInOrder) {
285 if ((next_burst_len <
286 conn->sess->sess_ops->MaxBurstLength) &&
287 ((cmd->write_data_done + payload_length) <
288 cmd->se_cmd.data_length)) {
289 pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
290 " before end of DataOUT sequence, protocol"
291 " error.\n", cmd->init_task_tag);
292 return DATAOUT_CANNOT_RECOVER;
294 } else {
295 if (next_burst_len < seq->xfer_len) {
296 pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
297 " before end of DataOUT sequence, protocol"
298 " error.\n", cmd->init_task_tag);
299 return DATAOUT_CANNOT_RECOVER;
302 } else {
303 if (conn->sess->sess_ops->DataSequenceInOrder) {
304 if (next_burst_len ==
305 conn->sess->sess_ops->MaxBurstLength) {
306 pr_err("Command ITT: 0x%08x reached"
307 " MaxBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is"
308 " not set, protocol error.", cmd->init_task_tag,
309 conn->sess->sess_ops->MaxBurstLength);
310 return DATAOUT_CANNOT_RECOVER;
312 if ((cmd->write_data_done + payload_length) ==
313 cmd->se_cmd.data_length) {
314 pr_err("Command ITT: 0x%08x reached"
315 " last DataOUT PDU in sequence but ISCSI_FLAG_"
316 "CMD_FINAL is not set, protocol error.\n",
317 cmd->init_task_tag);
318 return DATAOUT_CANNOT_RECOVER;
320 } else {
321 if (next_burst_len == seq->xfer_len) {
322 pr_err("Command ITT: 0x%08x reached"
323 " last DataOUT PDU in sequence but ISCSI_FLAG_"
324 "CMD_FINAL is not set, protocol error.\n",
325 cmd->init_task_tag);
326 return DATAOUT_CANNOT_RECOVER;
331 out:
332 return DATAOUT_NORMAL;
335 static int iscsit_dataout_check_datasn(
336 struct iscsi_cmd *cmd,
337 unsigned char *buf)
339 u32 data_sn = 0;
340 struct iscsi_conn *conn = cmd->conn;
341 struct iscsi_data *hdr = (struct iscsi_data *) buf;
342 u32 payload_length = ntoh24(hdr->dlength);
345 * Considering the target has no method of re-requesting DataOUT
346 * by DataSN, if we receieve a greater DataSN than expected we
347 * assume the functions for DataPDUInOrder=[Yes,No] below will
348 * handle it.
350 * If the DataSN is less than expected, dump the payload.
352 if (conn->sess->sess_ops->DataSequenceInOrder)
353 data_sn = cmd->data_sn;
354 else {
355 struct iscsi_seq *seq = cmd->seq_ptr;
356 data_sn = seq->data_sn;
359 if (be32_to_cpu(hdr->datasn) > data_sn) {
360 pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
361 " higher than expected 0x%08x.\n", cmd->init_task_tag,
362 be32_to_cpu(hdr->datasn), data_sn);
363 goto recover;
364 } else if (be32_to_cpu(hdr->datasn) < data_sn) {
365 pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
366 " lower than expected 0x%08x, discarding payload.\n",
367 cmd->init_task_tag, be32_to_cpu(hdr->datasn), data_sn);
368 goto dump;
371 return DATAOUT_NORMAL;
373 recover:
374 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
375 pr_err("Unable to perform within-command recovery"
376 " while ERL=0.\n");
377 return DATAOUT_CANNOT_RECOVER;
379 dump:
380 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
381 return DATAOUT_CANNOT_RECOVER;
383 return DATAOUT_WITHIN_COMMAND_RECOVERY;
386 static int iscsit_dataout_pre_datapduinorder_yes(
387 struct iscsi_cmd *cmd,
388 unsigned char *buf)
390 int dump = 0, recovery = 0;
391 struct iscsi_conn *conn = cmd->conn;
392 struct iscsi_data *hdr = (struct iscsi_data *) buf;
393 u32 payload_length = ntoh24(hdr->dlength);
396 * For DataSequenceInOrder=Yes: If the offset is greater than the global
397 * DataPDUInOrder=Yes offset counter in struct iscsi_cmd a protcol error has
398 * occurred and fail the connection.
400 * For DataSequenceInOrder=No: If the offset is greater than the per
401 * sequence DataPDUInOrder=Yes offset counter in struct iscsi_seq a protocol
402 * error has occurred and fail the connection.
404 if (conn->sess->sess_ops->DataSequenceInOrder) {
405 if (be32_to_cpu(hdr->offset) != cmd->write_data_done) {
406 pr_err("Command ITT: 0x%08x, received offset"
407 " %u different than expected %u.\n", cmd->init_task_tag,
408 be32_to_cpu(hdr->offset), cmd->write_data_done);
409 recovery = 1;
410 goto recover;
412 } else {
413 struct iscsi_seq *seq = cmd->seq_ptr;
415 if (be32_to_cpu(hdr->offset) > seq->offset) {
416 pr_err("Command ITT: 0x%08x, received offset"
417 " %u greater than expected %u.\n", cmd->init_task_tag,
418 be32_to_cpu(hdr->offset), seq->offset);
419 recovery = 1;
420 goto recover;
421 } else if (be32_to_cpu(hdr->offset) < seq->offset) {
422 pr_err("Command ITT: 0x%08x, received offset"
423 " %u less than expected %u, discarding payload.\n",
424 cmd->init_task_tag, be32_to_cpu(hdr->offset),
425 seq->offset);
426 dump = 1;
427 goto dump;
431 return DATAOUT_NORMAL;
433 recover:
434 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
435 pr_err("Unable to perform within-command recovery"
436 " while ERL=0.\n");
437 return DATAOUT_CANNOT_RECOVER;
439 dump:
440 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
441 return DATAOUT_CANNOT_RECOVER;
443 return (recovery) ? iscsit_recover_dataout_sequence(cmd,
444 be32_to_cpu(hdr->offset), payload_length) :
445 (dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY : DATAOUT_NORMAL;
448 static int iscsit_dataout_pre_datapduinorder_no(
449 struct iscsi_cmd *cmd,
450 unsigned char *buf)
452 struct iscsi_pdu *pdu;
453 struct iscsi_data *hdr = (struct iscsi_data *) buf;
454 u32 payload_length = ntoh24(hdr->dlength);
456 pdu = iscsit_get_pdu_holder(cmd, be32_to_cpu(hdr->offset),
457 payload_length);
458 if (!pdu)
459 return DATAOUT_CANNOT_RECOVER;
461 cmd->pdu_ptr = pdu;
463 switch (pdu->status) {
464 case ISCSI_PDU_NOT_RECEIVED:
465 case ISCSI_PDU_CRC_FAILED:
466 case ISCSI_PDU_TIMED_OUT:
467 break;
468 case ISCSI_PDU_RECEIVED_OK:
469 pr_err("Command ITT: 0x%08x received already gotten"
470 " Offset: %u, Length: %u\n", cmd->init_task_tag,
471 be32_to_cpu(hdr->offset), payload_length);
472 return iscsit_dump_data_payload(cmd->conn, payload_length, 1);
473 default:
474 return DATAOUT_CANNOT_RECOVER;
477 return DATAOUT_NORMAL;
480 static int iscsit_dataout_update_r2t(struct iscsi_cmd *cmd, u32 offset, u32 length)
482 struct iscsi_r2t *r2t;
484 if (cmd->unsolicited_data)
485 return 0;
487 r2t = iscsit_get_r2t_for_eos(cmd, offset, length);
488 if (!r2t)
489 return -1;
491 spin_lock_bh(&cmd->r2t_lock);
492 r2t->seq_complete = 1;
493 cmd->outstanding_r2ts--;
494 spin_unlock_bh(&cmd->r2t_lock);
496 return 0;
499 static int iscsit_dataout_update_datapduinorder_no(
500 struct iscsi_cmd *cmd,
501 u32 data_sn,
502 int f_bit)
504 int ret = 0;
505 struct iscsi_pdu *pdu = cmd->pdu_ptr;
507 pdu->data_sn = data_sn;
509 switch (pdu->status) {
510 case ISCSI_PDU_NOT_RECEIVED:
511 pdu->status = ISCSI_PDU_RECEIVED_OK;
512 break;
513 case ISCSI_PDU_CRC_FAILED:
514 pdu->status = ISCSI_PDU_RECEIVED_OK;
515 break;
516 case ISCSI_PDU_TIMED_OUT:
517 pdu->status = ISCSI_PDU_RECEIVED_OK;
518 break;
519 default:
520 return DATAOUT_CANNOT_RECOVER;
523 if (f_bit) {
524 ret = iscsit_dataout_datapduinorder_no_fbit(cmd, pdu);
525 if (ret == DATAOUT_CANNOT_RECOVER)
526 return ret;
529 return DATAOUT_NORMAL;
532 static int iscsit_dataout_post_crc_passed(
533 struct iscsi_cmd *cmd,
534 unsigned char *buf)
536 int ret, send_r2t = 0;
537 struct iscsi_conn *conn = cmd->conn;
538 struct iscsi_seq *seq = NULL;
539 struct iscsi_data *hdr = (struct iscsi_data *) buf;
540 u32 payload_length = ntoh24(hdr->dlength);
542 if (cmd->unsolicited_data) {
543 if ((cmd->first_burst_len + payload_length) ==
544 conn->sess->sess_ops->FirstBurstLength) {
545 if (iscsit_dataout_update_r2t(cmd, be32_to_cpu(hdr->offset),
546 payload_length) < 0)
547 return DATAOUT_CANNOT_RECOVER;
548 send_r2t = 1;
551 if (!conn->sess->sess_ops->DataPDUInOrder) {
552 ret = iscsit_dataout_update_datapduinorder_no(cmd,
553 be32_to_cpu(hdr->datasn),
554 (hdr->flags & ISCSI_FLAG_CMD_FINAL));
555 if (ret == DATAOUT_CANNOT_RECOVER)
556 return ret;
559 cmd->first_burst_len += payload_length;
561 if (conn->sess->sess_ops->DataSequenceInOrder)
562 cmd->data_sn++;
563 else {
564 seq = cmd->seq_ptr;
565 seq->data_sn++;
566 seq->offset += payload_length;
569 if (send_r2t) {
570 if (seq)
571 seq->status = DATAOUT_SEQUENCE_COMPLETE;
572 cmd->first_burst_len = 0;
573 cmd->unsolicited_data = 0;
575 } else {
576 if (conn->sess->sess_ops->DataSequenceInOrder) {
577 if ((cmd->next_burst_len + payload_length) ==
578 conn->sess->sess_ops->MaxBurstLength) {
579 if (iscsit_dataout_update_r2t(cmd,
580 be32_to_cpu(hdr->offset),
581 payload_length) < 0)
582 return DATAOUT_CANNOT_RECOVER;
583 send_r2t = 1;
586 if (!conn->sess->sess_ops->DataPDUInOrder) {
587 ret = iscsit_dataout_update_datapduinorder_no(
588 cmd, be32_to_cpu(hdr->datasn),
589 (hdr->flags & ISCSI_FLAG_CMD_FINAL));
590 if (ret == DATAOUT_CANNOT_RECOVER)
591 return ret;
594 cmd->next_burst_len += payload_length;
595 cmd->data_sn++;
597 if (send_r2t)
598 cmd->next_burst_len = 0;
599 } else {
600 seq = cmd->seq_ptr;
602 if ((seq->next_burst_len + payload_length) ==
603 seq->xfer_len) {
604 if (iscsit_dataout_update_r2t(cmd,
605 be32_to_cpu(hdr->offset),
606 payload_length) < 0)
607 return DATAOUT_CANNOT_RECOVER;
608 send_r2t = 1;
611 if (!conn->sess->sess_ops->DataPDUInOrder) {
612 ret = iscsit_dataout_update_datapduinorder_no(
613 cmd, be32_to_cpu(hdr->datasn),
614 (hdr->flags & ISCSI_FLAG_CMD_FINAL));
615 if (ret == DATAOUT_CANNOT_RECOVER)
616 return ret;
619 seq->data_sn++;
620 seq->offset += payload_length;
621 seq->next_burst_len += payload_length;
623 if (send_r2t) {
624 seq->next_burst_len = 0;
625 seq->status = DATAOUT_SEQUENCE_COMPLETE;
630 if (send_r2t && conn->sess->sess_ops->DataSequenceInOrder)
631 cmd->data_sn = 0;
633 cmd->write_data_done += payload_length;
635 if (cmd->write_data_done == cmd->se_cmd.data_length)
636 return DATAOUT_SEND_TO_TRANSPORT;
637 else if (send_r2t)
638 return DATAOUT_SEND_R2T;
639 else
640 return DATAOUT_NORMAL;
643 static int iscsit_dataout_post_crc_failed(
644 struct iscsi_cmd *cmd,
645 unsigned char *buf)
647 struct iscsi_conn *conn = cmd->conn;
648 struct iscsi_pdu *pdu;
649 struct iscsi_data *hdr = (struct iscsi_data *) buf;
650 u32 payload_length = ntoh24(hdr->dlength);
652 if (conn->sess->sess_ops->DataPDUInOrder)
653 goto recover;
655 * The rest of this function is only called when DataPDUInOrder=No.
657 pdu = cmd->pdu_ptr;
659 switch (pdu->status) {
660 case ISCSI_PDU_NOT_RECEIVED:
661 pdu->status = ISCSI_PDU_CRC_FAILED;
662 break;
663 case ISCSI_PDU_CRC_FAILED:
664 break;
665 case ISCSI_PDU_TIMED_OUT:
666 pdu->status = ISCSI_PDU_CRC_FAILED;
667 break;
668 default:
669 return DATAOUT_CANNOT_RECOVER;
672 recover:
673 return iscsit_recover_dataout_sequence(cmd, be32_to_cpu(hdr->offset),
674 payload_length);
678 * Called from iscsit_handle_data_out() before DataOUT Payload is received
679 * and CRC computed.
681 int iscsit_check_pre_dataout(
682 struct iscsi_cmd *cmd,
683 unsigned char *buf)
685 int ret;
686 struct iscsi_conn *conn = cmd->conn;
688 ret = iscsit_dataout_within_command_recovery_check(cmd, buf);
689 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
690 (ret == DATAOUT_CANNOT_RECOVER))
691 return ret;
693 ret = iscsit_dataout_check_datasn(cmd, buf);
694 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
695 (ret == DATAOUT_CANNOT_RECOVER))
696 return ret;
698 if (cmd->unsolicited_data) {
699 ret = iscsit_dataout_check_unsolicited_sequence(cmd, buf);
700 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
701 (ret == DATAOUT_CANNOT_RECOVER))
702 return ret;
703 } else {
704 ret = iscsit_dataout_check_sequence(cmd, buf);
705 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
706 (ret == DATAOUT_CANNOT_RECOVER))
707 return ret;
710 return (conn->sess->sess_ops->DataPDUInOrder) ?
711 iscsit_dataout_pre_datapduinorder_yes(cmd, buf) :
712 iscsit_dataout_pre_datapduinorder_no(cmd, buf);
716 * Called from iscsit_handle_data_out() after DataOUT Payload is received
717 * and CRC computed.
719 int iscsit_check_post_dataout(
720 struct iscsi_cmd *cmd,
721 unsigned char *buf,
722 u8 data_crc_failed)
724 struct iscsi_conn *conn = cmd->conn;
726 cmd->dataout_timeout_retries = 0;
728 if (!data_crc_failed)
729 return iscsit_dataout_post_crc_passed(cmd, buf);
730 else {
731 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
732 pr_err("Unable to recover from DataOUT CRC"
733 " failure while ERL=0, closing session.\n");
734 iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR,
735 buf);
736 return DATAOUT_CANNOT_RECOVER;
739 iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf);
740 return iscsit_dataout_post_crc_failed(cmd, buf);
744 void iscsit_handle_time2retain_timeout(struct timer_list *t)
746 struct iscsi_session *sess = from_timer(sess, t, time2retain_timer);
747 struct iscsi_portal_group *tpg = sess->tpg;
748 struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
750 spin_lock_bh(&se_tpg->session_lock);
751 if (sess->time2retain_timer_flags & ISCSI_TF_STOP) {
752 spin_unlock_bh(&se_tpg->session_lock);
753 return;
755 if (atomic_read(&sess->session_reinstatement)) {
756 pr_err("Exiting Time2Retain handler because"
757 " session_reinstatement=1\n");
758 spin_unlock_bh(&se_tpg->session_lock);
759 return;
761 sess->time2retain_timer_flags |= ISCSI_TF_EXPIRED;
763 pr_err("Time2Retain timer expired for SID: %u, cleaning up"
764 " iSCSI session.\n", sess->sid);
766 iscsit_fill_cxn_timeout_err_stats(sess);
767 spin_unlock_bh(&se_tpg->session_lock);
768 iscsit_close_session(sess);
771 void iscsit_start_time2retain_handler(struct iscsi_session *sess)
773 int tpg_active;
775 * Only start Time2Retain timer when the associated TPG is still in
776 * an ACTIVE (eg: not disabled or shutdown) state.
778 spin_lock(&sess->tpg->tpg_state_lock);
779 tpg_active = (sess->tpg->tpg_state == TPG_STATE_ACTIVE);
780 spin_unlock(&sess->tpg->tpg_state_lock);
782 if (!tpg_active)
783 return;
785 if (sess->time2retain_timer_flags & ISCSI_TF_RUNNING)
786 return;
788 pr_debug("Starting Time2Retain timer for %u seconds on"
789 " SID: %u\n", sess->sess_ops->DefaultTime2Retain, sess->sid);
791 sess->time2retain_timer_flags &= ~ISCSI_TF_STOP;
792 sess->time2retain_timer_flags |= ISCSI_TF_RUNNING;
793 mod_timer(&sess->time2retain_timer,
794 jiffies + sess->sess_ops->DefaultTime2Retain * HZ);
797 int iscsit_stop_time2retain_timer(struct iscsi_session *sess)
799 struct iscsi_portal_group *tpg = sess->tpg;
800 struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
802 lockdep_assert_held(&se_tpg->session_lock);
804 if (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)
805 return -1;
807 if (!(sess->time2retain_timer_flags & ISCSI_TF_RUNNING))
808 return 0;
810 sess->time2retain_timer_flags |= ISCSI_TF_STOP;
811 spin_unlock(&se_tpg->session_lock);
813 del_timer_sync(&sess->time2retain_timer);
815 spin_lock(&se_tpg->session_lock);
816 sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING;
817 pr_debug("Stopped Time2Retain Timer for SID: %u\n",
818 sess->sid);
819 return 0;
822 void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn)
824 spin_lock_bh(&conn->state_lock);
825 if (atomic_read(&conn->connection_exit)) {
826 spin_unlock_bh(&conn->state_lock);
827 goto sleep;
830 if (atomic_read(&conn->transport_failed)) {
831 spin_unlock_bh(&conn->state_lock);
832 goto sleep;
834 spin_unlock_bh(&conn->state_lock);
836 if (conn->tx_thread && conn->tx_thread_active)
837 send_sig(SIGINT, conn->tx_thread, 1);
838 if (conn->rx_thread && conn->rx_thread_active)
839 send_sig(SIGINT, conn->rx_thread, 1);
841 sleep:
842 wait_for_completion(&conn->conn_wait_rcfr_comp);
843 complete(&conn->conn_post_wait_comp);
846 void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep)
848 spin_lock_bh(&conn->state_lock);
849 if (atomic_read(&conn->connection_exit)) {
850 spin_unlock_bh(&conn->state_lock);
851 return;
854 if (atomic_read(&conn->transport_failed)) {
855 spin_unlock_bh(&conn->state_lock);
856 return;
859 if (atomic_read(&conn->connection_reinstatement)) {
860 spin_unlock_bh(&conn->state_lock);
861 return;
864 if (conn->tx_thread && conn->tx_thread_active)
865 send_sig(SIGINT, conn->tx_thread, 1);
866 if (conn->rx_thread && conn->rx_thread_active)
867 send_sig(SIGINT, conn->rx_thread, 1);
869 atomic_set(&conn->connection_reinstatement, 1);
870 if (!sleep) {
871 spin_unlock_bh(&conn->state_lock);
872 return;
875 atomic_set(&conn->sleep_on_conn_wait_comp, 1);
876 spin_unlock_bh(&conn->state_lock);
878 wait_for_completion(&conn->conn_wait_comp);
879 complete(&conn->conn_post_wait_comp);
881 EXPORT_SYMBOL(iscsit_cause_connection_reinstatement);
883 void iscsit_fall_back_to_erl0(struct iscsi_session *sess)
885 pr_debug("Falling back to ErrorRecoveryLevel=0 for SID:"
886 " %u\n", sess->sid);
888 atomic_set(&sess->session_fall_back_to_erl0, 1);
891 static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn)
893 struct iscsi_session *sess = conn->sess;
895 if ((sess->sess_ops->ErrorRecoveryLevel == 2) &&
896 !atomic_read(&sess->session_reinstatement) &&
897 !atomic_read(&sess->session_fall_back_to_erl0))
898 iscsit_connection_recovery_transport_reset(conn);
899 else {
900 pr_debug("Performing cleanup for failed iSCSI"
901 " Connection ID: %hu from %s\n", conn->cid,
902 sess->sess_ops->InitiatorName);
903 iscsit_close_connection(conn);
907 void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn, bool *conn_freed)
909 *conn_freed = false;
911 spin_lock_bh(&conn->state_lock);
912 if (atomic_read(&conn->connection_exit)) {
913 spin_unlock_bh(&conn->state_lock);
914 return;
916 atomic_set(&conn->connection_exit, 1);
918 if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
919 spin_unlock_bh(&conn->state_lock);
920 iscsit_close_connection(conn);
921 *conn_freed = true;
922 return;
925 if (conn->conn_state == TARG_CONN_STATE_CLEANUP_WAIT) {
926 spin_unlock_bh(&conn->state_lock);
927 return;
930 pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
931 conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
932 spin_unlock_bh(&conn->state_lock);
934 iscsit_handle_connection_cleanup(conn);
935 *conn_freed = true;