Blame view

drivers/scsi/libiscsi.c 90.6 KB
7996a778f   Mike Christie   [SCSI] iscsi: add...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /*
   * iSCSI lib functions
   *
   * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
   * Copyright (C) 2004 - 2006 Mike Christie
   * Copyright (C) 2004 - 2005 Dmitry Yusupov
   * Copyright (C) 2004 - 2005 Alex Aizman
   * maintained by open-iscsi@googlegroups.com
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   */
  #include <linux/types.h>
7996a778f   Mike Christie   [SCSI] iscsi: add...
25
26
  #include <linux/kfifo.h>
  #include <linux/delay.h>
118365721   vignesh babu   [SCSI] libiscsi: ...
27
  #include <linux/log2.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/slab.h>
acf3368ff   Paul Gortmaker   scsi: Fix up file...
29
  #include <linux/module.h>
8eb00539d   Mike Christie   [SCSI] libiscsi: ...
30
  #include <asm/unaligned.h>
7996a778f   Mike Christie   [SCSI] iscsi: add...
31
32
33
34
35
36
37
38
39
40
41
  #include <net/tcp.h>
  #include <scsi/scsi_cmnd.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_eh.h>
  #include <scsi/scsi_tcq.h>
  #include <scsi/scsi_host.h>
  #include <scsi/scsi.h>
  #include <scsi/iscsi_proto.h>
  #include <scsi/scsi_transport.h>
  #include <scsi/scsi_transport_iscsi.h>
  #include <scsi/libiscsi.h>
bd2199d41   Erez Zilber   libiscsi: add con...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  static int iscsi_dbg_lib_conn;
  module_param_named(debug_libiscsi_conn, iscsi_dbg_lib_conn, int,
  		   S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(debug_libiscsi_conn,
  		 "Turn on debugging for connections in libiscsi module. "
  		 "Set to 1 to turn on, and zero to turn off. Default is off.");
  
  static int iscsi_dbg_lib_session;
  module_param_named(debug_libiscsi_session, iscsi_dbg_lib_session, int,
  		   S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(debug_libiscsi_session,
  		 "Turn on debugging for sessions in libiscsi module. "
  		 "Set to 1 to turn on, and zero to turn off. Default is off.");
  
  static int iscsi_dbg_lib_eh;
  module_param_named(debug_libiscsi_eh, iscsi_dbg_lib_eh, int,
  		   S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(debug_libiscsi_eh,
  		 "Turn on debugging for error handling in libiscsi module. "
  		 "Set to 1 to turn on, and zero to turn off. Default is off.");
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
62
63
64
  
  #define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...)			\
  	do {							\
bd2199d41   Erez Zilber   libiscsi: add con...
65
  		if (iscsi_dbg_lib_conn)				\
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
66
67
68
69
70
71
72
  			iscsi_conn_printk(KERN_INFO, _conn,	\
  					     "%s " dbg_fmt,	\
  					     __func__, ##arg);	\
  	} while (0);
  
  #define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...)			\
  	do {								\
bd2199d41   Erez Zilber   libiscsi: add con...
73
74
75
76
77
78
79
80
81
  		if (iscsi_dbg_lib_session)				\
  			iscsi_session_printk(KERN_INFO, _session,	\
  					     "%s " dbg_fmt,		\
  					     __func__, ##arg);		\
  	} while (0);
  
  #define ISCSI_DBG_EH(_session, dbg_fmt, arg...)				\
  	do {								\
  		if (iscsi_dbg_lib_eh)					\
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
82
83
84
85
  			iscsi_session_printk(KERN_INFO, _session,	\
  					     "%s " dbg_fmt,		\
  					     __func__, ##arg);		\
  	} while (0);
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
86
87
88
89
  inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
  {
  	struct Scsi_Host *shost = conn->session->host;
  	struct iscsi_host *ihost = shost_priv(shost);
1336aed10   Mike Christie   [SCSI] libiscsi: ...
90
91
  	if (ihost->workq)
  		queue_work(ihost->workq, &conn->xmitwork);
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
92
93
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_queue_work);
4c0ba5d25   Mike Christie   [SCSI] libiscsi: ...
94
95
  static void __iscsi_update_cmdsn(struct iscsi_session *session,
  				 uint32_t exp_cmdsn, uint32_t max_cmdsn)
7996a778f   Mike Christie   [SCSI] iscsi: add...
96
  {
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
97
98
99
100
101
102
103
104
105
  	/*
  	 * standard specifies this check for when to update expected and
  	 * max sequence numbers
  	 */
  	if (iscsi_sna_lt(max_cmdsn, exp_cmdsn - 1))
  		return;
  
  	if (exp_cmdsn != session->exp_cmdsn &&
  	    !iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn))
7996a778f   Mike Christie   [SCSI] iscsi: add...
106
  		session->exp_cmdsn = exp_cmdsn;
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
107
108
109
110
111
112
113
  	if (max_cmdsn != session->max_cmdsn &&
  	    !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
  		session->max_cmdsn = max_cmdsn;
  		/*
  		 * if the window closed with IO queued, then kick the
  		 * xmit thread
  		 */
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
114
  		if (!list_empty(&session->leadconn->cmdqueue) ||
1336aed10   Mike Christie   [SCSI] libiscsi: ...
115
116
  		    !list_empty(&session->leadconn->mgmtqueue))
  			iscsi_conn_queue_work(session->leadconn);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
117
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
118
  }
4c0ba5d25   Mike Christie   [SCSI] libiscsi: ...
119
120
121
122
123
124
  
  void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
  {
  	__iscsi_update_cmdsn(session, be32_to_cpu(hdr->exp_cmdsn),
  			     be32_to_cpu(hdr->max_cmdsn));
  }
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
125
  EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
7996a778f   Mike Christie   [SCSI] iscsi: add...
126

577577da6   Mike Christie   [SCSI] libiscsi: ...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  /**
   * iscsi_prep_data_out_pdu - initialize Data-Out
   * @task: scsi command task
   * @r2t: R2T info
   * @hdr: iscsi data in pdu
   *
   * Notes:
   *	Initialize Data-Out within this R2T sequence and finds
   *	proper data_offset within this SCSI command.
   *
   *	This function is called with connection lock taken.
   **/
  void iscsi_prep_data_out_pdu(struct iscsi_task *task, struct iscsi_r2t_info *r2t,
  			   struct iscsi_data *hdr)
7996a778f   Mike Christie   [SCSI] iscsi: add...
141
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
142
  	struct iscsi_conn *conn = task->conn;
577577da6   Mike Christie   [SCSI] libiscsi: ...
143
144
145
  	unsigned int left = r2t->data_length - r2t->sent;
  
  	task->hdr_len = sizeof(struct iscsi_data);
7996a778f   Mike Christie   [SCSI] iscsi: add...
146
147
  
  	memset(hdr, 0, sizeof(struct iscsi_data));
577577da6   Mike Christie   [SCSI] libiscsi: ...
148
149
150
  	hdr->ttt = r2t->ttt;
  	hdr->datasn = cpu_to_be32(r2t->datasn);
  	r2t->datasn++;
7996a778f   Mike Christie   [SCSI] iscsi: add...
151
  	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
55bdabdf4   Andy Grover   iscsi: Use struct...
152
  	hdr->lun = task->lun;
577577da6   Mike Christie   [SCSI] libiscsi: ...
153
154
155
156
  	hdr->itt = task->hdr_itt;
  	hdr->exp_statsn = r2t->exp_statsn;
  	hdr->offset = cpu_to_be32(r2t->data_offset + r2t->sent);
  	if (left > conn->max_xmit_dlength) {
7996a778f   Mike Christie   [SCSI] iscsi: add...
157
  		hton24(hdr->dlength, conn->max_xmit_dlength);
577577da6   Mike Christie   [SCSI] libiscsi: ...
158
  		r2t->data_count = conn->max_xmit_dlength;
7996a778f   Mike Christie   [SCSI] iscsi: add...
159
160
  		hdr->flags = 0;
  	} else {
577577da6   Mike Christie   [SCSI] libiscsi: ...
161
162
  		hton24(hdr->dlength, left);
  		r2t->data_count = left;
7996a778f   Mike Christie   [SCSI] iscsi: add...
163
164
  		hdr->flags = ISCSI_FLAG_CMD_FINAL;
  	}
577577da6   Mike Christie   [SCSI] libiscsi: ...
165
  	conn->dataout_pdus_cnt++;
7996a778f   Mike Christie   [SCSI] iscsi: add...
166
  }
577577da6   Mike Christie   [SCSI] libiscsi: ...
167
  EXPORT_SYMBOL_GPL(iscsi_prep_data_out_pdu);
7996a778f   Mike Christie   [SCSI] iscsi: add...
168

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
169
  static int iscsi_add_hdr(struct iscsi_task *task, unsigned len)
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
170
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
171
  	unsigned exp_len = task->hdr_len + len;
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
172

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
173
  	if (exp_len > task->hdr_max) {
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
174
175
176
177
178
  		WARN_ON(1);
  		return -EINVAL;
  	}
  
  	WARN_ON(len & (ISCSI_PAD_LEN - 1)); /* caller must pad the AHS */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
179
  	task->hdr_len = exp_len;
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
180
181
  	return 0;
  }
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
182
183
184
  /*
   * make an extended cdb AHS
   */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
185
  static int iscsi_prep_ecdb_ahs(struct iscsi_task *task)
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
186
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
187
  	struct scsi_cmnd *cmd = task->sc;
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
188
189
190
191
  	unsigned rlen, pad_len;
  	unsigned short ahslength;
  	struct iscsi_ecdb_ahdr *ecdb_ahdr;
  	int rc;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
192
  	ecdb_ahdr = iscsi_next_hdr(task);
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
193
194
195
196
197
198
  	rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
  
  	BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
  	ahslength = rlen + sizeof(ecdb_ahdr->reserved);
  
  	pad_len = iscsi_padding(rlen);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
199
  	rc = iscsi_add_hdr(task, sizeof(ecdb_ahdr->ahslength) +
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
200
201
202
203
204
205
206
207
208
209
210
  	                   sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
  	if (rc)
  		return rc;
  
  	if (pad_len)
  		memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
  
  	ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
  	ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
  	ecdb_ahdr->reserved = 0;
  	memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
211
212
213
214
215
216
  	ISCSI_DBG_SESSION(task->conn->session,
  			  "iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
  		          "rlen %d pad_len %d ahs_length %d iscsi_headers_size "
  		          "%u
  ", cmd->cmd_len, rlen, pad_len, ahslength,
  		          task->hdr_len);
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
217
218
  	return 0;
  }
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
219
  static int iscsi_prep_bidi_ahs(struct iscsi_task *task)
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
220
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
221
  	struct scsi_cmnd *sc = task->sc;
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
222
223
  	struct iscsi_rlength_ahdr *rlen_ahdr;
  	int rc;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
224
225
  	rlen_ahdr = iscsi_next_hdr(task);
  	rc = iscsi_add_hdr(task, sizeof(*rlen_ahdr));
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
226
227
228
229
230
231
232
233
234
  	if (rc)
  		return rc;
  
  	rlen_ahdr->ahslength =
  		cpu_to_be16(sizeof(rlen_ahdr->read_length) +
  						  sizeof(rlen_ahdr->reserved));
  	rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH;
  	rlen_ahdr->reserved = 0;
  	rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
235
236
237
238
239
240
  	ISCSI_DBG_SESSION(task->conn->session,
  			  "bidi-in rlen_ahdr->read_length(%d) "
  		          "rlen_ahdr->ahslength(%d)
  ",
  		          be32_to_cpu(rlen_ahdr->read_length),
  		          be16_to_cpu(rlen_ahdr->ahslength));
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
241
242
  	return 0;
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
243
  /**
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
   * iscsi_check_tmf_restrictions - check if a task is affected by TMF
   * @task: iscsi task
   * @opcode: opcode to check for
   *
   * During TMF a task has to be checked if it's affected.
   * All unrelated I/O can be passed through, but I/O to the
   * affected LUN should be restricted.
   * If 'fast_abort' is set we won't be sending any I/O to the
   * affected LUN.
   * Otherwise the target is waiting for all TTTs to be completed,
   * so we have to send all outstanding Data-Out PDUs to the target.
   */
  static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
  {
  	struct iscsi_conn *conn = task->conn;
  	struct iscsi_tm *tmf = &conn->tmhdr;
  	unsigned int hdr_lun;
  
  	if (conn->tmf_state == TMF_INITIAL)
  		return 0;
  
  	if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC)
  		return 0;
  
  	switch (ISCSI_TM_FUNC_VALUE(tmf)) {
  	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
  		/*
  		 * Allow PDUs for unrelated LUNs
  		 */
55bdabdf4   Andy Grover   iscsi: Use struct...
273
  		hdr_lun = scsilun_to_int(&tmf->lun);
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
274
275
  		if (hdr_lun != task->sc->device->lun)
  			return 0;
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
276
277
  		/* fall through */
  	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
278
279
280
281
282
283
  		/*
  		 * Fail all SCSI cmd PDUs
  		 */
  		if (opcode != ISCSI_OP_SCSI_DATA_OUT) {
  			iscsi_conn_printk(KERN_INFO, conn,
  					  "task [op %x/%x itt "
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
284
  					  "0x%x/0x%x] "
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
285
286
287
  					  "rejected.
  ",
  					  task->hdr->opcode, opcode,
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
288
  					  task->itt, task->hdr_itt);
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
289
290
291
292
293
294
295
296
297
  			return -EACCES;
  		}
  		/*
  		 * And also all data-out PDUs in response to R2T
  		 * if fast_abort is set.
  		 */
  		if (conn->session->fast_abort) {
  			iscsi_conn_printk(KERN_INFO, conn,
  					  "task [op %x/%x itt "
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
298
299
  					  "0x%x/0x%x] fast abort.
  ",
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
300
  					  task->hdr->opcode, opcode,
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
301
  					  task->itt, task->hdr_itt);
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  			return -EACCES;
  		}
  		break;
  	case ISCSI_TM_FUNC_ABORT_TASK:
  		/*
  		 * the caller has already checked if the task
  		 * they want to abort was in the pending queue so if
  		 * we are here the cmd pdu has gone out already, and
  		 * we will only hit this for data-outs
  		 */
  		if (opcode == ISCSI_OP_SCSI_DATA_OUT &&
  		    task->hdr_itt == tmf->rtt) {
  			ISCSI_DBG_SESSION(conn->session,
  					  "Preventing task %x/%x from sending "
  					  "data-out due to abort task in "
  					  "progress
  ", task->itt,
  					  task->hdr_itt);
  			return -EACCES;
  		}
  		break;
  	}
  
  	return 0;
  }
  
  /**
7996a778f   Mike Christie   [SCSI] iscsi: add...
329
   * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
330
   * @task: iscsi task
7996a778f   Mike Christie   [SCSI] iscsi: add...
331
332
333
334
   *
   * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set
   * fields like dlength or final based on how much data it sends
   */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
335
  static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
7996a778f   Mike Christie   [SCSI] iscsi: add...
336
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
337
  	struct iscsi_conn *conn = task->conn;
7996a778f   Mike Christie   [SCSI] iscsi: add...
338
  	struct iscsi_session *session = conn->session;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
339
  	struct scsi_cmnd *sc = task->sc;
123521830   Nicholas Bellinger   iscsi: Resolve is...
340
  	struct iscsi_scsi_req *hdr;
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
341
  	unsigned hdrlength, cmd_len;
262ef6362   Mike Christie   [SCSI] libiscsi: ...
342
  	itt_t itt;
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
343
  	int rc;
7996a778f   Mike Christie   [SCSI] iscsi: add...
344

5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
345
346
347
  	rc = iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_CMD);
  	if (rc)
  		return rc;
184b57c63   Mike Christie   [SCSI] libiscsi: ...
348
349
350
351
352
  	if (conn->session->tt->alloc_pdu) {
  		rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD);
  		if (rc)
  			return rc;
  	}
123521830   Nicholas Bellinger   iscsi: Resolve is...
353
  	hdr = (struct iscsi_scsi_req *)task->hdr;
262ef6362   Mike Christie   [SCSI] libiscsi: ...
354
  	itt = hdr->itt;
577577da6   Mike Christie   [SCSI] libiscsi: ...
355
  	memset(hdr, 0, sizeof(*hdr));
2ff79d52d   Mike Christie   [SCSI] libiscsi: ...
356
357
358
359
360
  	if (session->tt->parse_pdu_itt)
  		hdr->itt = task->hdr_itt = itt;
  	else
  		hdr->itt = task->hdr_itt = build_itt(task->itt,
  						     task->conn->session->age);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
361
362
  	task->hdr_len = 0;
  	rc = iscsi_add_hdr(task, sizeof(*hdr));
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
363
364
  	if (rc)
  		return rc;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
365
366
  	hdr->opcode = ISCSI_OP_SCSI_CMD;
  	hdr->flags = ISCSI_ATTR_SIMPLE;
55bdabdf4   Andy Grover   iscsi: Use struct...
367
368
  	int_to_scsilun(sc->device->lun, &hdr->lun);
  	task->lun = hdr->lun;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
369
  	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
370
371
372
373
  	cmd_len = sc->cmd_len;
  	if (cmd_len < ISCSI_CDB_SIZE)
  		memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
  	else if (cmd_len > ISCSI_CDB_SIZE) {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
374
  		rc = iscsi_prep_ecdb_ahs(task);
38d1c069d   Boaz Harrosh   [SCSI] iscsi: ext...
375
376
377
378
379
  		if (rc)
  			return rc;
  		cmd_len = ISCSI_CDB_SIZE;
  	}
  	memcpy(hdr->cdb, sc->cmnd, cmd_len);
7996a778f   Mike Christie   [SCSI] iscsi: add...
380

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
381
  	task->imm_count = 0;
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
382
383
  	if (scsi_bidi_cmnd(sc)) {
  		hdr->flags |= ISCSI_FLAG_CMD_READ;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
384
  		rc = iscsi_prep_bidi_ahs(task);
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
385
386
387
  		if (rc)
  			return rc;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
388
  	if (sc->sc_data_direction == DMA_TO_DEVICE) {
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
389
  		unsigned out_len = scsi_out(sc)->length;
577577da6   Mike Christie   [SCSI] libiscsi: ...
390
  		struct iscsi_r2t_info *r2t = &task->unsol_r2t;
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
391
  		hdr->data_length = cpu_to_be32(out_len);
7996a778f   Mike Christie   [SCSI] iscsi: add...
392
393
394
395
396
397
398
399
400
401
402
  		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
  		/*
  		 * Write counters:
  		 *
  		 *	imm_count	bytes to be sent right after
  		 *			SCSI PDU Header
  		 *
  		 *	unsol_count	bytes(as Data-Out) to be sent
  		 *			without	R2T ack right after
  		 *			immediate data
  		 *
577577da6   Mike Christie   [SCSI] libiscsi: ...
403
  		 *	r2t data_length bytes to be sent via R2T ack's
7996a778f   Mike Christie   [SCSI] iscsi: add...
404
405
406
  		 *
  		 *      pad_count       bytes to be sent as zero-padding
  		 */
577577da6   Mike Christie   [SCSI] libiscsi: ...
407
  		memset(r2t, 0, sizeof(*r2t));
7996a778f   Mike Christie   [SCSI] iscsi: add...
408
409
  
  		if (session->imm_data_en) {
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
410
  			if (out_len >= session->first_burst)
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
411
  				task->imm_count = min(session->first_burst,
7996a778f   Mike Christie   [SCSI] iscsi: add...
412
413
  							conn->max_xmit_dlength);
  			else
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
414
  				task->imm_count = min(out_len,
7996a778f   Mike Christie   [SCSI] iscsi: add...
415
  							conn->max_xmit_dlength);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
416
  			hton24(hdr->dlength, task->imm_count);
7996a778f   Mike Christie   [SCSI] iscsi: add...
417
  		} else
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
418
  			zero_data(hdr->dlength);
7996a778f   Mike Christie   [SCSI] iscsi: add...
419

ffd0436ed   Mike Christie   [SCSI] libiscsi, ...
420
  		if (!session->initial_r2t_en) {
577577da6   Mike Christie   [SCSI] libiscsi: ...
421
422
423
424
425
  			r2t->data_length = min(session->first_burst, out_len) -
  					       task->imm_count;
  			r2t->data_offset = task->imm_count;
  			r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
  			r2t->exp_statsn = cpu_to_be32(conn->exp_statsn);
ffd0436ed   Mike Christie   [SCSI] libiscsi, ...
426
  		}
577577da6   Mike Christie   [SCSI] libiscsi: ...
427
  		if (!task->unsol_r2t.data_length)
7996a778f   Mike Christie   [SCSI] iscsi: add...
428
  			/* No unsolicit Data-Out's */
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
429
  			hdr->flags |= ISCSI_FLAG_CMD_FINAL;
7996a778f   Mike Christie   [SCSI] iscsi: add...
430
  	} else {
7996a778f   Mike Christie   [SCSI] iscsi: add...
431
432
  		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
  		zero_data(hdr->dlength);
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
433
  		hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
7996a778f   Mike Christie   [SCSI] iscsi: add...
434
435
436
437
  
  		if (sc->sc_data_direction == DMA_FROM_DEVICE)
  			hdr->flags |= ISCSI_FLAG_CMD_READ;
  	}
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
438
  	/* calculate size of additional header segments (AHSs) */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
439
  	hdrlength = task->hdr_len - sizeof(*hdr);
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
440
441
442
443
444
445
  
  	WARN_ON(hdrlength & (ISCSI_PAD_LEN-1));
  	hdrlength /= ISCSI_PAD_LEN;
  
  	WARN_ON(hdrlength >= 256);
  	hdr->hlength = hdrlength & 0xFF;
96b1f96dc   Mike Christie   [SCSI] libiscsi: ...
446
  	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
447

577577da6   Mike Christie   [SCSI] libiscsi: ...
448
  	if (session->tt->init_task && session->tt->init_task(task))
052d01448   Mike Christie   [SCSI] libiscsi: ...
449
  		return -EIO;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
450
  	task->state = ISCSI_TASK_RUNNING;
d3305f340   Mike Christie   [SCSI] libiscsi: ...
451
  	session->cmdsn++;
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
452

a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
453
  	conn->scsicmd_pdus_cnt++;
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
454
455
456
457
458
459
460
461
462
463
  	ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x "
  			  "itt 0x%x len %d bidi_len %d cmdsn %d win %d]
  ",
  			  scsi_bidi_cmnd(sc) ? "bidirectional" :
  			  sc->sc_data_direction == DMA_TO_DEVICE ?
  			  "write" : "read", conn->id, sc, sc->cmnd[0],
  			  task->itt, scsi_bufflen(sc),
  			  scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
  			  session->cmdsn,
  			  session->max_cmdsn - session->exp_cmdsn + 1);
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
464
  	return 0;
7996a778f   Mike Christie   [SCSI] iscsi: add...
465
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
466
467
  
  /**
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
468
   * iscsi_free_task - free a task
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
469
   * @task: iscsi cmd task
7996a778f   Mike Christie   [SCSI] iscsi: add...
470
471
   *
   * Must be called with session lock.
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
472
473
   * This function returns the scsi command to scsi-ml or cleans
   * up mgmt tasks then returns the task to the pool.
7996a778f   Mike Christie   [SCSI] iscsi: add...
474
   */
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
475
  static void iscsi_free_task(struct iscsi_task *task)
7996a778f   Mike Christie   [SCSI] iscsi: add...
476
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
477
  	struct iscsi_conn *conn = task->conn;
c1635cb78   Mike Christie   [SCSI] libiscsi: ...
478
  	struct iscsi_session *session = conn->session;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
479
  	struct scsi_cmnd *sc = task->sc;
f41d47217   Mike Christie   [SCSI] libiscsi: ...
480
  	int oldstate = task->state;
7996a778f   Mike Christie   [SCSI] iscsi: add...
481

4421c9ebe   Mike Christie   [SCSI] libiscsi: ...
482
483
484
  	ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p
  ",
  			  task->itt, task->state, task->sc);
