1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e48354ceSNicholas Bellinger /*******************************************************************************
3e48354ceSNicholas Bellinger  * This file contains the iSCSI Target DataIN value generation functions.
4e48354ceSNicholas Bellinger  *
54c76251eSNicholas Bellinger  * (c) Copyright 2007-2013 Datera, Inc.
6e48354ceSNicholas Bellinger  *
7e48354ceSNicholas Bellinger  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
8e48354ceSNicholas Bellinger  *
9e48354ceSNicholas Bellinger  ******************************************************************************/
10e48354ceSNicholas Bellinger 
118dcf07beSBart Van Assche #include <linux/slab.h>
12e48354ceSNicholas Bellinger #include <scsi/iscsi_proto.h>
1367f091f2SSagi Grimberg #include <target/iscsi/iscsi_target_core.h>
14e48354ceSNicholas Bellinger #include "iscsi_target_seq_pdu_list.h"
15e48354ceSNicholas Bellinger #include "iscsi_target_erl1.h"
16e48354ceSNicholas Bellinger #include "iscsi_target_util.h"
17e48354ceSNicholas Bellinger #include "iscsi_target.h"
18e48354ceSNicholas Bellinger #include "iscsi_target_datain_values.h"
19e48354ceSNicholas Bellinger 
iscsit_allocate_datain_req(void)20e48354ceSNicholas Bellinger struct iscsi_datain_req *iscsit_allocate_datain_req(void)
21e48354ceSNicholas Bellinger {
22e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
23e48354ceSNicholas Bellinger 
24e48354ceSNicholas Bellinger 	dr = kmem_cache_zalloc(lio_dr_cache, GFP_ATOMIC);
25e48354ceSNicholas Bellinger 	if (!dr) {
26e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for"
27e48354ceSNicholas Bellinger 				" struct iscsi_datain_req\n");
28e48354ceSNicholas Bellinger 		return NULL;
29e48354ceSNicholas Bellinger 	}
308b1e1244SAndy Grover 	INIT_LIST_HEAD(&dr->cmd_datain_node);
31e48354ceSNicholas Bellinger 
32e48354ceSNicholas Bellinger 	return dr;
33e48354ceSNicholas Bellinger }
34e48354ceSNicholas Bellinger 
iscsit_attach_datain_req(struct iscsit_cmd * cmd,struct iscsi_datain_req * dr)3566cd9d4eSMax Gurtovoy void iscsit_attach_datain_req(struct iscsit_cmd *cmd, struct iscsi_datain_req *dr)
36e48354ceSNicholas Bellinger {
37e48354ceSNicholas Bellinger 	spin_lock(&cmd->datain_lock);
388b1e1244SAndy Grover 	list_add_tail(&dr->cmd_datain_node, &cmd->datain_list);
39e48354ceSNicholas Bellinger 	spin_unlock(&cmd->datain_lock);
40e48354ceSNicholas Bellinger }
41e48354ceSNicholas Bellinger 
iscsit_free_datain_req(struct iscsit_cmd * cmd,struct iscsi_datain_req * dr)4266cd9d4eSMax Gurtovoy void iscsit_free_datain_req(struct iscsit_cmd *cmd, struct iscsi_datain_req *dr)
43e48354ceSNicholas Bellinger {
44e48354ceSNicholas Bellinger 	spin_lock(&cmd->datain_lock);
458b1e1244SAndy Grover 	list_del(&dr->cmd_datain_node);
46e48354ceSNicholas Bellinger 	spin_unlock(&cmd->datain_lock);
47e48354ceSNicholas Bellinger 
48e48354ceSNicholas Bellinger 	kmem_cache_free(lio_dr_cache, dr);
49e48354ceSNicholas Bellinger }
50e48354ceSNicholas Bellinger 
iscsit_free_all_datain_reqs(struct iscsit_cmd * cmd)5166cd9d4eSMax Gurtovoy void iscsit_free_all_datain_reqs(struct iscsit_cmd *cmd)
52e48354ceSNicholas Bellinger {
53e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr, *dr_tmp;
54e48354ceSNicholas Bellinger 
55e48354ceSNicholas Bellinger 	spin_lock(&cmd->datain_lock);
568b1e1244SAndy Grover 	list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, cmd_datain_node) {
578b1e1244SAndy Grover 		list_del(&dr->cmd_datain_node);
58e48354ceSNicholas Bellinger 		kmem_cache_free(lio_dr_cache, dr);
59e48354ceSNicholas Bellinger 	}
60e48354ceSNicholas Bellinger 	spin_unlock(&cmd->datain_lock);
61e48354ceSNicholas Bellinger }
62e48354ceSNicholas Bellinger 
iscsit_get_datain_req(struct iscsit_cmd * cmd)6366cd9d4eSMax Gurtovoy struct iscsi_datain_req *iscsit_get_datain_req(struct iscsit_cmd *cmd)
64e48354ceSNicholas Bellinger {
65e48354ceSNicholas Bellinger 	if (list_empty(&cmd->datain_list)) {
66e48354ceSNicholas Bellinger 		pr_err("cmd->datain_list is empty for ITT:"
67e48354ceSNicholas Bellinger 			" 0x%08x\n", cmd->init_task_tag);
68e48354ceSNicholas Bellinger 		return NULL;
69e48354ceSNicholas Bellinger 	}
70e48354ceSNicholas Bellinger 
718b1e1244SAndy Grover 	return list_first_entry(&cmd->datain_list, struct iscsi_datain_req,
728b1e1244SAndy Grover 				cmd_datain_node);
73e48354ceSNicholas Bellinger }
74e48354ceSNicholas Bellinger 
75e48354ceSNicholas Bellinger /*
76e48354ceSNicholas Bellinger  *	For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=Yes.
77e48354ceSNicholas Bellinger  */
iscsit_set_datain_values_yes_and_yes(struct iscsit_cmd * cmd,struct iscsi_datain * datain)78e48354ceSNicholas Bellinger static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_yes(
7966cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
80e48354ceSNicholas Bellinger 	struct iscsi_datain *datain)
81e48354ceSNicholas Bellinger {
82e48354ceSNicholas Bellinger 	u32 next_burst_len, read_data_done, read_data_left;
83*be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
84e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
85e48354ceSNicholas Bellinger 
86e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_req(cmd);
87e48354ceSNicholas Bellinger 	if (!dr)
88e48354ceSNicholas Bellinger 		return NULL;
89e48354ceSNicholas Bellinger 
90e48354ceSNicholas Bellinger 	if (dr->recovery && dr->generate_recovery_values) {
91e48354ceSNicholas Bellinger 		if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
92e48354ceSNicholas Bellinger 					cmd, dr) < 0)
93e48354ceSNicholas Bellinger 			return NULL;
94e48354ceSNicholas Bellinger 
95e48354ceSNicholas Bellinger 		dr->generate_recovery_values = 0;
96e48354ceSNicholas Bellinger 	}
97e48354ceSNicholas Bellinger 
98e48354ceSNicholas Bellinger 	next_burst_len = (!dr->recovery) ?
99e48354ceSNicholas Bellinger 			cmd->next_burst_len : dr->next_burst_len;
100e48354ceSNicholas Bellinger 	read_data_done = (!dr->recovery) ?
101e48354ceSNicholas Bellinger 			cmd->read_data_done : dr->read_data_done;
102e48354ceSNicholas Bellinger 
103ebf1d95cSAndy Grover 	read_data_left = (cmd->se_cmd.data_length - read_data_done);
104e48354ceSNicholas Bellinger 	if (!read_data_left) {
105e48354ceSNicholas Bellinger 		pr_err("ITT: 0x%08x read_data_left is zero!\n",
106e48354ceSNicholas Bellinger 				cmd->init_task_tag);
107e48354ceSNicholas Bellinger 		return NULL;
108e48354ceSNicholas Bellinger 	}
109e48354ceSNicholas Bellinger 
110e48354ceSNicholas Bellinger 	if ((read_data_left <= conn->conn_ops->MaxRecvDataSegmentLength) &&
111e48354ceSNicholas Bellinger 	    (read_data_left <= (conn->sess->sess_ops->MaxBurstLength -
112e48354ceSNicholas Bellinger 	     next_burst_len))) {
113e48354ceSNicholas Bellinger 		datain->length = read_data_left;
114e48354ceSNicholas Bellinger 
115e48354ceSNicholas Bellinger 		datain->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
116e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
117e48354ceSNicholas Bellinger 			datain->flags |= ISCSI_FLAG_DATA_ACK;
118e48354ceSNicholas Bellinger 	} else {
119e48354ceSNicholas Bellinger 		if ((next_burst_len +
120e48354ceSNicholas Bellinger 		     conn->conn_ops->MaxRecvDataSegmentLength) <
121e48354ceSNicholas Bellinger 		     conn->sess->sess_ops->MaxBurstLength) {
122e48354ceSNicholas Bellinger 			datain->length =
123e48354ceSNicholas Bellinger 				conn->conn_ops->MaxRecvDataSegmentLength;
124e48354ceSNicholas Bellinger 			next_burst_len += datain->length;
125e48354ceSNicholas Bellinger 		} else {
126e48354ceSNicholas Bellinger 			datain->length = (conn->sess->sess_ops->MaxBurstLength -
127e48354ceSNicholas Bellinger 					  next_burst_len);
128e48354ceSNicholas Bellinger 			next_burst_len = 0;
129e48354ceSNicholas Bellinger 
130e48354ceSNicholas Bellinger 			datain->flags |= ISCSI_FLAG_CMD_FINAL;
131e48354ceSNicholas Bellinger 			if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
132e48354ceSNicholas Bellinger 				datain->flags |= ISCSI_FLAG_DATA_ACK;
133e48354ceSNicholas Bellinger 		}
134e48354ceSNicholas Bellinger 	}
135e48354ceSNicholas Bellinger 
136e48354ceSNicholas Bellinger 	datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
137e48354ceSNicholas Bellinger 	datain->offset = read_data_done;
138e48354ceSNicholas Bellinger 
139e48354ceSNicholas Bellinger 	if (!dr->recovery) {
140e48354ceSNicholas Bellinger 		cmd->next_burst_len = next_burst_len;
141e48354ceSNicholas Bellinger 		cmd->read_data_done += datain->length;
142e48354ceSNicholas Bellinger 	} else {
143e48354ceSNicholas Bellinger 		dr->next_burst_len = next_burst_len;
144e48354ceSNicholas Bellinger 		dr->read_data_done += datain->length;
145e48354ceSNicholas Bellinger 	}
146e48354ceSNicholas Bellinger 
147e48354ceSNicholas Bellinger 	if (!dr->recovery) {
148e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
149e48354ceSNicholas Bellinger 			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
150e48354ceSNicholas Bellinger 
151e48354ceSNicholas Bellinger 		return dr;
152e48354ceSNicholas Bellinger 	}
153e48354ceSNicholas Bellinger 
154e48354ceSNicholas Bellinger 	if (!dr->runlength) {
155e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
156e48354ceSNicholas Bellinger 			dr->dr_complete =
157e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
158e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
159e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
160e48354ceSNicholas Bellinger 		}
161e48354ceSNicholas Bellinger 	} else {
162e48354ceSNicholas Bellinger 		if ((dr->begrun + dr->runlength) == dr->data_sn) {
163e48354ceSNicholas Bellinger 			dr->dr_complete =
164e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
165e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
166e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
167e48354ceSNicholas Bellinger 		}
168e48354ceSNicholas Bellinger 	}
169e48354ceSNicholas Bellinger 
170e48354ceSNicholas Bellinger 	return dr;
171e48354ceSNicholas Bellinger }
172e48354ceSNicholas Bellinger 
173e48354ceSNicholas Bellinger /*
174e48354ceSNicholas Bellinger  *	For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=Yes.
175e48354ceSNicholas Bellinger  */
iscsit_set_datain_values_no_and_yes(struct iscsit_cmd * cmd,struct iscsi_datain * datain)176e48354ceSNicholas Bellinger static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
17766cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
178e48354ceSNicholas Bellinger 	struct iscsi_datain *datain)
179e48354ceSNicholas Bellinger {
180e48354ceSNicholas Bellinger 	u32 offset, read_data_done, read_data_left, seq_send_order;
181*be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
182e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
183e48354ceSNicholas Bellinger 	struct iscsi_seq *seq;
184e48354ceSNicholas Bellinger 
185e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_req(cmd);
186e48354ceSNicholas Bellinger 	if (!dr)
187e48354ceSNicholas Bellinger 		return NULL;
188e48354ceSNicholas Bellinger 
189e48354ceSNicholas Bellinger 	if (dr->recovery && dr->generate_recovery_values) {
190e48354ceSNicholas Bellinger 		if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
191e48354ceSNicholas Bellinger 					cmd, dr) < 0)
192e48354ceSNicholas Bellinger 			return NULL;
193e48354ceSNicholas Bellinger 
194e48354ceSNicholas Bellinger 		dr->generate_recovery_values = 0;
195e48354ceSNicholas Bellinger 	}
196e48354ceSNicholas Bellinger 
197e48354ceSNicholas Bellinger 	read_data_done = (!dr->recovery) ?
198e48354ceSNicholas Bellinger 			cmd->read_data_done : dr->read_data_done;
199e48354ceSNicholas Bellinger 	seq_send_order = (!dr->recovery) ?
200e48354ceSNicholas Bellinger 			cmd->seq_send_order : dr->seq_send_order;
201e48354ceSNicholas Bellinger 
202ebf1d95cSAndy Grover 	read_data_left = (cmd->se_cmd.data_length - read_data_done);
203e48354ceSNicholas Bellinger 	if (!read_data_left) {
204e48354ceSNicholas Bellinger 		pr_err("ITT: 0x%08x read_data_left is zero!\n",
205e48354ceSNicholas Bellinger 				cmd->init_task_tag);
206e48354ceSNicholas Bellinger 		return NULL;
207e48354ceSNicholas Bellinger 	}
208e48354ceSNicholas Bellinger 
209e48354ceSNicholas Bellinger 	seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
210e48354ceSNicholas Bellinger 	if (!seq)
211e48354ceSNicholas Bellinger 		return NULL;
212e48354ceSNicholas Bellinger 
213e48354ceSNicholas Bellinger 	seq->sent = 1;
214e48354ceSNicholas Bellinger 
215e48354ceSNicholas Bellinger 	if (!dr->recovery && !seq->next_burst_len)
216e48354ceSNicholas Bellinger 		seq->first_datasn = cmd->data_sn;
217e48354ceSNicholas Bellinger 
218e48354ceSNicholas Bellinger 	offset = (seq->offset + seq->next_burst_len);
219e48354ceSNicholas Bellinger 
220e48354ceSNicholas Bellinger 	if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
221ebf1d95cSAndy Grover 	     cmd->se_cmd.data_length) {
222ebf1d95cSAndy Grover 		datain->length = (cmd->se_cmd.data_length - offset);
223e48354ceSNicholas Bellinger 		datain->offset = offset;
224e48354ceSNicholas Bellinger 
225e48354ceSNicholas Bellinger 		datain->flags |= ISCSI_FLAG_CMD_FINAL;
226e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
227e48354ceSNicholas Bellinger 			datain->flags |= ISCSI_FLAG_DATA_ACK;
228e48354ceSNicholas Bellinger 
229e48354ceSNicholas Bellinger 		seq->next_burst_len = 0;
230e48354ceSNicholas Bellinger 		seq_send_order++;
231e48354ceSNicholas Bellinger 	} else {
232e48354ceSNicholas Bellinger 		if ((seq->next_burst_len +
233e48354ceSNicholas Bellinger 		     conn->conn_ops->MaxRecvDataSegmentLength) <
234e48354ceSNicholas Bellinger 		     conn->sess->sess_ops->MaxBurstLength) {
235e48354ceSNicholas Bellinger 			datain->length =
236e48354ceSNicholas Bellinger 				conn->conn_ops->MaxRecvDataSegmentLength;
237e48354ceSNicholas Bellinger 			datain->offset = (seq->offset + seq->next_burst_len);
238e48354ceSNicholas Bellinger 
239e48354ceSNicholas Bellinger 			seq->next_burst_len += datain->length;
240e48354ceSNicholas Bellinger 		} else {
241e48354ceSNicholas Bellinger 			datain->length = (conn->sess->sess_ops->MaxBurstLength -
242e48354ceSNicholas Bellinger 					  seq->next_burst_len);
243e48354ceSNicholas Bellinger 			datain->offset = (seq->offset + seq->next_burst_len);
244e48354ceSNicholas Bellinger 
245e48354ceSNicholas Bellinger 			datain->flags |= ISCSI_FLAG_CMD_FINAL;
246e48354ceSNicholas Bellinger 			if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
247e48354ceSNicholas Bellinger 				datain->flags |= ISCSI_FLAG_DATA_ACK;
248e48354ceSNicholas Bellinger 
249e48354ceSNicholas Bellinger 			seq->next_burst_len = 0;
250e48354ceSNicholas Bellinger 			seq_send_order++;
251e48354ceSNicholas Bellinger 		}
252e48354ceSNicholas Bellinger 	}
253e48354ceSNicholas Bellinger 
254ebf1d95cSAndy Grover 	if ((read_data_done + datain->length) == cmd->se_cmd.data_length)
255e48354ceSNicholas Bellinger 		datain->flags |= ISCSI_FLAG_DATA_STATUS;
256e48354ceSNicholas Bellinger 
257e48354ceSNicholas Bellinger 	datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
258e48354ceSNicholas Bellinger 	if (!dr->recovery) {
259e48354ceSNicholas Bellinger 		cmd->seq_send_order = seq_send_order;
260e48354ceSNicholas Bellinger 		cmd->read_data_done += datain->length;
261e48354ceSNicholas Bellinger 	} else {
262e48354ceSNicholas Bellinger 		dr->seq_send_order = seq_send_order;
263e48354ceSNicholas Bellinger 		dr->read_data_done += datain->length;
264e48354ceSNicholas Bellinger 	}
265e48354ceSNicholas Bellinger 
266e48354ceSNicholas Bellinger 	if (!dr->recovery) {
267e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_CMD_FINAL)
268e48354ceSNicholas Bellinger 			seq->last_datasn = datain->data_sn;
269e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
270e48354ceSNicholas Bellinger 			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
271e48354ceSNicholas Bellinger 
272e48354ceSNicholas Bellinger 		return dr;
273e48354ceSNicholas Bellinger 	}
274e48354ceSNicholas Bellinger 
275e48354ceSNicholas Bellinger 	if (!dr->runlength) {
276e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
277e48354ceSNicholas Bellinger 			dr->dr_complete =
278e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
279e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
280e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
281e48354ceSNicholas Bellinger 		}
282e48354ceSNicholas Bellinger 	} else {
283e48354ceSNicholas Bellinger 		if ((dr->begrun + dr->runlength) == dr->data_sn) {
284e48354ceSNicholas Bellinger 			dr->dr_complete =
285e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
286e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
287e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
288e48354ceSNicholas Bellinger 		}
289e48354ceSNicholas Bellinger 	}
290e48354ceSNicholas Bellinger 
291e48354ceSNicholas Bellinger 	return dr;
292e48354ceSNicholas Bellinger }
293e48354ceSNicholas Bellinger 
294e48354ceSNicholas Bellinger /*
295e48354ceSNicholas Bellinger  *	For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=No.
296e48354ceSNicholas Bellinger  */
iscsit_set_datain_values_yes_and_no(struct iscsit_cmd * cmd,struct iscsi_datain * datain)297e48354ceSNicholas Bellinger static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
29866cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
299e48354ceSNicholas Bellinger 	struct iscsi_datain *datain)
300e48354ceSNicholas Bellinger {
301e48354ceSNicholas Bellinger 	u32 next_burst_len, read_data_done, read_data_left;
302*be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
303e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
304e48354ceSNicholas Bellinger 	struct iscsi_pdu *pdu;
305e48354ceSNicholas Bellinger 
306e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_req(cmd);
307e48354ceSNicholas Bellinger 	if (!dr)
308e48354ceSNicholas Bellinger 		return NULL;
309e48354ceSNicholas Bellinger 
310e48354ceSNicholas Bellinger 	if (dr->recovery && dr->generate_recovery_values) {
311e48354ceSNicholas Bellinger 		if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
312e48354ceSNicholas Bellinger 					cmd, dr) < 0)
313e48354ceSNicholas Bellinger 			return NULL;
314e48354ceSNicholas Bellinger 
315e48354ceSNicholas Bellinger 		dr->generate_recovery_values = 0;
316e48354ceSNicholas Bellinger 	}
317e48354ceSNicholas Bellinger 
318e48354ceSNicholas Bellinger 	next_burst_len = (!dr->recovery) ?
319e48354ceSNicholas Bellinger 			cmd->next_burst_len : dr->next_burst_len;
320e48354ceSNicholas Bellinger 	read_data_done = (!dr->recovery) ?
321e48354ceSNicholas Bellinger 			cmd->read_data_done : dr->read_data_done;
322e48354ceSNicholas Bellinger 
323ebf1d95cSAndy Grover 	read_data_left = (cmd->se_cmd.data_length - read_data_done);
324e48354ceSNicholas Bellinger 	if (!read_data_left) {
325e48354ceSNicholas Bellinger 		pr_err("ITT: 0x%08x read_data_left is zero!\n",
326e48354ceSNicholas Bellinger 				cmd->init_task_tag);
327e48354ceSNicholas Bellinger 		return dr;
328e48354ceSNicholas Bellinger 	}
329e48354ceSNicholas Bellinger 
330e48354ceSNicholas Bellinger 	pdu = iscsit_get_pdu_holder_for_seq(cmd, NULL);
331e48354ceSNicholas Bellinger 	if (!pdu)
332e48354ceSNicholas Bellinger 		return dr;
333e48354ceSNicholas Bellinger 
334ebf1d95cSAndy Grover 	if ((read_data_done + pdu->length) == cmd->se_cmd.data_length) {
335e48354ceSNicholas Bellinger 		pdu->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
336e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
337e48354ceSNicholas Bellinger 			pdu->flags |= ISCSI_FLAG_DATA_ACK;
338e48354ceSNicholas Bellinger 
339e48354ceSNicholas Bellinger 		next_burst_len = 0;
340e48354ceSNicholas Bellinger 	} else {
341e48354ceSNicholas Bellinger 		if ((next_burst_len + conn->conn_ops->MaxRecvDataSegmentLength) <
342e48354ceSNicholas Bellinger 		     conn->sess->sess_ops->MaxBurstLength)
343e48354ceSNicholas Bellinger 			next_burst_len += pdu->length;
344e48354ceSNicholas Bellinger 		else {
345e48354ceSNicholas Bellinger 			pdu->flags |= ISCSI_FLAG_CMD_FINAL;
346e48354ceSNicholas Bellinger 			if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
347e48354ceSNicholas Bellinger 				pdu->flags |= ISCSI_FLAG_DATA_ACK;
348e48354ceSNicholas Bellinger 
349e48354ceSNicholas Bellinger 			next_burst_len = 0;
350e48354ceSNicholas Bellinger 		}
351e48354ceSNicholas Bellinger 	}
352e48354ceSNicholas Bellinger 
353e48354ceSNicholas Bellinger 	pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
354e48354ceSNicholas Bellinger 	if (!dr->recovery) {
355e48354ceSNicholas Bellinger 		cmd->next_burst_len = next_burst_len;
356e48354ceSNicholas Bellinger 		cmd->read_data_done += pdu->length;
357e48354ceSNicholas Bellinger 	} else {
358e48354ceSNicholas Bellinger 		dr->next_burst_len = next_burst_len;
359e48354ceSNicholas Bellinger 		dr->read_data_done += pdu->length;
360e48354ceSNicholas Bellinger 	}
361e48354ceSNicholas Bellinger 
362e48354ceSNicholas Bellinger 	datain->flags = pdu->flags;
363e48354ceSNicholas Bellinger 	datain->length = pdu->length;
364e48354ceSNicholas Bellinger 	datain->offset = pdu->offset;
365e48354ceSNicholas Bellinger 	datain->data_sn = pdu->data_sn;
366e48354ceSNicholas Bellinger 
367e48354ceSNicholas Bellinger 	if (!dr->recovery) {
368e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
369e48354ceSNicholas Bellinger 			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
370e48354ceSNicholas Bellinger 
371e48354ceSNicholas Bellinger 		return dr;
372e48354ceSNicholas Bellinger 	}
373e48354ceSNicholas Bellinger 
374e48354ceSNicholas Bellinger 	if (!dr->runlength) {
375e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
376e48354ceSNicholas Bellinger 			dr->dr_complete =
377e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
378e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
379e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
380e48354ceSNicholas Bellinger 		}
381e48354ceSNicholas Bellinger 	} else {
382e48354ceSNicholas Bellinger 		if ((dr->begrun + dr->runlength) == dr->data_sn) {
383e48354ceSNicholas Bellinger 			dr->dr_complete =
384e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
385e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
386e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
387e48354ceSNicholas Bellinger 		}
388e48354ceSNicholas Bellinger 	}
389e48354ceSNicholas Bellinger 
390e48354ceSNicholas Bellinger 	return dr;
391e48354ceSNicholas Bellinger }
392e48354ceSNicholas Bellinger 
393e48354ceSNicholas Bellinger /*
394e48354ceSNicholas Bellinger  *	For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=No.
395e48354ceSNicholas Bellinger  */
iscsit_set_datain_values_no_and_no(struct iscsit_cmd * cmd,struct iscsi_datain * datain)396e48354ceSNicholas Bellinger static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
39766cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
398e48354ceSNicholas Bellinger 	struct iscsi_datain *datain)
399e48354ceSNicholas Bellinger {
400e48354ceSNicholas Bellinger 	u32 read_data_done, read_data_left, seq_send_order;
401*be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
402e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
403e48354ceSNicholas Bellinger 	struct iscsi_pdu *pdu;
404e48354ceSNicholas Bellinger 	struct iscsi_seq *seq = NULL;
405e48354ceSNicholas Bellinger 
406e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_req(cmd);
407e48354ceSNicholas Bellinger 	if (!dr)
408e48354ceSNicholas Bellinger 		return NULL;
409e48354ceSNicholas Bellinger 
410e48354ceSNicholas Bellinger 	if (dr->recovery && dr->generate_recovery_values) {
411e48354ceSNicholas Bellinger 		if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
412e48354ceSNicholas Bellinger 					cmd, dr) < 0)
413e48354ceSNicholas Bellinger 			return NULL;
414e48354ceSNicholas Bellinger 
415e48354ceSNicholas Bellinger 		dr->generate_recovery_values = 0;
416e48354ceSNicholas Bellinger 	}
417e48354ceSNicholas Bellinger 
418e48354ceSNicholas Bellinger 	read_data_done = (!dr->recovery) ?
419e48354ceSNicholas Bellinger 			cmd->read_data_done : dr->read_data_done;
420e48354ceSNicholas Bellinger 	seq_send_order = (!dr->recovery) ?
421e48354ceSNicholas Bellinger 			cmd->seq_send_order : dr->seq_send_order;
422e48354ceSNicholas Bellinger 
423ebf1d95cSAndy Grover 	read_data_left = (cmd->se_cmd.data_length - read_data_done);
424e48354ceSNicholas Bellinger 	if (!read_data_left) {
425e48354ceSNicholas Bellinger 		pr_err("ITT: 0x%08x read_data_left is zero!\n",
426e48354ceSNicholas Bellinger 				cmd->init_task_tag);
427e48354ceSNicholas Bellinger 		return NULL;
428e48354ceSNicholas Bellinger 	}
429e48354ceSNicholas Bellinger 
430e48354ceSNicholas Bellinger 	seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
431e48354ceSNicholas Bellinger 	if (!seq)
432e48354ceSNicholas Bellinger 		return NULL;
433e48354ceSNicholas Bellinger 
434e48354ceSNicholas Bellinger 	seq->sent = 1;
435e48354ceSNicholas Bellinger 
436e48354ceSNicholas Bellinger 	if (!dr->recovery && !seq->next_burst_len)
437e48354ceSNicholas Bellinger 		seq->first_datasn = cmd->data_sn;
438e48354ceSNicholas Bellinger 
439e48354ceSNicholas Bellinger 	pdu = iscsit_get_pdu_holder_for_seq(cmd, seq);
440e48354ceSNicholas Bellinger 	if (!pdu)
441e48354ceSNicholas Bellinger 		return NULL;
442e48354ceSNicholas Bellinger 
443e48354ceSNicholas Bellinger 	if (seq->pdu_send_order == seq->pdu_count) {
444e48354ceSNicholas Bellinger 		pdu->flags |= ISCSI_FLAG_CMD_FINAL;
445e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
446e48354ceSNicholas Bellinger 			pdu->flags |= ISCSI_FLAG_DATA_ACK;
447e48354ceSNicholas Bellinger 
448e48354ceSNicholas Bellinger 		seq->next_burst_len = 0;
449e48354ceSNicholas Bellinger 		seq_send_order++;
450e48354ceSNicholas Bellinger 	} else
451e48354ceSNicholas Bellinger 		seq->next_burst_len += pdu->length;
452e48354ceSNicholas Bellinger 
453ebf1d95cSAndy Grover 	if ((read_data_done + pdu->length) == cmd->se_cmd.data_length)
454e48354ceSNicholas Bellinger 		pdu->flags |= ISCSI_FLAG_DATA_STATUS;
455e48354ceSNicholas Bellinger 
456e48354ceSNicholas Bellinger 	pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
457e48354ceSNicholas Bellinger 	if (!dr->recovery) {
458e48354ceSNicholas Bellinger 		cmd->seq_send_order = seq_send_order;
459e48354ceSNicholas Bellinger 		cmd->read_data_done += pdu->length;
460e48354ceSNicholas Bellinger 	} else {
461e48354ceSNicholas Bellinger 		dr->seq_send_order = seq_send_order;
462e48354ceSNicholas Bellinger 		dr->read_data_done += pdu->length;
463e48354ceSNicholas Bellinger 	}
464e48354ceSNicholas Bellinger 
465e48354ceSNicholas Bellinger 	datain->flags = pdu->flags;
466e48354ceSNicholas Bellinger 	datain->length = pdu->length;
467e48354ceSNicholas Bellinger 	datain->offset = pdu->offset;
468e48354ceSNicholas Bellinger 	datain->data_sn = pdu->data_sn;
469e48354ceSNicholas Bellinger 
470e48354ceSNicholas Bellinger 	if (!dr->recovery) {
471e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_CMD_FINAL)
472e48354ceSNicholas Bellinger 			seq->last_datasn = datain->data_sn;
473e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
474e48354ceSNicholas Bellinger 			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
475e48354ceSNicholas Bellinger 
476e48354ceSNicholas Bellinger 		return dr;
477e48354ceSNicholas Bellinger 	}
478e48354ceSNicholas Bellinger 
479e48354ceSNicholas Bellinger 	if (!dr->runlength) {
480e48354ceSNicholas Bellinger 		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
481e48354ceSNicholas Bellinger 			dr->dr_complete =
482e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
483e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
484e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
485e48354ceSNicholas Bellinger 		}
486e48354ceSNicholas Bellinger 	} else {
487e48354ceSNicholas Bellinger 		if ((dr->begrun + dr->runlength) == dr->data_sn) {
488e48354ceSNicholas Bellinger 			dr->dr_complete =
489e48354ceSNicholas Bellinger 			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
490e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
491e48354ceSNicholas Bellinger 				DATAIN_COMPLETE_CONNECTION_RECOVERY;
492e48354ceSNicholas Bellinger 		}
493e48354ceSNicholas Bellinger 	}
494e48354ceSNicholas Bellinger 
495e48354ceSNicholas Bellinger 	return dr;
496e48354ceSNicholas Bellinger }
497e48354ceSNicholas Bellinger 
iscsit_get_datain_values(struct iscsit_cmd * cmd,struct iscsi_datain * datain)498e48354ceSNicholas Bellinger struct iscsi_datain_req *iscsit_get_datain_values(
49966cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
500e48354ceSNicholas Bellinger 	struct iscsi_datain *datain)
501e48354ceSNicholas Bellinger {
502*be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
503e48354ceSNicholas Bellinger 
504e48354ceSNicholas Bellinger 	if (conn->sess->sess_ops->DataSequenceInOrder &&
505e48354ceSNicholas Bellinger 	    conn->sess->sess_ops->DataPDUInOrder)
506e48354ceSNicholas Bellinger 		return iscsit_set_datain_values_yes_and_yes(cmd, datain);
507e48354ceSNicholas Bellinger 	else if (!conn->sess->sess_ops->DataSequenceInOrder &&
508e48354ceSNicholas Bellinger 		  conn->sess->sess_ops->DataPDUInOrder)
509e48354ceSNicholas Bellinger 		return iscsit_set_datain_values_no_and_yes(cmd, datain);
510e48354ceSNicholas Bellinger 	else if (conn->sess->sess_ops->DataSequenceInOrder &&
511e48354ceSNicholas Bellinger 		 !conn->sess->sess_ops->DataPDUInOrder)
512e48354ceSNicholas Bellinger 		return iscsit_set_datain_values_yes_and_no(cmd, datain);
513e48354ceSNicholas Bellinger 	else if (!conn->sess->sess_ops->DataSequenceInOrder &&
514e48354ceSNicholas Bellinger 		   !conn->sess->sess_ops->DataPDUInOrder)
515e48354ceSNicholas Bellinger 		return iscsit_set_datain_values_no_and_no(cmd, datain);
516e48354ceSNicholas Bellinger 
517e48354ceSNicholas Bellinger 	return NULL;
518e48354ceSNicholas Bellinger }
519d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_get_datain_values);
520