|  |  | @ -492,6 +492,7 @@ static struct iscsit_transport iscsi_target_transport = { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	.iscsit_alloc_cmd	= iscsit_alloc_cmd, |  |  |  | 	.iscsit_alloc_cmd	= iscsit_alloc_cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  | 	.iscsit_get_login_rx	= iscsit_get_login_rx, |  |  |  | 	.iscsit_get_login_rx	= iscsit_get_login_rx, | 
			
		
	
		
		
			
				
					
					|  |  |  | 	.iscsit_put_login_tx	= iscsit_put_login_tx, |  |  |  | 	.iscsit_put_login_tx	= iscsit_put_login_tx, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	.iscsit_get_dataout	= iscsit_build_r2ts_for_cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int __init iscsi_target_init_module(void) |  |  |  | static int __init iscsi_target_init_module(void) | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -650,6 +651,14 @@ static int iscsit_add_reject( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |  |  |  | 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ret = wait_for_completion_interruptible(&cmd->reject_comp); |  |  |  | 	ret = wait_for_completion_interruptible(&cmd->reject_comp); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * Perform the kref_put now if se_cmd has been setup by | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * iscsit_setup_scsi_cmd() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (cmd->se_cmd.se_tfo != NULL) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (ret != 0) |  |  |  | 	if (ret != 0) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return -1; |  |  |  | 		return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -698,11 +707,20 @@ int iscsit_add_reject_from_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |  |  |  | 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ret = wait_for_completion_interruptible(&cmd->reject_comp); |  |  |  | 	ret = wait_for_completion_interruptible(&cmd->reject_comp); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * Perform the kref_put now if se_cmd has already been setup by | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * scsit_setup_scsi_cmd() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (cmd->se_cmd.se_tfo != NULL) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (ret != 0) |  |  |  | 	if (ret != 0) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return -1; |  |  |  | 		return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return (!fail_conn) ? 0 : -1; |  |  |  | 	return (!fail_conn) ? 0 : -1; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_add_reject_from_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /*
 |  |  |  | /*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Map some portion of the allocated scatterlist to an iovec, suitable for |  |  |  |  * Map some portion of the allocated scatterlist to an iovec, suitable for | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -761,6 +779,9 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	conn->exp_statsn = exp_statsn; |  |  |  | 	conn->exp_statsn = exp_statsn; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (conn->sess->sess_ops->RDMAExtensions) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	spin_lock_bh(&conn->cmd_lock); |  |  |  | 	spin_lock_bh(&conn->cmd_lock); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { |  |  |  | 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		spin_lock(&cmd->istate_lock); |  |  |  | 		spin_lock(&cmd->istate_lock); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -793,12 +814,10 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return 0; |  |  |  | 	return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_scsi_cmd( |  |  |  | int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_conn *conn, |  |  |  | 			  unsigned char *buf) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned char *buf) |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int data_direction, payload_length, cmdsn_ret = 0, immed_ret; |  |  |  | 	int data_direction, payload_length; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd = NULL; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_scsi_req *hdr; |  |  |  | 	struct iscsi_scsi_req *hdr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int iscsi_task_attr; |  |  |  | 	int iscsi_task_attr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int sam_task_attr; |  |  |  | 	int sam_task_attr; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -821,8 +840,8 @@ static int iscsit_handle_scsi_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) { |  |  |  | 	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL" |  |  |  | 		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL" | 
			
		
	
		
		
			
				
					
					|  |  |  | 				" not set. Bad iSCSI Initiator.\n"); |  |  |  | 				" not set. Bad iSCSI Initiator.\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (((hdr->flags & ISCSI_FLAG_CMD_READ) || |  |  |  | 	if (((hdr->flags & ISCSI_FLAG_CMD_READ) || | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -842,8 +861,8 @@ static int iscsit_handle_scsi_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" |  |  |  | 		pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" set when Expected Data Transfer Length is 0 for" |  |  |  | 			" set when Expected Data Transfer Length is 0 for" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); |  |  |  | 			" CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | done: |  |  |  | done: | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -852,29 +871,29 @@ done: | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE" |  |  |  | 		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" MUST be set if Expected Data Transfer Length is not 0." |  |  |  | 			" MUST be set if Expected Data Transfer Length is not 0." | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" Bad iSCSI Initiator\n"); |  |  |  | 			" Bad iSCSI Initiator\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if ((hdr->flags & ISCSI_FLAG_CMD_READ) && |  |  |  | 	if ((hdr->flags & ISCSI_FLAG_CMD_READ) && | 
			
		
	
		
		
			
				
					
					|  |  |  | 	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) { |  |  |  | 	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("Bidirectional operations not supported!\n"); |  |  |  | 		pr_err("Bidirectional operations not supported!\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (hdr->opcode & ISCSI_OP_IMMEDIATE) { |  |  |  | 	if (hdr->opcode & ISCSI_OP_IMMEDIATE) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("Illegally set Immediate Bit in iSCSI Initiator" |  |  |  | 		pr_err("Illegally set Immediate Bit in iSCSI Initiator" | 
			
		
	
		
		
			
				
					
					|  |  |  | 				" Scsi Command PDU.\n"); |  |  |  | 				" Scsi Command PDU.\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (payload_length && !conn->sess->sess_ops->ImmediateData) { |  |  |  | 	if (payload_length && !conn->sess->sess_ops->ImmediateData) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("ImmediateData=No but DataSegmentLength=%u," |  |  |  | 		pr_err("ImmediateData=No but DataSegmentLength=%u," | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" protocol error.\n", payload_length); |  |  |  | 			" protocol error.\n", payload_length); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if ((be32_to_cpu(hdr->data_length )== payload_length) && |  |  |  | 	if ((be32_to_cpu(hdr->data_length )== payload_length) && | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -882,43 +901,38 @@ done: | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("Expected Data Transfer Length and Length of" |  |  |  | 		pr_err("Expected Data Transfer Length and Length of" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL" |  |  |  | 			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" bit is not set protocol error\n"); |  |  |  | 			" bit is not set protocol error\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (payload_length > be32_to_cpu(hdr->data_length)) { |  |  |  | 	if (payload_length > be32_to_cpu(hdr->data_length)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("DataSegmentLength: %u is greater than" |  |  |  | 		pr_err("DataSegmentLength: %u is greater than" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" EDTL: %u, protocol error.\n", payload_length, |  |  |  | 			" EDTL: %u, protocol error.\n", payload_length, | 
			
		
	
		
		
			
				
					
					|  |  |  | 				hdr->data_length); |  |  |  | 				hdr->data_length); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { |  |  |  | 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("DataSegmentLength: %u is greater than" |  |  |  | 		pr_err("DataSegmentLength: %u is greater than" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" MaxXmitDataSegmentLength: %u, protocol error.\n", |  |  |  | 			" MaxXmitDataSegmentLength: %u, protocol error.\n", | 
			
		
	
		
		
			
				
					
					|  |  |  | 			payload_length, conn->conn_ops->MaxXmitDataSegmentLength); |  |  |  | 			payload_length, conn->conn_ops->MaxXmitDataSegmentLength); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (payload_length > conn->sess->sess_ops->FirstBurstLength) { |  |  |  | 	if (payload_length > conn->sess->sess_ops->FirstBurstLength) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("DataSegmentLength: %u is greater than" |  |  |  | 		pr_err("DataSegmentLength: %u is greater than" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" FirstBurstLength: %u, protocol error.\n", |  |  |  | 			" FirstBurstLength: %u, protocol error.\n", | 
			
		
	
		
		
			
				
					
					|  |  |  | 			payload_length, conn->sess->sess_ops->FirstBurstLength); |  |  |  | 			payload_length, conn->sess->sess_ops->FirstBurstLength); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 					buf, conn); |  |  |  | 				1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : |  |  |  | 	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : | 
			
		
	
		
		
			
				
					
					|  |  |  | 			 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE : |  |  |  | 			 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE : | 
			
		
	
		
		
			
				
					
					|  |  |  | 			  DMA_NONE; |  |  |  | 			  DMA_NONE; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!cmd) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					 buf, conn); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->data_direction = data_direction; |  |  |  | 	cmd->data_direction = data_direction; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK; |  |  |  | 	iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/*
 |  |  |  | 	/*
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -961,7 +975,8 @@ done: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn); |  |  |  | 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->first_burst_len	= payload_length; |  |  |  | 	cmd->first_burst_len	= payload_length; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (cmd->data_direction == DMA_FROM_DEVICE) { |  |  |  | 	if (!conn->sess->sess_ops->RDMAExtensions && | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	     cmd->data_direction == DMA_FROM_DEVICE) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		struct iscsi_datain_req *dr; |  |  |  | 		struct iscsi_datain_req *dr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		dr = iscsit_allocate_datain_req(); |  |  |  | 		dr = iscsit_allocate_datain_req(); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -983,7 +998,10 @@ done: | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x," |  |  |  | 	pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x," | 
			
		
	
		
		
			
				
					
					|  |  |  | 		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, |  |  |  | 		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, | 
			
		
	
		
		
			
				
					
					|  |  |  | 		hdr->cmdsn, hdr->data_length, payload_length, conn->cid); |  |  |  | 		hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		conn->cid); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, |  |  |  | 	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  | 						     scsilun_to_int(&hdr->lun)); |  |  |  | 						     scsilun_to_int(&hdr->lun)); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1017,12 +1035,24 @@ attach_cmd: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	core_alua_check_nonop_delay(&cmd->se_cmd); |  |  |  | 	core_alua_check_nonop_delay(&cmd->se_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (iscsit_allocate_iovecs(cmd) < 0) { |  |  |  | 	return 0; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject_from_cmd( |  |  |  | } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, |  |  |  | EXPORT_SYMBOL(iscsit_setup_scsi_cmd); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				1, 0, buf, cmd); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	iscsit_set_dataout_sequence_values(cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	spin_lock_bh(&cmd->dataout_timeout_lock); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	iscsit_start_dataout_timer(cmd, cmd->conn); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	spin_unlock_bh(&cmd->dataout_timeout_lock); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_set_unsoliticed_dataout); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			    struct iscsi_scsi_req *hdr) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	int cmdsn_ret = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/*
 |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if |  |  |  | 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * the Immediate Bit is not set, and no Immediate |  |  |  | 	 * the Immediate Bit is not set, and no Immediate | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1035,12 +1065,17 @@ attach_cmd: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!cmd->immediate_data) { |  |  |  | 	if (!cmd->immediate_data) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); |  |  |  | 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) |  |  |  | 		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			if (!cmd->sense_reason) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 			return 0; |  |  |  | 			return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) |  |  |  | 		} else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			return iscsit_add_reject_from_cmd( |  |  |  | 			return iscsit_add_reject_from_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 				ISCSI_REASON_PROTOCOL_ERROR, |  |  |  | 				ISCSI_REASON_PROTOCOL_ERROR, | 
			
		
	
		
		
			
				
					
					|  |  |  | 				1, 0, buf, cmd); |  |  |  | 				1, 0, (unsigned char *)hdr, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); |  |  |  | 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1049,25 +1084,23 @@ attach_cmd: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * If no Immediate Data is attached, it's OK to return now. |  |  |  | 	 * If no Immediate Data is attached, it's OK to return now. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!cmd->immediate_data) { |  |  |  | 	if (!cmd->immediate_data) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (!cmd->sense_reason && cmd->unsolicited_data) { |  |  |  | 		if (!cmd->sense_reason && cmd->unsolicited_data) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			iscsit_set_dataout_sequence_values(cmd); |  |  |  | 			iscsit_set_unsoliticed_dataout(cmd); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 		if (!cmd->sense_reason) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			spin_lock_bh(&cmd->dataout_timeout_lock); |  |  |  | 			return 0; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			iscsit_start_dataout_timer(cmd, cmd->conn); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			spin_unlock_bh(&cmd->dataout_timeout_lock); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return 0; |  |  |  | 		return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/*
 |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Early CHECK_CONDITIONs never make it to the transport processing |  |  |  | 	 * Early CHECK_CONDITIONs with ImmediateData never make it to command | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * thread.  They are processed in CmdSN order by |  |  |  | 	 * execution.  These exceptions are processed in CmdSN order using | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * iscsit_check_received_cmdsn() below. |  |  |  | 	 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below. | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (cmd->sense_reason) { |  |  |  | 	if (cmd->sense_reason) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; |  |  |  | 		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		goto after_immediate_data; |  |  |  | 		return 1; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/*
 |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Call directly into transport_generic_new_cmd() to perform |  |  |  | 	 * Call directly into transport_generic_new_cmd() to perform | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1075,11 +1108,27 @@ attach_cmd: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); |  |  |  | 	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (cmd->sense_reason) { |  |  |  | 	if (cmd->sense_reason) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; |  |  |  | 		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		goto after_immediate_data; |  |  |  | 		return 1; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	immed_ret = iscsit_handle_immediate_data(cmd, buf, payload_length); |  |  |  | 	return 0; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_process_scsi_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static int | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			  bool dump_payload) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (dump_payload == true) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		goto after_immediate_data; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	immed_ret = iscsit_handle_immediate_data(cmd, hdr, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 					cmd->first_burst_len); | 
			
		
	
		
		
			
				
					
					|  |  |  | after_immediate_data: |  |  |  | after_immediate_data: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) { |  |  |  | 	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		/*
 |  |  |  | 		/*
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1087,26 +1136,19 @@ after_immediate_data: | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * DataCRC, check against ExpCmdSN/MaxCmdSN if |  |  |  | 		 * DataCRC, check against ExpCmdSN/MaxCmdSN if | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * Immediate Bit is not set. |  |  |  | 		 * Immediate Bit is not set. | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 */ |  |  |  | 		 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); |  |  |  | 		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		/*
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * Special case for Unsupported SAM WRITE Opcodes |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * and ImmediateData=Yes. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (cmd->sense_reason) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				return -1; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else if (cmd->unsolicited_data) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			iscsit_set_dataout_sequence_values(cmd); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			spin_lock_bh(&cmd->dataout_timeout_lock); |  |  |  | 		if (cmd->sense_reason) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			iscsit_start_dataout_timer(cmd, cmd->conn); |  |  |  | 			if (iscsit_dump_data_payload(cmd->conn, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			spin_unlock_bh(&cmd->dataout_timeout_lock); |  |  |  | 					cmd->first_burst_len, 1) < 0) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 				return -1; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} else if (cmd->unsolicited_data) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			iscsit_set_unsoliticed_dataout(cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) |  |  |  | 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) | 
			
		
	
		
		
			
				
					
					|  |  |  | 			return iscsit_add_reject_from_cmd( |  |  |  | 			return iscsit_add_reject_from_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 				ISCSI_REASON_PROTOCOL_ERROR, |  |  |  | 				ISCSI_REASON_PROTOCOL_ERROR, | 
			
		
	
		
		
			
				
					
					|  |  |  | 				1, 0, buf, cmd); |  |  |  | 				1, 0, (unsigned char *)hdr, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { |  |  |  | 	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		/*
 |  |  |  | 		/*
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1121,13 +1163,47 @@ after_immediate_data: | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * CmdSN and issue a retry to plug the sequence. |  |  |  | 		 * CmdSN and issue a retry to plug the sequence. | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 */ |  |  |  | 		 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		cmd->i_state = ISTATE_REMOVE; |  |  |  | 		cmd->i_state = ISTATE_REMOVE; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state); |  |  |  | 		iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, cmd->i_state); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */ |  |  |  | 	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return -1; |  |  |  | 		return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return 0; |  |  |  | 	return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static int | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			   unsigned char *buf) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	int rc, immed_data; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	bool dump_payload = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	rc = iscsit_setup_scsi_cmd(conn, cmd, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (rc < 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return rc; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * Allocation iovecs needed for struct socket operations for | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * traditional iSCSI block I/O. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (iscsit_allocate_iovecs(cmd) < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return iscsit_add_reject_from_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				1, 0, buf, cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	immed_data = cmd->immediate_data; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	rc = iscsit_process_scsi_cmd(conn, cmd, hdr); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (rc < 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return rc; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	else if (rc > 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		dump_payload = true; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (!immed_data) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return iscsit_get_immediate_data(cmd, hdr, dump_payload); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static u32 iscsit_do_crypto_hash_sg( |  |  |  | static u32 iscsit_do_crypto_hash_sg( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct hash_desc *hash, |  |  |  | 	struct hash_desc *hash, | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd, |  |  |  | 	struct iscsi_cmd *cmd, | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1190,20 +1266,16 @@ static void iscsit_do_crypto_hash_buf( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	crypto_hash_final(hash, data_crc); |  |  |  | 	crypto_hash_final(hash, data_crc); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) |  |  |  | int | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			  struct iscsi_cmd **out_cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int iov_ret, ooo_cmdsn = 0, ret; |  |  |  | 	struct iscsi_data *hdr = (struct iscsi_data *)buf; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	u8 data_crc_failed = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	u32 checksum, iov_count = 0, padding = 0, rx_got = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	u32 rx_size = 0, payload_length; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd = NULL; |  |  |  | 	struct iscsi_cmd *cmd = NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct se_cmd *se_cmd; |  |  |  | 	struct se_cmd *se_cmd; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_data *hdr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct kvec *iov; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned long flags; |  |  |  | 	unsigned long flags; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 	u32 payload_length = ntoh24(hdr->dlength); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	hdr			= (struct iscsi_data *) buf; |  |  |  | 	int rc; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	payload_length		= ntoh24(hdr->dlength); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!payload_length) { |  |  |  | 	if (!payload_length) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("DataOUT payload is ZERO, protocol error.\n"); |  |  |  | 		pr_err("DataOUT payload is ZERO, protocol error.\n"); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1236,7 +1308,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x," |  |  |  | 	pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x," | 
			
		
	
		
		
			
				
					
					|  |  |  | 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n", |  |  |  | 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n", | 
			
		
	
		
		
			
				
					
					|  |  |  | 		hdr->itt, hdr->ttt, hdr->datasn, hdr->offset, |  |  |  | 		hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset), | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		payload_length, conn->cid); |  |  |  | 		payload_length, conn->cid); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) { |  |  |  | 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) { | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1328,12 +1400,26 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Preform DataSN, DataSequenceInOrder, DataPDUInOrder, and |  |  |  | 	 * Preform DataSN, DataSequenceInOrder, DataPDUInOrder, and | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * within-command recovery checks before receiving the payload. |  |  |  | 	 * within-command recovery checks before receiving the payload. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ret = iscsit_check_pre_dataout(cmd, buf); |  |  |  | 	rc = iscsit_check_pre_dataout(cmd, buf); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	if (ret == DATAOUT_WITHIN_COMMAND_RECOVERY) |  |  |  | 	if (rc == DATAOUT_WITHIN_COMMAND_RECOVERY) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		return 0; |  |  |  | 		return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	else if (ret == DATAOUT_CANNOT_RECOVER) |  |  |  | 	else if (rc == DATAOUT_CANNOT_RECOVER) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		return -1; |  |  |  | 		return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	*out_cmd = cmd; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_check_dataout_hdr); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static int | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		   struct iscsi_data *hdr) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct kvec *iov; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	u32 payload_length = ntoh24(hdr->dlength); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	int iov_ret, data_crc_failed = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	rx_size += payload_length; |  |  |  | 	rx_size += payload_length; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	iov = &cmd->iov_data[0]; |  |  |  | 	iov = &cmd->iov_data[0]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1386,17 +1472,27 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) | 
			
		
	
		
		
			
				
					
					|  |  |  | 				payload_length); |  |  |  | 				payload_length); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return data_crc_failed; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | int | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | iscsit_check_dataout_payload(struct iscsi_cmd *cmd, struct iscsi_data *hdr, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			     bool data_crc_failed) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct iscsi_conn *conn = cmd->conn; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	int rc, ooo_cmdsn; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/*
 |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Increment post receive data and CRC values or perform |  |  |  | 	 * Increment post receive data and CRC values or perform | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * within-command recovery. |  |  |  | 	 * within-command recovery. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ret = iscsit_check_post_dataout(cmd, buf, data_crc_failed); |  |  |  | 	rc = iscsit_check_post_dataout(cmd, (unsigned char *)hdr, data_crc_failed); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	if ((ret == DATAOUT_NORMAL) || (ret == DATAOUT_WITHIN_COMMAND_RECOVERY)) |  |  |  | 	if ((rc == DATAOUT_NORMAL) || (rc == DATAOUT_WITHIN_COMMAND_RECOVERY)) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		return 0; |  |  |  | 		return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	else if (ret == DATAOUT_SEND_R2T) { |  |  |  | 	else if (rc == DATAOUT_SEND_R2T) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		iscsit_set_dataout_sequence_values(cmd); |  |  |  | 		iscsit_set_dataout_sequence_values(cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		iscsit_build_r2ts_for_cmd(cmd, conn, false); |  |  |  | 		conn->conn_transport->iscsit_get_dataout(conn, cmd, false); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	} else if (ret == DATAOUT_SEND_TO_TRANSPORT) { |  |  |  | 	} else if (rc == DATAOUT_SEND_TO_TRANSPORT) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		/*
 |  |  |  | 		/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * Handle extra special case for out of order |  |  |  | 		 * Handle extra special case for out of order | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * Unsolicited Data Out. |  |  |  | 		 * Unsolicited Data Out. | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1417,15 +1513,37 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return 0; |  |  |  | 	return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_check_dataout_payload); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_nop_out( |  |  |  | static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_conn *conn, |  |  |  | { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned char *buf) |  |  |  | 	struct iscsi_cmd *cmd; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct iscsi_data *hdr = (struct iscsi_data *)buf; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	int rc; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	bool data_crc_failed = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	rc = iscsit_check_dataout_hdr(conn, buf, &cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (rc < 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return rc; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	else if (!cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	rc = iscsit_get_dataout(conn, cmd, hdr); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (rc < 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return rc; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	else if (rc > 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		data_crc_failed = true; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			unsigned char *buf) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned char *ping_data = NULL; |  |  |  | 	unsigned char *ping_data = NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size; |  |  |  | 	int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	u32 checksum, data_crc, padding = 0, payload_length; |  |  |  | 	u32 checksum, data_crc, padding = 0, payload_length; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd = NULL; |  |  |  | 	struct iscsi_cmd *cmd_p = NULL; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	struct kvec *iov = NULL; |  |  |  | 	struct kvec *iov = NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_nopout *hdr; |  |  |  | 	struct iscsi_nopout *hdr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1448,7 +1566,7 @@ static int iscsit_handle_nop_out( | 
			
		
	
		
		
			
				
					
					|  |  |  | 					buf, conn); |  |  |  | 					buf, conn); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%09x," |  |  |  | 	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n", |  |  |  | 		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n", | 
			
		
	
		
		
			
				
					
					|  |  |  | 		hdr->itt == RESERVED_ITT ? "Response" : "Request", |  |  |  | 		hdr->itt == RESERVED_ITT ? "Response" : "Request", | 
			
		
	
		
		
			
				
					
					|  |  |  | 		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn, |  |  |  | 		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn, | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1461,7 +1579,6 @@ static int iscsit_handle_nop_out( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * can contain ping data. |  |  |  | 	 * can contain ping data. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { |  |  |  | 	if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (!cmd) |  |  |  | 		if (!cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  | 			return iscsit_add_reject( |  |  |  | 			return iscsit_add_reject( | 
			
		
	
		
		
			
				
					
					|  |  |  | 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, |  |  |  | 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1596,14 +1713,14 @@ static int iscsit_handle_nop_out( | 
			
		
	
		
		
			
				
					
					|  |  |  | 		/*
 |  |  |  | 		/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * This was a response to a unsolicited NOPIN ping. |  |  |  | 		 * This was a response to a unsolicited NOPIN ping. | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 */ |  |  |  | 		 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		cmd = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt)); |  |  |  | 		cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		if (!cmd) |  |  |  | 		if (!cmd_p) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			return -1; |  |  |  | 			return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		iscsit_stop_nopin_response_timer(conn); |  |  |  | 		iscsit_stop_nopin_response_timer(conn); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		cmd->i_state = ISTATE_REMOVE; |  |  |  | 		cmd_p->i_state = ISTATE_REMOVE; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state); |  |  |  | 		iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		iscsit_start_nopin_timer(conn); |  |  |  | 		iscsit_start_nopin_timer(conn); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} else { |  |  |  | 	} else { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		/*
 |  |  |  | 		/*
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1627,12 +1744,12 @@ ping_out: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	kfree(ping_data); |  |  |  | 	kfree(ping_data); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return ret; |  |  |  | 	return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_handle_nop_out); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_task_mgt_cmd( |  |  |  | int | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_conn *conn, |  |  |  | iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned char *buf) |  |  |  | 			   unsigned char *buf) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct se_tmr_req *se_tmr; |  |  |  | 	struct se_tmr_req *se_tmr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_tmr_req *tmr_req; |  |  |  | 	struct iscsi_tmr_req *tmr_req; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_tm *hdr; |  |  |  | 	struct iscsi_tm *hdr; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1661,18 +1778,13 @@ static int iscsit_handle_task_mgt_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("Task Management Request TASK_REASSIGN not" |  |  |  | 		pr_err("Task Management Request TASK_REASSIGN not" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" issued as immediate command, bad iSCSI Initiator" |  |  |  | 			" issued as immediate command, bad iSCSI Initiator" | 
			
		
	
		
		
			
				
					
					|  |  |  | 				"implementation\n"); |  |  |  | 				"implementation\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, |  |  |  | 		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 					buf, conn); |  |  |  | 					1, 1, buf, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) && |  |  |  | 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) && | 
			
		
	
		
		
			
				
					
					|  |  |  | 	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG) |  |  |  | 	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG); |  |  |  | 		hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!cmd) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					 1, buf, conn); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->data_direction = DMA_NONE; |  |  |  | 	cmd->data_direction = DMA_NONE; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL); |  |  |  | 	cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -1843,6 +1955,7 @@ attach: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |  |  |  | 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return 0; |  |  |  | 	return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /* #warning FIXME: Support Text Command parameters besides SendTargets */ |  |  |  | /* #warning FIXME: Support Text Command parameters besides SendTargets */ | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_text_cmd( |  |  |  | static int iscsit_handle_text_cmd( | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -2105,13 +2218,12 @@ int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *cmd, struct iscsi_conn | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return 0; |  |  |  | 	return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_logout_cmd( |  |  |  | int | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_conn *conn, |  |  |  | iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned char *buf) |  |  |  | 			unsigned char *buf) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int cmdsn_ret, logout_remove = 0; |  |  |  | 	int cmdsn_ret, logout_remove = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	u8 reason_code = 0; |  |  |  | 	u8 reason_code = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_logout *hdr; |  |  |  | 	struct iscsi_logout *hdr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn); |  |  |  | 	struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -2135,14 +2247,10 @@ static int iscsit_handle_logout_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) { |  |  |  | 	if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		pr_err("Received logout request on connection that" |  |  |  | 		pr_err("Received logout request on connection that" | 
			
		
	
		
		
			
				
					
					|  |  |  | 			" is not in logged in state, ignoring request.\n"); |  |  |  | 			" is not in logged in state, ignoring request.\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		iscsit_release_cmd(cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return 0; |  |  |  | 		return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!cmd) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					buf, conn); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->iscsi_opcode       = ISCSI_OP_LOGOUT; |  |  |  | 	cmd->iscsi_opcode       = ISCSI_OP_LOGOUT; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->i_state            = ISTATE_SEND_LOGOUTRSP; |  |  |  | 	cmd->i_state            = ISTATE_SEND_LOGOUTRSP; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0); |  |  |  | 	cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -2192,6 +2300,7 @@ static int iscsit_handle_logout_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return logout_remove; |  |  |  | 	return logout_remove; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | EXPORT_SYMBOL(iscsit_handle_logout_cmd); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_snack( |  |  |  | static int iscsit_handle_snack( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_conn *conn, |  |  |  | 	struct iscsi_conn *conn, | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -2259,7 +2368,7 @@ static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int iscsit_handle_immediate_data( |  |  |  | static int iscsit_handle_immediate_data( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd, |  |  |  | 	struct iscsi_cmd *cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned char *buf, |  |  |  | 	struct iscsi_scsi_req *hdr, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	u32 length) |  |  |  | 	u32 length) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int iov_ret, rx_got = 0, rx_size = 0; |  |  |  | 	int iov_ret, rx_got = 0, rx_size = 0; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -2315,12 +2424,12 @@ static int iscsit_handle_immediate_data( | 
			
		
	
		
		
			
				
					
					|  |  |  | 					" in ERL=0.\n"); |  |  |  | 					" in ERL=0.\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 				iscsit_add_reject_from_cmd( |  |  |  | 				iscsit_add_reject_from_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 						ISCSI_REASON_DATA_DIGEST_ERROR, |  |  |  | 						ISCSI_REASON_DATA_DIGEST_ERROR, | 
			
		
	
		
		
			
				
					
					|  |  |  | 						1, 0, buf, cmd); |  |  |  | 						1, 0, (unsigned char *)hdr, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 				return IMMEDIATE_DATA_CANNOT_RECOVER; |  |  |  | 				return IMMEDIATE_DATA_CANNOT_RECOVER; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} else { |  |  |  | 			} else { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				iscsit_add_reject_from_cmd( |  |  |  | 				iscsit_add_reject_from_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 						ISCSI_REASON_DATA_DIGEST_ERROR, |  |  |  | 						ISCSI_REASON_DATA_DIGEST_ERROR, | 
			
		
	
		
		
			
				
					
					|  |  |  | 						0, 0, buf, cmd); |  |  |  | 						0, 0, (unsigned char *)hdr, cmd); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 				return IMMEDIATE_DATA_ERL1_CRC_FAILURE; |  |  |  | 				return IMMEDIATE_DATA_ERL1_CRC_FAILURE; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { |  |  |  | 		} else { | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -2955,8 +3064,8 @@ static int iscsit_send_r2t( | 
			
		
	
		
		
			
				
					
					|  |  |  |  *		connection recovery. |  |  |  |  *		connection recovery. | 
			
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | int iscsit_build_r2ts_for_cmd( |  |  |  | int iscsit_build_r2ts_for_cmd( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_cmd *cmd, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct iscsi_conn *conn, |  |  |  | 	struct iscsi_conn *conn, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct iscsi_cmd *cmd, | 
			
		
	
		
		
			
				
					
					|  |  |  | 	bool recovery) |  |  |  | 	bool recovery) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int first_r2t = 1; |  |  |  | 	int first_r2t = 1; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -3758,6 +3867,83 @@ out: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return 0; |  |  |  | 	return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)buf; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct iscsi_cmd *cmd; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	int ret = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	switch (hdr->opcode & ISCSI_OPCODE_MASK) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case ISCSI_OP_SCSI_CMD: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (!cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 						1, buf, conn); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		ret = iscsit_handle_scsi_cmd(conn, cmd, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case ISCSI_OP_SCSI_DATA_OUT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		ret = iscsit_handle_data_out(conn, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case ISCSI_OP_NOOP_OUT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		cmd = NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			if (!cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 						1, buf, conn); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		ret = iscsit_handle_nop_out(conn, cmd, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case ISCSI_OP_SCSI_TMFUNC: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (!cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 						1, buf, conn); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case ISCSI_OP_TEXT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		ret = iscsit_handle_text_cmd(conn, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case ISCSI_OP_LOGOUT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (!cmd) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 						1, buf, conn); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		ret = iscsit_handle_logout_cmd(conn, cmd, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (ret > 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			wait_for_completion_timeout(&conn->conn_logout_comp, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 					SECONDS_FOR_LOGOUT_COMP * HZ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case ISCSI_OP_SNACK: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		ret = iscsit_handle_snack(conn, buf); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	default: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		pr_err("Got unknown iSCSI OpCode: 0x%02x\n", hdr->opcode); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (!conn->sess->sess_ops->ErrorRecoveryLevel) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			pr_err("Cannot recover from unknown" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			" opcode while ERL=0, closing iSCSI connection.\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (!conn->conn_ops->OFMarker) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			pr_err("Unable to recover from unknown" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			" opcode while OFMarker=No, closing iSCSI" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				" connection.\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (iscsit_recover_from_unknown_opcode(conn) < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			pr_err("Unable to recover from unknown" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				" opcode, closing iSCSI connection.\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | int iscsi_target_rx_thread(void *arg) |  |  |  | int iscsi_target_rx_thread(void *arg) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int ret; |  |  |  | 	int ret; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -3777,6 +3963,18 @@ restart: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!conn) |  |  |  | 	if (!conn) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		goto out; |  |  |  | 		goto out; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		struct completion comp; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		int rc; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		init_completion(&comp); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		rc = wait_for_completion_interruptible(&comp); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (rc < 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			goto transport_err; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		goto out; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	while (!kthread_should_stop()) { |  |  |  | 	while (!kthread_should_stop()) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		/*
 |  |  |  | 		/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 * Ensure that both TX and RX per connection kthreads |  |  |  | 		 * Ensure that both TX and RX per connection kthreads | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -3848,62 +4046,9 @@ restart: | 
			
		
	
		
		
			
				
					
					|  |  |  | 			goto transport_err; |  |  |  | 			goto transport_err; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		switch (opcode) { |  |  |  | 		ret = iscsi_target_rx_opcode(conn, buffer); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		case ISCSI_OP_SCSI_CMD: |  |  |  | 		if (ret < 0) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_handle_scsi_cmd(conn, buffer) < 0) |  |  |  | 			goto transport_err; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		case ISCSI_OP_SCSI_DATA_OUT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_handle_data_out(conn, buffer) < 0) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		case ISCSI_OP_NOOP_OUT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_handle_nop_out(conn, buffer) < 0) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		case ISCSI_OP_SCSI_TMFUNC: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_handle_task_mgt_cmd(conn, buffer) < 0) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		case ISCSI_OP_TEXT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_handle_text_cmd(conn, buffer) < 0) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		case ISCSI_OP_LOGOUT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			ret = iscsit_handle_logout_cmd(conn, buffer); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (ret > 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				wait_for_completion_timeout(&conn->conn_logout_comp, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 						SECONDS_FOR_LOGOUT_COMP * HZ); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} else if (ret < 0) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		case ISCSI_OP_SNACK: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_handle_snack(conn, buffer) < 0) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		default: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			pr_err("Got unknown iSCSI OpCode: 0x%02x\n", |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					opcode); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (!conn->sess->sess_ops->ErrorRecoveryLevel) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				pr_err("Cannot recover from unknown" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				" opcode while ERL=0, closing iSCSI connection" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				".\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (!conn->conn_ops->OFMarker) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				pr_err("Unable to recover from unknown" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				" opcode while OFMarker=No, closing iSCSI" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					" connection.\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (iscsit_recover_from_unknown_opcode(conn) < 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				pr_err("Unable to recover from unknown" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					" opcode, closing iSCSI connection.\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto transport_err; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | transport_err: |  |  |  | transport_err: | 
			
		
	
	
		
		
			
				
					
					|  |  | 
 |