577577da6   Mike Christie   [SCSI] libiscsi: ...
485
  	session->tt->cleanup_task(task);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
486
  	task->state = ISCSI_TASK_FREE;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
487
  	task->sc = NULL;
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
488
  	/*
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
489
  	 * login task is preallocated so do not free
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
490
  	 */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
491
  	if (conn->login_task == task)
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
492
  		return;
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
493
  	kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*));
052d01448   Mike Christie   [SCSI] libiscsi: ...
494

3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
495
  	if (sc) {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
496
  		task->sc = NULL;
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
497
498
499
  		/* SCSI eh reuses commands to verify us */
  		sc->SCp.ptr = NULL;
  		/*
f41d47217   Mike Christie   [SCSI] libiscsi: ...
500
501
  		 * queue command may call this to free the task, so
  		 * it will decide how to return sc to scsi-ml.
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
502
  		 */
f41d47217   Mike Christie   [SCSI] libiscsi: ...
503
  		if (oldstate != ISCSI_TASK_REQUEUE_SCSIQ)
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
504
505
  			sc->scsi_done(sc);
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
506
  }
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
507
  void __iscsi_get_task(struct iscsi_task *task)
60ecebf5a   Mike Christie   [SCSI] add refcou...
508
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
509
  	atomic_inc(&task->refcount);
60ecebf5a   Mike Christie   [SCSI] add refcou...
510
  }
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
511
  EXPORT_SYMBOL_GPL(__iscsi_get_task);
60ecebf5a   Mike Christie   [SCSI] add refcou...
512

8eea2f55a   Eddie Wai   [SCSI] bnx2i: Add...
513
  void __iscsi_put_task(struct iscsi_task *task)
60ecebf5a   Mike Christie   [SCSI] add refcou...
514
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
515
  	if (atomic_dec_and_test(&task->refcount))
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
516
  		iscsi_free_task(task);
60ecebf5a   Mike Christie   [SCSI] add refcou...
517
  }
8eea2f55a   Eddie Wai   [SCSI] bnx2i: Add...
518
  EXPORT_SYMBOL_GPL(__iscsi_put_task);
60ecebf5a   Mike Christie   [SCSI] add refcou...
519

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
520
  void iscsi_put_task(struct iscsi_task *task)
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
521
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
522
  	struct iscsi_session *session = task->conn->session;
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
523
524
  
  	spin_lock_bh(&session->lock);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
525
  	__iscsi_put_task(task);
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
526
527
  	spin_unlock_bh(&session->lock);
  }
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
528
  EXPORT_SYMBOL_GPL(iscsi_put_task);
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
529

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
530
531
532
  /**
   * iscsi_complete_task - finish a task
   * @task: iscsi cmd task
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
533
   * @state: state to complete task with
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
534
535
536
   *
   * Must be called with session lock.
   */
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
537
  static void iscsi_complete_task(struct iscsi_task *task, int state)
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
538
539
  {
  	struct iscsi_conn *conn = task->conn;
4421c9ebe   Mike Christie   [SCSI] libiscsi: ...
540
541
542
543
  	ISCSI_DBG_SESSION(conn->session,
  			  "complete task itt 0x%x state %d sc %p
  ",
  			  task->itt, task->state, task->sc);
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
544
545
  	if (task->state == ISCSI_TASK_COMPLETED ||
  	    task->state == ISCSI_TASK_ABRT_TMF ||
f41d47217   Mike Christie   [SCSI] libiscsi: ...
546
547
  	    task->state == ISCSI_TASK_ABRT_SESS_RECOV ||
  	    task->state == ISCSI_TASK_REQUEUE_SCSIQ)
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
548
549
  		return;
  	WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
550
  	task->state = state;
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
551
552
553
554
555
556
557
558
559
560
561
562
563
  
  	if (!list_empty(&task->running))
  		list_del_init(&task->running);
  
  	if (conn->task == task)
  		conn->task = NULL;
  
  	if (conn->ping_task == task)
  		conn->ping_task = NULL;
  
  	/* release get from queueing */
  	__iscsi_put_task(task);
  }
4c0ba5d25   Mike Christie   [SCSI] libiscsi: ...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  /**
   * iscsi_complete_scsi_task - finish scsi task normally
   * @task: iscsi task for scsi cmd
   * @exp_cmdsn: expected cmd sn in cpu format
   * @max_cmdsn: max cmd sn in cpu format
   *
   * This is used when drivers do not need or cannot perform
   * lower level pdu processing.
   *
   * Called with session lock
   */
  void iscsi_complete_scsi_task(struct iscsi_task *task,
  			      uint32_t exp_cmdsn, uint32_t max_cmdsn)
  {
  	struct iscsi_conn *conn = task->conn;
  
  	ISCSI_DBG_SESSION(conn->session, "[itt 0x%x]
  ", task->itt);
  
  	conn->last_recv = jiffies;
  	__iscsi_update_cmdsn(conn->session, exp_cmdsn, max_cmdsn);
  	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
  }
  EXPORT_SYMBOL_GPL(iscsi_complete_scsi_task);
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
588
  /*
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
589
590
591
   * session lock must be held and if not called for a task that is
   * still pending or from the xmit thread, then xmit thread must
   * be suspended.
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
592
   */
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
593
  static void fail_scsi_task(struct iscsi_task *task, int err)
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
594
  {
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
595
  	struct iscsi_conn *conn = task->conn;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
596
  	struct scsi_cmnd *sc;
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
597
  	int state;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
598

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
599
600
601
602
603
  	/*
  	 * if a command completes and we get a successful tmf response
  	 * we will hit this because the scsi eh abort code does not take
  	 * a ref to the task.
  	 */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
604
  	sc = task->sc;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
605
606
  	if (!sc)
  		return;
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
607
  	if (task->state == ISCSI_TASK_PENDING) {
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
608
609
610
611
612
  		/*
  		 * cmd never made it to the xmit thread, so we should not count
  		 * the cmd in the sequencing
  		 */
  		conn->session->queued_cmdsn--;
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
613
614
615
616
617
618
  		/* it was never sent so just complete like normal */
  		state = ISCSI_TASK_COMPLETED;
  	} else if (err == DID_TRANSPORT_DISRUPTED)
  		state = ISCSI_TASK_ABRT_SESS_RECOV;
  	else
  		state = ISCSI_TASK_ABRT_TMF;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
619

b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
620
  	sc->result = err << 16;
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
621
622
623
624
625
626
  	if (!scsi_bidi_cmnd(sc))
  		scsi_set_resid(sc, scsi_bufflen(sc));
  	else {
  		scsi_out(sc)->resid = scsi_out(sc)->length;
  		scsi_in(sc)->resid = scsi_in(sc)->length;
  	}
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
627

b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
628
  	iscsi_complete_task(task, state);
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
629
  }
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
630
  static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
631
  				struct iscsi_task *task)
052d01448   Mike Christie   [SCSI] libiscsi: ...
632
633
  {
  	struct iscsi_session *session = conn->session;
577577da6   Mike Christie   [SCSI] libiscsi: ...
634
  	struct iscsi_hdr *hdr = task->hdr;
052d01448   Mike Christie   [SCSI] libiscsi: ...
635
  	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
636
  	uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK;
052d01448   Mike Christie   [SCSI] libiscsi: ...
637
638
639
  
  	if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
  		return -ENOTCONN;
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
640
  	if (opcode != ISCSI_OP_LOGIN && opcode != ISCSI_OP_TEXT)
052d01448   Mike Christie   [SCSI] libiscsi: ...
641
642
643
644
645
646
  		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
  	/*
  	 * pre-format CmdSN for outgoing PDU.
  	 */
  	nop->cmdsn = cpu_to_be32(session->cmdsn);
  	if (hdr->itt != RESERVED_ITT) {
052d01448   Mike Christie   [SCSI] libiscsi: ...
647
  		/*
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
648
  		 * TODO: We always use immediate for normal session pdus.
052d01448   Mike Christie   [SCSI] libiscsi: ...
649
650
  		 * If we start to send tmfs or nops as non-immediate then
  		 * we should start checking the cmdsn numbers for mgmt tasks.
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
651
652
653
  		 *
  		 * During discovery sessions iscsid sends TEXT as non immediate,
  		 * but we always only send one PDU at a time.
052d01448   Mike Christie   [SCSI] libiscsi: ...
654
655
656
657
658
659
660
  		 */
  		if (conn->c_stage == ISCSI_CONN_STARTED &&
  		    !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
  			session->queued_cmdsn++;
  			session->cmdsn++;
  		}
  	}
ae15f8017   Mike Christie   [SCSI] libiscsi: ...
661
662
  	if (session->tt->init_task && session->tt->init_task(task))
  		return -EIO;
052d01448   Mike Christie   [SCSI] libiscsi: ...
663
664
665
  
  	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
  		session->state = ISCSI_STATE_LOGGING_OUT;
577577da6   Mike Christie   [SCSI] libiscsi: ...
666
  	task->state = ISCSI_TASK_RUNNING;
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
667
668
669
670
  	ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x "
  			  "datalen %d]
  ", hdr->opcode & ISCSI_OPCODE_MASK,
  			  hdr->itt, task->data_count);
052d01448   Mike Christie   [SCSI] libiscsi: ...
671
672
  	return 0;
  }
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
673
  static struct iscsi_task *
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
674
675
676
677
  __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
  		      char *data, uint32_t data_size)
  {
  	struct iscsi_session *session = conn->session;
1336aed10   Mike Christie   [SCSI] libiscsi: ...
678
  	struct iscsi_host *ihost = shost_priv(session->host);
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
679
  	uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
680
  	struct iscsi_task *task;
262ef6362   Mike Christie   [SCSI] libiscsi: ...
681
  	itt_t itt;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
682
683
684
  
  	if (session->state == ISCSI_STATE_TERMINATE)
  		return NULL;
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
685
  	if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) {
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
686
687
688
  		/*
  		 * Login and Text are sent serially, in
  		 * request-followed-by-response sequence.
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
689
690
  		 * Same task can be used. Same ITT must be used.
  		 * Note that login_task is preallocated at conn_create().
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
691
  		 */
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
692
693
694
695
696
697
  		if (conn->login_task->state != ISCSI_TASK_FREE) {
  			iscsi_conn_printk(KERN_ERR, conn, "Login/Text in "
  					  "progress. Cannot start new task.
  ");
  			return NULL;
  		}
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
698
  		task = conn->login_task;
4f704dc03   Mike Christie   [SCSI] libiscsi: ...
699
  	} else {
26013ad4c   Mike Christie   [SCSI] libiscsi: ...
700
701
  		if (session->state != ISCSI_STATE_LOGGED_IN)
  			return NULL;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
702
703
  		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
  		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
704
  		if (!kfifo_out(&session->cmdpool.queue,
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
705
  				 (void*)&task, sizeof(void*)))
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
706
707
  			return NULL;
  	}
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
708
709
710
711
712
  	/*
  	 * released in complete pdu for task we expect a response for, and
  	 * released by the lld when it has transmitted the task for
  	 * pdus we do not expect a response for.
  	 */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
713
714
715
  	atomic_set(&task->refcount, 1);
  	task->conn = conn;
  	task->sc = NULL;
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
716
717
  	INIT_LIST_HEAD(&task->running);
  	task->state = ISCSI_TASK_PENDING;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
718
719
  
  	if (data_size) {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
720
721
  		memcpy(task->data, data, data_size);
  		task->data_count = data_size;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
722
  	} else
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
723
  		task->data_count = 0;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
724

184b57c63   Mike Christie   [SCSI] libiscsi: ...
725
726
727
728
729
  	if (conn->session->tt->alloc_pdu) {
  		if (conn->session->tt->alloc_pdu(task, hdr->opcode)) {
  			iscsi_conn_printk(KERN_ERR, conn, "Could not allocate "
  					 "pdu for mgmt task.
  ");
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
730
  			goto free_task;
184b57c63   Mike Christie   [SCSI] libiscsi: ...
731
  		}
577577da6   Mike Christie   [SCSI] libiscsi: ...
732
  	}
184b57c63   Mike Christie   [SCSI] libiscsi: ...
733

262ef6362   Mike Christie   [SCSI] libiscsi: ...
734
  	itt = task->hdr->itt;
577577da6   Mike Christie   [SCSI] libiscsi: ...
735
  	task->hdr_len = sizeof(struct iscsi_hdr);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
736
  	memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr));
262ef6362   Mike Christie   [SCSI] libiscsi: ...
737
738
739
740
741
742
743
744
  
  	if (hdr->itt != RESERVED_ITT) {
  		if (session->tt->parse_pdu_itt)
  			task->hdr->itt = itt;
  		else
  			task->hdr->itt = build_itt(task->itt,
  						   task->conn->session->age);
  	}
1336aed10   Mike Christie   [SCSI] libiscsi: ...
745
  	if (!ihost->workq) {
577577da6   Mike Christie   [SCSI] libiscsi: ...
746
747
  		if (iscsi_prep_mgmt_task(conn, task))
  			goto free_task;
052d01448   Mike Christie   [SCSI] libiscsi: ...
748

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
749
  		if (session->tt->xmit_task(task))
577577da6   Mike Christie   [SCSI] libiscsi: ...
750
  			goto free_task;
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
751
752
  	} else {
  		list_add_tail(&task->running, &conn->mgmtqueue);
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
753
  		iscsi_conn_queue_work(conn);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
754
  	}
052d01448   Mike Christie   [SCSI] libiscsi: ...
755

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
756
  	return task;
577577da6   Mike Christie   [SCSI] libiscsi: ...
757
758
759
760
  
  free_task:
  	__iscsi_put_task(task);
  	return NULL;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
761
762
763
764
765
766
767
768
769
770
771
772
773
  }
  
  int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
  			char *data, uint32_t data_size)
  {
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	struct iscsi_session *session = conn->session;
  	int err = 0;
  
  	spin_lock_bh(&session->lock);
  	if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
  		err = -EPERM;
  	spin_unlock_bh(&session->lock);
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
774
775
776
  	return err;
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
7996a778f   Mike Christie   [SCSI] iscsi: add...
777
778
779
780
  /**
   * iscsi_cmd_rsp - SCSI Command Response processing
   * @conn: iscsi connection
   * @hdr: iscsi header
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
781
   * @task: scsi command task
7996a778f   Mike Christie   [SCSI] iscsi: add...
782
783
784
785
   * @data: cmd data buffer
   * @datalen: len of buffer
   *
   * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
786
   * then completes the command and task.
7996a778f   Mike Christie   [SCSI] iscsi: add...
787
   **/
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
788
  static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
789
  			       struct iscsi_task *task, char *data,
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
790
  			       int datalen)
7996a778f   Mike Christie   [SCSI] iscsi: add...
791
  {
123521830   Nicholas Bellinger   iscsi: Resolve is...
792
  	struct iscsi_scsi_rsp *rhdr = (struct iscsi_scsi_rsp *)hdr;
7996a778f   Mike Christie   [SCSI] iscsi: add...
793
  	struct iscsi_session *session = conn->session;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
794
  	struct scsi_cmnd *sc = task->sc;
7996a778f   Mike Christie   [SCSI] iscsi: add...
795

77a23c21a   Mike Christie   [SCSI] libiscsi: ...
796
  	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
7996a778f   Mike Christie   [SCSI] iscsi: add...
797
798
799
800
801
802
803
804
805
806
  	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
  
  	sc->result = (DID_OK << 16) | rhdr->cmd_status;
  
  	if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) {
  		sc->result = DID_ERROR << 16;
  		goto out;
  	}
  
  	if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) {
9b80cb4be   Mike Christie   [SCSI] libiscsi: ...
807
  		uint16_t senselen;
7996a778f   Mike Christie   [SCSI] iscsi: add...
808
809
810
  
  		if (datalen < 2) {
  invalid_datalen:
322d739da   Mike Christie   [SCSI] iscsi: fix...
811
812
813
814
  			iscsi_conn_printk(KERN_ERR,  conn,
  					 "Got CHECK_CONDITION but invalid data "
  					 "buffer size of %d
  ", datalen);
7996a778f   Mike Christie   [SCSI] iscsi: add...
815
816
817
  			sc->result = DID_BAD_TARGET << 16;
  			goto out;
  		}
8f333991b   Harvey Harrison   [SCSI] scsi: use ...
818
  		senselen = get_unaligned_be16(data);
7996a778f   Mike Christie   [SCSI] iscsi: add...
819
820
821
822
  		if (datalen < senselen)
  			goto invalid_datalen;
  
  		memcpy(sc->sense_buffer, data + 2,
9b80cb4be   Mike Christie   [SCSI] libiscsi: ...
823
  		       min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
824
825
826
827
  		ISCSI_DBG_SESSION(session, "copied %d bytes of sense
  ",
  				  min_t(uint16_t, senselen,
  				  SCSI_SENSE_BUFFERSIZE));
7996a778f   Mike Christie   [SCSI] iscsi: add...
828
  	}
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
829
830
831
832
833
834
835
836
837
838
839
  	if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
  			   ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
  		int res_count = be32_to_cpu(rhdr->bi_residual_count);
  
  		if (scsi_bidi_cmnd(sc) && res_count > 0 &&
  				(rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW ||
  				 res_count <= scsi_in(sc)->length))
  			scsi_in(sc)->resid = res_count;
  		else
  			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
  	}
7207fea45   Boaz Harrosh   [SCSI] iscsi: Pre...
840
841
  	if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
  	                   ISCSI_FLAG_CMD_OVERFLOW)) {
7996a778f   Mike Christie   [SCSI] iscsi: add...
842
  		int res_count = be32_to_cpu(rhdr->residual_count);
7207fea45   Boaz Harrosh   [SCSI] iscsi: Pre...
843
844
845
  		if (res_count > 0 &&
  		    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
  		     res_count <= scsi_bufflen(sc)))
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
846
  			/* write side for bidi or uni-io set_resid */
