cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iscsi_target_erl0.c (26622B)


      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.
      5 *
      6 * (c) Copyright 2007-2013 Datera, Inc.
      7 *
      8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
      9 *
     10 ******************************************************************************/
     11
     12#include <linux/sched/signal.h>
     13
     14#include <scsi/iscsi_proto.h>
     15#include <target/target_core_base.h>
     16#include <target/target_core_fabric.h>
     17
     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"
     25
     26/*
     27 *	Used to set values in struct iscsit_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.
     30 */
     31void iscsit_set_dataout_sequence_values(
     32	struct iscsit_cmd *cmd)
     33{
     34	struct iscsit_conn *conn = cmd->conn;
     35	/*
     36	 * Still set seq_start_offset and seq_end_offset for Unsolicited
     37	 * DataOUT, even if DataSequenceInOrder=No.
     38	 */
     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;
     44	}
     45
     46	if (!conn->sess->sess_ops->DataSequenceInOrder)
     47		return;
     48
     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);
     62	}
     63}
     64
     65static int iscsit_dataout_within_command_recovery_check(
     66	struct iscsit_cmd *cmd,
     67	unsigned char *buf)
     68{
     69	struct iscsit_conn *conn = cmd->conn;
     70	struct iscsi_data *hdr = (struct iscsi_data *) buf;
     71	u32 payload_length = ntoh24(hdr->dlength);
     72
     73	/*
     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.
     79	 *
     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.
     84	 */
     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;
     89
     90		cmd->cmd_flags &= ~ICF_WITHIN_COMMAND_RECOVERY;
     91	} else {
     92		struct iscsi_seq *seq;
     93
     94		seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
     95					    payload_length);
     96		if (!seq)
     97			return DATAOUT_CANNOT_RECOVER;
     98		/*
     99		 * Set the struct iscsi_seq pointer to reuse later.
    100		 */
    101		cmd->seq_ptr = seq;
    102
    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;
    114		}
    115
    116		if (seq->status == DATAOUT_SEQUENCE_COMPLETE)
    117			goto dump;
    118
    119		if (seq->status != DATAOUT_SEQUENCE_COMPLETE)
    120			seq->status = 0;
    121	}
    122
    123	return DATAOUT_NORMAL;
    124
    125dump:
    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);
    129}
    130
    131static int iscsit_dataout_check_unsolicited_sequence(
    132	struct iscsit_cmd *cmd,
    133	unsigned char *buf)
    134{
    135	u32 first_burst_len;
    136	struct iscsit_conn *conn = cmd->conn;
    137	struct iscsi_data *hdr = (struct iscsi_data *) buf;
    138	u32 payload_length = ntoh24(hdr->dlength);
    139
    140
    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;
    149	}
    150
    151	first_burst_len = (cmd->first_burst_len + payload_length);
    152
    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;
    160	}
    161
    162	/*
    163	 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
    164	 * checks for the current Unsolicited DataOUT Sequence.
    165	 */
    166	if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
    167		/*
    168		 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
    169		 * sequence checks are handled in
    170		 * iscsit_dataout_datapduinorder_no_fbit().
    171		 */
    172		if (!conn->sess->sess_ops->DataPDUInOrder)
    173			goto out;
    174
    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;
    185		}
    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;
    193		}
    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;
    199		}
    200	}
    201
    202out:
    203	return DATAOUT_NORMAL;
    204}
    205
    206static int iscsit_dataout_check_sequence(
    207	struct iscsit_cmd *cmd,
    208	unsigned char *buf)
    209{
    210	u32 next_burst_len;
    211	struct iscsit_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);
    215
    216	/*
    217	 * For DataSequenceInOrder=Yes: Check that the offset and offset+length
    218	 * is within range as defined by iscsi_set_dataout_sequence_values().
    219	 *
    220	 * For DataSequenceInOrder=No: Check that an struct iscsi_seq exists for
    221	 * offset+length tuple.
    222	 */
    223	if (conn->sess->sess_ops->DataSequenceInOrder) {
    224		/*
    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.
    228		 */
    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);
    236
    237			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
    238				return DATAOUT_CANNOT_RECOVER;
    239			return DATAOUT_WITHIN_COMMAND_RECOVERY;
    240		}
    241
    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;
    248		/*
    249		 * Set the struct iscsi_seq pointer to reuse later.
    250		 */
    251		cmd->seq_ptr = seq;
    252
    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;
    257		}
    258
    259		next_burst_len = (seq->next_burst_len + payload_length);
    260	}
    261
    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;
    269	}
    270
    271	/*
    272	 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
    273	 * checks for the current DataOUT Sequence.
    274	 */
    275	if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
    276		/*
    277		 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
    278		 * sequence checks are handled in
    279		 * iscsit_dataout_datapduinorder_no_fbit().
    280		 */
    281		if (!conn->sess->sess_ops->DataPDUInOrder)
    282			goto out;
    283
    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;
    293			}
    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;
    300			}
    301		}
    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;
    311			}
    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;
    319			}
    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;
    327			}
    328		}
    329	}
    330
    331out:
    332	return DATAOUT_NORMAL;
    333}
    334
    335static int iscsit_dataout_check_datasn(
    336	struct iscsit_cmd *cmd,
    337	unsigned char *buf)
    338{
    339	u32 data_sn = 0;
    340	struct iscsit_conn *conn = cmd->conn;
    341	struct iscsi_data *hdr = (struct iscsi_data *) buf;
    342	u32 payload_length = ntoh24(hdr->dlength);
    343
    344	/*
    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.
    349	 *
    350	 * If the DataSN is less than expected, dump the payload.
    351	 */
    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;
    357	}
    358
    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;
    369	}
    370
    371	return DATAOUT_NORMAL;
    372
    373recover:
    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;
    378	}
    379dump:
    380	if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
    381		return DATAOUT_CANNOT_RECOVER;
    382
    383	return DATAOUT_WITHIN_COMMAND_RECOVERY;
    384}
    385
    386static int iscsit_dataout_pre_datapduinorder_yes(
    387	struct iscsit_cmd *cmd,
    388	unsigned char *buf)
    389{
    390	int dump = 0, recovery = 0;
    391	struct iscsit_conn *conn = cmd->conn;
    392	struct iscsi_data *hdr = (struct iscsi_data *) buf;
    393	u32 payload_length = ntoh24(hdr->dlength);
    394
    395	/*
    396	 * For DataSequenceInOrder=Yes: If the offset is greater than the global
    397	 * DataPDUInOrder=Yes offset counter in struct iscsit_cmd a protcol error has
    398	 * occurred and fail the connection.
    399	 *
    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.
    403	 */
    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;
    411		}
    412	} else {
    413		struct iscsi_seq *seq = cmd->seq_ptr;
    414
    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;
    428		}
    429	}
    430
    431	return DATAOUT_NORMAL;
    432
    433recover:
    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;
    438	}
    439dump:
    440	if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
    441		return DATAOUT_CANNOT_RECOVER;
    442
    443	return (recovery) ? iscsit_recover_dataout_sequence(cmd,
    444		be32_to_cpu(hdr->offset), payload_length) :
    445	       (dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY : DATAOUT_NORMAL;
    446}
    447
    448static int iscsit_dataout_pre_datapduinorder_no(
    449	struct iscsit_cmd *cmd,
    450	unsigned char *buf)
    451{
    452	struct iscsi_pdu *pdu;
    453	struct iscsi_data *hdr = (struct iscsi_data *) buf;
    454	u32 payload_length = ntoh24(hdr->dlength);
    455
    456	pdu = iscsit_get_pdu_holder(cmd, be32_to_cpu(hdr->offset),
    457				    payload_length);
    458	if (!pdu)
    459		return DATAOUT_CANNOT_RECOVER;
    460
    461	cmd->pdu_ptr = pdu;
    462
    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;
    475	}
    476
    477	return DATAOUT_NORMAL;
    478}
    479
    480static int iscsit_dataout_update_r2t(struct iscsit_cmd *cmd, u32 offset, u32 length)
    481{
    482	struct iscsi_r2t *r2t;
    483
    484	if (cmd->unsolicited_data)
    485		return 0;
    486
    487	r2t = iscsit_get_r2t_for_eos(cmd, offset, length);
    488	if (!r2t)
    489		return -1;
    490
    491	spin_lock_bh(&cmd->r2t_lock);
    492	r2t->seq_complete = 1;
    493	cmd->outstanding_r2ts--;
    494	spin_unlock_bh(&cmd->r2t_lock);
    495
    496	return 0;
    497}
    498
    499static int iscsit_dataout_update_datapduinorder_no(
    500	struct iscsit_cmd *cmd,
    501	u32 data_sn,
    502	int f_bit)
    503{
    504	int ret = 0;
    505	struct iscsi_pdu *pdu = cmd->pdu_ptr;
    506
    507	pdu->data_sn = data_sn;
    508
    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;
    521	}
    522
    523	if (f_bit) {
    524		ret = iscsit_dataout_datapduinorder_no_fbit(cmd, pdu);
    525		if (ret == DATAOUT_CANNOT_RECOVER)
    526			return ret;
    527	}
    528
    529	return DATAOUT_NORMAL;
    530}
    531
    532static int iscsit_dataout_post_crc_passed(
    533	struct iscsit_cmd *cmd,
    534	unsigned char *buf)
    535{
    536	int ret, send_r2t = 0;
    537	struct iscsit_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);
    541
    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;
    549		}
    550
    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;
    557		}
    558
    559		cmd->first_burst_len += payload_length;
    560
    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;
    567		}
    568
    569		if (send_r2t) {
    570			if (seq)
    571				seq->status = DATAOUT_SEQUENCE_COMPLETE;
    572			cmd->first_burst_len = 0;
    573			cmd->unsolicited_data = 0;
    574		}
    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;
    584			}
    585
    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;
    592			}
    593
    594			cmd->next_burst_len += payload_length;
    595			cmd->data_sn++;
    596
    597			if (send_r2t)
    598				cmd->next_burst_len = 0;
    599		} else {
    600			seq = cmd->seq_ptr;
    601
    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;
    609			}
    610
    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;
    617			}
    618
    619			seq->data_sn++;
    620			seq->offset += payload_length;
    621			seq->next_burst_len += payload_length;
    622
    623			if (send_r2t) {
    624				seq->next_burst_len = 0;
    625				seq->status = DATAOUT_SEQUENCE_COMPLETE;
    626			}
    627		}
    628	}
    629
    630	if (send_r2t && conn->sess->sess_ops->DataSequenceInOrder)
    631		cmd->data_sn = 0;
    632
    633	cmd->write_data_done += payload_length;
    634
    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;
    641}
    642
    643static int iscsit_dataout_post_crc_failed(
    644	struct iscsit_cmd *cmd,
    645	unsigned char *buf)
    646{
    647	struct iscsit_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);
    651
    652	if (conn->sess->sess_ops->DataPDUInOrder)
    653		goto recover;
    654	/*
    655	 * The rest of this function is only called when DataPDUInOrder=No.
    656	 */
    657	pdu = cmd->pdu_ptr;
    658
    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;
    670	}
    671
    672recover:
    673	return iscsit_recover_dataout_sequence(cmd, be32_to_cpu(hdr->offset),
    674						payload_length);
    675}
    676
    677/*
    678 *	Called from iscsit_handle_data_out() before DataOUT Payload is received
    679 *	and CRC computed.
    680 */
    681int iscsit_check_pre_dataout(
    682	struct iscsit_cmd *cmd,
    683	unsigned char *buf)
    684{
    685	int ret;
    686	struct iscsit_conn *conn = cmd->conn;
    687
    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;
    692
    693	ret = iscsit_dataout_check_datasn(cmd, buf);
    694	if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
    695	    (ret == DATAOUT_CANNOT_RECOVER))
    696		return ret;
    697
    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;
    708	}
    709
    710	return (conn->sess->sess_ops->DataPDUInOrder) ?
    711		iscsit_dataout_pre_datapduinorder_yes(cmd, buf) :
    712		iscsit_dataout_pre_datapduinorder_no(cmd, buf);
    713}
    714
    715/*
    716 *	Called from iscsit_handle_data_out() after DataOUT Payload is received
    717 *	and CRC computed.
    718 */
    719int iscsit_check_post_dataout(
    720	struct iscsit_cmd *cmd,
    721	unsigned char *buf,
    722	u8 data_crc_failed)
    723{
    724	struct iscsit_conn *conn = cmd->conn;
    725
    726	cmd->dataout_timeout_retries = 0;
    727
    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;
    737		}
    738
    739		iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf);
    740		return iscsit_dataout_post_crc_failed(cmd, buf);
    741	}
    742}
    743
    744void iscsit_handle_time2retain_timeout(struct timer_list *t)
    745{
    746	struct iscsit_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;
    749
    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;
    754	}
    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;
    760	}
    761	sess->time2retain_timer_flags |= ISCSI_TF_EXPIRED;
    762
    763	pr_err("Time2Retain timer expired for SID: %u, cleaning up"
    764			" iSCSI session.\n", sess->sid);
    765
    766	iscsit_fill_cxn_timeout_err_stats(sess);
    767	spin_unlock_bh(&se_tpg->session_lock);
    768	iscsit_close_session(sess, false);
    769}
    770
    771void iscsit_start_time2retain_handler(struct iscsit_session *sess)
    772{
    773	int tpg_active;
    774	/*
    775	 * Only start Time2Retain timer when the associated TPG is still in
    776	 * an ACTIVE (eg: not disabled or shutdown) state.
    777	 */
    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);
    781
    782	if (!tpg_active)
    783		return;
    784
    785	if (sess->time2retain_timer_flags & ISCSI_TF_RUNNING)
    786		return;
    787
    788	pr_debug("Starting Time2Retain timer for %u seconds on"
    789		" SID: %u\n", sess->sess_ops->DefaultTime2Retain, sess->sid);
    790
    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);
    795}
    796
    797int iscsit_stop_time2retain_timer(struct iscsit_session *sess)
    798{
    799	struct iscsi_portal_group *tpg = sess->tpg;
    800	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
    801
    802	lockdep_assert_held(&se_tpg->session_lock);
    803
    804	if (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)
    805		return -1;
    806
    807	if (!(sess->time2retain_timer_flags & ISCSI_TF_RUNNING))
    808		return 0;
    809
    810	sess->time2retain_timer_flags |= ISCSI_TF_STOP;
    811	spin_unlock(&se_tpg->session_lock);
    812
    813	del_timer_sync(&sess->time2retain_timer);
    814
    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;
    820}
    821
    822void iscsit_connection_reinstatement_rcfr(struct iscsit_conn *conn)
    823{
    824	spin_lock_bh(&conn->state_lock);
    825	if (atomic_read(&conn->connection_exit)) {
    826		spin_unlock_bh(&conn->state_lock);
    827		goto sleep;
    828	}
    829
    830	if (atomic_read(&conn->transport_failed)) {
    831		spin_unlock_bh(&conn->state_lock);
    832		goto sleep;
    833	}
    834	spin_unlock_bh(&conn->state_lock);
    835
    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);
    840
    841sleep:
    842	wait_for_completion(&conn->conn_wait_rcfr_comp);
    843	complete(&conn->conn_post_wait_comp);
    844}
    845
    846void iscsit_cause_connection_reinstatement(struct iscsit_conn *conn, int sleep)
    847{
    848	spin_lock_bh(&conn->state_lock);
    849	if (atomic_read(&conn->connection_exit)) {
    850		spin_unlock_bh(&conn->state_lock);
    851		return;
    852	}
    853
    854	if (atomic_read(&conn->transport_failed)) {
    855		spin_unlock_bh(&conn->state_lock);
    856		return;
    857	}
    858
    859	if (atomic_read(&conn->connection_reinstatement)) {
    860		spin_unlock_bh(&conn->state_lock);
    861		return;
    862	}
    863
    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);
    868
    869	atomic_set(&conn->connection_reinstatement, 1);
    870	if (!sleep) {
    871		spin_unlock_bh(&conn->state_lock);
    872		return;
    873	}
    874
    875	atomic_set(&conn->sleep_on_conn_wait_comp, 1);
    876	spin_unlock_bh(&conn->state_lock);
    877
    878	wait_for_completion(&conn->conn_wait_comp);
    879	complete(&conn->conn_post_wait_comp);
    880}
    881EXPORT_SYMBOL(iscsit_cause_connection_reinstatement);
    882
    883void iscsit_fall_back_to_erl0(struct iscsit_session *sess)
    884{
    885	pr_debug("Falling back to ErrorRecoveryLevel=0 for SID:"
    886			" %u\n", sess->sid);
    887
    888	atomic_set(&sess->session_fall_back_to_erl0, 1);
    889}
    890
    891static void iscsit_handle_connection_cleanup(struct iscsit_conn *conn)
    892{
    893	struct iscsit_session *sess = conn->sess;
    894
    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);
    904	}
    905}
    906
    907void iscsit_take_action_for_connection_exit(struct iscsit_conn *conn, bool *conn_freed)
    908{
    909	*conn_freed = false;
    910
    911	spin_lock_bh(&conn->state_lock);
    912	if (atomic_read(&conn->connection_exit)) {
    913		spin_unlock_bh(&conn->state_lock);
    914		return;
    915	}
    916	atomic_set(&conn->connection_exit, 1);
    917
    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;
    923	}
    924
    925	if (conn->conn_state == TARG_CONN_STATE_CLEANUP_WAIT) {
    926		spin_unlock_bh(&conn->state_lock);
    927		return;
    928	}
    929
    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);
    933
    934	iscsit_handle_connection_cleanup(conn);
    935	*conn_freed = true;
    936}