1c1389915   FUJITA Tomonori   [SCSI] iscsi_tcp:...
847
  			scsi_set_resid(sc, res_count);
7996a778f   Mike Christie   [SCSI] iscsi: add...
848
849
  		else
  			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
850
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
851
  out:
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
852
853
  	ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]
  ",
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
854
  			  sc, sc->result, task->itt);
7996a778f   Mike Christie   [SCSI] iscsi: add...
855
  	conn->scsirsp_pdus_cnt++;
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
856
  	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
7996a778f   Mike Christie   [SCSI] iscsi: add...
857
  }
1d9edf027   Mike Christie   [SCSI] libiscsi: ...
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
  /**
   * iscsi_data_in_rsp - SCSI Data-In Response processing
   * @conn: iscsi connection
   * @hdr:  iscsi pdu
   * @task: scsi command task
   **/
  static void
  iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
  		  struct iscsi_task *task)
  {
  	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)hdr;
  	struct scsi_cmnd *sc = task->sc;
  
  	if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS))
  		return;
edbc9aa05   Mike Christie   [SCSI] libiscsi: ...
873
  	iscsi_update_cmdsn(conn->session, (struct iscsi_nopin *)hdr);
1d9edf027   Mike Christie   [SCSI] libiscsi: ...
874
875
876
877
878
879
880
881
882
883
884
885
886
  	sc->result = (DID_OK << 16) | rhdr->cmd_status;
  	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
  	if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
  	                   ISCSI_FLAG_DATA_OVERFLOW)) {
  		int res_count = be32_to_cpu(rhdr->residual_count);
  
  		if (res_count > 0 &&
  		    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
  		     res_count <= scsi_in(sc)->length))
  			scsi_in(sc)->resid = res_count;
  		else
  			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
  	}
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
887
888
889
890
  	ISCSI_DBG_SESSION(conn->session, "data in with status done "
  			  "[sc %p res %d itt 0x%x]
  ",
  			  sc, sc->result, task->itt);
1d9edf027   Mike Christie   [SCSI] libiscsi: ...
891
  	conn->scsirsp_pdus_cnt++;
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
892
  	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
1d9edf027   Mike Christie   [SCSI] libiscsi: ...
893
  }
7ea8b8284   Mike Christie   [SCSI] iscsi bugf...
894
895
896
897
898
899
  static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
  {
  	struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
  
  	conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
  	conn->tmfrsp_pdus_cnt++;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
900
  	if (conn->tmf_state != TMF_QUEUED)
7ea8b8284   Mike Christie   [SCSI] iscsi bugf...
901
902
903
  		return;
  
  	if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
904
  		conn->tmf_state = TMF_SUCCESS;
7ea8b8284   Mike Christie   [SCSI] iscsi bugf...
905
  	else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
906
  		conn->tmf_state = TMF_NOT_FOUND;
7ea8b8284   Mike Christie   [SCSI] iscsi bugf...
907
  	else
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
908
  		conn->tmf_state = TMF_FAILED;
7ea8b8284   Mike Christie   [SCSI] iscsi bugf...
909
910
  	wake_up(&conn->ehwait);
  }
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
911
912
913
  static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
  {
          struct iscsi_nopout hdr;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
914
  	struct iscsi_task *task;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
915

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
916
  	if (!rhdr && conn->ping_task)
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
917
918
919
920
921
922
923
  		return;
  
  	memset(&hdr, 0, sizeof(struct iscsi_nopout));
  	hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
  	hdr.flags = ISCSI_FLAG_CMD_FINAL;
  
  	if (rhdr) {
55bdabdf4   Andy Grover   iscsi: Use struct...
924
  		hdr.lun = rhdr->lun;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
925
926
927
928
  		hdr.ttt = rhdr->ttt;
  		hdr.itt = RESERVED_ITT;
  	} else
  		hdr.ttt = RESERVED_ITT;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
929
930
  	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
  	if (!task)
322d739da   Mike Christie   [SCSI] iscsi: fix...
931
932
  		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout
  ");
d3acf0226   Mike Christie   [SCSI] libiscsi R...
933
934
935
936
937
  	else if (!rhdr) {
  		/* only track our nops */
  		conn->ping_task = task;
  		conn->last_ping = jiffies;
  	}
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
938
  }
8afa1439f   Mike Christie   [SCSI] libiscsi: ...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
  static int iscsi_nop_out_rsp(struct iscsi_task *task,
  			     struct iscsi_nopin *nop, char *data, int datalen)
  {
  	struct iscsi_conn *conn = task->conn;
  	int rc = 0;
  
  	if (conn->ping_task != task) {
  		/*
  		 * If this is not in response to one of our
  		 * nops then it must be from userspace.
  		 */
  		if (iscsi_recv_pdu(conn->cls_conn, (struct iscsi_hdr *)nop,
  				   data, datalen))
  			rc = ISCSI_ERR_CONN_FAILED;
  	} else
  		mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
  	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
  	return rc;
  }
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
958
959
960
961
962
  static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
  			       char *data, int datalen)
  {
  	struct iscsi_reject *reject = (struct iscsi_reject *)hdr;
  	struct iscsi_hdr rejected_pdu;
8afa1439f   Mike Christie   [SCSI] libiscsi: ...
963
  	int opcode, rc = 0;
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
964
965
  
  	conn->exp_statsn = be32_to_cpu(reject->statsn) + 1;
8afa1439f   Mike Christie   [SCSI] libiscsi: ...
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  	if (ntoh24(reject->dlength) > datalen ||
  	    ntoh24(reject->dlength) < sizeof(struct iscsi_hdr)) {
  		iscsi_conn_printk(KERN_ERR, conn, "Cannot handle rejected "
  				  "pdu. Invalid data length (pdu dlength "
  				  "%u, datalen %d
  ", ntoh24(reject->dlength),
  				  datalen);
  		return ISCSI_ERR_PROTO;
  	}
  	memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
  	opcode = rejected_pdu.opcode & ISCSI_OPCODE_MASK;
  
  	switch (reject->reason) {
  	case ISCSI_REASON_DATA_DIGEST_ERROR:
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "pdu (op 0x%x itt 0x%x) rejected "
  				  "due to DataDigest error.
  ",
  				  rejected_pdu.itt, opcode);
  		break;
  	case ISCSI_REASON_IMM_CMD_REJECT:
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "pdu (op 0x%x itt 0x%x) rejected. Too many "
  				  "immediate commands.
  ",
  				  rejected_pdu.itt, opcode);
  		/*
  		 * We only send one TMF at a time so if the target could not
  		 * handle it, then it should get fixed (RFC mandates that
  		 * a target can handle one immediate TMF per conn).
  		 *
  		 * For nops-outs, we could have sent more than one if
  		 * the target is sending us lots of nop-ins
  		 */
  		if (opcode != ISCSI_OP_NOOP_OUT)
  			return 0;
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
1002

8afa1439f   Mike Christie   [SCSI] libiscsi: ...
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  		 if (rejected_pdu.itt == cpu_to_be32(ISCSI_RESERVED_TAG))
  			/*
  			 * nop-out in response to target's nop-out rejected.
  			 * Just resend.
  			 */
  			iscsi_send_nopout(conn,
  					  (struct iscsi_nopin*)&rejected_pdu);
  		else {
  			struct iscsi_task *task;
  			/*
  			 * Our nop as ping got dropped. We know the target
  			 * and transport are ok so just clean up
  			 */
  			task = iscsi_itt_to_task(conn, rejected_pdu.itt);
  			if (!task) {
  				iscsi_conn_printk(KERN_ERR, conn,
  						 "Invalid pdu reject. Could "
  						 "not lookup rejected task.
  ");
  				rc = ISCSI_ERR_BAD_ITT;
  			} else
  				rc = iscsi_nop_out_rsp(task,
  					(struct iscsi_nopin*)&rejected_pdu,
  					NULL, 0);
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
1027
  		}
8afa1439f   Mike Christie   [SCSI] libiscsi: ...
1028
1029
1030
1031
1032
1033
1034
1035
  		break;
  	default:
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "pdu (op 0x%x itt 0x%x) rejected. Reason "
  				  "code 0x%x
  ", rejected_pdu.itt,
  				  rejected_pdu.opcode, reject->reason);
  		break;
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
1036
  	}
8afa1439f   Mike Christie   [SCSI] libiscsi: ...
1037
  	return rc;
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
1038
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
1039
  /**
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1040
1041
1042
1043
1044
1045
1046
1047
1048
   * iscsi_itt_to_task - look up task by itt
   * @conn: iscsi connection
   * @itt: itt
   *
   * This should be used for mgmt tasks like login and nops, or if
   * the LDD's itt space does not include the session age.
   *
   * The session lock must be held.
   */
8f9256cea   Mike Christie   [SCSI] libiscsi: ...
1049
  struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1050
1051
  {
  	struct iscsi_session *session = conn->session;
262ef6362   Mike Christie   [SCSI] libiscsi: ...
1052
  	int i;
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1053
1054
1055
  
  	if (itt == RESERVED_ITT)
  		return NULL;
262ef6362   Mike Christie   [SCSI] libiscsi: ...
1056
1057
1058
1059
  	if (session->tt->parse_pdu_itt)
  		session->tt->parse_pdu_itt(conn, itt, &i, NULL);
  	else
  		i = get_itt(itt);
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1060
1061
1062
1063
1064
  	if (i >= session->cmds_max)
  		return NULL;
  
  	return session->cmds[i];
  }
8f9256cea   Mike Christie   [SCSI] libiscsi: ...
1065
  EXPORT_SYMBOL_GPL(iscsi_itt_to_task);
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1066
1067
  
  /**
7996a778f   Mike Christie   [SCSI] iscsi: add...
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
   * __iscsi_complete_pdu - complete pdu
   * @conn: iscsi conn
   * @hdr: iscsi header
   * @data: data buffer
   * @datalen: len of data buffer
   *
   * Completes pdu processing by freeing any resources allocated at
   * queuecommand or send generic. session lock must be held and verify
   * itt must have been called.
   */
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1078
1079
  int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
  			 char *data, int datalen)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1080
1081
1082
  {
  	struct iscsi_session *session = conn->session;
  	int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1083
  	struct iscsi_task *task;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1084
  	uint32_t itt;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1085
  	conn->last_recv = jiffies;
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1086
1087
1088
  	rc = iscsi_verify_itt(conn, hdr->itt);
  	if (rc)
  		return rc;
b43773564   Al Viro   [PATCH] iscsi end...
1089
1090
  	if (hdr->itt != RESERVED_ITT)
  		itt = get_itt(hdr->itt);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1091
  	else
b43773564   Al Viro   [PATCH] iscsi end...
1092
  		itt = ~0U;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1093

1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
1094
1095
1096
  	ISCSI_DBG_SESSION(session, "[op 0x%x cid %d itt 0x%x len %d]
  ",
  			  opcode, conn->id, itt, datalen);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1097

3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1098
  	if (itt == ~0U) {
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1099
  		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
1100

7996a778f   Mike Christie   [SCSI] iscsi: add...
1101
1102
  		switch(opcode) {
  		case ISCSI_OP_NOOP_IN:
40527afea   Mike Christie   [SCSI] iscsi bugf...
1103
  			if (datalen) {
7996a778f   Mike Christie   [SCSI] iscsi: add...
1104
  				rc = ISCSI_ERR_PROTO;
40527afea   Mike Christie   [SCSI] iscsi bugf...
1105
1106
  				break;
  			}
b43773564   Al Viro   [PATCH] iscsi end...
1107
  			if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG))
40527afea   Mike Christie   [SCSI] iscsi bugf...
1108
  				break;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1109
  			iscsi_send_nopout(conn, (struct iscsi_nopin*)hdr);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1110
1111
  			break;
  		case ISCSI_OP_REJECT:
62f383003   Mike Christie   [SCSI] iscsi_tcp:...
1112
1113
  			rc = iscsi_handle_reject(conn, hdr, data, datalen);
  			break;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1114
  		case ISCSI_OP_ASYNC_EVENT:
8d2860b3c   Mike Christie   [SCSI] iscsi: inc...
1115
  			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
5831c737f   Mike Christie   [SCSI] libiscsi: ...
1116
1117
  			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
  				rc = ISCSI_ERR_CONN_FAILED;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1118
1119
1120
1121
1122
  			break;
  		default:
  			rc = ISCSI_ERR_BAD_OPCODE;
  			break;
  		}
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1123
1124
  		goto out;
  	}
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1125
1126
  	switch(opcode) {
  	case ISCSI_OP_SCSI_CMD_RSP:
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1127
1128
1129
1130
  	case ISCSI_OP_SCSI_DATA_IN:
  		task = iscsi_itt_to_ctask(conn, hdr->itt);
  		if (!task)
  			return ISCSI_ERR_BAD_ITT;
d355e57d5   Mike Christie   libiscsi: don't r...
1131
  		task->last_xfer = jiffies;
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
  		break;
  	case ISCSI_OP_R2T:
  		/*
  		 * LLD handles R2Ts if they need to.
  		 */
  		return 0;
  	case ISCSI_OP_LOGOUT_RSP:
  	case ISCSI_OP_LOGIN_RSP:
  	case ISCSI_OP_TEXT_RSP:
  	case ISCSI_OP_SCSI_TMFUNC_RSP:
  	case ISCSI_OP_NOOP_IN:
  		task = iscsi_itt_to_task(conn, hdr->itt);
  		if (!task)
  			return ISCSI_ERR_BAD_ITT;
  		break;
  	default:
  		return ISCSI_ERR_BAD_OPCODE;
  	}
  
  	switch(opcode) {
  	case ISCSI_OP_SCSI_CMD_RSP:
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1153
  		iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen);
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1154
1155
  		break;
  	case ISCSI_OP_SCSI_DATA_IN:
1d9edf027   Mike Christie   [SCSI] libiscsi: ...
1156
  		iscsi_data_in_rsp(conn, hdr, task);
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1157
  		break;
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
  	case ISCSI_OP_LOGOUT_RSP:
  		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
  		if (datalen) {
  			rc = ISCSI_ERR_PROTO;
  			break;
  		}
  		conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
  		goto recv_pdu;
  	case ISCSI_OP_LOGIN_RSP:
  	case ISCSI_OP_TEXT_RSP:
  		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
  		/*
  		 * login related PDU's exp_statsn is handled in
  		 * userspace
  		 */
  		goto recv_pdu;
  	case ISCSI_OP_SCSI_TMFUNC_RSP:
  		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
  		if (datalen) {
  			rc = ISCSI_ERR_PROTO;
  			break;
  		}
  
  		iscsi_tmf_rsp(conn, hdr);
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
1182
  		iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1183
1184
1185
1186
1187
1188
1189
1190
  		break;
  	case ISCSI_OP_NOOP_IN:
  		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
  		if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) {
  			rc = ISCSI_ERR_PROTO;
  			break;
  		}
  		conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
8afa1439f   Mike Christie   [SCSI] libiscsi: ...
1191
1192
  		rc = iscsi_nop_out_rsp(task, (struct iscsi_nopin*)hdr,
  				       data, datalen);
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1193
1194
1195
1196
1197
  		break;
  	default:
  		rc = ISCSI_ERR_BAD_OPCODE;
  		break;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1198

3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1199
1200
1201
1202
1203
  out:
  	return rc;
  recv_pdu:
  	if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
  		rc = ISCSI_ERR_CONN_FAILED;
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
1204
  	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1205
1206
  	return rc;
  }
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1207
  EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
  
  int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
  		       char *data, int datalen)
  {
  	int rc;
  
  	spin_lock(&conn->session->lock);
  	rc = __iscsi_complete_pdu(conn, hdr, data, datalen);
  	spin_unlock(&conn->session->lock);
  	return rc;
  }
  EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1220
  int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1221
1222
  {
  	struct iscsi_session *session = conn->session;
262ef6362   Mike Christie   [SCSI] libiscsi: ...
1223
  	int age = 0, i = 0;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1224

0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1225
1226
  	if (itt == RESERVED_ITT)
  		return 0;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1227

262ef6362   Mike Christie   [SCSI] libiscsi: ...
1228
1229
1230
1231
1232
1233
1234
1235
  	if (session->tt->parse_pdu_itt)
  		session->tt->parse_pdu_itt(conn, itt, &i, &age);
  	else {
  		i = get_itt(itt);
  		age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK;
  	}
  
  	if (age != session->age) {
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1236
1237
1238
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "received itt %x expected session age (%x)
  ",
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1239
  				  (__force u32)itt, session->age);
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1240
1241
  		return ISCSI_ERR_BAD_ITT;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1242

3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
1243
1244
1245
1246
1247
1248
  	if (i >= session->cmds_max) {
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "received invalid itt index %u (max cmds "
  				   "%u.
  ", i, session->cmds_max);
  		return ISCSI_ERR_BAD_ITT;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1249
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1250
1251
1252
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_verify_itt);
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
  /**
   * iscsi_itt_to_ctask - look up ctask by itt
   * @conn: iscsi connection
   * @itt: itt
   *
   * This should be used for cmd tasks.
   *
   * The session lock must be held.
   */
  struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1263
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1264
  	struct iscsi_task *task;
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1265
1266
1267
  
  	if (iscsi_verify_itt(conn, itt))
  		return NULL;
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1268
1269
  	task = iscsi_itt_to_task(conn, itt);
  	if (!task || !task->sc)
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1270
  		return NULL;
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1271
1272
1273
1274
1275
  	if (task->sc->SCp.phase != conn->session->age) {
  		iscsi_session_printk(KERN_ERR, conn->session,
  				  "task's session age %d, expected %d
  ",
  				  task->sc->SCp.phase, conn->session->age);
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1276
  		return NULL;
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
1277
  	}
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1278

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1279
  	return task;
0af967f5d   Mike Christie   [SCSI] libiscsi, ...
1280
1281
  }
  EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
40a06e755   Mike Christie   [SCSI] libiscsi: ...
1282
  void iscsi_session_failure(struct iscsi_session *session,
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1283
1284
  			   enum iscsi_err err)
  {
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1285
1286
  	struct iscsi_conn *conn;
  	struct device *dev;
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1287

bfcf72e44   Mike Christie   [SCSI] libiscsi: ...
1288
  	spin_lock_bh(&session->lock);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1289
1290
  	conn = session->leadconn;
  	if (session->state == ISCSI_STATE_TERMINATE || !conn) {
bfcf72e44   Mike Christie   [SCSI] libiscsi: ...
1291
  		spin_unlock_bh(&session->lock);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1292
1293
1294
1295
  		return;
  	}
  
  	dev = get_device(&conn->cls_conn->dev);
bfcf72e44   Mike Christie   [SCSI] libiscsi: ...
1296
  	spin_unlock_bh(&session->lock);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
  	if (!dev)
  	        return;
  	/*
  	 * if the host is being removed bypass the connection
  	 * recovery initialization because we are going to kill
  	 * the session.
  	 */
  	if (err == ISCSI_ERR_INVALID_HOST)
  		iscsi_conn_error_event(conn->cls_conn, err);
  	else
  		iscsi_conn_failure(conn, err);
  	put_device(dev);
  }
  EXPORT_SYMBOL_GPL(iscsi_session_failure);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1311
1312
1313
  void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
  {
  	struct iscsi_session *session = conn->session;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1314

bfcf72e44   Mike Christie   [SCSI] libiscsi: ...
1315
  	spin_lock_bh(&session->lock);
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1316
  	if (session->state == ISCSI_STATE_FAILED) {
bfcf72e44   Mike Christie   [SCSI] libiscsi: ...
1317
  		spin_unlock_bh(&session->lock);
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1318
1319
  		return;
  	}
67a611149   Mike Christie   [SCSI] iscsi: don...
1320
  	if (conn->stop_stage == 0)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1321
  		session->state = ISCSI_STATE_FAILED;
bfcf72e44   Mike Christie   [SCSI] libiscsi: ...
1322
  	spin_unlock_bh(&session->lock);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1323

7996a778f   Mike Christie   [SCSI] iscsi: add...
1324
1325
  	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
  	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1326
  	iscsi_conn_error_event(conn->cls_conn, err);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1327
1328
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_failure);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1329
1330
1331
1332
1333
1334
1335
  static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
  {
  	struct iscsi_session *session = conn->session;
  
  	/*
  	 * Check for iSCSI window and take care of CmdSN wrap-around
  	 */
e07264071   Mike Christie   [SCSI] libiscsi: ...
1336
  	if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) {
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
1337
1338
1339
1340
1341
  		ISCSI_DBG_SESSION(session, "iSCSI CmdSN closed. ExpCmdSn "
  				  "%u MaxCmdSN %u CmdSN %u/%u
  ",
  				  session->exp_cmdsn, session->max_cmdsn,
  				  session->cmdsn, session->queued_cmdsn);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1342
1343
1344
1345
  		return -ENOSPC;
  	}
  	return 0;
  }
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1346
  static int iscsi_xmit_task(struct iscsi_conn *conn)
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1347
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1348
  	struct iscsi_task *task = conn->task;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1349
  	int rc;
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1350

70b31c152   Mike Christie   [SCSI] libiscsi, ...
1351
1352
  	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx))
  		return -ENODATA;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1353
  	__iscsi_get_task(task);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1354
  	spin_unlock_bh(&conn->session->lock);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1355
  	rc = conn->session->tt->xmit_task(task);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1356
  	spin_lock_bh(&conn->session->lock);
d355e57d5   Mike Christie   libiscsi: don't r...
1357
  	if (!rc) {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1358
  		/* done with this task */
d355e57d5   Mike Christie   libiscsi: don't r...
1359
  		task->last_xfer = jiffies;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1360
  		conn->task = NULL;
d355e57d5   Mike Christie   libiscsi: don't r...
1361
1362
  	}
  	__iscsi_put_task(task);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1363
1364
  	return rc;
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
1365
  /**
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1366
1367
   * iscsi_requeue_task - requeue task to run from session workqueue
   * @task: task to requeue
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1368
   *
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1369
   * LLDs that need to run a task from the session workqueue should call
052d01448   Mike Christie   [SCSI] libiscsi: ...
1370
1371
   * this. The session lock must be held. This should only be called
   * by software drivers.
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1372
   */
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1373
  void iscsi_requeue_task(struct iscsi_task *task)
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1374
  {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1375
  	struct iscsi_conn *conn = task->conn;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1376

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1377
1378
1379
1380
1381
1382
  	/*
  	 * this may be on the requeue list already if the xmit_task callout
  	 * is handling the r2ts while we are adding new ones
  	 */
  	if (list_empty(&task->running))
  		list_add_tail(&task->running, &conn->requeue);
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
1383
  	iscsi_conn_queue_work(conn);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1384
  }
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1385
  EXPORT_SYMBOL_GPL(iscsi_requeue_task);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1386
1387
  
  /**
7996a778f   Mike Christie   [SCSI] iscsi: add...
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
   * iscsi_data_xmit - xmit any command into the scheduled connection
   * @conn: iscsi connection
   *
   * Notes:
   *	The function can return -EAGAIN in which case the caller must
   *	re-schedule it again later or recover. '0' return code means
   *	successful xmit.
   **/
  static int iscsi_data_xmit(struct iscsi_conn *conn)
  {
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
1398
  	struct iscsi_task *task;
3219e5294   Mike Christie   [SCSI] iscsi: fix...
1399
  	int rc = 0;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1400

77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1401
  	spin_lock_bh(&conn->session->lock);
70b31c152   Mike Christie   [SCSI] libiscsi, ...
1402
  	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
1403
1404
  		ISCSI_DBG_SESSION(conn->session, "Tx suspended!
  ");
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1405
  		spin_unlock_bh(&conn->session->lock);
3219e5294   Mike Christie   [SCSI] iscsi: fix...
1406
  		return -ENODATA;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1407
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1408

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1409
1410
  	if (conn->task) {
  		rc = iscsi_xmit_task(conn);
3219e5294   Mike Christie   [SCSI] iscsi: fix...
1411
  	        if (rc)
70b31c152   Mike Christie   [SCSI] libiscsi, ...
1412
  		        goto done;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1413
  	}
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1414
1415
1416
1417
1418
1419
  	/*
  	 * process mgmt pdus like nops before commands since we should
  	 * only have one nop-out as a ping from us and targets should not
  	 * overflow us with nop-ins
  	 */
  check_mgmt:
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1420
  	while (!list_empty(&conn->mgmtqueue)) {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1421
1422
  		conn->task = list_entry(conn->mgmtqueue.next,
  					 struct iscsi_task, running);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1423
  		list_del_init(&conn->task->running);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1424
1425
1426
  		if (iscsi_prep_mgmt_task(conn, conn->task)) {
  			__iscsi_put_task(conn->task);
  			conn->task = NULL;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1427
1428
  			continue;
  		}
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1429
  		rc = iscsi_xmit_task(conn);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1430
  		if (rc)
70b31c152   Mike Christie   [SCSI] libiscsi, ...
1431
  			goto done;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1432
  	}
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1433
  	/* process pending command queue */
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1434
  	while (!list_empty(&conn->cmdqueue)) {
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
1435
1436
  		conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task,
  					running);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1437
  		list_del_init(&conn->task->running);
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1438
  		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
1439
  			fail_scsi_task(conn->task, DID_IMM_RETRY);
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1440
1441
  			continue;
  		}
577577da6   Mike Christie   [SCSI] libiscsi: ...
1442
1443
  		rc = iscsi_prep_scsi_cmd_pdu(conn->task);
  		if (rc) {
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
1444
  			if (rc == -ENOMEM || rc == -EACCES) {
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1445
1446
  				list_add_tail(&conn->task->running,
  					      &conn->cmdqueue);
577577da6   Mike Christie   [SCSI] libiscsi: ...
1447
  				conn->task = NULL;
70b31c152   Mike Christie   [SCSI] libiscsi, ...
1448
  				goto done;
577577da6   Mike Christie   [SCSI] libiscsi: ...
1449
  			} else
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
1450
  				fail_scsi_task(conn->task, DID_ABORT);
004d6530f   Boaz Harrosh   [SCSI] iscsi_tcp,...
1451
1452
  			continue;
  		}
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1453
  		rc = iscsi_xmit_task(conn);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1454
  		if (rc)
70b31c152   Mike Christie   [SCSI] libiscsi, ...
1455
  			goto done;
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1456
  		/*
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1457
  		 * we could continuously get new task requests so
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1458
1459
1460
  		 * we need to check the mgmt queue for nops that need to
  		 * be sent to aviod starvation
  		 */
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1461
1462
1463
1464
1465
  		if (!list_empty(&conn->mgmtqueue))
  			goto check_mgmt;
  	}
  
  	while (!list_empty(&conn->requeue)) {
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1466
1467
1468
1469
1470
  		/*
  		 * we always do fastlogout - conn stop code will clean up.
  		 */
  		if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
  			break;
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
1471
1472
1473
1474
1475
1476
  		task = list_entry(conn->requeue.next, struct iscsi_task,
  				  running);
  		if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
  			break;
  
  		conn->task = task;
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1477
  		list_del_init(&conn->task->running);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1478
  		conn->task->state = ISCSI_TASK_RUNNING;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1479
  		rc = iscsi_xmit_task(conn);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1480
  		if (rc)
70b31c152   Mike Christie   [SCSI] libiscsi, ...
1481
  			goto done;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1482
  		if (!list_empty(&conn->mgmtqueue))
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1483
  			goto check_mgmt;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1484
  	}
b6c395ed0   Mike Christie   [SCSI] iscsi bugf...
1485
  	spin_unlock_bh(&conn->session->lock);
3219e5294   Mike Christie   [SCSI] iscsi: fix...
1486
  	return -ENODATA;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1487

70b31c152   Mike Christie   [SCSI] libiscsi, ...
1488
  done:
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1489
  	spin_unlock_bh(&conn->session->lock);
3219e5294   Mike Christie   [SCSI] iscsi: fix...
1490
  	return rc;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1491
  }
c4028958b   David Howells   WorkStruct: make ...
1492
  static void iscsi_xmitworker(struct work_struct *work)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1493
  {
c4028958b   David Howells   WorkStruct: make ...
1494
1495
  	struct iscsi_conn *conn =
  		container_of(work, struct iscsi_conn, xmitwork);
3219e5294   Mike Christie   [SCSI] iscsi: fix...
1496
  	int rc;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1497
1498
1499
  	/*
  	 * serialize Xmit worker on a per-connection basis.
  	 */
3219e5294   Mike Christie   [SCSI] iscsi: fix...
1500
1501
1502
  	do {
  		rc = iscsi_data_xmit(conn);
  	} while (rc >= 0 || rc == -EAGAIN);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1503
  }
577577da6   Mike Christie   [SCSI] libiscsi: ...
1504
1505
1506
1507
  static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
  						  struct scsi_cmnd *sc)
  {
  	struct iscsi_task *task;
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
1508
  	if (!kfifo_out(&conn->session->cmdpool.queue,
577577da6   Mike Christie   [SCSI] libiscsi: ...
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
  			 (void *) &task, sizeof(void *)))
  		return NULL;
  
  	sc->SCp.phase = conn->session->age;
  	sc->SCp.ptr = (char *) task;
  
  	atomic_set(&task->refcount, 1);
  	task->state = ISCSI_TASK_PENDING;
  	task->conn = conn;
  	task->sc = sc;
d355e57d5   Mike Christie   libiscsi: don't r...
1519
1520
1521
  	task->have_checked_conn = false;
  	task->last_timeout = jiffies;
  	task->last_xfer = jiffies;
577577da6   Mike Christie   [SCSI] libiscsi: ...
1522
1523
1524
  	INIT_LIST_HEAD(&task->running);
  	return task;
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
1525
1526
1527
1528
1529
  enum {
  	FAILURE_BAD_HOST = 1,
  	FAILURE_SESSION_FAILED,
  	FAILURE_SESSION_FREED,
  	FAILURE_WINDOW_CLOSED,
60ecebf5a   Mike Christie   [SCSI] add refcou...
1530
  	FAILURE_OOM,
7996a778f   Mike Christie   [SCSI] iscsi: add...
1531
  	FAILURE_SESSION_TERMINATE,
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1532
  	FAILURE_SESSION_IN_RECOVERY,
7996a778f   Mike Christie   [SCSI] iscsi: add...
1533
  	FAILURE_SESSION_RECOVERY_TIMEOUT,
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1534
  	FAILURE_SESSION_LOGGING_OUT,
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1535
  	FAILURE_SESSION_NOT_READY,
7996a778f   Mike Christie   [SCSI] iscsi: add...
1536
  };
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1537
  int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1538
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
1539
  	struct iscsi_cls_session *cls_session;
1336aed10   Mike Christie   [SCSI] libiscsi: ...
1540
  	struct iscsi_host *ihost;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1541
1542
1543
  	int reason = 0;
  	struct iscsi_session *session;
  	struct iscsi_conn *conn;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1544
  	struct iscsi_task *task = NULL;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1545

7996a778f   Mike Christie   [SCSI] iscsi: add...
1546
  	sc->result = 0;
f47f2cf5d   Mike Christie   [SCSI] libiscsi: ...
1547
  	sc->SCp.ptr = NULL;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1548

1336aed10   Mike Christie   [SCSI] libiscsi: ...
1549
  	ihost = shost_priv(host);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1550

756135215   Mike Christie   [SCSI] iscsi: rem...
1551
1552
  	cls_session = starget_to_session(scsi_target(sc->device));
  	session = cls_session->dd_data;
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1553
  	spin_lock_bh(&session->lock);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1554

756135215   Mike Christie   [SCSI] iscsi: rem...
1555
  	reason = iscsi_session_chkready(cls_session);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1556
1557
1558
1559
  	if (reason) {
  		sc->result = reason;
  		goto fault;
  	}
301e0f7e4   Mike Christie   [SCSI] libiscsi: ...
1560
  	if (session->state != ISCSI_STATE_LOGGED_IN) {
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1561
1562
1563
1564
1565
1566
  		/*
  		 * to handle the race between when we set the recovery state
  		 * and block the session we requeue here (commands could
  		 * be entering our queuecommand while a block is starting
  		 * up because the block code is not locked)
  		 */
9000bcd64   Mike Christie   [SCSI] libiscsi: ...
1567
  		switch (session->state) {
301e0f7e4   Mike Christie   [SCSI] libiscsi: ...
1568
  		case ISCSI_STATE_FAILED:
9000bcd64   Mike Christie   [SCSI] libiscsi: ...
1569
  		case ISCSI_STATE_IN_RECOVERY:
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1570
  			reason = FAILURE_SESSION_IN_RECOVERY;
301e0f7e4   Mike Christie   [SCSI] libiscsi: ...
1571
1572
  			sc->result = DID_IMM_RETRY << 16;
  			break;
9000bcd64   Mike Christie   [SCSI] libiscsi: ...
1573
1574
  		case ISCSI_STATE_LOGGING_OUT:
  			reason = FAILURE_SESSION_LOGGING_OUT;
301e0f7e4   Mike Christie   [SCSI] libiscsi: ...
1575
1576
  			sc->result = DID_IMM_RETRY << 16;
  			break;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1577
  		case ISCSI_STATE_RECOVERY_FAILED:
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1578
  			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
56d7fcfa8   Mike Christie   [SCSI] iscsi clas...
1579
  			sc->result = DID_TRANSPORT_FAILFAST << 16;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1580
1581
  			break;
  		case ISCSI_STATE_TERMINATE:
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1582
  			reason = FAILURE_SESSION_TERMINATE;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1583
  			sc->result = DID_NO_CONNECT << 16;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1584
  			break;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1585
  		default:
656cffc95   Mike Christie   [SCSI] iscsi: fix...
1586
  			reason = FAILURE_SESSION_FREED;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1587
  			sc->result = DID_NO_CONNECT << 16;
b3a7ea8d5   Mike Christie   [SCSI] libiscsi: ...
1588
  		}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1589
1590
  		goto fault;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1591
  	conn = session->leadconn;
986440479   Mike Christie   [SCSI] libiscsi: ...
1592
1593
  	if (!conn) {
  		reason = FAILURE_SESSION_FREED;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1594
  		sc->result = DID_NO_CONNECT << 16;
986440479   Mike Christie   [SCSI] libiscsi: ...
1595
1596
  		goto fault;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1597

661134ad3   Mike Christie   [SCSI] libiscsi, ...
1598
1599
1600
1601
1602
  	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
  		reason = FAILURE_SESSION_IN_RECOVERY;
  		sc->result = DID_REQUEUE;
  		goto fault;
  	}
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1603
1604
1605
1606
  	if (iscsi_check_cmdsn_window_closed(conn)) {
  		reason = FAILURE_WINDOW_CLOSED;
  		goto reject;
  	}
577577da6   Mike Christie   [SCSI] libiscsi: ...
1607
1608
  	task = iscsi_alloc_task(conn, sc);
  	if (!task) {
60ecebf5a   Mike Christie   [SCSI] add refcou...
1609
1610
1611
  		reason = FAILURE_OOM;
  		goto reject;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1612

1336aed10   Mike Christie   [SCSI] libiscsi: ...
1613
  	if (!ihost->workq) {
577577da6   Mike Christie   [SCSI] libiscsi: ...
1614
1615
  		reason = iscsi_prep_scsi_cmd_pdu(task);
  		if (reason) {
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
1616
  			if (reason == -ENOMEM ||  reason == -EACCES) {
577577da6   Mike Christie   [SCSI] libiscsi: ...
1617
1618
1619
1620
1621
1622
  				reason = FAILURE_OOM;
  				goto prepd_reject;
  			} else {
  				sc->result = DID_ABORT << 16;
  				goto prepd_fault;
  			}
052d01448   Mike Christie   [SCSI] libiscsi: ...
1623
  		}
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1624
  		if (session->tt->xmit_task(task)) {
d3305f340   Mike Christie   [SCSI] libiscsi: ...
1625
  			session->cmdsn--;
052d01448   Mike Christie   [SCSI] libiscsi: ...
1626
  			reason = FAILURE_SESSION_NOT_READY;
577577da6   Mike Christie   [SCSI] libiscsi: ...
1627
  			goto prepd_reject;
052d01448   Mike Christie   [SCSI] libiscsi: ...
1628
  		}
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1629
1630
  	} else {
  		list_add_tail(&task->running, &conn->cmdqueue);
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
1631
  		iscsi_conn_queue_work(conn);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1632
  	}
052d01448   Mike Christie   [SCSI] libiscsi: ...
1633
1634
  
  	session->queued_cmdsn++;
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1635
  	spin_unlock_bh(&session->lock);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1636
  	return 0;
577577da6   Mike Christie   [SCSI] libiscsi: ...
1637
  prepd_reject:
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1638
  	iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1639
  reject:
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1640
  	spin_unlock_bh(&session->lock);
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
1641
1642
1643
  	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)
  ",
  			  sc->cmnd[0], reason);
d6d13ee19   Mike Christie   [SCSI] libiscsi: ...
1644
  	return SCSI_MLQUEUE_TARGET_BUSY;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1645

577577da6   Mike Christie   [SCSI] libiscsi: ...
1646
  prepd_fault:
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1647
  	iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1648
  fault:
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1649
  	spin_unlock_bh(&session->lock);
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
1650
1651
1652
  	ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)
  ",
  			  sc->cmnd[0], reason);
c07d44440   Boaz Harrosh   [SCSI] iscsi: bid...
1653
1654
1655
1656
1657
1658
  	if (!scsi_bidi_cmnd(sc))
  		scsi_set_resid(sc, scsi_bufflen(sc));
  	else {
  		scsi_out(sc)->resid = scsi_out(sc)->length;
  		scsi_in(sc)->resid = scsi_in(sc)->length;
  	}
f41d47217   Mike Christie   [SCSI] libiscsi: ...
1659
  	sc->scsi_done(sc);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1660
1661
1662
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_queuecommand);
e881a172d   Mike Christie   [SCSI] modify cha...
1663
  int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1664
  {
1796e7229   Mike Christie   [SCSI] libiscsi: ...
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
  	switch (reason) {
  	case SCSI_QDEPTH_DEFAULT:
  		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
  		break;
  	case SCSI_QDEPTH_QFULL:
  		scsi_track_queue_full(sdev, depth);
  		break;
  	case SCSI_QDEPTH_RAMP_UP:
  		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
  		break;
  	default:
e881a172d   Mike Christie   [SCSI] modify cha...
1676
  		return -EOPNOTSUPP;
1796e7229   Mike Christie   [SCSI] libiscsi: ...
1677
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
1678
1679
1680
  	return sdev->queue_depth;
  }
  EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
6b5d6c443   Mike Christie   [SCSI] cxgb3i, is...
1681
1682
1683
1684
1685
1686
1687
1688
1689
  int iscsi_target_alloc(struct scsi_target *starget)
  {
  	struct iscsi_cls_session *cls_session = starget_to_session(starget);
  	struct iscsi_session *session = cls_session->dd_data;
  
  	starget->can_queue = session->scsi_cmds_max;
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_target_alloc);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1690
  static void iscsi_tmf_timedout(unsigned long data)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1691
  {
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1692
  	struct iscsi_conn *conn = (struct iscsi_conn *)data;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1693
1694
1695
  	struct iscsi_session *session = conn->session;
  
  	spin_lock(&session->lock);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1696
1697
  	if (conn->tmf_state == TMF_QUEUED) {
  		conn->tmf_state = TMF_TIMEDOUT;
bd2199d41   Erez Zilber   libiscsi: add con...
1698
1699
  		ISCSI_DBG_EH(session, "tmf timedout
  ");
7996a778f   Mike Christie   [SCSI] iscsi: add...
1700
1701
1702
1703
1704
  		/* unblock eh_abort() */
  		wake_up(&conn->ehwait);
  	}
  	spin_unlock(&session->lock);
  }
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1705
  static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1706
1707
  				   struct iscsi_tm *hdr, int age,
  				   int timeout)
7996a778f   Mike Christie   [SCSI] iscsi: add...
1708
  {
7996a778f   Mike Christie   [SCSI] iscsi: add...
1709
  	struct iscsi_session *session = conn->session;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1710
  	struct iscsi_task *task;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1711

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1712
  	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1713
  				      NULL, 0);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1714
  	if (!task) {
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1715
  		spin_unlock_bh(&session->lock);
df4da5cdf   Mike Christie   [SCSI] libiscsi: ...
1716
1717
  		iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF.
  ");
7996a778f   Mike Christie   [SCSI] iscsi: add...
1718
  		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1719
  		spin_lock_bh(&session->lock);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1720
  		return -EPERM;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1721
  	}
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1722
  	conn->tmfcmd_pdus_cnt++;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1723
  	conn->tmf_timer.expires = timeout * HZ + jiffies;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1724
1725
1726
  	conn->tmf_timer.function = iscsi_tmf_timedout;
  	conn->tmf_timer.data = (unsigned long)conn;
  	add_timer(&conn->tmf_timer);
bd2199d41   Erez Zilber   libiscsi: add con...
1727
1728
  	ISCSI_DBG_EH(session, "tmf set timeout
  ");
7996a778f   Mike Christie   [SCSI] iscsi: add...
1729

7996a778f   Mike Christie   [SCSI] iscsi: add...
1730
  	spin_unlock_bh(&session->lock);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1731
  	mutex_unlock(&session->eh_mutex);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1732
1733
1734
1735
  
  	/*
  	 * block eh thread until:
  	 *
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1736
1737
  	 * 1) tmf response
  	 * 2) tmf timeout
7996a778f   Mike Christie   [SCSI] iscsi: add...
1738
1739
1740
  	 * 3) session is terminated or restarted or userspace has
  	 * given up on recovery
  	 */
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1741
  	wait_event_interruptible(conn->ehwait, age != session->age ||
7996a778f   Mike Christie   [SCSI] iscsi: add...
1742
  				 session->state != ISCSI_STATE_LOGGED_IN ||
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1743
  				 conn->tmf_state != TMF_QUEUED);
7996a778f   Mike Christie   [SCSI] iscsi: add...
1744
1745
  	if (signal_pending(current))
  		flush_signals(current);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1746
  	del_timer_sync(&conn->tmf_timer);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1747
  	mutex_lock(&session->eh_mutex);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
1748
  	spin_lock_bh(&session->lock);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
1749
  	/* if the session drops it will clean up the task */
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1750
1751
1752
  	if (age != session->age ||
  	    session->state != ISCSI_STATE_LOGGED_IN)
  		return -ENOTCONN;
7996a778f   Mike Christie   [SCSI] iscsi: add...
1753
1754
1755
1756
  	return 0;
  }
  
  /*
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1757
1758
1759
   * Fail commands. session lock held and recv side suspended and xmit
   * thread flushed
   */
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1760
1761
  static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun,
  			    int error)
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1762
  {
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1763
1764
  	struct iscsi_task *task;
  	int i;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1765

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1766
1767
1768
1769
  	for (i = 0; i < conn->session->cmds_max; i++) {
  		task = conn->session->cmds[i];
  		if (!task->sc || task->state == ISCSI_TASK_FREE)
  			continue;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1770

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1771
1772
  		if (lun != -1 && lun != task->sc->device->lun)
  			continue;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1773

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
1774
1775
1776
1777
  		ISCSI_DBG_SESSION(conn->session,
  				  "failing sc %p itt 0x%x state %d
  ",
  				  task->sc, task->itt, task->state);
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
1778
  		fail_scsi_task(task, error);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
1779
1780
  	}
  }
661134ad3   Mike Christie   [SCSI] libiscsi, ...
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
  /**
   * iscsi_suspend_queue - suspend iscsi_queuecommand
   * @conn: iscsi conn to stop queueing IO on
   *
   * This grabs the session lock to make sure no one is in
   * xmit_task/queuecommand, and then sets suspend to prevent
   * new commands from being queued. This only needs to be called
   * by offload drivers that need to sync a path like ep disconnect
   * with the iscsi_queuecommand/xmit_task. To start IO again libiscsi
   * will call iscsi_start_tx and iscsi_unblock_session when in FFP.
   */
  void iscsi_suspend_queue(struct iscsi_conn *conn)
  {
  	spin_lock_bh(&conn->session->lock);
  	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
  	spin_unlock_bh(&conn->session->lock);
  }
  EXPORT_SYMBOL_GPL(iscsi_suspend_queue);
  
  /**
   * iscsi_suspend_tx - suspend iscsi_data_xmit
   * @conn: iscsi conn tp stop processing IO on.
   *
   * This function sets the suspend bit to prevent iscsi_data_xmit
   * from sending new IO, and if work is queued on the xmit thread
   * it will wait for it to be completed.
   */
b40977d95   Mike Christie   [SCSI] iser: fix ...
1808
  void iscsi_suspend_tx(struct iscsi_conn *conn)
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1809
  {
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
1810
1811
  	struct Scsi_Host *shost = conn->session->host;
  	struct iscsi_host *ihost = shost_priv(shost);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1812
  	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1336aed10   Mike Christie   [SCSI] libiscsi: ...
1813
  	if (ihost->workq)
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
1814
  		flush_workqueue(ihost->workq);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1815
  }
b40977d95   Mike Christie   [SCSI] iser: fix ...
1816
  EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1817
1818
1819
1820
  
  static void iscsi_start_tx(struct iscsi_conn *conn)
  {
  	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1336aed10   Mike Christie   [SCSI] libiscsi: ...
1821
  	iscsi_conn_queue_work(conn);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
1822
  }
4c48a8293   Mike Christie   [SCSI] libiscsi: ...
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
  /*
   * We want to make sure a ping is in flight. It has timed out.
   * And we are not busy processing a pdu that is making
   * progress but got started before the ping and is taking a while
   * to complete so the ping is just stuck behind it in a queue.
   */
  static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
  {
  	if (conn->ping_task &&
  	    time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
  			   (conn->ping_timeout * HZ), jiffies))
  		return 1;
  	else
  		return 0;
  }
d355e57d5   Mike Christie   libiscsi: don't r...
1838
  static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1839
  {
d355e57d5   Mike Christie   libiscsi: don't r...
1840
  	enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
92ed4d699   Mike Christie   [SCSI] libiscsi: ...
1841
  	struct iscsi_task *task = NULL, *running_task;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1842
1843
1844
  	struct iscsi_cls_session *cls_session;
  	struct iscsi_session *session;
  	struct iscsi_conn *conn;
92ed4d699   Mike Christie   [SCSI] libiscsi: ...
1845
  	int i;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1846

d355e57d5   Mike Christie   libiscsi: don't r...
1847
  	cls_session = starget_to_session(scsi_target(sc->device));
756135215   Mike Christie   [SCSI] iscsi: rem...
1848
  	session = cls_session->dd_data;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1849

bd2199d41   Erez Zilber   libiscsi: add con...
1850
1851
  	ISCSI_DBG_EH(session, "scsi cmd %p timedout
  ", sc);
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1852
1853
1854
1855
1856
1857
1858
  
  	spin_lock(&session->lock);
  	if (session->state != ISCSI_STATE_LOGGED_IN) {
  		/*
  		 * We are probably in the middle of iscsi recovery so let
  		 * that complete and handle the error.
  		 */
242f9dcb8   Jens Axboe   block: unify requ...
1859
  		rc = BLK_EH_RESET_TIMER;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1860
1861
1862
1863
1864
1865
  		goto done;
  	}
  
  	conn = session->leadconn;
  	if (!conn) {
  		/* In the middle of shuting down */
242f9dcb8   Jens Axboe   block: unify requ...
1866
  		rc = BLK_EH_RESET_TIMER;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1867
1868
  		goto done;
  	}
d355e57d5   Mike Christie   libiscsi: don't r...
1869
  	task = (struct iscsi_task *)sc->SCp.ptr;
92ed4d699   Mike Christie   [SCSI] libiscsi: ...
1870
1871
1872
1873
1874
1875
  	if (!task) {
  		/*
  		 * Raced with completion. Just reset timer, and let it
  		 * complete normally
  		 */
  		rc = BLK_EH_RESET_TIMER;
d355e57d5   Mike Christie   libiscsi: don't r...
1876
  		goto done;
92ed4d699   Mike Christie   [SCSI] libiscsi: ...
1877
  	}
d355e57d5   Mike Christie   libiscsi: don't r...
1878
1879
1880
1881
1882
1883
1884
  	/*
  	 * If we have sent (at least queued to the network layer) a pdu or
  	 * recvd one for the task since the last timeout ask for
  	 * more time. If on the next timeout we have not made progress
  	 * we can check if it is the task or connection when we send the
  	 * nop as a ping.
  	 */
92ed4d699   Mike Christie   [SCSI] libiscsi: ...
1885
  	if (time_after(task->last_xfer, task->last_timeout)) {
bd2199d41   Erez Zilber   libiscsi: add con...
1886
1887
  		ISCSI_DBG_EH(session, "Command making progress. Asking "
  			     "scsi-ml for more time to complete. "
92ed4d699   Mike Christie   [SCSI] libiscsi: ...
1888
  			     "Last data xfer at %lu. Last timeout was at "
bd2199d41   Erez Zilber   libiscsi: add con...
1889
1890
  			     "%lu
  .", task->last_xfer, task->last_timeout);
d355e57d5   Mike Christie   libiscsi: don't r...
1891
1892
1893
1894
  		task->have_checked_conn = false;
  		rc = BLK_EH_RESET_TIMER;
  		goto done;
  	}
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1895
1896
1897
1898
1899
1900
  	if (!conn->recv_timeout && !conn->ping_timeout)
  		goto done;
  	/*
  	 * if the ping timedout then we are in the middle of cleaning up
  	 * and can let the iscsi eh handle it
  	 */
4c48a8293   Mike Christie   [SCSI] libiscsi: ...
1901
  	if (iscsi_has_ping_timed_out(conn)) {
242f9dcb8   Jens Axboe   block: unify requ...
1902
  		rc = BLK_EH_RESET_TIMER;
4c48a8293   Mike Christie   [SCSI] libiscsi: ...
1903
1904
  		goto done;
  	}
d355e57d5   Mike Christie   libiscsi: don't r...
1905

92ed4d699   Mike Christie   [SCSI] libiscsi: ...
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
  	for (i = 0; i < conn->session->cmds_max; i++) {
  		running_task = conn->session->cmds[i];
  		if (!running_task->sc || running_task == task ||
  		     running_task->state != ISCSI_TASK_RUNNING)
  			continue;
  
  		/*
  		 * Only check if cmds started before this one have made
  		 * progress, or this could never fail
  		 */
  		if (time_after(running_task->sc->jiffies_at_alloc,
  			       task->sc->jiffies_at_alloc))
  			continue;
  
  		if (time_after(running_task->last_xfer, task->last_timeout)) {
  			/*
  			 * This task has not made progress, but a task
  			 * started before us has transferred data since
  			 * we started/last-checked. We could be queueing
  			 * too many tasks or the LU is bad.
  			 *
  			 * If the device is bad the cmds ahead of us on
  			 * other devs will complete, and this loop will
  			 * eventually fail starting the scsi eh.
  			 */
  			ISCSI_DBG_EH(session, "Command has not made progress "
  				     "but commands ahead of it have. "
  				     "Asking scsi-ml for more time to "
  				     "complete. Our last xfer vs running task "
  				     "last xfer %lu/%lu. Last check %lu.
  ",
  				     task->last_xfer, running_task->last_xfer,
  				     task->last_timeout);
  			rc = BLK_EH_RESET_TIMER;
  			goto done;
  		}
  	}
d355e57d5   Mike Christie   libiscsi: don't r...
1943
1944
1945
  	/* Assumes nop timeout is shorter than scsi cmd timeout */
  	if (task->have_checked_conn)
  		goto done;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1946
  	/*
d355e57d5   Mike Christie   libiscsi: don't r...
1947
1948
  	 * Checking the transport already or nop from a cmd timeout still
  	 * running
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1949
  	 */
d355e57d5   Mike Christie   libiscsi: don't r...
1950
1951
  	if (conn->ping_task) {
  		task->have_checked_conn = true;
242f9dcb8   Jens Axboe   block: unify requ...
1952
  		rc = BLK_EH_RESET_TIMER;
4c48a8293   Mike Christie   [SCSI] libiscsi: ...
1953
1954
  		goto done;
  	}
d355e57d5   Mike Christie   libiscsi: don't r...
1955
1956
1957
1958
  	/* Make sure there is a transport check done */
  	iscsi_send_nopout(conn, NULL);
  	task->have_checked_conn = true;
  	rc = BLK_EH_RESET_TIMER;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1959
  done:
d355e57d5   Mike Christie   libiscsi: don't r...
1960
1961
  	if (task)
  		task->last_timeout = jiffies;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1962
  	spin_unlock(&session->lock);
bd2199d41   Erez Zilber   libiscsi: add con...
1963
1964
1965
  	ISCSI_DBG_EH(session, "return %s
  ", rc == BLK_EH_RESET_TIMER ?
  		     "timer reset" : "nh");
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1966
1967
1968
1969
1970
1971
1972
  	return rc;
  }
  
  static void iscsi_check_transport_timeouts(unsigned long data)
  {
  	struct iscsi_conn *conn = (struct iscsi_conn *)data;
  	struct iscsi_session *session = conn->session;
4cf104359   Mike Christie   [SCSI] libiscsi r...
1973
  	unsigned long recv_timeout, next_timeout = 0, last_recv;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1974
1975
1976
1977
  
  	spin_lock(&session->lock);
  	if (session->state != ISCSI_STATE_LOGGED_IN)
  		goto done;
4cf104359   Mike Christie   [SCSI] libiscsi r...
1978
1979
  	recv_timeout = conn->recv_timeout;
  	if (!recv_timeout)
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1980
  		goto done;
4cf104359   Mike Christie   [SCSI] libiscsi r...
1981
  	recv_timeout *= HZ;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1982
  	last_recv = conn->last_recv;
4c48a8293   Mike Christie   [SCSI] libiscsi: ...
1983
1984
  
  	if (iscsi_has_ping_timed_out(conn)) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1985
  		iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
4c48a8293   Mike Christie   [SCSI] libiscsi: ...
1986
1987
1988
1989
1990
  				  "expired, recv timeout %d, last rx %lu, "
  				  "last ping %lu, now %lu
  ",
  				  conn->ping_timeout, conn->recv_timeout,
  				  last_recv, conn->last_ping, jiffies);
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
1991
1992
1993
1994
  		spin_unlock(&session->lock);
  		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
  		return;
  	}
4cf104359   Mike Christie   [SCSI] libiscsi r...
1995
  	if (time_before_eq(last_recv + recv_timeout, jiffies)) {
c8611f975   Mike Christie   [SCSI] libiscsi r...
1996
  		/* send a ping to try to provoke some traffic */
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
1997
1998
  		ISCSI_DBG_CONN(conn, "Sending nopout as ping
  ");
c8611f975   Mike Christie   [SCSI] libiscsi r...
1999
  		iscsi_send_nopout(conn, NULL);
4cf104359   Mike Christie   [SCSI] libiscsi r...
2000
  		next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
ad294e9cd   Mike Christie   [SCSI] libiscsi: ...
2001
  	} else
4cf104359   Mike Christie   [SCSI] libiscsi r...
2002
  		next_timeout = last_recv + recv_timeout;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2003

1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
2004
2005
  	ISCSI_DBG_CONN(conn, "Setting next tmo %lu
  ", next_timeout);
ad294e9cd   Mike Christie   [SCSI] libiscsi: ...
2006
  	mod_timer(&conn->transport_timer, next_timeout);
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2007
2008
2009
  done:
  	spin_unlock(&session->lock);
  }
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2010
  static void iscsi_prep_abort_task_pdu(struct iscsi_task *task,
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2011
2012
2013
2014
2015
2016
  				      struct iscsi_tm *hdr)
  {
  	memset(hdr, 0, sizeof(*hdr));
  	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
  	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK;
  	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
55bdabdf4   Andy Grover   iscsi: Use struct...
2017
  	hdr->lun = task->lun;
577577da6   Mike Christie   [SCSI] libiscsi: ...
2018
2019
  	hdr->rtt = task->hdr_itt;
  	hdr->refcmdsn = task->cmdsn;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2020
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
2021
2022
  int iscsi_eh_abort(struct scsi_cmnd *sc)
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
2023
2024
  	struct iscsi_cls_session *cls_session;
  	struct iscsi_session *session;
f47f2cf5d   Mike Christie   [SCSI] libiscsi: ...
2025
  	struct iscsi_conn *conn;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2026
  	struct iscsi_task *task;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2027
2028
  	struct iscsi_tm *hdr;
  	int rc, age;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2029

756135215   Mike Christie   [SCSI] iscsi: rem...
2030
2031
  	cls_session = starget_to_session(scsi_target(sc->device));
  	session = cls_session->dd_data;
bd2199d41   Erez Zilber   libiscsi: add con...
2032
2033
  	ISCSI_DBG_EH(session, "aborting sc %p
  ", sc);
4421c9ebe   Mike Christie   [SCSI] libiscsi: ...
2034

6724add1b   Mike Christie   [SCSI] libiscsi: ...
2035
2036
  	mutex_lock(&session->eh_mutex);
  	spin_lock_bh(&session->lock);
f47f2cf5d   Mike Christie   [SCSI] libiscsi: ...
2037
2038
2039
2040
2041
  	/*
  	 * if session was ISCSI_STATE_IN_RECOVERY then we may not have
  	 * got the command.
  	 */
  	if (!sc->SCp.ptr) {
bd2199d41   Erez Zilber   libiscsi: add con...
2042
2043
2044
  		ISCSI_DBG_EH(session, "sc never reached iscsi layer or "
  				      "it completed.
  ");
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2045
2046
  		spin_unlock_bh(&session->lock);
  		mutex_unlock(&session->eh_mutex);
f47f2cf5d   Mike Christie   [SCSI] libiscsi: ...
2047
2048
  		return SUCCESS;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
2049
2050
2051
2052
  	/*
  	 * If we are not logged in or we have started a new session
  	 * then let the host reset code handle this
  	 */
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2053
2054
2055
2056
  	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN ||
  	    sc->SCp.phase != session->age) {
  		spin_unlock_bh(&session->lock);
  		mutex_unlock(&session->eh_mutex);
bd2199d41   Erez Zilber   libiscsi: add con...
2057
  		ISCSI_DBG_EH(session, "failing abort due to dropped "
4421c9ebe   Mike Christie   [SCSI] libiscsi: ...
2058
2059
  				  "session.
  ");
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2060
2061
2062
2063
2064
2065
  		return FAILED;
  	}
  
  	conn = session->leadconn;
  	conn->eh_abort_cnt++;
  	age = session->age;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2066
  	task = (struct iscsi_task *)sc->SCp.ptr;
bd2199d41   Erez Zilber   libiscsi: add con...
2067
2068
2069
  	ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]
  ",
  		     sc, task->itt);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2070

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2071
2072
  	/* task completed before time out */
  	if (!task->sc) {
bd2199d41   Erez Zilber   libiscsi: add con...
2073
2074
  		ISCSI_DBG_EH(session, "sc completed while abort in progress
  ");
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2075
  		goto success;
7ea8b8284   Mike Christie   [SCSI] iscsi bugf...
2076
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
2077

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2078
  	if (task->state == ISCSI_TASK_PENDING) {
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
2079
  		fail_scsi_task(task, DID_ABORT);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2080
2081
  		goto success;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
2082

843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2083
2084
  	/* only have one tmf outstanding at a time */
  	if (conn->tmf_state != TMF_INITIAL)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2085
  		goto failed;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2086
  	conn->tmf_state = TMF_QUEUED;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2087

843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2088
  	hdr = &conn->tmhdr;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2089
  	iscsi_prep_abort_task_pdu(task, hdr);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2090

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2091
  	if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2092
2093
2094
2095
2096
2097
  		rc = FAILED;
  		goto failed;
  	}
  
  	switch (conn->tmf_state) {
  	case TMF_SUCCESS:
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2098
  		spin_unlock_bh(&session->lock);
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
2099
2100
2101
2102
  		/*
  		 * stop tx side incase the target had sent a abort rsp but
  		 * the initiator was still writing out data.
  		 */
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2103
  		iscsi_suspend_tx(conn);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2104
  		/*
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
2105
2106
2107
  		 * we do not stop the recv side because targets have been
  		 * good and have never sent us a successful tmf response
  		 * then sent more data for the cmd.
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2108
  		 */
6187c2420   Mike Christie   [SCSI] libiscsi: ...
2109
  		spin_lock_bh(&session->lock);
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
2110
  		fail_scsi_task(task, DID_ABORT);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2111
  		conn->tmf_state = TMF_INITIAL;
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
2112
  		memset(hdr, 0, sizeof(*hdr));
6187c2420   Mike Christie   [SCSI] libiscsi: ...
2113
  		spin_unlock_bh(&session->lock);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2114
  		iscsi_start_tx(conn);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2115
  		goto success_unlocked;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2116
2117
  	case TMF_TIMEDOUT:
  		spin_unlock_bh(&session->lock);
df4da5cdf   Mike Christie   [SCSI] libiscsi: ...
2118
  		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2119
2120
2121
2122
  		goto failed_unlocked;
  	case TMF_NOT_FOUND:
  		if (!sc->SCp.ptr) {
  			conn->tmf_state = TMF_INITIAL;
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
2123
  			memset(hdr, 0, sizeof(*hdr));
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2124
  			/* task completed before tmf abort response */
bd2199d41   Erez Zilber   libiscsi: add con...
2125
2126
2127
  			ISCSI_DBG_EH(session, "sc completed while abort	in "
  					      "progress
  ");
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2128
  			goto success;
7ea8b8284   Mike Christie   [SCSI] iscsi bugf...
2129
2130
2131
  		}
  		/* fall through */
  	default:
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2132
2133
  		conn->tmf_state = TMF_INITIAL;
  		goto failed;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2134
  	}
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2135
  success:
7996a778f   Mike Christie   [SCSI] iscsi: add...
2136
  	spin_unlock_bh(&session->lock);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2137
  success_unlocked:
bd2199d41   Erez Zilber   libiscsi: add con...
2138
2139
2140
  	ISCSI_DBG_EH(session, "abort success [sc %p itt 0x%x]
  ",
  		     sc, task->itt);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2141
  	mutex_unlock(&session->eh_mutex);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2142
2143
2144
2145
  	return SUCCESS;
  
  failed:
  	spin_unlock_bh(&session->lock);
77a23c21a   Mike Christie   [SCSI] libiscsi: ...
2146
  failed_unlocked:
bd2199d41   Erez Zilber   libiscsi: add con...
2147
2148
2149
  	ISCSI_DBG_EH(session, "abort failed [sc %p itt 0x%x]
  ", sc,
  		     task ? task->itt : 0);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2150
  	mutex_unlock(&session->eh_mutex);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2151
2152
2153
  	return FAILED;
  }
  EXPORT_SYMBOL_GPL(iscsi_eh_abort);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2154
2155
2156
2157
2158
2159
  static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
  {
  	memset(hdr, 0, sizeof(*hdr));
  	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
  	hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK;
  	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
55bdabdf4   Andy Grover   iscsi: Use struct...
2160
  	int_to_scsilun(sc->device->lun, &hdr->lun);
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2161
  	hdr->rtt = RESERVED_ITT;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2162
2163
2164
2165
  }
  
  int iscsi_eh_device_reset(struct scsi_cmnd *sc)
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
2166
2167
  	struct iscsi_cls_session *cls_session;
  	struct iscsi_session *session;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2168
2169
2170
  	struct iscsi_conn *conn;
  	struct iscsi_tm *hdr;
  	int rc = FAILED;
756135215   Mike Christie   [SCSI] iscsi: rem...
2171
2172
  	cls_session = starget_to_session(scsi_target(sc->device));
  	session = cls_session->dd_data;
bd2199d41   Erez Zilber   libiscsi: add con...
2173
2174
  	ISCSI_DBG_EH(session, "LU Reset [sc %p lun %u]
  ", sc, sc->device->lun);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
  
  	mutex_lock(&session->eh_mutex);
  	spin_lock_bh(&session->lock);
  	/*
  	 * Just check if we are not logged in. We cannot check for
  	 * the phase because the reset could come from a ioctl.
  	 */
  	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN)
  		goto unlock;
  	conn = session->leadconn;
  
  	/* only have one tmf outstanding at a time */
  	if (conn->tmf_state != TMF_INITIAL)
  		goto unlock;
  	conn->tmf_state = TMF_QUEUED;
  
  	hdr = &conn->tmhdr;
  	iscsi_prep_lun_reset_pdu(sc, hdr);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2193
  	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2194
  				    session->lu_reset_timeout)) {
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2195
2196
2197
2198
2199
2200
2201
2202
2203
  		rc = FAILED;
  		goto unlock;
  	}
  
  	switch (conn->tmf_state) {
  	case TMF_SUCCESS:
  		break;
  	case TMF_TIMEDOUT:
  		spin_unlock_bh(&session->lock);
df4da5cdf   Mike Christie   [SCSI] libiscsi: ...
2204
  		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
  		goto done;
  	default:
  		conn->tmf_state = TMF_INITIAL;
  		goto unlock;
  	}
  
  	rc = SUCCESS;
  	spin_unlock_bh(&session->lock);
  
  	iscsi_suspend_tx(conn);
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
2215

a34391483   Mike Christie   libiscsi: fix loc...
2216
  	spin_lock_bh(&session->lock);
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
2217
  	memset(hdr, 0, sizeof(*hdr));
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2218
  	fail_scsi_tasks(conn, sc->device->lun, DID_ERROR);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2219
  	conn->tmf_state = TMF_INITIAL;
a34391483   Mike Christie   libiscsi: fix loc...
2220
  	spin_unlock_bh(&session->lock);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2221
2222
2223
2224
2225
2226
2227
  
  	iscsi_start_tx(conn);
  	goto done;
  
  unlock:
  	spin_unlock_bh(&session->lock);
  done:
bd2199d41   Erez Zilber   libiscsi: add con...
2228
2229
2230
  	ISCSI_DBG_EH(session, "dev reset result = %s
  ",
  		     rc == SUCCESS ? "SUCCESS" : "FAILED");
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2231
2232
2233
2234
  	mutex_unlock(&session->eh_mutex);
  	return rc;
  }
  EXPORT_SYMBOL_GPL(iscsi_eh_device_reset);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
  void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
  {
  	struct iscsi_session *session = cls_session->dd_data;
  
  	spin_lock_bh(&session->lock);
  	if (session->state != ISCSI_STATE_LOGGED_IN) {
  		session->state = ISCSI_STATE_RECOVERY_FAILED;
  		if (session->leadconn)
  			wake_up(&session->leadconn->ehwait);
  	}
  	spin_unlock_bh(&session->lock);
  }
  EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
  
  /**
   * iscsi_eh_session_reset - drop session and attempt relogin
   * @sc: scsi command
   *
   * This function will wait for a relogin, session termination from
   * userspace, or a recovery/replacement timeout.
   */
309ce156a   Jayamohan Kallickal   [SCSI] libiscsi: ...
2256
  int iscsi_eh_session_reset(struct scsi_cmnd *sc)
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
  {
  	struct iscsi_cls_session *cls_session;
  	struct iscsi_session *session;
  	struct iscsi_conn *conn;
  
  	cls_session = starget_to_session(scsi_target(sc->device));
  	session = cls_session->dd_data;
  	conn = session->leadconn;
  
  	mutex_lock(&session->eh_mutex);
  	spin_lock_bh(&session->lock);
  	if (session->state == ISCSI_STATE_TERMINATE) {
  failed:
  		ISCSI_DBG_EH(session,
  			     "failing session reset: Could not log back into "
  			     "%s, %s [age %d]
  ", session->targetname,
  			     conn->persistent_address, session->age);
  		spin_unlock_bh(&session->lock);
  		mutex_unlock(&session->eh_mutex);
  		return FAILED;
  	}
  
  	spin_unlock_bh(&session->lock);
  	mutex_unlock(&session->eh_mutex);
  	/*
  	 * we drop the lock here but the leadconn cannot be destoyed while
  	 * we are in the scsi eh
  	 */
df4da5cdf   Mike Christie   [SCSI] libiscsi: ...
2286
  	iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
  
  	ISCSI_DBG_EH(session, "wait for relogin
  ");
  	wait_event_interruptible(conn->ehwait,
  				 session->state == ISCSI_STATE_TERMINATE ||
  				 session->state == ISCSI_STATE_LOGGED_IN ||
  				 session->state == ISCSI_STATE_RECOVERY_FAILED);
  	if (signal_pending(current))
  		flush_signals(current);
  
  	mutex_lock(&session->eh_mutex);
  	spin_lock_bh(&session->lock);
  	if (session->state == ISCSI_STATE_LOGGED_IN) {
  		ISCSI_DBG_EH(session,
  			     "session reset succeeded for %s,%s
  ",
  			     session->targetname, conn->persistent_address);
  	} else
  		goto failed;
  	spin_unlock_bh(&session->lock);
  	mutex_unlock(&session->eh_mutex);
  	return SUCCESS;
  }
309ce156a   Jayamohan Kallickal   [SCSI] libiscsi: ...
2310
  EXPORT_SYMBOL_GPL(iscsi_eh_session_reset);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
  
  static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
  {
  	memset(hdr, 0, sizeof(*hdr));
  	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
  	hdr->flags = ISCSI_TM_FUNC_TARGET_WARM_RESET & ISCSI_FLAG_TM_FUNC_MASK;
  	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
  	hdr->rtt = RESERVED_ITT;
  }
  
  /**
   * iscsi_eh_target_reset - reset target
   * @sc: scsi command
   *
309ce156a   Jayamohan Kallickal   [SCSI] libiscsi: ...
2325
   * This will attempt to send a warm target reset.
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
   */
  int iscsi_eh_target_reset(struct scsi_cmnd *sc)
  {
  	struct iscsi_cls_session *cls_session;
  	struct iscsi_session *session;
  	struct iscsi_conn *conn;
  	struct iscsi_tm *hdr;
  	int rc = FAILED;
  
  	cls_session = starget_to_session(scsi_target(sc->device));
  	session = cls_session->dd_data;
  
  	ISCSI_DBG_EH(session, "tgt Reset [sc %p tgt %s]
  ", sc,
  		     session->targetname);
  
  	mutex_lock(&session->eh_mutex);
  	spin_lock_bh(&session->lock);
  	/*
  	 * Just check if we are not logged in. We cannot check for
  	 * the phase because the reset could come from a ioctl.
  	 */
  	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN)
  		goto unlock;
  	conn = session->leadconn;
  
  	/* only have one tmf outstanding at a time */
  	if (conn->tmf_state != TMF_INITIAL)
  		goto unlock;
  	conn->tmf_state = TMF_QUEUED;
  
  	hdr = &conn->tmhdr;
  	iscsi_prep_tgt_reset_pdu(sc, hdr);
  
  	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
  				    session->tgt_reset_timeout)) {
  		rc = FAILED;
  		goto unlock;
  	}
  
  	switch (conn->tmf_state) {
  	case TMF_SUCCESS:
  		break;
  	case TMF_TIMEDOUT:
  		spin_unlock_bh(&session->lock);
df4da5cdf   Mike Christie   [SCSI] libiscsi: ...
2371
  		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
  		goto done;
  	default:
  		conn->tmf_state = TMF_INITIAL;
  		goto unlock;
  	}
  
  	rc = SUCCESS;
  	spin_unlock_bh(&session->lock);
  
  	iscsi_suspend_tx(conn);
  
  	spin_lock_bh(&session->lock);
  	memset(hdr, 0, sizeof(*hdr));
  	fail_scsi_tasks(conn, -1, DID_ERROR);
  	conn->tmf_state = TMF_INITIAL;
  	spin_unlock_bh(&session->lock);
  
  	iscsi_start_tx(conn);
  	goto done;
  
  unlock:
  	spin_unlock_bh(&session->lock);
  done:
  	ISCSI_DBG_EH(session, "tgt %s reset result = %s
  ", session->targetname,
  		     rc == SUCCESS ? "SUCCESS" : "FAILED");
  	mutex_unlock(&session->eh_mutex);
309ce156a   Jayamohan Kallickal   [SCSI] libiscsi: ...
2399
2400
2401
  	return rc;
  }
  EXPORT_SYMBOL_GPL(iscsi_eh_target_reset);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2402

309ce156a   Jayamohan Kallickal   [SCSI] libiscsi: ...
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
  /**
   * iscsi_eh_recover_target - reset target and possibly the session
   * @sc: scsi command
   *
   * This will attempt to send a warm target reset. If that fails,
   * we will escalate to ERL0 session recovery.
   */
  int iscsi_eh_recover_target(struct scsi_cmnd *sc)
  {
  	int rc;
  
  	rc = iscsi_eh_target_reset(sc);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2415
2416
2417
2418
  	if (rc == FAILED)
  		rc = iscsi_eh_session_reset(sc);
  	return rc;
  }
309ce156a   Jayamohan Kallickal   [SCSI] libiscsi: ...
2419
  EXPORT_SYMBOL_GPL(iscsi_eh_recover_target);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2420

6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2421
2422
2423
2424
2425
2426
  /*
   * Pre-allocate a pool of @max items of @item_size. By default, the pool
   * should be accessed via kfifo_{get,put} on q->queue.
   * Optionally, the caller can obtain the array of object pointers
   * by passing in a non-NULL @items pointer
   */
7996a778f   Mike Christie   [SCSI] iscsi: add...
2427
  int
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2428
  iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2429
  {
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2430
  	int i, num_arrays = 1;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2431

6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2432
  	memset(q, 0, sizeof(*q));
7996a778f   Mike Christie   [SCSI] iscsi: add...
2433
2434
  
  	q->max = max;
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2435
2436
2437
2438
2439
2440
2441
  
  	/* If the user passed an items pointer, he wants a copy of
  	 * the array. */
  	if (items)
  		num_arrays++;
  	q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL);
  	if (q->pool == NULL)
f474a37bc   Jean Delvare   [SCSI] libiscsi: ...
2442
  		return -ENOMEM;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2443

c1e13f256   Stefani Seibold   kfifo: move out s...
2444
  	kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*));
7996a778f   Mike Christie   [SCSI] iscsi: add...
2445
2446
  
  	for (i = 0; i < max; i++) {
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2447
  		q->pool[i] = kzalloc(item_size, GFP_KERNEL);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2448
  		if (q->pool[i] == NULL) {
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2449
2450
  			q->max = i;
  			goto enomem;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2451
  		}
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
2452
  		kfifo_in(&q->queue, (void*)&q->pool[i], sizeof(void*));
7996a778f   Mike Christie   [SCSI] iscsi: add...
2453
  	}
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2454
2455
2456
2457
2458
  
  	if (items) {
  		*items = q->pool + max;
  		memcpy(*items, q->pool, max * sizeof(void *));
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
2459
  	return 0;
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2460
2461
2462
2463
  
  enomem:
  	iscsi_pool_free(q);
  	return -ENOMEM;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2464
2465
  }
  EXPORT_SYMBOL_GPL(iscsi_pool_init);
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2466
  void iscsi_pool_free(struct iscsi_pool *q)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2467
2468
2469
2470
  {
  	int i;
  
  	for (i = 0; i < q->max; i++)
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2471
  		kfree(q->pool[i]);
f474a37bc   Jean Delvare   [SCSI] libiscsi: ...
2472
  	kfree(q->pool);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2473
2474
  }
  EXPORT_SYMBOL_GPL(iscsi_pool_free);
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
  /**
   * iscsi_host_add - add host to system
   * @shost: scsi host
   * @pdev: parent device
   *
   * This should be called by partial offload and software iscsi drivers
   * to add a host to the system.
   */
  int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
  {
8e9a20cee   Mike Christie   [SCSI] libiscsi, ...
2485
2486
  	if (!shost->can_queue)
  		shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX;
4d1083509   Mike Christie   [SCSI] iscsi lib:...
2487
2488
  	if (!shost->cmd_per_lun)
  		shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN;
308cec14e   Mike Christie   [SCSI] libiscsi: ...
2489
2490
  	if (!shost->transportt->eh_timed_out)
  		shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2491
2492
2493
2494
2495
2496
2497
2498
  	return scsi_add_host(shost, pdev);
  }
  EXPORT_SYMBOL_GPL(iscsi_host_add);
  
  /**
   * iscsi_host_alloc - allocate a host and driver data
   * @sht: scsi host template
   * @dd_data_size: driver host data size
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
2499
   * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2500
2501
2502
2503
2504
   *
   * This should be called by partial offload and software iscsi drivers.
   * To access the driver specific memory use the iscsi_host_priv() macro.
   */
  struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
4d1083509   Mike Christie   [SCSI] iscsi lib:...
2505
  				   int dd_data_size, bool xmit_can_sleep)
756135215   Mike Christie   [SCSI] iscsi: rem...
2506
  {
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2507
  	struct Scsi_Host *shost;
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2508
  	struct iscsi_host *ihost;
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2509
2510
2511
2512
  
  	shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
  	if (!shost)
  		return NULL;
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2513
  	ihost = shost_priv(shost);
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
2514
2515
2516
2517
2518
2519
2520
2521
  
  	if (xmit_can_sleep) {
  		snprintf(ihost->workq_name, sizeof(ihost->workq_name),
  			"iscsi_q_%d", shost->host_no);
  		ihost->workq = create_singlethread_workqueue(ihost->workq_name);
  		if (!ihost->workq)
  			goto free_host;
  	}
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2522
2523
2524
2525
  	spin_lock_init(&ihost->lock);
  	ihost->state = ISCSI_HOST_SETUP;
  	ihost->num_sessions = 0;
  	init_waitqueue_head(&ihost->session_removal_wq);
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2526
  	return shost;
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
2527
2528
2529
2530
  
  free_host:
  	scsi_host_put(shost);
  	return NULL;
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2531
2532
  }
  EXPORT_SYMBOL_GPL(iscsi_host_alloc);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2533
2534
  static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
  {
40a06e755   Mike Christie   [SCSI] libiscsi: ...
2535
  	iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_INVALID_HOST);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2536
  }
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2537
2538
2539
2540
  /**
   * iscsi_host_remove - remove host and sessions
   * @shost: scsi host
   *
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2541
2542
   * If there are any sessions left, this will initiate the removal and wait
   * for the completion.
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2543
2544
2545
   */
  void iscsi_host_remove(struct Scsi_Host *shost)
  {
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
  	struct iscsi_host *ihost = shost_priv(shost);
  	unsigned long flags;
  
  	spin_lock_irqsave(&ihost->lock, flags);
  	ihost->state = ISCSI_HOST_REMOVED;
  	spin_unlock_irqrestore(&ihost->lock, flags);
  
  	iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
  	wait_event_interruptible(ihost->session_removal_wq,
  				 ihost->num_sessions == 0);
  	if (signal_pending(current))
  		flush_signals(current);
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2558
  	scsi_remove_host(shost);
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
2559
2560
  	if (ihost->workq)
  		destroy_workqueue(ihost->workq);
756135215   Mike Christie   [SCSI] iscsi: rem...
2561
  }
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2562
  EXPORT_SYMBOL_GPL(iscsi_host_remove);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2563

a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2564
  void iscsi_host_free(struct Scsi_Host *shost)
756135215   Mike Christie   [SCSI] iscsi: rem...
2565
2566
  {
  	struct iscsi_host *ihost = shost_priv(shost);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2567

756135215   Mike Christie   [SCSI] iscsi: rem...
2568
2569
2570
  	kfree(ihost->netdev);
  	kfree(ihost->hwaddress);
  	kfree(ihost->initiatorname);
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2571
  	scsi_host_put(shost);
756135215   Mike Christie   [SCSI] iscsi: rem...
2572
  }
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
2573
  EXPORT_SYMBOL_GPL(iscsi_host_free);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2574

e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
  static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost)
  {
  	struct iscsi_host *ihost = shost_priv(shost);
  	unsigned long flags;
  
  	shost = scsi_host_get(shost);
  	if (!shost) {
  		printk(KERN_ERR "Invalid state. Cannot notify host removal "
  		      "of session teardown event because host already "
  		      "removed.
  ");
  		return;
  	}
  
  	spin_lock_irqsave(&ihost->lock, flags);
  	ihost->num_sessions--;
  	if (ihost->num_sessions == 0)
  		wake_up(&ihost->session_removal_wq);
  	spin_unlock_irqrestore(&ihost->lock, flags);
  	scsi_host_put(shost);
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
2596
2597
  /**
   * iscsi_session_setup - create iscsi cls session and host and session
7996a778f   Mike Christie   [SCSI] iscsi: add...
2598
   * @iscsit: iscsi transport template
756135215   Mike Christie   [SCSI] iscsi: rem...
2599
2600
   * @shost: scsi host
   * @cmds_max: session can queue
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2601
   * @cmd_task_size: LLD task private data size
7996a778f   Mike Christie   [SCSI] iscsi: add...
2602
   * @initial_cmdsn: initial CmdSN
7996a778f   Mike Christie   [SCSI] iscsi: add...
2603
2604
2605
   *
   * This can be used by software iscsi_transports that allocate
   * a session per scsi host.
3cf7b233f   Mike Christie   [SCSI] libiscsi: ...
2606
2607
2608
2609
   *
   * Callers should set cmds_max to the largest total numer (mgmt + scsi) of
   * tasks they support. The iscsi layer reserves ISCSI_MGMT_CMDS_MAX tasks
   * for nop handling and login/logout requests.
756135215   Mike Christie   [SCSI] iscsi: rem...
2610
   */
7996a778f   Mike Christie   [SCSI] iscsi: add...
2611
  struct iscsi_cls_session *
756135215   Mike Christie   [SCSI] iscsi: rem...
2612
  iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
b8b9e1b81   Jayamohan Kallickal   [SCSI] libiscsi: ...
2613
  		    uint16_t cmds_max, int dd_size, int cmd_task_size,
7970634b8   Mike Christie   [SCSI] iscsi clas...
2614
  		    uint32_t initial_cmdsn, unsigned int id)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2615
  {
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2616
  	struct iscsi_host *ihost = shost_priv(shost);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2617
2618
  	struct iscsi_session *session;
  	struct iscsi_cls_session *cls_session;
3cf7b233f   Mike Christie   [SCSI] libiscsi: ...
2619
  	int cmd_i, scsi_cmds, total_cmds = cmds_max;
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2620
2621
2622
2623
2624
2625
2626
2627
2628
  	unsigned long flags;
  
  	spin_lock_irqsave(&ihost->lock, flags);
  	if (ihost->state == ISCSI_HOST_REMOVED) {
  		spin_unlock_irqrestore(&ihost->lock, flags);
  		return NULL;
  	}
  	ihost->num_sessions++;
  	spin_unlock_irqrestore(&ihost->lock, flags);
8e9a20cee   Mike Christie   [SCSI] libiscsi, ...
2629
2630
2631
  
  	if (!total_cmds)
  		total_cmds = ISCSI_DEF_XMIT_CMDS_MAX;
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
2632
  	/*
3cf7b233f   Mike Christie   [SCSI] libiscsi: ...
2633
2634
2635
  	 * The iscsi layer needs some tasks for nop handling and tmfs,
  	 * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX
  	 * + 1 command for scsi IO.
3e5c28ad0   Mike Christie   [SCSI] libiscsi: ...
2636
  	 */
3cf7b233f   Mike Christie   [SCSI] libiscsi: ...
2637
2638
2639
2640
2641
  	if (total_cmds < ISCSI_TOTAL_CMDS_MIN) {
  		printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
  		       "must be a power of two that is at least %d.
  ",
  		       total_cmds, ISCSI_TOTAL_CMDS_MIN);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2642
  		goto dec_session_count;
3cf7b233f   Mike Christie   [SCSI] libiscsi: ...
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
  	}
  
  	if (total_cmds > ISCSI_TOTAL_CMDS_MAX) {
  		printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
  		       "must be a power of 2 less than or equal to %d.
  ",
  		       cmds_max, ISCSI_TOTAL_CMDS_MAX);
  		total_cmds = ISCSI_TOTAL_CMDS_MAX;
  	}
  
  	if (!is_power_of_2(total_cmds)) {
  		printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
  		       "must be a power of 2.
  ", total_cmds);
  		total_cmds = rounddown_pow_of_two(total_cmds);
  		if (total_cmds < ISCSI_TOTAL_CMDS_MIN)
  			return NULL;
  		printk(KERN_INFO "iscsi: Rounding can_queue to %d.
  ",
  		       total_cmds);
1548271ec   Mike Christie   [SCSI] libiscsi: ...
2663
  	}
3cf7b233f   Mike Christie   [SCSI] libiscsi: ...
2664
  	scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX;
1548271ec   Mike Christie   [SCSI] libiscsi: ...
2665

5d91e209f   Mike Christie   [SCSI] iscsi: rem...
2666
  	cls_session = iscsi_alloc_session(shost, iscsit,
b8b9e1b81   Jayamohan Kallickal   [SCSI] libiscsi: ...
2667
2668
  					  sizeof(struct iscsi_session) +
  					  dd_size);
756135215   Mike Christie   [SCSI] iscsi: rem...
2669
  	if (!cls_session)
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2670
  		goto dec_session_count;
756135215   Mike Christie   [SCSI] iscsi: rem...
2671
2672
  	session = cls_session->dd_data;
  	session->cls_session = cls_session;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2673
2674
  	session->host = shost;
  	session->state = ISCSI_STATE_FREE;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2675
  	session->fast_abort = 1;
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2676
  	session->tgt_reset_timeout = 30;
4cd49ea13   Mike Christie   [SCSI] libiscsi, ...
2677
2678
  	session->lu_reset_timeout = 15;
  	session->abort_timeout = 10;
3cf7b233f   Mike Christie   [SCSI] libiscsi: ...
2679
2680
  	session->scsi_cmds_max = scsi_cmds;
  	session->cmds_max = total_cmds;
e07264071   Mike Christie   [SCSI] libiscsi: ...
2681
  	session->queued_cmdsn = session->cmdsn = initial_cmdsn;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2682
2683
2684
2685
  	session->exp_cmdsn = initial_cmdsn + 1;
  	session->max_cmdsn = initial_cmdsn + 1;
  	session->max_r2t = 1;
  	session->tt = iscsit;
b8b9e1b81   Jayamohan Kallickal   [SCSI] libiscsi: ...
2686
  	session->dd_data = cls_session->dd_data + sizeof(*session);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2687
  	mutex_init(&session->eh_mutex);
756135215   Mike Christie   [SCSI] iscsi: rem...
2688
  	spin_lock_init(&session->lock);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2689
2690
2691
2692
  
  	/* initialize SCSI PDU commands pool */
  	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
  			    (void***)&session->cmds,
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2693
  			    cmd_task_size + sizeof(struct iscsi_task)))
7996a778f   Mike Christie   [SCSI] iscsi: add...
2694
2695
2696
2697
  		goto cmdpool_alloc_fail;
  
  	/* pre-format cmds pool with ITT */
  	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2698
  		struct iscsi_task *task = session->cmds[cmd_i];
7996a778f   Mike Christie   [SCSI] iscsi: add...
2699

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2700
2701
2702
  		if (cmd_task_size)
  			task->dd_data = &task[1];
  		task->itt = cmd_i;
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2703
  		task->state = ISCSI_TASK_FREE;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2704
  		INIT_LIST_HEAD(&task->running);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2705
  	}
f53a88da1   Mike Christie   [SCSI] iscsi: fix...
2706
  	if (!try_module_get(iscsit->owner))
756135215   Mike Christie   [SCSI] iscsi: rem...
2707
  		goto module_get_fail;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2708

7970634b8   Mike Christie   [SCSI] iscsi clas...
2709
  	if (iscsi_add_session(cls_session, id))
756135215   Mike Christie   [SCSI] iscsi: rem...
2710
  		goto cls_session_fail;
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2711

7996a778f   Mike Christie   [SCSI] iscsi: add...
2712
2713
2714
  	return cls_session;
  
  cls_session_fail:
756135215   Mike Christie   [SCSI] iscsi: rem...
2715
2716
  	module_put(iscsit->owner);
  module_get_fail:
6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2717
  	iscsi_pool_free(&session->cmdpool);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2718
  cmdpool_alloc_fail:
756135215   Mike Christie   [SCSI] iscsi: rem...
2719
  	iscsi_free_session(cls_session);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2720
2721
  dec_session_count:
  	iscsi_host_dec_session_cnt(shost);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2722
2723
2724
2725
2726
2727
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(iscsi_session_setup);
  
  /**
   * iscsi_session_teardown - destroy session, host, and cls_session
756135215   Mike Christie   [SCSI] iscsi: rem...
2728
   * @cls_session: iscsi session
7996a778f   Mike Christie   [SCSI] iscsi: add...
2729
   *
756135215   Mike Christie   [SCSI] iscsi: rem...
2730
2731
2732
   * The driver must have called iscsi_remove_session before
   * calling this.
   */
7996a778f   Mike Christie   [SCSI] iscsi: add...
2733
2734
  void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
2735
  	struct iscsi_session *session = cls_session->dd_data;
63f75cc8a   Mike Christie   [SCSI] iscsi bugf...
2736
  	struct module *owner = cls_session->transport->owner;
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2737
  	struct Scsi_Host *shost = session->host;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2738

6320377fd   Olaf Kirch   [SCSI] libiscsi, ...
2739
  	iscsi_pool_free(&session->cmdpool);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2740

b2c641673   Mike Christie   [SCSI] iscsi clas...
2741
2742
2743
2744
  	kfree(session->password);
  	kfree(session->password_in);
  	kfree(session->username);
  	kfree(session->username_in);
f3ff0c362   Mike Christie   [SCSI] iscsi bugf...
2745
  	kfree(session->targetname);
88dfd340b   Mike Christie   [SCSI] iscsi clas...
2746
2747
  	kfree(session->initiatorname);
  	kfree(session->ifacename);
f3ff0c362   Mike Christie   [SCSI] iscsi bugf...
2748

756135215   Mike Christie   [SCSI] iscsi: rem...
2749
  	iscsi_destroy_session(cls_session);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
2750
  	iscsi_host_dec_session_cnt(shost);
63f75cc8a   Mike Christie   [SCSI] iscsi bugf...
2751
  	module_put(owner);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2752
2753
2754
2755
2756
2757
  }
  EXPORT_SYMBOL_GPL(iscsi_session_teardown);
  
  /**
   * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn
   * @cls_session: iscsi_cls_session
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
2758
   * @dd_size: private driver data size
7996a778f   Mike Christie   [SCSI] iscsi: add...
2759
   * @conn_idx: cid
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
2760
   */
7996a778f   Mike Christie   [SCSI] iscsi: add...
2761
  struct iscsi_cls_conn *
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
2762
2763
  iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
  		 uint32_t conn_idx)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2764
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
2765
  	struct iscsi_session *session = cls_session->dd_data;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2766
2767
  	struct iscsi_conn *conn;
  	struct iscsi_cls_conn *cls_conn;
d36ab6f32   Mike Christie   [SCSI] iscsi: onl...
2768
  	char *data;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2769

5d91e209f   Mike Christie   [SCSI] iscsi: rem...
2770
2771
  	cls_conn = iscsi_create_conn(cls_session, sizeof(*conn) + dd_size,
  				     conn_idx);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2772
2773
2774
  	if (!cls_conn)
  		return NULL;
  	conn = cls_conn->dd_data;
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
2775
  	memset(conn, 0, sizeof(*conn) + dd_size);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2776

5d91e209f   Mike Christie   [SCSI] iscsi: rem...
2777
  	conn->dd_data = cls_conn->dd_data + sizeof(*conn);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2778
2779
2780
2781
2782
  	conn->session = session;
  	conn->cls_conn = cls_conn;
  	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
  	conn->id = conn_idx;
  	conn->exp_statsn = 0;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2783
  	conn->tmf_state = TMF_INITIAL;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2784
2785
2786
2787
  
  	init_timer(&conn->transport_timer);
  	conn->transport_timer.data = (unsigned long)conn;
  	conn->transport_timer.function = iscsi_check_transport_timeouts;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2788
  	INIT_LIST_HEAD(&conn->mgmtqueue);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2789
  	INIT_LIST_HEAD(&conn->cmdqueue);
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2790
  	INIT_LIST_HEAD(&conn->requeue);
c4028958b   David Howells   WorkStruct: make ...
2791
  	INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2792

9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2793
  	/* allocate login_task used for the login/text sequences */
7996a778f   Mike Christie   [SCSI] iscsi: add...
2794
  	spin_lock_bh(&session->lock);
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
2795
  	if (!kfifo_out(&session->cmdpool.queue,
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2796
                           (void*)&conn->login_task,
7996a778f   Mike Christie   [SCSI] iscsi: add...
2797
2798
  			 sizeof(void*))) {
  		spin_unlock_bh(&session->lock);
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2799
  		goto login_task_alloc_fail;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2800
2801
  	}
  	spin_unlock_bh(&session->lock);
cfeb2cf95   Mike Christie   [SCSI] libiscsi: ...
2802
2803
  	data = (char *) __get_free_pages(GFP_KERNEL,
  					 get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
d36ab6f32   Mike Christie   [SCSI] iscsi: onl...
2804
  	if (!data)
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2805
2806
  		goto login_task_data_alloc_fail;
  	conn->login_task->data = conn->data = data;
d36ab6f32   Mike Christie   [SCSI] iscsi: onl...
2807

843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2808
  	init_timer(&conn->tmf_timer);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2809
2810
2811
  	init_waitqueue_head(&conn->ehwait);
  
  	return cls_conn;
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2812
  login_task_data_alloc_fail:
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
2813
  	kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
d36ab6f32   Mike Christie   [SCSI] iscsi: onl...
2814
  		    sizeof(void*));
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2815
  login_task_alloc_fail:
7996a778f   Mike Christie   [SCSI] iscsi: add...
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
  	iscsi_destroy_conn(cls_conn);
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_setup);
  
  /**
   * iscsi_conn_teardown - teardown iscsi connection
   * cls_conn: iscsi class connection
   *
   * TODO: we may need to make this into a two step process
   * like scsi-mls remove + put host
   */
  void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
  {
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	struct iscsi_session *session = conn->session;
  	unsigned long flags;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2833
  	del_timer_sync(&conn->transport_timer);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
  	spin_lock_bh(&session->lock);
  	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
  	if (session->leadconn == conn) {
  		/*
  		 * leading connection? then give up on recovery.
  		 */
  		session->state = ISCSI_STATE_TERMINATE;
  		wake_up(&conn->ehwait);
  	}
  	spin_unlock_bh(&session->lock);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
  	/*
  	 * Block until all in-progress commands for this connection
  	 * time out or fail.
  	 */
  	for (;;) {
  		spin_lock_irqsave(session->host->host_lock, flags);
  		if (!session->host->host_busy) { /* OK for ERL == 0 */
  			spin_unlock_irqrestore(session->host->host_lock, flags);
  			break;
  		}
  		spin_unlock_irqrestore(session->host->host_lock, flags);
  		msleep_interruptible(500);
322d739da   Mike Christie   [SCSI] iscsi: fix...
2856
2857
2858
2859
2860
  		iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
  				  "host_busy %d host_failed %d
  ",
  				  session->host->host_busy,
  				  session->host->host_failed);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2861
2862
2863
2864
2865
  		/*
  		 * force eh_abort() to unblock
  		 */
  		wake_up(&conn->ehwait);
  	}
779ea1207   Mike Christie   [SCSI] libiscsi: ...
2866
  	/* flush queued up work because we free the connection below */
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2867
  	iscsi_suspend_tx(conn);
779ea1207   Mike Christie   [SCSI] libiscsi: ...
2868

7996a778f   Mike Christie   [SCSI] iscsi: add...
2869
  	spin_lock_bh(&session->lock);
cfeb2cf95   Mike Christie   [SCSI] libiscsi: ...
2870
2871
  	free_pages((unsigned long) conn->data,
  		   get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
f3ff0c362   Mike Christie   [SCSI] iscsi bugf...
2872
  	kfree(conn->persistent_address);
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
2873
  	kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
7996a778f   Mike Christie   [SCSI] iscsi: add...
2874
  		    sizeof(void*));
e07264071   Mike Christie   [SCSI] libiscsi: ...
2875
  	if (session->leadconn == conn)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2876
  		session->leadconn = NULL;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2877
  	spin_unlock_bh(&session->lock);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2878
2879
2880
2881
2882
2883
2884
2885
  	iscsi_destroy_conn(cls_conn);
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_teardown);
  
  int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
  {
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	struct iscsi_session *session = conn->session;
ffd0436ed   Mike Christie   [SCSI] libiscsi, ...
2886
  	if (!session) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
2887
2888
2889
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "can't start unbound connection
  ");
7996a778f   Mike Christie   [SCSI] iscsi: add...
2890
2891
  		return -EPERM;
  	}
db98ccde0   Mike Christie   [SCSI] libiscsi: ...
2892
2893
  	if ((session->imm_data_en || !session->initial_r2t_en) &&
  	     session->first_burst > session->max_burst) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
2894
2895
2896
2897
  		iscsi_conn_printk(KERN_INFO, conn, "invalid burst lengths: "
  				  "first_burst %d max_burst %d
  ",
  				  session->first_burst, session->max_burst);
ffd0436ed   Mike Christie   [SCSI] libiscsi, ...
2898
2899
  		return -EINVAL;
  	}
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2900
  	if (conn->ping_timeout && !conn->recv_timeout) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
2901
2902
2903
  		iscsi_conn_printk(KERN_ERR, conn, "invalid recv timeout of "
  				  "zero. Using 5 seconds
  .");
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2904
2905
2906
2907
  		conn->recv_timeout = 5;
  	}
  
  	if (conn->recv_timeout && !conn->ping_timeout) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
2908
2909
2910
  		iscsi_conn_printk(KERN_ERR, conn, "invalid ping timeout of "
  				  "zero. Using 5 seconds.
  ");
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2911
2912
  		conn->ping_timeout = 5;
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
2913
2914
2915
  	spin_lock_bh(&session->lock);
  	conn->c_stage = ISCSI_CONN_STARTED;
  	session->state = ISCSI_STATE_LOGGED_IN;
e07264071   Mike Christie   [SCSI] libiscsi: ...
2916
  	session->queued_cmdsn = session->cmdsn;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2917

f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2918
2919
2920
2921
2922
  	conn->last_recv = jiffies;
  	conn->last_ping = jiffies;
  	if (conn->recv_timeout && conn->ping_timeout)
  		mod_timer(&conn->transport_timer,
  			  jiffies + (conn->recv_timeout * HZ));
7996a778f   Mike Christie   [SCSI] iscsi: add...
2923
2924
2925
2926
2927
2928
  	switch(conn->stop_stage) {
  	case STOP_CONN_RECOVER:
  		/*
  		 * unblock eh_abort() if it is blocked. re-try all
  		 * commands after successful recovery
  		 */
7996a778f   Mike Christie   [SCSI] iscsi: add...
2929
  		conn->stop_stage = 0;
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
2930
  		conn->tmf_state = TMF_INITIAL;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2931
  		session->age++;
8b1d03434   Mike Christie   [SCSI] libiscsi: ...
2932
2933
  		if (session->age == 16)
  			session->age = 0;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
2934
  		break;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2935
  	case STOP_CONN_TERM:
7996a778f   Mike Christie   [SCSI] iscsi: add...
2936
  		conn->stop_stage = 0;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2937
2938
2939
2940
2941
  		break;
  	default:
  		break;
  	}
  	spin_unlock_bh(&session->lock);
756135215   Mike Christie   [SCSI] iscsi: rem...
2942
  	iscsi_unblock_session(session->cls_session);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
2943
  	wake_up(&conn->ehwait);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2944
2945
2946
2947
2948
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_start);
  
  static void
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2949
  fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2950
  {
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2951
  	struct iscsi_task *task;
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
2952
  	int i, state;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2953

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2954
2955
2956
2957
  	for (i = 0; i < conn->session->cmds_max; i++) {
  		task = conn->session->cmds[i];
  		if (task->sc)
  			continue;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2958

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2959
2960
  		if (task->state == ISCSI_TASK_FREE)
  			continue;
7996a778f   Mike Christie   [SCSI] iscsi: add...
2961

3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2962
2963
2964
2965
  		ISCSI_DBG_SESSION(conn->session,
  				  "failing mgmt itt 0x%x state %d
  ",
  				  task->itt, task->state);
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
2966
2967
2968
2969
  		state = ISCSI_TASK_ABRT_SESS_RECOV;
  		if (task->state == ISCSI_TASK_PENDING)
  			state = ISCSI_TASK_COMPLETED;
  		iscsi_complete_task(task, state);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
2970
  	}
7996a778f   Mike Christie   [SCSI] iscsi: add...
2971
  }
656cffc95   Mike Christie   [SCSI] iscsi: fix...
2972
2973
  static void iscsi_start_session_recovery(struct iscsi_session *session,
  					 struct iscsi_conn *conn, int flag)
7996a778f   Mike Christie   [SCSI] iscsi: add...
2974
  {
ed2abc7ff   Mike Christie   [SCSI] iscsi: fix...
2975
  	int old_stop_stage;
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2976
  	mutex_lock(&session->eh_mutex);
7996a778f   Mike Christie   [SCSI] iscsi: add...
2977
  	spin_lock_bh(&session->lock);
ed2abc7ff   Mike Christie   [SCSI] iscsi: fix...
2978
  	if (conn->stop_stage == STOP_CONN_TERM) {
7996a778f   Mike Christie   [SCSI] iscsi: add...
2979
  		spin_unlock_bh(&session->lock);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
2980
2981
2982
2983
2984
  		mutex_unlock(&session->eh_mutex);
  		return;
  	}
  
  	/*
ed2abc7ff   Mike Christie   [SCSI] iscsi: fix...
2985
  	 * When this is called for the in_login state, we only want to clean
9c19a7d03   Mike Christie   [SCSI] libiscsi: ...
2986
  	 * up the login task and connection. We do not need to block and set
67a611149   Mike Christie   [SCSI] iscsi: don...
2987
  	 * the recovery state again
ed2abc7ff   Mike Christie   [SCSI] iscsi: fix...
2988
  	 */
67a611149   Mike Christie   [SCSI] iscsi: don...
2989
2990
2991
2992
  	if (flag == STOP_CONN_TERM)
  		session->state = ISCSI_STATE_TERMINATE;
  	else if (conn->stop_stage != STOP_CONN_RECOVER)
  		session->state = ISCSI_STATE_IN_RECOVERY;
4ae0a6c15   Mike Christie   [SCSI] libiscsi: ...
2993
2994
2995
  
  	old_stop_stage = conn->stop_stage;
  	conn->stop_stage = flag;
26013ad4c   Mike Christie   [SCSI] libiscsi: ...
2996
  	spin_unlock_bh(&session->lock);
ed2abc7ff   Mike Christie   [SCSI] iscsi: fix...
2997

26013ad4c   Mike Christie   [SCSI] libiscsi: ...
2998
2999
3000
3001
  	del_timer_sync(&conn->transport_timer);
  	iscsi_suspend_tx(conn);
  
  	spin_lock_bh(&session->lock);
67a611149   Mike Christie   [SCSI] iscsi: don...
3002
  	conn->c_stage = ISCSI_CONN_STOPPED;
7996a778f   Mike Christie   [SCSI] iscsi: add...
3003
  	spin_unlock_bh(&session->lock);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
3004

7996a778f   Mike Christie   [SCSI] iscsi: add...
3005
3006
3007
3008
3009
3010
3011
3012
3013
  	/*
  	 * for connection level recovery we should not calculate
  	 * header digest. conn->hdr_size used for optimization
  	 * in hdr_extract() and will be re-negotiated at
  	 * set_param() time.
  	 */
  	if (flag == STOP_CONN_RECOVER) {
  		conn->hdrdgst_en = 0;
  		conn->datadgst_en = 0;
656cffc95   Mike Christie   [SCSI] iscsi: fix...
3014
  		if (session->state == ISCSI_STATE_IN_RECOVERY &&
67a611149   Mike Christie   [SCSI] iscsi: don...
3015
  		    old_stop_stage != STOP_CONN_RECOVER) {
1b2c7af87   Mike Christie   [SCSI] libiscsi: ...
3016
3017
  			ISCSI_DBG_SESSION(session, "blocking session
  ");
756135215   Mike Christie   [SCSI] iscsi: rem...
3018
  			iscsi_block_session(session->cls_session);
67a611149   Mike Christie   [SCSI] iscsi: don...
3019
  		}
7996a778f   Mike Christie   [SCSI] iscsi: add...
3020
  	}
656cffc95   Mike Christie   [SCSI] iscsi: fix...
3021

656cffc95   Mike Christie   [SCSI] iscsi: fix...
3022
3023
3024
3025
  	/*
  	 * flush queues.
  	 */
  	spin_lock_bh(&session->lock);
b3cd5050b   Mike Christie   [SCSI] libiscsi: ...
3026
  	fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
3bbaaad95   Mike Christie   [SCSI] libiscsi: ...
3027
  	fail_mgmt_tasks(session, conn);
5d12c05e2   Mike Christie   [SCSI] libiscsi: ...
3028
  	memset(&conn->tmhdr, 0, sizeof(conn->tmhdr));
656cffc95   Mike Christie   [SCSI] iscsi: fix...
3029
  	spin_unlock_bh(&session->lock);
6724add1b   Mike Christie   [SCSI] libiscsi: ...
3030
  	mutex_unlock(&session->eh_mutex);
7996a778f   Mike Christie   [SCSI] iscsi: add...
3031
  }
7996a778f   Mike Christie   [SCSI] iscsi: add...
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
  
  void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
  {
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	struct iscsi_session *session = conn->session;
  
  	switch (flag) {
  	case STOP_CONN_RECOVER:
  	case STOP_CONN_TERM:
  		iscsi_start_session_recovery(session, conn, flag);
8d2860b3c   Mike Christie   [SCSI] iscsi: inc...
3042
  		break;
7996a778f   Mike Christie   [SCSI] iscsi: add...
3043
  	default:
322d739da   Mike Christie   [SCSI] iscsi: fix...
3044
3045
3046
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "invalid stop flag %d
  ", flag);
7996a778f   Mike Christie   [SCSI] iscsi: add...
3047
3048
3049
3050
3051
3052
3053
  	}
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_stop);
  
  int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
  		    struct iscsi_cls_conn *cls_conn, int is_leading)
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
3054
  	struct iscsi_session *session = cls_session->dd_data;
986440479   Mike Christie   [SCSI] libiscsi: ...
3055
  	struct iscsi_conn *conn = cls_conn->dd_data;
7996a778f   Mike Christie   [SCSI] iscsi: add...
3056

7996a778f   Mike Christie   [SCSI] iscsi: add...
3057
  	spin_lock_bh(&session->lock);
7996a778f   Mike Christie   [SCSI] iscsi: add...
3058
3059
  	if (is_leading)
  		session->leadconn = conn;
986440479   Mike Christie   [SCSI] libiscsi: ...
3060
  	spin_unlock_bh(&session->lock);
7996a778f   Mike Christie   [SCSI] iscsi: add...
3061
3062
3063
3064
3065
3066
3067
3068
3069
  
  	/*
  	 * Unblock xmitworker(), Login Phase will pass through.
  	 */
  	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
  	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_bind);
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
  static int iscsi_switch_str_param(char **param, char *new_val_buf)
  {
  	char *new_val;
  
  	if (*param) {
  		if (!strcmp(*param, new_val_buf))
  			return 0;
  	}
  
  	new_val = kstrdup(new_val_buf, GFP_NOIO);
  	if (!new_val)
  		return -ENOMEM;
  
  	kfree(*param);
  	*param = new_val;
  	return 0;
  }
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3087
3088
3089
3090
3091
3092
  
  int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
  		    enum iscsi_param param, char *buf, int buflen)
  {
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	struct iscsi_session *session = conn->session;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3093
3094
  
  	switch(param) {
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
3095
3096
3097
  	case ISCSI_PARAM_FAST_ABORT:
  		sscanf(buf, "%d", &session->fast_abort);
  		break;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
3098
3099
3100
3101
3102
3103
  	case ISCSI_PARAM_ABORT_TMO:
  		sscanf(buf, "%d", &session->abort_timeout);
  		break;
  	case ISCSI_PARAM_LU_RESET_TMO:
  		sscanf(buf, "%d", &session->lu_reset_timeout);
  		break;
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
3104
3105
3106
  	case ISCSI_PARAM_TGT_RESET_TMO:
  		sscanf(buf, "%d", &session->tgt_reset_timeout);
  		break;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
3107
3108
3109
3110
3111
3112
  	case ISCSI_PARAM_PING_TMO:
  		sscanf(buf, "%d", &conn->ping_timeout);
  		break;
  	case ISCSI_PARAM_RECV_TMO:
  		sscanf(buf, "%d", &conn->recv_timeout);
  		break;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
  	case ISCSI_PARAM_MAX_RECV_DLENGTH:
  		sscanf(buf, "%d", &conn->max_recv_dlength);
  		break;
  	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
  		sscanf(buf, "%d", &conn->max_xmit_dlength);
  		break;
  	case ISCSI_PARAM_HDRDGST_EN:
  		sscanf(buf, "%d", &conn->hdrdgst_en);
  		break;
  	case ISCSI_PARAM_DATADGST_EN:
  		sscanf(buf, "%d", &conn->datadgst_en);
  		break;
  	case ISCSI_PARAM_INITIAL_R2T_EN:
  		sscanf(buf, "%d", &session->initial_r2t_en);
  		break;
  	case ISCSI_PARAM_MAX_R2T:
  		sscanf(buf, "%d", &session->max_r2t);
  		break;
  	case ISCSI_PARAM_IMM_DATA_EN:
  		sscanf(buf, "%d", &session->imm_data_en);
  		break;
  	case ISCSI_PARAM_FIRST_BURST:
  		sscanf(buf, "%d", &session->first_burst);
  		break;
  	case ISCSI_PARAM_MAX_BURST:
  		sscanf(buf, "%d", &session->max_burst);
  		break;
  	case ISCSI_PARAM_PDU_INORDER_EN:
  		sscanf(buf, "%d", &session->pdu_inorder_en);
  		break;
  	case ISCSI_PARAM_DATASEQ_INORDER_EN:
  		sscanf(buf, "%d", &session->dataseq_inorder_en);
  		break;
  	case ISCSI_PARAM_ERL:
  		sscanf(buf, "%d", &session->erl);
  		break;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3149
3150
3151
  	case ISCSI_PARAM_EXP_STATSN:
  		sscanf(buf, "%u", &conn->exp_statsn);
  		break;
b2c641673   Mike Christie   [SCSI] iscsi clas...
3152
  	case ISCSI_PARAM_USERNAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3153
  		return iscsi_switch_str_param(&session->username, buf);
b2c641673   Mike Christie   [SCSI] iscsi clas...
3154
  	case ISCSI_PARAM_USERNAME_IN:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3155
  		return iscsi_switch_str_param(&session->username_in, buf);
b2c641673   Mike Christie   [SCSI] iscsi clas...
3156
  	case ISCSI_PARAM_PASSWORD:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3157
  		return iscsi_switch_str_param(&session->password, buf);
b2c641673   Mike Christie   [SCSI] iscsi clas...
3158
  	case ISCSI_PARAM_PASSWORD_IN:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3159
  		return iscsi_switch_str_param(&session->password_in, buf);
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3160
  	case ISCSI_PARAM_TARGET_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3161
  		return iscsi_switch_str_param(&session->targetname, buf);
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3162
3163
3164
3165
3166
3167
3168
  	case ISCSI_PARAM_TPGT:
  		sscanf(buf, "%d", &session->tpgt);
  		break;
  	case ISCSI_PARAM_PERSISTENT_PORT:
  		sscanf(buf, "%d", &conn->persistent_port);
  		break;
  	case ISCSI_PARAM_PERSISTENT_ADDRESS:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3169
  		return iscsi_switch_str_param(&conn->persistent_address, buf);
88dfd340b   Mike Christie   [SCSI] iscsi clas...
3170
  	case ISCSI_PARAM_IFACE_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3171
  		return iscsi_switch_str_param(&session->ifacename, buf);
88dfd340b   Mike Christie   [SCSI] iscsi clas...
3172
  	case ISCSI_PARAM_INITIATOR_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3173
  		return iscsi_switch_str_param(&session->initiatorname, buf);
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
  	default:
  		return -ENOSYS;
  	}
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_set_param);
  
  int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
  			    enum iscsi_param param, char *buf)
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
3185
  	struct iscsi_session *session = cls_session->dd_data;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3186
3187
3188
  	int len;
  
  	switch(param) {
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
3189
3190
3191
3192
  	case ISCSI_PARAM_FAST_ABORT:
  		len = sprintf(buf, "%d
  ", session->fast_abort);
  		break;
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
3193
3194
3195
3196
3197
3198
3199
3200
  	case ISCSI_PARAM_ABORT_TMO:
  		len = sprintf(buf, "%d
  ", session->abort_timeout);
  		break;
  	case ISCSI_PARAM_LU_RESET_TMO:
  		len = sprintf(buf, "%d
  ", session->lu_reset_timeout);
  		break;
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
3201
3202
3203
3204
  	case ISCSI_PARAM_TGT_RESET_TMO:
  		len = sprintf(buf, "%d
  ", session->tgt_reset_timeout);
  		break;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
  	case ISCSI_PARAM_INITIAL_R2T_EN:
  		len = sprintf(buf, "%d
  ", session->initial_r2t_en);
  		break;
  	case ISCSI_PARAM_MAX_R2T:
  		len = sprintf(buf, "%hu
  ", session->max_r2t);
  		break;
  	case ISCSI_PARAM_IMM_DATA_EN:
  		len = sprintf(buf, "%d
  ", session->imm_data_en);
  		break;
  	case ISCSI_PARAM_FIRST_BURST:
  		len = sprintf(buf, "%u
  ", session->first_burst);
  		break;
  	case ISCSI_PARAM_MAX_BURST:
  		len = sprintf(buf, "%u
  ", session->max_burst);
  		break;
  	case ISCSI_PARAM_PDU_INORDER_EN:
  		len = sprintf(buf, "%d
  ", session->pdu_inorder_en);
  		break;
  	case ISCSI_PARAM_DATASEQ_INORDER_EN:
  		len = sprintf(buf, "%d
  ", session->dataseq_inorder_en);
  		break;
  	case ISCSI_PARAM_ERL:
  		len = sprintf(buf, "%d
  ", session->erl);
  		break;
  	case ISCSI_PARAM_TARGET_NAME:
  		len = sprintf(buf, "%s
  ", session->targetname);
  		break;
  	case ISCSI_PARAM_TPGT:
  		len = sprintf(buf, "%d
  ", session->tpgt);
  		break;
b2c641673   Mike Christie   [SCSI] iscsi clas...
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
  	case ISCSI_PARAM_USERNAME:
  		len = sprintf(buf, "%s
  ", session->username);
  		break;
  	case ISCSI_PARAM_USERNAME_IN:
  		len = sprintf(buf, "%s
  ", session->username_in);
  		break;
  	case ISCSI_PARAM_PASSWORD:
  		len = sprintf(buf, "%s
  ", session->password);
  		break;
  	case ISCSI_PARAM_PASSWORD_IN:
  		len = sprintf(buf, "%s
  ", session->password_in);
  		break;
88dfd340b   Mike Christie   [SCSI] iscsi clas...
3261
3262
3263
3264
3265
  	case ISCSI_PARAM_IFACE_NAME:
  		len = sprintf(buf, "%s
  ", session->ifacename);
  		break;
  	case ISCSI_PARAM_INITIATOR_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3266
3267
  		len = sprintf(buf, "%s
  ", session->initiatorname);
88dfd340b   Mike Christie   [SCSI] iscsi clas...
3268
  		break;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3269
3270
3271
3272
3273
3274
3275
  	default:
  		return -ENOSYS;
  	}
  
  	return len;
  }
  EXPORT_SYMBOL_GPL(iscsi_session_get_param);
00f3708e6   Mike Christie   [SCSI] libiscsi: ...
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
  int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
  			      enum iscsi_param param, char *buf)
  {
  	struct sockaddr_in6 *sin6 = NULL;
  	struct sockaddr_in *sin = NULL;
  	int len;
  
  	switch (addr->ss_family) {
  	case AF_INET:
  		sin = (struct sockaddr_in *)addr;
  		break;
  	case AF_INET6:
  		sin6 = (struct sockaddr_in6 *)addr;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	switch (param) {
  	case ISCSI_PARAM_CONN_ADDRESS:
  	case ISCSI_HOST_PARAM_IPADDRESS:
  		if (sin)
  			len = sprintf(buf, "%pI4
  ", &sin->sin_addr.s_addr);
  		else
  			len = sprintf(buf, "%pI6
  ", &sin6->sin6_addr);
  		break;
  	case ISCSI_PARAM_CONN_PORT:
  		if (sin)
  			len = sprintf(buf, "%hu
  ", be16_to_cpu(sin->sin_port));
  		else
  			len = sprintf(buf, "%hu
  ",
  				      be16_to_cpu(sin6->sin6_port));
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return len;
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_get_addr_param);
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3320
3321
3322
3323
3324
3325
3326
  int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
  			 enum iscsi_param param, char *buf)
  {
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	int len;
  
  	switch(param) {
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
3327
3328
3329
3330
3331
3332
3333
3334
  	case ISCSI_PARAM_PING_TMO:
  		len = sprintf(buf, "%u
  ", conn->ping_timeout);
  		break;
  	case ISCSI_PARAM_RECV_TMO:
  		len = sprintf(buf, "%u
  ", conn->recv_timeout);
  		break;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
  	case ISCSI_PARAM_MAX_RECV_DLENGTH:
  		len = sprintf(buf, "%u
  ", conn->max_recv_dlength);
  		break;
  	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
  		len = sprintf(buf, "%u
  ", conn->max_xmit_dlength);
  		break;
  	case ISCSI_PARAM_HDRDGST_EN:
  		len = sprintf(buf, "%d
  ", conn->hdrdgst_en);
  		break;
  	case ISCSI_PARAM_DATADGST_EN:
  		len = sprintf(buf, "%d
  ", conn->datadgst_en);
  		break;
  	case ISCSI_PARAM_IFMARKER_EN:
  		len = sprintf(buf, "%d
  ", conn->ifmarker_en);
  		break;
  	case ISCSI_PARAM_OFMARKER_EN:
  		len = sprintf(buf, "%d
  ", conn->ofmarker_en);
  		break;
  	case ISCSI_PARAM_EXP_STATSN:
  		len = sprintf(buf, "%u
  ", conn->exp_statsn);
  		break;
  	case ISCSI_PARAM_PERSISTENT_PORT:
  		len = sprintf(buf, "%d
  ", conn->persistent_port);
  		break;
  	case ISCSI_PARAM_PERSISTENT_ADDRESS:
  		len = sprintf(buf, "%s
  ", conn->persistent_address);
  		break;
  	default:
  		return -ENOSYS;
  	}
  
  	return len;
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3378
3379
3380
  int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
  			 char *buf)
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
3381
  	struct iscsi_host *ihost = shost_priv(shost);
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3382
3383
3384
  	int len;
  
  	switch (param) {
d8196ed21   Mike Christie   [SCSI] iscsi clas...
3385
  	case ISCSI_HOST_PARAM_NETDEV_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3386
3387
  		len = sprintf(buf, "%s
  ", ihost->netdev);
d8196ed21   Mike Christie   [SCSI] iscsi clas...
3388
  		break;
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3389
  	case ISCSI_HOST_PARAM_HWADDRESS:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3390
3391
  		len = sprintf(buf, "%s
  ", ihost->hwaddress);
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3392
  		break;
8ad5781ae   Mike Christie   [SCSI] iscsi clas...
3393
  	case ISCSI_HOST_PARAM_INITIATOR_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3394
3395
  		len = sprintf(buf, "%s
  ", ihost->initiatorname);
8ad5781ae   Mike Christie   [SCSI] iscsi clas...
3396
  		break;
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
  	default:
  		return -ENOSYS;
  	}
  
  	return len;
  }
  EXPORT_SYMBOL_GPL(iscsi_host_get_param);
  
  int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
  			 char *buf, int buflen)
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
3408
  	struct iscsi_host *ihost = shost_priv(shost);
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3409
3410
  
  	switch (param) {
d8196ed21   Mike Christie   [SCSI] iscsi clas...
3411
  	case ISCSI_HOST_PARAM_NETDEV_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3412
  		return iscsi_switch_str_param(&ihost->netdev, buf);
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3413
  	case ISCSI_HOST_PARAM_HWADDRESS:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3414
  		return iscsi_switch_str_param(&ihost->hwaddress, buf);
8ad5781ae   Mike Christie   [SCSI] iscsi clas...
3415
  	case ISCSI_HOST_PARAM_INITIATOR_NAME:
5700b1af9   Mike Christie   [SCSI] libiscsi: ...
3416
  		return iscsi_switch_str_param(&ihost->initiatorname, buf);
0801c242a   Mike Christie   [SCSI] libiscsi, ...
3417
3418
3419
3420
3421
3422
3423
  	default:
  		return -ENOSYS;
  	}
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_host_set_param);
7996a778f   Mike Christie   [SCSI] iscsi: add...
3424
3425
3426
  MODULE_AUTHOR("Mike Christie");
  MODULE_DESCRIPTION("iSCSI library functions");
  MODULE_LICENSE("GPL");