1e48354ceSNicholas Bellinger /*******************************************************************************
2e48354ceSNicholas Bellinger  * This file contains main functions related to the iSCSI Target Core Driver.
3e48354ceSNicholas Bellinger  *
44c76251eSNicholas Bellinger  * (c) Copyright 2007-2013 Datera, Inc.
5e48354ceSNicholas Bellinger  *
6e48354ceSNicholas Bellinger  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
7e48354ceSNicholas Bellinger  *
8e48354ceSNicholas Bellinger  * This program is free software; you can redistribute it and/or modify
9e48354ceSNicholas Bellinger  * it under the terms of the GNU General Public License as published by
10e48354ceSNicholas Bellinger  * the Free Software Foundation; either version 2 of the License, or
11e48354ceSNicholas Bellinger  * (at your option) any later version.
12e48354ceSNicholas Bellinger  *
13e48354ceSNicholas Bellinger  * This program is distributed in the hope that it will be useful,
14e48354ceSNicholas Bellinger  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15e48354ceSNicholas Bellinger  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16e48354ceSNicholas Bellinger  * GNU General Public License for more details.
17e48354ceSNicholas Bellinger  ******************************************************************************/
18e48354ceSNicholas Bellinger 
1969110e3cSHerbert Xu #include <crypto/hash.h>
20e48354ceSNicholas Bellinger #include <linux/string.h>
21e48354ceSNicholas Bellinger #include <linux/kthread.h>
22e48354ceSNicholas Bellinger #include <linux/completion.h>
23827509e3SPaul Gortmaker #include <linux/module.h>
245538d294SDavid S. Miller #include <linux/vmalloc.h>
2540401530SAl Viro #include <linux/idr.h>
268dcf07beSBart Van Assche #include <linux/delay.h>
273f07c014SIngo Molnar #include <linux/sched/signal.h>
28e48354ceSNicholas Bellinger #include <asm/unaligned.h>
298dcf07beSBart Van Assche #include <net/ipv6.h>
30ba929992SBart Van Assche #include <scsi/scsi_proto.h>
31e48354ceSNicholas Bellinger #include <scsi/iscsi_proto.h>
32d28b1169SAndy Grover #include <scsi/scsi_tcq.h>
33e48354ceSNicholas Bellinger #include <target/target_core_base.h>
34c4795fb2SChristoph Hellwig #include <target/target_core_fabric.h>
35e48354ceSNicholas Bellinger 
3667f091f2SSagi Grimberg #include <target/iscsi/iscsi_target_core.h>
37e48354ceSNicholas Bellinger #include "iscsi_target_parameters.h"
38e48354ceSNicholas Bellinger #include "iscsi_target_seq_pdu_list.h"
39e48354ceSNicholas Bellinger #include "iscsi_target_datain_values.h"
40e48354ceSNicholas Bellinger #include "iscsi_target_erl0.h"
41e48354ceSNicholas Bellinger #include "iscsi_target_erl1.h"
42e48354ceSNicholas Bellinger #include "iscsi_target_erl2.h"
43e48354ceSNicholas Bellinger #include "iscsi_target_login.h"
44e48354ceSNicholas Bellinger #include "iscsi_target_tmr.h"
45e48354ceSNicholas Bellinger #include "iscsi_target_tpg.h"
46e48354ceSNicholas Bellinger #include "iscsi_target_util.h"
47e48354ceSNicholas Bellinger #include "iscsi_target.h"
48e48354ceSNicholas Bellinger #include "iscsi_target_device.h"
4967f091f2SSagi Grimberg #include <target/iscsi/iscsi_target_stat.h>
50e48354ceSNicholas Bellinger 
51baa4d64bSNicholas Bellinger #include <target/iscsi/iscsi_transport.h>
52baa4d64bSNicholas Bellinger 
53e48354ceSNicholas Bellinger static LIST_HEAD(g_tiqn_list);
54e48354ceSNicholas Bellinger static LIST_HEAD(g_np_list);
55e48354ceSNicholas Bellinger static DEFINE_SPINLOCK(tiqn_lock);
56ee291e63SAndy Grover static DEFINE_MUTEX(np_lock);
57e48354ceSNicholas Bellinger 
58e48354ceSNicholas Bellinger static struct idr tiqn_idr;
59e48354ceSNicholas Bellinger struct idr sess_idr;
60e48354ceSNicholas Bellinger struct mutex auth_id_lock;
61e48354ceSNicholas Bellinger spinlock_t sess_idr_lock;
62e48354ceSNicholas Bellinger 
63e48354ceSNicholas Bellinger struct iscsit_global *iscsit_global;
64e48354ceSNicholas Bellinger 
65e48354ceSNicholas Bellinger struct kmem_cache *lio_qr_cache;
66e48354ceSNicholas Bellinger struct kmem_cache *lio_dr_cache;
67e48354ceSNicholas Bellinger struct kmem_cache *lio_ooo_cache;
68e48354ceSNicholas Bellinger struct kmem_cache *lio_r2t_cache;
69e48354ceSNicholas Bellinger 
70e48354ceSNicholas Bellinger static int iscsit_handle_immediate_data(struct iscsi_cmd *,
712ec5a8c1SNicholas Bellinger 			struct iscsi_scsi_req *, u32);
72e48354ceSNicholas Bellinger 
73e48354ceSNicholas Bellinger struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf)
74e48354ceSNicholas Bellinger {
75e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = NULL;
76e48354ceSNicholas Bellinger 
77e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
78e48354ceSNicholas Bellinger 	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
79e48354ceSNicholas Bellinger 		if (!strcmp(tiqn->tiqn, buf)) {
80e48354ceSNicholas Bellinger 
81e48354ceSNicholas Bellinger 			spin_lock(&tiqn->tiqn_state_lock);
82e48354ceSNicholas Bellinger 			if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
83e48354ceSNicholas Bellinger 				tiqn->tiqn_access_count++;
84e48354ceSNicholas Bellinger 				spin_unlock(&tiqn->tiqn_state_lock);
85e48354ceSNicholas Bellinger 				spin_unlock(&tiqn_lock);
86e48354ceSNicholas Bellinger 				return tiqn;
87e48354ceSNicholas Bellinger 			}
88e48354ceSNicholas Bellinger 			spin_unlock(&tiqn->tiqn_state_lock);
89e48354ceSNicholas Bellinger 		}
90e48354ceSNicholas Bellinger 	}
91e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
92e48354ceSNicholas Bellinger 
93e48354ceSNicholas Bellinger 	return NULL;
94e48354ceSNicholas Bellinger }
95e48354ceSNicholas Bellinger 
96e48354ceSNicholas Bellinger static int iscsit_set_tiqn_shutdown(struct iscsi_tiqn *tiqn)
97e48354ceSNicholas Bellinger {
98e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
99e48354ceSNicholas Bellinger 	if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
100e48354ceSNicholas Bellinger 		tiqn->tiqn_state = TIQN_STATE_SHUTDOWN;
101e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_state_lock);
102e48354ceSNicholas Bellinger 		return 0;
103e48354ceSNicholas Bellinger 	}
104e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
105e48354ceSNicholas Bellinger 
106e48354ceSNicholas Bellinger 	return -1;
107e48354ceSNicholas Bellinger }
108e48354ceSNicholas Bellinger 
109e48354ceSNicholas Bellinger void iscsit_put_tiqn_for_login(struct iscsi_tiqn *tiqn)
110e48354ceSNicholas Bellinger {
111e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
112e48354ceSNicholas Bellinger 	tiqn->tiqn_access_count--;
113e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
114e48354ceSNicholas Bellinger }
115e48354ceSNicholas Bellinger 
116e48354ceSNicholas Bellinger /*
117e48354ceSNicholas Bellinger  * Note that IQN formatting is expected to be done in userspace, and
118e48354ceSNicholas Bellinger  * no explict IQN format checks are done here.
119e48354ceSNicholas Bellinger  */
120e48354ceSNicholas Bellinger struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf)
121e48354ceSNicholas Bellinger {
122e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = NULL;
123e48354ceSNicholas Bellinger 	int ret;
124e48354ceSNicholas Bellinger 
1258f50c7f5SDan Carpenter 	if (strlen(buf) >= ISCSI_IQN_LEN) {
126e48354ceSNicholas Bellinger 		pr_err("Target IQN exceeds %d bytes\n",
127e48354ceSNicholas Bellinger 				ISCSI_IQN_LEN);
128e48354ceSNicholas Bellinger 		return ERR_PTR(-EINVAL);
129e48354ceSNicholas Bellinger 	}
130e48354ceSNicholas Bellinger 
1313829f381SMarkus Elfring 	tiqn = kzalloc(sizeof(*tiqn), GFP_KERNEL);
132c46e22f1SMarkus Elfring 	if (!tiqn)
133e48354ceSNicholas Bellinger 		return ERR_PTR(-ENOMEM);
134e48354ceSNicholas Bellinger 
135e48354ceSNicholas Bellinger 	sprintf(tiqn->tiqn, "%s", buf);
136e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&tiqn->tiqn_list);
137e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&tiqn->tiqn_tpg_list);
138e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->tiqn_state_lock);
139e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->tiqn_tpg_lock);
140e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->sess_err_stats.lock);
141e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->login_stats.lock);
142e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->logout_stats.lock);
143e48354ceSNicholas Bellinger 
144e48354ceSNicholas Bellinger 	tiqn->tiqn_state = TIQN_STATE_ACTIVE;
145e48354ceSNicholas Bellinger 
146c9365bd0STejun Heo 	idr_preload(GFP_KERNEL);
147e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
148c9365bd0STejun Heo 
149c9365bd0STejun Heo 	ret = idr_alloc(&tiqn_idr, NULL, 0, 0, GFP_NOWAIT);
150e48354ceSNicholas Bellinger 	if (ret < 0) {
151c9365bd0STejun Heo 		pr_err("idr_alloc() failed for tiqn->tiqn_index\n");
152e48354ceSNicholas Bellinger 		spin_unlock(&tiqn_lock);
153c9365bd0STejun Heo 		idr_preload_end();
154e48354ceSNicholas Bellinger 		kfree(tiqn);
155e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
156e48354ceSNicholas Bellinger 	}
157c9365bd0STejun Heo 	tiqn->tiqn_index = ret;
158e48354ceSNicholas Bellinger 	list_add_tail(&tiqn->tiqn_list, &g_tiqn_list);
159c9365bd0STejun Heo 
160e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
161c9365bd0STejun Heo 	idr_preload_end();
162e48354ceSNicholas Bellinger 
163e48354ceSNicholas Bellinger 	pr_debug("CORE[0] - Added iSCSI Target IQN: %s\n", tiqn->tiqn);
164e48354ceSNicholas Bellinger 
165e48354ceSNicholas Bellinger 	return tiqn;
166e48354ceSNicholas Bellinger 
167e48354ceSNicholas Bellinger }
168e48354ceSNicholas Bellinger 
169e48354ceSNicholas Bellinger static void iscsit_wait_for_tiqn(struct iscsi_tiqn *tiqn)
170e48354ceSNicholas Bellinger {
171e48354ceSNicholas Bellinger 	/*
172e48354ceSNicholas Bellinger 	 * Wait for accesses to said struct iscsi_tiqn to end.
173e48354ceSNicholas Bellinger 	 */
174e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
175e48354ceSNicholas Bellinger 	while (tiqn->tiqn_access_count != 0) {
176e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_state_lock);
177e48354ceSNicholas Bellinger 		msleep(10);
178e48354ceSNicholas Bellinger 		spin_lock(&tiqn->tiqn_state_lock);
179e48354ceSNicholas Bellinger 	}
180e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
181e48354ceSNicholas Bellinger }
182e48354ceSNicholas Bellinger 
183e48354ceSNicholas Bellinger void iscsit_del_tiqn(struct iscsi_tiqn *tiqn)
184e48354ceSNicholas Bellinger {
185e48354ceSNicholas Bellinger 	/*
186e48354ceSNicholas Bellinger 	 * iscsit_set_tiqn_shutdown sets tiqn->tiqn_state = TIQN_STATE_SHUTDOWN
187e48354ceSNicholas Bellinger 	 * while holding tiqn->tiqn_state_lock.  This means that all subsequent
188e48354ceSNicholas Bellinger 	 * attempts to access this struct iscsi_tiqn will fail from both transport
189e48354ceSNicholas Bellinger 	 * fabric and control code paths.
190e48354ceSNicholas Bellinger 	 */
191e48354ceSNicholas Bellinger 	if (iscsit_set_tiqn_shutdown(tiqn) < 0) {
192e48354ceSNicholas Bellinger 		pr_err("iscsit_set_tiqn_shutdown() failed\n");
193e48354ceSNicholas Bellinger 		return;
194e48354ceSNicholas Bellinger 	}
195e48354ceSNicholas Bellinger 
196e48354ceSNicholas Bellinger 	iscsit_wait_for_tiqn(tiqn);
197e48354ceSNicholas Bellinger 
198e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
199e48354ceSNicholas Bellinger 	list_del(&tiqn->tiqn_list);
200e48354ceSNicholas Bellinger 	idr_remove(&tiqn_idr, tiqn->tiqn_index);
201e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
202e48354ceSNicholas Bellinger 
203e48354ceSNicholas Bellinger 	pr_debug("CORE[0] - Deleted iSCSI Target IQN: %s\n",
204e48354ceSNicholas Bellinger 			tiqn->tiqn);
205e48354ceSNicholas Bellinger 	kfree(tiqn);
206e48354ceSNicholas Bellinger }
207e48354ceSNicholas Bellinger 
208e48354ceSNicholas Bellinger int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
209e48354ceSNicholas Bellinger {
210e48354ceSNicholas Bellinger 	int ret;
211e48354ceSNicholas Bellinger 	/*
212e48354ceSNicholas Bellinger 	 * Determine if the network portal is accepting storage traffic.
213e48354ceSNicholas Bellinger 	 */
214e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
215e48354ceSNicholas Bellinger 	if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
216e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
217e48354ceSNicholas Bellinger 		return -1;
218e48354ceSNicholas Bellinger 	}
219e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
220e48354ceSNicholas Bellinger 	/*
221e48354ceSNicholas Bellinger 	 * Determine if the portal group is accepting storage traffic.
222e48354ceSNicholas Bellinger 	 */
223e48354ceSNicholas Bellinger 	spin_lock_bh(&tpg->tpg_state_lock);
224e48354ceSNicholas Bellinger 	if (tpg->tpg_state != TPG_STATE_ACTIVE) {
225e48354ceSNicholas Bellinger 		spin_unlock_bh(&tpg->tpg_state_lock);
226e48354ceSNicholas Bellinger 		return -1;
227e48354ceSNicholas Bellinger 	}
228e48354ceSNicholas Bellinger 	spin_unlock_bh(&tpg->tpg_state_lock);
229e48354ceSNicholas Bellinger 
230e48354ceSNicholas Bellinger 	/*
231e48354ceSNicholas Bellinger 	 * Here we serialize access across the TIQN+TPG Tuple.
232e48354ceSNicholas Bellinger 	 */
233a91eb7d9SNicholas Bellinger 	ret = down_interruptible(&tpg->np_login_sem);
234ee7619f2SNicholas Bellinger 	if (ret != 0)
235e48354ceSNicholas Bellinger 		return -1;
236e48354ceSNicholas Bellinger 
237a91eb7d9SNicholas Bellinger 	spin_lock_bh(&tpg->tpg_state_lock);
238a91eb7d9SNicholas Bellinger 	if (tpg->tpg_state != TPG_STATE_ACTIVE) {
239a91eb7d9SNicholas Bellinger 		spin_unlock_bh(&tpg->tpg_state_lock);
240a91eb7d9SNicholas Bellinger 		up(&tpg->np_login_sem);
241a91eb7d9SNicholas Bellinger 		return -1;
242a91eb7d9SNicholas Bellinger 	}
243a91eb7d9SNicholas Bellinger 	spin_unlock_bh(&tpg->tpg_state_lock);
244e48354ceSNicholas Bellinger 
245e48354ceSNicholas Bellinger 	return 0;
246e48354ceSNicholas Bellinger }
247e48354ceSNicholas Bellinger 
248a91eb7d9SNicholas Bellinger void iscsit_login_kref_put(struct kref *kref)
249a91eb7d9SNicholas Bellinger {
250a91eb7d9SNicholas Bellinger 	struct iscsi_tpg_np *tpg_np = container_of(kref,
251a91eb7d9SNicholas Bellinger 				struct iscsi_tpg_np, tpg_np_kref);
252a91eb7d9SNicholas Bellinger 
253a91eb7d9SNicholas Bellinger 	complete(&tpg_np->tpg_np_comp);
254a91eb7d9SNicholas Bellinger }
255a91eb7d9SNicholas Bellinger 
256a91eb7d9SNicholas Bellinger int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg,
257a91eb7d9SNicholas Bellinger 		       struct iscsi_tpg_np *tpg_np)
258e48354ceSNicholas Bellinger {
259e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
260e48354ceSNicholas Bellinger 
261a91eb7d9SNicholas Bellinger 	up(&tpg->np_login_sem);
262e48354ceSNicholas Bellinger 
263a91eb7d9SNicholas Bellinger 	if (tpg_np)
264a91eb7d9SNicholas Bellinger 		kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
265e48354ceSNicholas Bellinger 
266e48354ceSNicholas Bellinger 	if (tiqn)
267e48354ceSNicholas Bellinger 		iscsit_put_tiqn_for_login(tiqn);
268e48354ceSNicholas Bellinger 
269e48354ceSNicholas Bellinger 	return 0;
270e48354ceSNicholas Bellinger }
271e48354ceSNicholas Bellinger 
27205b96892SNicholas Bellinger bool iscsit_check_np_match(
27313a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
27405b96892SNicholas Bellinger 	struct iscsi_np *np,
275e48354ceSNicholas Bellinger 	int network_transport)
276e48354ceSNicholas Bellinger {
277e48354ceSNicholas Bellinger 	struct sockaddr_in *sock_in, *sock_in_e;
278e48354ceSNicholas Bellinger 	struct sockaddr_in6 *sock_in6, *sock_in6_e;
27905b96892SNicholas Bellinger 	bool ip_match = false;
28069d75574SAndy Grover 	u16 port, port_e;
281e48354ceSNicholas Bellinger 
28205b96892SNicholas Bellinger 	if (sockaddr->ss_family == AF_INET6) {
28305b96892SNicholas Bellinger 		sock_in6 = (struct sockaddr_in6 *)sockaddr;
28405b96892SNicholas Bellinger 		sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;
28505b96892SNicholas Bellinger 
28605b96892SNicholas Bellinger 		if (!memcmp(&sock_in6->sin6_addr.in6_u,
28705b96892SNicholas Bellinger 			    &sock_in6_e->sin6_addr.in6_u,
28805b96892SNicholas Bellinger 			    sizeof(struct in6_addr)))
28905b96892SNicholas Bellinger 			ip_match = true;
29005b96892SNicholas Bellinger 
29105b96892SNicholas Bellinger 		port = ntohs(sock_in6->sin6_port);
29269d75574SAndy Grover 		port_e = ntohs(sock_in6_e->sin6_port);
29305b96892SNicholas Bellinger 	} else {
29405b96892SNicholas Bellinger 		sock_in = (struct sockaddr_in *)sockaddr;
29505b96892SNicholas Bellinger 		sock_in_e = (struct sockaddr_in *)&np->np_sockaddr;
29605b96892SNicholas Bellinger 
29705b96892SNicholas Bellinger 		if (sock_in->sin_addr.s_addr == sock_in_e->sin_addr.s_addr)
29805b96892SNicholas Bellinger 			ip_match = true;
29905b96892SNicholas Bellinger 
30005b96892SNicholas Bellinger 		port = ntohs(sock_in->sin_port);
30169d75574SAndy Grover 		port_e = ntohs(sock_in_e->sin_port);
30205b96892SNicholas Bellinger 	}
30305b96892SNicholas Bellinger 
30469d75574SAndy Grover 	if (ip_match && (port_e == port) &&
30505b96892SNicholas Bellinger 	    (np->np_network_transport == network_transport))
30605b96892SNicholas Bellinger 		return true;
30705b96892SNicholas Bellinger 
30805b96892SNicholas Bellinger 	return false;
30905b96892SNicholas Bellinger }
31005b96892SNicholas Bellinger 
311ee291e63SAndy Grover /*
312ee291e63SAndy Grover  * Called with mutex np_lock held
313ee291e63SAndy Grover  */
31405b96892SNicholas Bellinger static struct iscsi_np *iscsit_get_np(
31513a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
31605b96892SNicholas Bellinger 	int network_transport)
31705b96892SNicholas Bellinger {
31805b96892SNicholas Bellinger 	struct iscsi_np *np;
31905b96892SNicholas Bellinger 	bool match;
32005b96892SNicholas Bellinger 
321e48354ceSNicholas Bellinger 	list_for_each_entry(np, &g_np_list, np_list) {
322ee291e63SAndy Grover 		spin_lock_bh(&np->np_thread_lock);
323e48354ceSNicholas Bellinger 		if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
324ee291e63SAndy Grover 			spin_unlock_bh(&np->np_thread_lock);
325e48354ceSNicholas Bellinger 			continue;
326e48354ceSNicholas Bellinger 		}
327e48354ceSNicholas Bellinger 
32805b96892SNicholas Bellinger 		match = iscsit_check_np_match(sockaddr, np, network_transport);
3290bcc297eSChristophe Vu-Brugier 		if (match) {
330e48354ceSNicholas Bellinger 			/*
331e48354ceSNicholas Bellinger 			 * Increment the np_exports reference count now to
332e48354ceSNicholas Bellinger 			 * prevent iscsit_del_np() below from being called
333e48354ceSNicholas Bellinger 			 * while iscsi_tpg_add_network_portal() is called.
334e48354ceSNicholas Bellinger 			 */
335e48354ceSNicholas Bellinger 			np->np_exports++;
336ee291e63SAndy Grover 			spin_unlock_bh(&np->np_thread_lock);
337e48354ceSNicholas Bellinger 			return np;
338e48354ceSNicholas Bellinger 		}
339ee291e63SAndy Grover 		spin_unlock_bh(&np->np_thread_lock);
340e48354ceSNicholas Bellinger 	}
341e48354ceSNicholas Bellinger 
342e48354ceSNicholas Bellinger 	return NULL;
343e48354ceSNicholas Bellinger }
344e48354ceSNicholas Bellinger 
345e48354ceSNicholas Bellinger struct iscsi_np *iscsit_add_np(
34613a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
347e48354ceSNicholas Bellinger 	int network_transport)
348e48354ceSNicholas Bellinger {
349e48354ceSNicholas Bellinger 	struct iscsi_np *np;
350e48354ceSNicholas Bellinger 	int ret;
351ee291e63SAndy Grover 
352ee291e63SAndy Grover 	mutex_lock(&np_lock);
353ee291e63SAndy Grover 
354e48354ceSNicholas Bellinger 	/*
355e48354ceSNicholas Bellinger 	 * Locate the existing struct iscsi_np if already active..
356e48354ceSNicholas Bellinger 	 */
357e48354ceSNicholas Bellinger 	np = iscsit_get_np(sockaddr, network_transport);
358ee291e63SAndy Grover 	if (np) {
359ee291e63SAndy Grover 		mutex_unlock(&np_lock);
360e48354ceSNicholas Bellinger 		return np;
361ee291e63SAndy Grover 	}
362e48354ceSNicholas Bellinger 
3633829f381SMarkus Elfring 	np = kzalloc(sizeof(*np), GFP_KERNEL);
364e48354ceSNicholas Bellinger 	if (!np) {
365ee291e63SAndy Grover 		mutex_unlock(&np_lock);
366e48354ceSNicholas Bellinger 		return ERR_PTR(-ENOMEM);
367e48354ceSNicholas Bellinger 	}
368e48354ceSNicholas Bellinger 
369e48354ceSNicholas Bellinger 	np->np_flags |= NPF_IP_NETWORK;
370e48354ceSNicholas Bellinger 	np->np_network_transport = network_transport;
371e48354ceSNicholas Bellinger 	spin_lock_init(&np->np_thread_lock);
372e48354ceSNicholas Bellinger 	init_completion(&np->np_restart_comp);
373e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&np->np_list);
374e48354ceSNicholas Bellinger 
375e48354ceSNicholas Bellinger 	ret = iscsi_target_setup_login_socket(np, sockaddr);
376e48354ceSNicholas Bellinger 	if (ret != 0) {
377e48354ceSNicholas Bellinger 		kfree(np);
378ee291e63SAndy Grover 		mutex_unlock(&np_lock);
379e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
380e48354ceSNicholas Bellinger 	}
381e48354ceSNicholas Bellinger 
382e48354ceSNicholas Bellinger 	np->np_thread = kthread_run(iscsi_target_login_thread, np, "iscsi_np");
383e48354ceSNicholas Bellinger 	if (IS_ERR(np->np_thread)) {
384e48354ceSNicholas Bellinger 		pr_err("Unable to create kthread: iscsi_np\n");
385e48354ceSNicholas Bellinger 		ret = PTR_ERR(np->np_thread);
386e48354ceSNicholas Bellinger 		kfree(np);
387ee291e63SAndy Grover 		mutex_unlock(&np_lock);
388e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
389e48354ceSNicholas Bellinger 	}
390e48354ceSNicholas Bellinger 	/*
391e48354ceSNicholas Bellinger 	 * Increment the np_exports reference count now to prevent
392e48354ceSNicholas Bellinger 	 * iscsit_del_np() below from being run while a new call to
393e48354ceSNicholas Bellinger 	 * iscsi_tpg_add_network_portal() for a matching iscsi_np is
394e48354ceSNicholas Bellinger 	 * active.  We don't need to hold np->np_thread_lock at this
395e48354ceSNicholas Bellinger 	 * point because iscsi_np has not been added to g_np_list yet.
396e48354ceSNicholas Bellinger 	 */
397e48354ceSNicholas Bellinger 	np->np_exports = 1;
398ee291e63SAndy Grover 	np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
399e48354ceSNicholas Bellinger 
400e48354ceSNicholas Bellinger 	list_add_tail(&np->np_list, &g_np_list);
401ee291e63SAndy Grover 	mutex_unlock(&np_lock);
402e48354ceSNicholas Bellinger 
40369d75574SAndy Grover 	pr_debug("CORE[0] - Added Network Portal: %pISpc on %s\n",
40469d75574SAndy Grover 		&np->np_sockaddr, np->np_transport->name);
405e48354ceSNicholas Bellinger 
406e48354ceSNicholas Bellinger 	return np;
407e48354ceSNicholas Bellinger }
408e48354ceSNicholas Bellinger 
409e48354ceSNicholas Bellinger int iscsit_reset_np_thread(
410e48354ceSNicholas Bellinger 	struct iscsi_np *np,
411e48354ceSNicholas Bellinger 	struct iscsi_tpg_np *tpg_np,
412a91eb7d9SNicholas Bellinger 	struct iscsi_portal_group *tpg,
413a91eb7d9SNicholas Bellinger 	bool shutdown)
414e48354ceSNicholas Bellinger {
415e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
416e48354ceSNicholas Bellinger 	if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) {
417e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
418e48354ceSNicholas Bellinger 		return 0;
419e48354ceSNicholas Bellinger 	}
420e48354ceSNicholas Bellinger 	np->np_thread_state = ISCSI_NP_THREAD_RESET;
421978d13d6SNicholas Bellinger 	atomic_inc(&np->np_reset_count);
422e48354ceSNicholas Bellinger 
423e48354ceSNicholas Bellinger 	if (np->np_thread) {
424e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
425e48354ceSNicholas Bellinger 		send_sig(SIGINT, np->np_thread, 1);
426e48354ceSNicholas Bellinger 		wait_for_completion(&np->np_restart_comp);
427e48354ceSNicholas Bellinger 		spin_lock_bh(&np->np_thread_lock);
428e48354ceSNicholas Bellinger 	}
429e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
430e48354ceSNicholas Bellinger 
431a91eb7d9SNicholas Bellinger 	if (tpg_np && shutdown) {
432a91eb7d9SNicholas Bellinger 		kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
433a91eb7d9SNicholas Bellinger 
434a91eb7d9SNicholas Bellinger 		wait_for_completion(&tpg_np->tpg_np_comp);
435a91eb7d9SNicholas Bellinger 	}
436a91eb7d9SNicholas Bellinger 
437e48354ceSNicholas Bellinger 	return 0;
438e48354ceSNicholas Bellinger }
439e48354ceSNicholas Bellinger 
440baa4d64bSNicholas Bellinger static void iscsit_free_np(struct iscsi_np *np)
441e48354ceSNicholas Bellinger {
442bf6932f4SAl Viro 	if (np->np_socket)
443e48354ceSNicholas Bellinger 		sock_release(np->np_socket);
444e48354ceSNicholas Bellinger }
445e48354ceSNicholas Bellinger 
446e48354ceSNicholas Bellinger int iscsit_del_np(struct iscsi_np *np)
447e48354ceSNicholas Bellinger {
448e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
449e48354ceSNicholas Bellinger 	np->np_exports--;
450e48354ceSNicholas Bellinger 	if (np->np_exports) {
4512363d196SNicholas Bellinger 		np->enabled = true;
452e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
453e48354ceSNicholas Bellinger 		return 0;
454e48354ceSNicholas Bellinger 	}
455e48354ceSNicholas Bellinger 	np->np_thread_state = ISCSI_NP_THREAD_SHUTDOWN;
456e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
457e48354ceSNicholas Bellinger 
458e48354ceSNicholas Bellinger 	if (np->np_thread) {
459e48354ceSNicholas Bellinger 		/*
460e48354ceSNicholas Bellinger 		 * We need to send the signal to wakeup Linux/Net
461e48354ceSNicholas Bellinger 		 * which may be sleeping in sock_accept()..
462e48354ceSNicholas Bellinger 		 */
463e48354ceSNicholas Bellinger 		send_sig(SIGINT, np->np_thread, 1);
464e48354ceSNicholas Bellinger 		kthread_stop(np->np_thread);
465db6077fdSNicholas Bellinger 		np->np_thread = NULL;
466e48354ceSNicholas Bellinger 	}
467baa4d64bSNicholas Bellinger 
468baa4d64bSNicholas Bellinger 	np->np_transport->iscsit_free_np(np);
469e48354ceSNicholas Bellinger 
470ee291e63SAndy Grover 	mutex_lock(&np_lock);
471e48354ceSNicholas Bellinger 	list_del(&np->np_list);
472ee291e63SAndy Grover 	mutex_unlock(&np_lock);
473e48354ceSNicholas Bellinger 
47469d75574SAndy Grover 	pr_debug("CORE[0] - Removed Network Portal: %pISpc on %s\n",
47569d75574SAndy Grover 		&np->np_sockaddr, np->np_transport->name);
476e48354ceSNicholas Bellinger 
477baa4d64bSNicholas Bellinger 	iscsit_put_transport(np->np_transport);
478e48354ceSNicholas Bellinger 	kfree(np);
479e48354ceSNicholas Bellinger 	return 0;
480e48354ceSNicholas Bellinger }
481e48354ceSNicholas Bellinger 
482e8205ccaSVarun Prakash static void iscsit_get_rx_pdu(struct iscsi_conn *);
4832ec5a8c1SNicholas Bellinger 
484d2faaefbSVarun Prakash int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
4852ec5a8c1SNicholas Bellinger {
486a4467018SNicholas Bellinger 	return iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
4872ec5a8c1SNicholas Bellinger }
488d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_queue_rsp);
4892ec5a8c1SNicholas Bellinger 
490d2faaefbSVarun Prakash void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
491131e6abcSNicholas Bellinger {
492131e6abcSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
493064cdd2dSNicholas Bellinger 	if (!list_empty(&cmd->i_conn_node) &&
494064cdd2dSNicholas Bellinger 	    !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
495131e6abcSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
496131e6abcSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
497131e6abcSNicholas Bellinger 
4984412a671SBart Van Assche 	__iscsit_free_cmd(cmd, true);
499131e6abcSNicholas Bellinger }
500d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_aborted_task);
501131e6abcSNicholas Bellinger 
5022854bb23SVarun Prakash static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *,
503e1dfb21fSBart Van Assche 				      u32, u32, const void *, void *);
5042854bb23SVarun Prakash static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *);
5052854bb23SVarun Prakash 
5062854bb23SVarun Prakash static int
5072854bb23SVarun Prakash iscsit_xmit_nondatain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
5082854bb23SVarun Prakash 			  const void *data_buf, u32 data_buf_len)
5092854bb23SVarun Prakash {
5102854bb23SVarun Prakash 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)cmd->pdu;
5112854bb23SVarun Prakash 	struct kvec *iov;
5122854bb23SVarun Prakash 	u32 niov = 0, tx_size = ISCSI_HDR_LEN;
5132854bb23SVarun Prakash 	int ret;
5142854bb23SVarun Prakash 
5152854bb23SVarun Prakash 	iov = &cmd->iov_misc[0];
5162854bb23SVarun Prakash 	iov[niov].iov_base	= cmd->pdu;
5172854bb23SVarun Prakash 	iov[niov++].iov_len	= ISCSI_HDR_LEN;
5182854bb23SVarun Prakash 
5192854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5202854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5212854bb23SVarun Prakash 
5222854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr,
5232854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
524e1dfb21fSBart Van Assche 					  header_digest);
5252854bb23SVarun Prakash 
5262854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
5272854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
5282854bb23SVarun Prakash 		pr_debug("Attaching CRC32C HeaderDigest"
5292854bb23SVarun Prakash 			 " to opcode 0x%x 0x%08x\n",
5302854bb23SVarun Prakash 			 hdr->opcode, *header_digest);
5312854bb23SVarun Prakash 	}
5322854bb23SVarun Prakash 
5332854bb23SVarun Prakash 	if (data_buf_len) {
5342854bb23SVarun Prakash 		u32 padding = ((-data_buf_len) & 3);
5352854bb23SVarun Prakash 
5362854bb23SVarun Prakash 		iov[niov].iov_base	= (void *)data_buf;
5372854bb23SVarun Prakash 		iov[niov++].iov_len	= data_buf_len;
5382854bb23SVarun Prakash 		tx_size += data_buf_len;
5392854bb23SVarun Prakash 
5402854bb23SVarun Prakash 		if (padding != 0) {
5412854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->pad_bytes;
5422854bb23SVarun Prakash 			iov[niov++].iov_len = padding;
5432854bb23SVarun Prakash 			tx_size += padding;
5442854bb23SVarun Prakash 			pr_debug("Attaching %u additional"
5452854bb23SVarun Prakash 				 " padding bytes.\n", padding);
5462854bb23SVarun Prakash 		}
5472854bb23SVarun Prakash 
5482854bb23SVarun Prakash 		if (conn->conn_ops->DataDigest) {
5492854bb23SVarun Prakash 			iscsit_do_crypto_hash_buf(conn->conn_tx_hash,
5502854bb23SVarun Prakash 						  data_buf, data_buf_len,
551e1dfb21fSBart Van Assche 						  padding, &cmd->pad_bytes,
552e1dfb21fSBart Van Assche 						  &cmd->data_crc);
5532854bb23SVarun Prakash 
5542854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->data_crc;
5552854bb23SVarun Prakash 			iov[niov++].iov_len = ISCSI_CRC_LEN;
5562854bb23SVarun Prakash 			tx_size += ISCSI_CRC_LEN;
5572854bb23SVarun Prakash 			pr_debug("Attached DataDigest for %u"
5582854bb23SVarun Prakash 				 " bytes opcode 0x%x, CRC 0x%08x\n",
5592854bb23SVarun Prakash 				 data_buf_len, hdr->opcode, cmd->data_crc);
5602854bb23SVarun Prakash 		}
5612854bb23SVarun Prakash 	}
5622854bb23SVarun Prakash 
5632854bb23SVarun Prakash 	cmd->iov_misc_count = niov;
5642854bb23SVarun Prakash 	cmd->tx_size = tx_size;
5652854bb23SVarun Prakash 
5662854bb23SVarun Prakash 	ret = iscsit_send_tx_data(cmd, conn, 1);
5672854bb23SVarun Prakash 	if (ret < 0) {
5682854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
5692854bb23SVarun Prakash 		return ret;
5702854bb23SVarun Prakash 	}
5712854bb23SVarun Prakash 
5722854bb23SVarun Prakash 	return 0;
5732854bb23SVarun Prakash }
5742854bb23SVarun Prakash 
5752854bb23SVarun Prakash static int iscsit_map_iovec(struct iscsi_cmd *, struct kvec *, u32, u32);
5762854bb23SVarun Prakash static void iscsit_unmap_iovec(struct iscsi_cmd *);
5772854bb23SVarun Prakash static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsi_cmd *,
5782854bb23SVarun Prakash 				    u32, u32, u32, u8 *);
5792854bb23SVarun Prakash static int
5802854bb23SVarun Prakash iscsit_xmit_datain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
5812854bb23SVarun Prakash 		       const struct iscsi_datain *datain)
5822854bb23SVarun Prakash {
5832854bb23SVarun Prakash 	struct kvec *iov;
5842854bb23SVarun Prakash 	u32 iov_count = 0, tx_size = 0;
5852854bb23SVarun Prakash 	int ret, iov_ret;
5862854bb23SVarun Prakash 
5872854bb23SVarun Prakash 	iov = &cmd->iov_data[0];
5882854bb23SVarun Prakash 	iov[iov_count].iov_base	= cmd->pdu;
5892854bb23SVarun Prakash 	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
5902854bb23SVarun Prakash 	tx_size += ISCSI_HDR_LEN;
5912854bb23SVarun Prakash 
5922854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5932854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5942854bb23SVarun Prakash 
5952854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu,
5962854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
597e1dfb21fSBart Van Assche 					  header_digest);
5982854bb23SVarun Prakash 
5992854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
6002854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
6012854bb23SVarun Prakash 
6022854bb23SVarun Prakash 		pr_debug("Attaching CRC32 HeaderDigest for DataIN PDU 0x%08x\n",
6032854bb23SVarun Prakash 			 *header_digest);
6042854bb23SVarun Prakash 	}
6052854bb23SVarun Prakash 
6062854bb23SVarun Prakash 	iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1],
6072854bb23SVarun Prakash 				   datain->offset, datain->length);
6082854bb23SVarun Prakash 	if (iov_ret < 0)
6092854bb23SVarun Prakash 		return -1;
6102854bb23SVarun Prakash 
6112854bb23SVarun Prakash 	iov_count += iov_ret;
6122854bb23SVarun Prakash 	tx_size += datain->length;
6132854bb23SVarun Prakash 
6142854bb23SVarun Prakash 	cmd->padding = ((-datain->length) & 3);
6152854bb23SVarun Prakash 	if (cmd->padding) {
6162854bb23SVarun Prakash 		iov[iov_count].iov_base		= cmd->pad_bytes;
6172854bb23SVarun Prakash 		iov[iov_count++].iov_len	= cmd->padding;
6182854bb23SVarun Prakash 		tx_size += cmd->padding;
6192854bb23SVarun Prakash 
6202854bb23SVarun Prakash 		pr_debug("Attaching %u padding bytes\n", cmd->padding);
6212854bb23SVarun Prakash 	}
6222854bb23SVarun Prakash 
6232854bb23SVarun Prakash 	if (conn->conn_ops->DataDigest) {
6242854bb23SVarun Prakash 		cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash,
6252854bb23SVarun Prakash 							 cmd, datain->offset,
6262854bb23SVarun Prakash 							 datain->length,
6272854bb23SVarun Prakash 							 cmd->padding,
6282854bb23SVarun Prakash 							 cmd->pad_bytes);
6292854bb23SVarun Prakash 
6302854bb23SVarun Prakash 		iov[iov_count].iov_base	= &cmd->data_crc;
6312854bb23SVarun Prakash 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
6322854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
6332854bb23SVarun Prakash 
6342854bb23SVarun Prakash 		pr_debug("Attached CRC32C DataDigest %d bytes, crc 0x%08x\n",
6352854bb23SVarun Prakash 			 datain->length + cmd->padding, cmd->data_crc);
6362854bb23SVarun Prakash 	}
6372854bb23SVarun Prakash 
6382854bb23SVarun Prakash 	cmd->iov_data_count = iov_count;
6392854bb23SVarun Prakash 	cmd->tx_size = tx_size;
6402854bb23SVarun Prakash 
6412854bb23SVarun Prakash 	ret = iscsit_fe_sendpage_sg(cmd, conn);
6422854bb23SVarun Prakash 
6432854bb23SVarun Prakash 	iscsit_unmap_iovec(cmd);
6442854bb23SVarun Prakash 
6452854bb23SVarun Prakash 	if (ret < 0) {
6462854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
6472854bb23SVarun Prakash 		return ret;
6482854bb23SVarun Prakash 	}
6492854bb23SVarun Prakash 
6502854bb23SVarun Prakash 	return 0;
6512854bb23SVarun Prakash }
6522854bb23SVarun Prakash 
6532854bb23SVarun Prakash static int iscsit_xmit_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
6542854bb23SVarun Prakash 			   struct iscsi_datain_req *dr, const void *buf,
6552854bb23SVarun Prakash 			   u32 buf_len)
6562854bb23SVarun Prakash {
6572854bb23SVarun Prakash 	if (dr)
6582854bb23SVarun Prakash 		return iscsit_xmit_datain_pdu(conn, cmd, buf);
6592854bb23SVarun Prakash 	else
6602854bb23SVarun Prakash 		return iscsit_xmit_nondatain_pdu(conn, cmd, buf, buf_len);
6612854bb23SVarun Prakash }
6622854bb23SVarun Prakash 
663e70beee7SNicholas Bellinger static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
664e70beee7SNicholas Bellinger {
665e70beee7SNicholas Bellinger 	return TARGET_PROT_NORMAL;
666e70beee7SNicholas Bellinger }
667e70beee7SNicholas Bellinger 
668baa4d64bSNicholas Bellinger static struct iscsit_transport iscsi_target_transport = {
669baa4d64bSNicholas Bellinger 	.name			= "iSCSI/TCP",
670baa4d64bSNicholas Bellinger 	.transport_type		= ISCSI_TCP,
671bd027d85SNicholas Bellinger 	.rdma_shutdown		= false,
672baa4d64bSNicholas Bellinger 	.owner			= NULL,
673baa4d64bSNicholas Bellinger 	.iscsit_setup_np	= iscsit_setup_np,
674baa4d64bSNicholas Bellinger 	.iscsit_accept_np	= iscsit_accept_np,
675baa4d64bSNicholas Bellinger 	.iscsit_free_np		= iscsit_free_np,
676baa4d64bSNicholas Bellinger 	.iscsit_get_login_rx	= iscsit_get_login_rx,
677baa4d64bSNicholas Bellinger 	.iscsit_put_login_tx	= iscsit_put_login_tx,
6783e1c81a9SNicholas Bellinger 	.iscsit_get_dataout	= iscsit_build_r2ts_for_cmd,
6792ec5a8c1SNicholas Bellinger 	.iscsit_immediate_queue	= iscsit_immediate_queue,
6802ec5a8c1SNicholas Bellinger 	.iscsit_response_queue	= iscsit_response_queue,
6812ec5a8c1SNicholas Bellinger 	.iscsit_queue_data_in	= iscsit_queue_rsp,
6822ec5a8c1SNicholas Bellinger 	.iscsit_queue_status	= iscsit_queue_rsp,
683131e6abcSNicholas Bellinger 	.iscsit_aborted_task	= iscsit_aborted_task,
6842854bb23SVarun Prakash 	.iscsit_xmit_pdu	= iscsit_xmit_pdu,
685e8205ccaSVarun Prakash 	.iscsit_get_rx_pdu	= iscsit_get_rx_pdu,
686e70beee7SNicholas Bellinger 	.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
687baa4d64bSNicholas Bellinger };
688baa4d64bSNicholas Bellinger 
689e48354ceSNicholas Bellinger static int __init iscsi_target_init_module(void)
690e48354ceSNicholas Bellinger {
69188dcd2daSNicholas Bellinger 	int ret = 0, size;
692e48354ceSNicholas Bellinger 
693e48354ceSNicholas Bellinger 	pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
6943829f381SMarkus Elfring 	iscsit_global = kzalloc(sizeof(*iscsit_global), GFP_KERNEL);
695c46e22f1SMarkus Elfring 	if (!iscsit_global)
696e48354ceSNicholas Bellinger 		return -1;
697c46e22f1SMarkus Elfring 
69888dcd2daSNicholas Bellinger 	spin_lock_init(&iscsit_global->ts_bitmap_lock);
699e48354ceSNicholas Bellinger 	mutex_init(&auth_id_lock);
700e48354ceSNicholas Bellinger 	spin_lock_init(&sess_idr_lock);
701e48354ceSNicholas Bellinger 	idr_init(&tiqn_idr);
702e48354ceSNicholas Bellinger 	idr_init(&sess_idr);
703e48354ceSNicholas Bellinger 
7049ac8928eSChristoph Hellwig 	ret = target_register_template(&iscsi_ops);
7059ac8928eSChristoph Hellwig 	if (ret)
706e48354ceSNicholas Bellinger 		goto out;
707e48354ceSNicholas Bellinger 
70888dcd2daSNicholas Bellinger 	size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
70988dcd2daSNicholas Bellinger 	iscsit_global->ts_bitmap = vzalloc(size);
710c46e22f1SMarkus Elfring 	if (!iscsit_global->ts_bitmap)
711e48354ceSNicholas Bellinger 		goto configfs_out;
712e48354ceSNicholas Bellinger 
713e48354ceSNicholas Bellinger 	lio_qr_cache = kmem_cache_create("lio_qr_cache",
714e48354ceSNicholas Bellinger 			sizeof(struct iscsi_queue_req),
715e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_queue_req), 0, NULL);
716e48354ceSNicholas Bellinger 	if (!lio_qr_cache) {
717e48354ceSNicholas Bellinger 		pr_err("nable to kmem_cache_create() for"
718e48354ceSNicholas Bellinger 				" lio_qr_cache\n");
71988dcd2daSNicholas Bellinger 		goto bitmap_out;
720e48354ceSNicholas Bellinger 	}
721e48354ceSNicholas Bellinger 
722e48354ceSNicholas Bellinger 	lio_dr_cache = kmem_cache_create("lio_dr_cache",
723e48354ceSNicholas Bellinger 			sizeof(struct iscsi_datain_req),
724e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_datain_req), 0, NULL);
725e48354ceSNicholas Bellinger 	if (!lio_dr_cache) {
726e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
727e48354ceSNicholas Bellinger 				" lio_dr_cache\n");
728e48354ceSNicholas Bellinger 		goto qr_out;
729e48354ceSNicholas Bellinger 	}
730e48354ceSNicholas Bellinger 
731e48354ceSNicholas Bellinger 	lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
732e48354ceSNicholas Bellinger 			sizeof(struct iscsi_ooo_cmdsn),
733e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_ooo_cmdsn), 0, NULL);
734e48354ceSNicholas Bellinger 	if (!lio_ooo_cache) {
735e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
736e48354ceSNicholas Bellinger 				" lio_ooo_cache\n");
737e48354ceSNicholas Bellinger 		goto dr_out;
738e48354ceSNicholas Bellinger 	}
739e48354ceSNicholas Bellinger 
740e48354ceSNicholas Bellinger 	lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
741e48354ceSNicholas Bellinger 			sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
742e48354ceSNicholas Bellinger 			0, NULL);
743e48354ceSNicholas Bellinger 	if (!lio_r2t_cache) {
744e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
745e48354ceSNicholas Bellinger 				" lio_r2t_cache\n");
746e48354ceSNicholas Bellinger 		goto ooo_out;
747e48354ceSNicholas Bellinger 	}
748e48354ceSNicholas Bellinger 
749baa4d64bSNicholas Bellinger 	iscsit_register_transport(&iscsi_target_transport);
750baa4d64bSNicholas Bellinger 
751e48354ceSNicholas Bellinger 	if (iscsit_load_discovery_tpg() < 0)
752e48354ceSNicholas Bellinger 		goto r2t_out;
753e48354ceSNicholas Bellinger 
754e48354ceSNicholas Bellinger 	return ret;
755e48354ceSNicholas Bellinger r2t_out:
7567f2c53bbSLino Sanfilippo 	iscsit_unregister_transport(&iscsi_target_transport);
757e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
758e48354ceSNicholas Bellinger ooo_out:
759e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
760e48354ceSNicholas Bellinger dr_out:
761e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
762e48354ceSNicholas Bellinger qr_out:
763e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
76488dcd2daSNicholas Bellinger bitmap_out:
76588dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
766e48354ceSNicholas Bellinger configfs_out:
7679ac8928eSChristoph Hellwig 	/* XXX: this probably wants it to be it's own unwind step.. */
7689ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7699ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
7709ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
771e48354ceSNicholas Bellinger out:
772e48354ceSNicholas Bellinger 	kfree(iscsit_global);
773e48354ceSNicholas Bellinger 	return -ENOMEM;
774e48354ceSNicholas Bellinger }
775e48354ceSNicholas Bellinger 
776e48354ceSNicholas Bellinger static void __exit iscsi_target_cleanup_module(void)
777e48354ceSNicholas Bellinger {
778e48354ceSNicholas Bellinger 	iscsit_release_discovery_tpg();
779baa4d64bSNicholas Bellinger 	iscsit_unregister_transport(&iscsi_target_transport);
780e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
781e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
782e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
783e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
784e48354ceSNicholas Bellinger 
7859ac8928eSChristoph Hellwig 	/*
7869ac8928eSChristoph Hellwig 	 * Shutdown discovery sessions and disable discovery TPG
7879ac8928eSChristoph Hellwig 	 */
7889ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7899ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
790e48354ceSNicholas Bellinger 
7919ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
792e48354ceSNicholas Bellinger 
79388dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
794e48354ceSNicholas Bellinger 	kfree(iscsit_global);
795e48354ceSNicholas Bellinger }
796e48354ceSNicholas Bellinger 
797d2faaefbSVarun Prakash int iscsit_add_reject(
798ba159914SNicholas Bellinger 	struct iscsi_conn *conn,
799e48354ceSNicholas Bellinger 	u8 reason,
800ba159914SNicholas Bellinger 	unsigned char *buf)
801e48354ceSNicholas Bellinger {
802e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
803e48354ceSNicholas Bellinger 
804676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
805e48354ceSNicholas Bellinger 	if (!cmd)
806e48354ceSNicholas Bellinger 		return -1;
807e48354ceSNicholas Bellinger 
808e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
809ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
810e48354ceSNicholas Bellinger 
8111c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
812e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
813e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
814aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
815e48354ceSNicholas Bellinger 		return -1;
816e48354ceSNicholas Bellinger 	}
817e48354ceSNicholas Bellinger 
818e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
8192fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
820e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
821e48354ceSNicholas Bellinger 
822e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
823e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
824e48354ceSNicholas Bellinger 
825e48354ceSNicholas Bellinger 	return -1;
826e48354ceSNicholas Bellinger }
827d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_add_reject);
828e48354ceSNicholas Bellinger 
829ba159914SNicholas Bellinger static int iscsit_add_reject_from_cmd(
830ba159914SNicholas Bellinger 	struct iscsi_cmd *cmd,
831e48354ceSNicholas Bellinger 	u8 reason,
832ba159914SNicholas Bellinger 	bool add_to_conn,
833ba159914SNicholas Bellinger 	unsigned char *buf)
834e48354ceSNicholas Bellinger {
835e48354ceSNicholas Bellinger 	struct iscsi_conn *conn;
836cfe2b621SBart Van Assche 	const bool do_put = cmd->se_cmd.se_tfo != NULL;
837e48354ceSNicholas Bellinger 
838e48354ceSNicholas Bellinger 	if (!cmd->conn) {
839e48354ceSNicholas Bellinger 		pr_err("cmd->conn is NULL for ITT: 0x%08x\n",
840e48354ceSNicholas Bellinger 				cmd->init_task_tag);
841e48354ceSNicholas Bellinger 		return -1;
842e48354ceSNicholas Bellinger 	}
843e48354ceSNicholas Bellinger 	conn = cmd->conn;
844e48354ceSNicholas Bellinger 
845e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
846ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
847e48354ceSNicholas Bellinger 
8481c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
849e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
850e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
851aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
852e48354ceSNicholas Bellinger 		return -1;
853e48354ceSNicholas Bellinger 	}
854e48354ceSNicholas Bellinger 
855e48354ceSNicholas Bellinger 	if (add_to_conn) {
856e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
8572fbb471eSAndy Grover 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
858e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
859e48354ceSNicholas Bellinger 	}
860e48354ceSNicholas Bellinger 
861e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
862e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
8633e1c81a9SNicholas Bellinger 	/*
8643e1c81a9SNicholas Bellinger 	 * Perform the kref_put now if se_cmd has already been setup by
8653e1c81a9SNicholas Bellinger 	 * scsit_setup_scsi_cmd()
8663e1c81a9SNicholas Bellinger 	 */
867cfe2b621SBart Van Assche 	if (do_put) {
8683e1c81a9SNicholas Bellinger 		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
869afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
8703e1c81a9SNicholas Bellinger 	}
871e48354ceSNicholas Bellinger 	return -1;
872e48354ceSNicholas Bellinger }
873ba159914SNicholas Bellinger 
874ba159914SNicholas Bellinger static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason,
875ba159914SNicholas Bellinger 				 unsigned char *buf)
876ba159914SNicholas Bellinger {
877ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, true, buf);
878ba159914SNicholas Bellinger }
879ba159914SNicholas Bellinger 
880ba159914SNicholas Bellinger int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf)
881ba159914SNicholas Bellinger {
882ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, false, buf);
883ba159914SNicholas Bellinger }
884d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_reject_cmd);
885e48354ceSNicholas Bellinger 
886e48354ceSNicholas Bellinger /*
887e48354ceSNicholas Bellinger  * Map some portion of the allocated scatterlist to an iovec, suitable for
888bfb79eacSAndy Grover  * kernel sockets to copy data in/out.
889e48354ceSNicholas Bellinger  */
890e48354ceSNicholas Bellinger static int iscsit_map_iovec(
891e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
892e48354ceSNicholas Bellinger 	struct kvec *iov,
893e48354ceSNicholas Bellinger 	u32 data_offset,
894e48354ceSNicholas Bellinger 	u32 data_length)
895e48354ceSNicholas Bellinger {
896e48354ceSNicholas Bellinger 	u32 i = 0;
897e48354ceSNicholas Bellinger 	struct scatterlist *sg;
898e48354ceSNicholas Bellinger 	unsigned int page_off;
899e48354ceSNicholas Bellinger 
900e48354ceSNicholas Bellinger 	/*
901bfb79eacSAndy Grover 	 * We know each entry in t_data_sg contains a page.
902e48354ceSNicholas Bellinger 	 */
9032b16509cSImran Haider 	u32 ent = data_offset / PAGE_SIZE;
9042b16509cSImran Haider 
9052b16509cSImran Haider 	if (ent >= cmd->se_cmd.t_data_nents) {
9062b16509cSImran Haider 		pr_err("Initial page entry out-of-bounds\n");
9072b16509cSImran Haider 		return -1;
9082b16509cSImran Haider 	}
9092b16509cSImran Haider 
9102b16509cSImran Haider 	sg = &cmd->se_cmd.t_data_sg[ent];
911e48354ceSNicholas Bellinger 	page_off = (data_offset % PAGE_SIZE);
912e48354ceSNicholas Bellinger 
913e48354ceSNicholas Bellinger 	cmd->first_data_sg = sg;
914e48354ceSNicholas Bellinger 	cmd->first_data_sg_off = page_off;
915e48354ceSNicholas Bellinger 
916e48354ceSNicholas Bellinger 	while (data_length) {
917e48354ceSNicholas Bellinger 		u32 cur_len = min_t(u32, data_length, sg->length - page_off);
918e48354ceSNicholas Bellinger 
919e48354ceSNicholas Bellinger 		iov[i].iov_base = kmap(sg_page(sg)) + sg->offset + page_off;
920e48354ceSNicholas Bellinger 		iov[i].iov_len = cur_len;
921e48354ceSNicholas Bellinger 
922e48354ceSNicholas Bellinger 		data_length -= cur_len;
923e48354ceSNicholas Bellinger 		page_off = 0;
924e48354ceSNicholas Bellinger 		sg = sg_next(sg);
925e48354ceSNicholas Bellinger 		i++;
926e48354ceSNicholas Bellinger 	}
927e48354ceSNicholas Bellinger 
928e48354ceSNicholas Bellinger 	cmd->kmapped_nents = i;
929e48354ceSNicholas Bellinger 
930e48354ceSNicholas Bellinger 	return i;
931e48354ceSNicholas Bellinger }
932e48354ceSNicholas Bellinger 
933e48354ceSNicholas Bellinger static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)
934e48354ceSNicholas Bellinger {
935e48354ceSNicholas Bellinger 	u32 i;
936e48354ceSNicholas Bellinger 	struct scatterlist *sg;
937e48354ceSNicholas Bellinger 
938e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
939e48354ceSNicholas Bellinger 
940e48354ceSNicholas Bellinger 	for (i = 0; i < cmd->kmapped_nents; i++)
941e48354ceSNicholas Bellinger 		kunmap(sg_page(&sg[i]));
942e48354ceSNicholas Bellinger }
943e48354ceSNicholas Bellinger 
944e48354ceSNicholas Bellinger static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
945e48354ceSNicholas Bellinger {
946f56cbbb4SNicholas Bellinger 	LIST_HEAD(ack_list);
947f56cbbb4SNicholas Bellinger 	struct iscsi_cmd *cmd, *cmd_p;
948e48354ceSNicholas Bellinger 
949e48354ceSNicholas Bellinger 	conn->exp_statsn = exp_statsn;
950e48354ceSNicholas Bellinger 
9513e1c81a9SNicholas Bellinger 	if (conn->sess->sess_ops->RDMAExtensions)
9523e1c81a9SNicholas Bellinger 		return;
9533e1c81a9SNicholas Bellinger 
954e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
955f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
956e48354ceSNicholas Bellinger 		spin_lock(&cmd->istate_lock);
957e48354ceSNicholas Bellinger 		if ((cmd->i_state == ISTATE_SENT_STATUS) &&
95864c13330SSteve Hodgson 		    iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
959e48354ceSNicholas Bellinger 			cmd->i_state = ISTATE_REMOVE;
960e48354ceSNicholas Bellinger 			spin_unlock(&cmd->istate_lock);
961f56cbbb4SNicholas Bellinger 			list_move_tail(&cmd->i_conn_node, &ack_list);
962e48354ceSNicholas Bellinger 			continue;
963e48354ceSNicholas Bellinger 		}
964e48354ceSNicholas Bellinger 		spin_unlock(&cmd->istate_lock);
965e48354ceSNicholas Bellinger 	}
966e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
967f56cbbb4SNicholas Bellinger 
968f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
9695159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
970f56cbbb4SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
971f56cbbb4SNicholas Bellinger 	}
972e48354ceSNicholas Bellinger }
973e48354ceSNicholas Bellinger 
974e48354ceSNicholas Bellinger static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
975e48354ceSNicholas Bellinger {
976f80e8ed3SNicholas Bellinger 	u32 iov_count = max(1UL, DIV_ROUND_UP(cmd->se_cmd.data_length, PAGE_SIZE));
977e48354ceSNicholas Bellinger 
978c0427f15SChristoph Hellwig 	iov_count += ISCSI_IOV_DATA_BUFFER;
979f1725110SMarkus Elfring 	cmd->iov_data = kcalloc(iov_count, sizeof(*cmd->iov_data), GFP_KERNEL);
980c46e22f1SMarkus Elfring 	if (!cmd->iov_data)
981e48354ceSNicholas Bellinger 		return -ENOMEM;
982e48354ceSNicholas Bellinger 
983e48354ceSNicholas Bellinger 	cmd->orig_iov_data_count = iov_count;
984e48354ceSNicholas Bellinger 	return 0;
985e48354ceSNicholas Bellinger }
986e48354ceSNicholas Bellinger 
9873e1c81a9SNicholas Bellinger int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
988e48354ceSNicholas Bellinger 			  unsigned char *buf)
989e48354ceSNicholas Bellinger {
9903e1c81a9SNicholas Bellinger 	int data_direction, payload_length;
991e48354ceSNicholas Bellinger 	struct iscsi_scsi_req *hdr;
992d28b1169SAndy Grover 	int iscsi_task_attr;
993d28b1169SAndy Grover 	int sam_task_attr;
994e48354ceSNicholas Bellinger 
99504f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->cmd_pdus);
996e48354ceSNicholas Bellinger 
997e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_scsi_req *) buf;
998e48354ceSNicholas Bellinger 	payload_length		= ntoh24(hdr->dlength);
999e48354ceSNicholas Bellinger 
1000e48354ceSNicholas Bellinger 	/* FIXME; Add checks for AdditionalHeaderSegment */
1001e48354ceSNicholas Bellinger 
1002e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_WRITE) &&
1003e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1004e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
1005e48354ceSNicholas Bellinger 				" not set. Bad iSCSI Initiator.\n");
1006ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1007ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1008e48354ceSNicholas Bellinger 	}
1009e48354ceSNicholas Bellinger 
1010e48354ceSNicholas Bellinger 	if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
1011e48354ceSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
1012e48354ceSNicholas Bellinger 		/*
10134454b66cSNicholas Bellinger 		 * From RFC-3720 Section 10.3.1:
10144454b66cSNicholas Bellinger 		 *
10154454b66cSNicholas Bellinger 		 * "Either or both of R and W MAY be 1 when either the
10164454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length and/or Bidirectional Read
10174454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length are 0"
10184454b66cSNicholas Bellinger 		 *
10194454b66cSNicholas Bellinger 		 * For this case, go ahead and clear the unnecssary bits
10204454b66cSNicholas Bellinger 		 * to avoid any confusion with ->data_direction.
1021e48354ceSNicholas Bellinger 		 */
1022e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_READ;
1023e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
1024e48354ceSNicholas Bellinger 
10254454b66cSNicholas Bellinger 		pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
1026e48354ceSNicholas Bellinger 			" set when Expected Data Transfer Length is 0 for"
10274454b66cSNicholas Bellinger 			" CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
1028e48354ceSNicholas Bellinger 	}
1029e48354ceSNicholas Bellinger 
1030e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
1031e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
1032e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
1033e48354ceSNicholas Bellinger 			" MUST be set if Expected Data Transfer Length is not 0."
1034e48354ceSNicholas Bellinger 			" Bad iSCSI Initiator\n");
1035ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1036ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1037e48354ceSNicholas Bellinger 	}
1038e48354ceSNicholas Bellinger 
1039e48354ceSNicholas Bellinger 	if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
1040e48354ceSNicholas Bellinger 	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
1041e48354ceSNicholas Bellinger 		pr_err("Bidirectional operations not supported!\n");
1042ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1043ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1044e48354ceSNicholas Bellinger 	}
1045e48354ceSNicholas Bellinger 
1046e48354ceSNicholas Bellinger 	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1047e48354ceSNicholas Bellinger 		pr_err("Illegally set Immediate Bit in iSCSI Initiator"
1048e48354ceSNicholas Bellinger 				" Scsi Command PDU.\n");
1049ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1050ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1051e48354ceSNicholas Bellinger 	}
1052e48354ceSNicholas Bellinger 
1053e48354ceSNicholas Bellinger 	if (payload_length && !conn->sess->sess_ops->ImmediateData) {
1054e48354ceSNicholas Bellinger 		pr_err("ImmediateData=No but DataSegmentLength=%u,"
1055e48354ceSNicholas Bellinger 			" protocol error.\n", payload_length);
1056ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1057ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1058e48354ceSNicholas Bellinger 	}
1059e48354ceSNicholas Bellinger 
106050e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->data_length) == payload_length) &&
1061e48354ceSNicholas Bellinger 	    (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
1062e48354ceSNicholas Bellinger 		pr_err("Expected Data Transfer Length and Length of"
1063e48354ceSNicholas Bellinger 			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
1064e48354ceSNicholas Bellinger 			" bit is not set protocol error\n");
1065ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1066ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1067e48354ceSNicholas Bellinger 	}
1068e48354ceSNicholas Bellinger 
106950e5c87dSChristoph Hellwig 	if (payload_length > be32_to_cpu(hdr->data_length)) {
1070e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1071e48354ceSNicholas Bellinger 			" EDTL: %u, protocol error.\n", payload_length,
1072e48354ceSNicholas Bellinger 				hdr->data_length);
1073ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1074ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1075e48354ceSNicholas Bellinger 	}
1076e48354ceSNicholas Bellinger 
107721f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1078e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
107921f5aa7eSNicholas Bellinger 			" MaxXmitDataSegmentLength: %u, protocol error.\n",
108021f5aa7eSNicholas Bellinger 			payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
1081ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1082ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1083e48354ceSNicholas Bellinger 	}
1084e48354ceSNicholas Bellinger 
1085e48354ceSNicholas Bellinger 	if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
1086e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1087e48354ceSNicholas Bellinger 			" FirstBurstLength: %u, protocol error.\n",
1088e48354ceSNicholas Bellinger 			payload_length, conn->sess->sess_ops->FirstBurstLength);
1089ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1090ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1091e48354ceSNicholas Bellinger 	}
1092e48354ceSNicholas Bellinger 
1093e48354ceSNicholas Bellinger 	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
1094e48354ceSNicholas Bellinger 			 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE :
1095e48354ceSNicholas Bellinger 			  DMA_NONE;
1096e48354ceSNicholas Bellinger 
1097d28b1169SAndy Grover 	cmd->data_direction = data_direction;
1098d28b1169SAndy Grover 	iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK;
1099d28b1169SAndy Grover 	/*
1100d28b1169SAndy Grover 	 * Figure out the SAM Task Attribute for the incoming SCSI CDB
1101d28b1169SAndy Grover 	 */
1102d28b1169SAndy Grover 	if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
1103d28b1169SAndy Grover 	    (iscsi_task_attr == ISCSI_ATTR_SIMPLE))
110468d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1105d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
110668d81f40SChristoph Hellwig 		sam_task_attr = TCM_ORDERED_TAG;
1107d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
110868d81f40SChristoph Hellwig 		sam_task_attr = TCM_HEAD_TAG;
1109d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ACA)
111068d81f40SChristoph Hellwig 		sam_task_attr = TCM_ACA_TAG;
1111d28b1169SAndy Grover 	else {
1112d28b1169SAndy Grover 		pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
111368d81f40SChristoph Hellwig 			" TCM_SIMPLE_TAG\n", iscsi_task_attr);
111468d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1115d28b1169SAndy Grover 	}
1116d28b1169SAndy Grover 
1117e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_CMD;
1118e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_NEW_CMD;
1119e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
1120e48354ceSNicholas Bellinger 	cmd->immediate_data	= (payload_length) ? 1 : 0;
1121e48354ceSNicholas Bellinger 	cmd->unsolicited_data	= ((!(hdr->flags & ISCSI_FLAG_CMD_FINAL) &&
1122e48354ceSNicholas Bellinger 				     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) ? 1 : 0);
1123e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data)
1124e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;
1125e48354ceSNicholas Bellinger 
1126e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
11279547308bSAlexei Potashnik 	if (hdr->flags & ISCSI_FLAG_CMD_READ)
1128c1e34b64SSagi Grimberg 		cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
11299547308bSAlexei Potashnik 	else
1130e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag = 0xFFFFFFFF;
113150e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
113250e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1133e48354ceSNicholas Bellinger 	cmd->first_burst_len	= payload_length;
1134e48354ceSNicholas Bellinger 
11353e1c81a9SNicholas Bellinger 	if (!conn->sess->sess_ops->RDMAExtensions &&
11363e1c81a9SNicholas Bellinger 	     cmd->data_direction == DMA_FROM_DEVICE) {
1137e48354ceSNicholas Bellinger 		struct iscsi_datain_req *dr;
1138e48354ceSNicholas Bellinger 
1139e48354ceSNicholas Bellinger 		dr = iscsit_allocate_datain_req();
1140e48354ceSNicholas Bellinger 		if (!dr)
1141ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1142ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1143e48354ceSNicholas Bellinger 
1144e48354ceSNicholas Bellinger 		iscsit_attach_datain_req(cmd, dr);
1145e48354ceSNicholas Bellinger 	}
1146e48354ceSNicholas Bellinger 
1147e48354ceSNicholas Bellinger 	/*
1148065ca1e4SAndy Grover 	 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
1149065ca1e4SAndy Grover 	 */
11509ac8928eSChristoph Hellwig 	transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
115150e5c87dSChristoph Hellwig 			conn->sess->se_sess, be32_to_cpu(hdr->data_length),
115250e5c87dSChristoph Hellwig 			cmd->data_direction, sam_task_attr,
115350e5c87dSChristoph Hellwig 			cmd->sense_buffer + 2);
1154065ca1e4SAndy Grover 
1155065ca1e4SAndy Grover 	pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
1156065ca1e4SAndy Grover 		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
11573e1c81a9SNicholas Bellinger 		hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
11583e1c81a9SNicholas Bellinger 		conn->cid);
11593e1c81a9SNicholas Bellinger 
1160afc16604SBart Van Assche 	target_get_sess_cmd(&cmd->se_cmd, true);
1161065ca1e4SAndy Grover 
1162de103c93SChristoph Hellwig 	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
11634f26998aSAndy Grover 						     scsilun_to_int(&hdr->lun));
1164de103c93SChristoph Hellwig 	if (cmd->sense_reason)
1165e48354ceSNicholas Bellinger 		goto attach_cmd;
1166a12f41f8SAndy Grover 
1167649ee054SBart Van Assche 	/* only used for printks or comparing with ->ref_task_tag */
1168649ee054SBart Van Assche 	cmd->se_cmd.tag = (__force u32)cmd->init_task_tag;
1169de103c93SChristoph Hellwig 	cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
1170de103c93SChristoph Hellwig 	if (cmd->sense_reason) {
1171de103c93SChristoph Hellwig 		if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
1172ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1173ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1174de103c93SChristoph Hellwig 		}
1175de103c93SChristoph Hellwig 
1176de103c93SChristoph Hellwig 		goto attach_cmd;
1177de103c93SChristoph Hellwig 	}
1178de103c93SChristoph Hellwig 
1179de103c93SChristoph Hellwig 	if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
1180ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1181ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1182e48354ceSNicholas Bellinger 	}
1183e48354ceSNicholas Bellinger 
1184e48354ceSNicholas Bellinger attach_cmd:
1185e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
11862fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1187e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
1188e48354ceSNicholas Bellinger 	/*
1189e48354ceSNicholas Bellinger 	 * Check if we need to delay processing because of ALUA
1190e48354ceSNicholas Bellinger 	 * Active/NonOptimized primary access state..
1191e48354ceSNicholas Bellinger 	 */
1192e48354ceSNicholas Bellinger 	core_alua_check_nonop_delay(&cmd->se_cmd);
1193bfb79eacSAndy Grover 
11943e1c81a9SNicholas Bellinger 	return 0;
1195de103c93SChristoph Hellwig }
11963e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_scsi_cmd);
1197de103c93SChristoph Hellwig 
11983e1c81a9SNicholas Bellinger void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *cmd)
11993e1c81a9SNicholas Bellinger {
12003e1c81a9SNicholas Bellinger 	iscsit_set_dataout_sequence_values(cmd);
12013e1c81a9SNicholas Bellinger 
12023e1c81a9SNicholas Bellinger 	spin_lock_bh(&cmd->dataout_timeout_lock);
12033e1c81a9SNicholas Bellinger 	iscsit_start_dataout_timer(cmd, cmd->conn);
12043e1c81a9SNicholas Bellinger 	spin_unlock_bh(&cmd->dataout_timeout_lock);
12053e1c81a9SNicholas Bellinger }
12063e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_set_unsoliticed_dataout);
12073e1c81a9SNicholas Bellinger 
12083e1c81a9SNicholas Bellinger int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
12093e1c81a9SNicholas Bellinger 			    struct iscsi_scsi_req *hdr)
12103e1c81a9SNicholas Bellinger {
12113e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0;
1212e48354ceSNicholas Bellinger 	/*
1213e48354ceSNicholas Bellinger 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
1214e48354ceSNicholas Bellinger 	 * the Immediate Bit is not set, and no Immediate
1215e48354ceSNicholas Bellinger 	 * Data is attached.
1216e48354ceSNicholas Bellinger 	 *
1217e48354ceSNicholas Bellinger 	 * A PDU/CmdSN carrying Immediate Data can only
1218e48354ceSNicholas Bellinger 	 * be processed after the DataCRC has passed.
1219e48354ceSNicholas Bellinger 	 * If the DataCRC fails, the CmdSN MUST NOT
1220e48354ceSNicholas Bellinger 	 * be acknowledged. (See below)
1221e48354ceSNicholas Bellinger 	 */
1222e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
1223561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1224561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
1225561bf158SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1226561bf158SNicholas Bellinger 			return -1;
1227561bf158SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1228afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
12293e1c81a9SNicholas Bellinger 			return 0;
12303e1c81a9SNicholas Bellinger 		}
1231e48354ceSNicholas Bellinger 	}
1232e48354ceSNicholas Bellinger 
123350e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1234e48354ceSNicholas Bellinger 
1235e48354ceSNicholas Bellinger 	/*
1236e48354ceSNicholas Bellinger 	 * If no Immediate Data is attached, it's OK to return now.
1237e48354ceSNicholas Bellinger 	 */
1238e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
12393e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason && cmd->unsolicited_data)
12403e1c81a9SNicholas Bellinger 			iscsit_set_unsoliticed_dataout(cmd);
12413e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason)
12423e1c81a9SNicholas Bellinger 			return 0;
1243e48354ceSNicholas Bellinger 
1244afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
1245e48354ceSNicholas Bellinger 		return 0;
1246e48354ceSNicholas Bellinger 	}
1247e48354ceSNicholas Bellinger 
1248e48354ceSNicholas Bellinger 	/*
12493e1c81a9SNicholas Bellinger 	 * Early CHECK_CONDITIONs with ImmediateData never make it to command
12503e1c81a9SNicholas Bellinger 	 * execution.  These exceptions are processed in CmdSN order using
12513e1c81a9SNicholas Bellinger 	 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
1252e48354ceSNicholas Bellinger 	 */
12538fa4011eSBart Van Assche 	if (cmd->sense_reason)
12543e1c81a9SNicholas Bellinger 		return 1;
1255e48354ceSNicholas Bellinger 	/*
1256e48354ceSNicholas Bellinger 	 * Call directly into transport_generic_new_cmd() to perform
1257e48354ceSNicholas Bellinger 	 * the backend memory allocation.
1258e48354ceSNicholas Bellinger 	 */
1259de103c93SChristoph Hellwig 	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
1260561bf158SNicholas Bellinger 	if (cmd->sense_reason)
12613e1c81a9SNicholas Bellinger 		return 1;
1262e48354ceSNicholas Bellinger 
12633e1c81a9SNicholas Bellinger 	return 0;
12643e1c81a9SNicholas Bellinger }
12653e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_scsi_cmd);
12663e1c81a9SNicholas Bellinger 
12673e1c81a9SNicholas Bellinger static int
12683e1c81a9SNicholas Bellinger iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
12693e1c81a9SNicholas Bellinger 			  bool dump_payload)
12703e1c81a9SNicholas Bellinger {
12713e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
12723e1c81a9SNicholas Bellinger 	/*
12733e1c81a9SNicholas Bellinger 	 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
12743e1c81a9SNicholas Bellinger 	 */
12750bcc297eSChristophe Vu-Brugier 	if (dump_payload)
12763e1c81a9SNicholas Bellinger 		goto after_immediate_data;
1277abb85a9bSNicholas Bellinger 	/*
1278abb85a9bSNicholas Bellinger 	 * Check for underflow case where both EDTL and immediate data payload
1279abb85a9bSNicholas Bellinger 	 * exceeds what is presented by CDB's TRANSFER LENGTH, and what has
1280abb85a9bSNicholas Bellinger 	 * already been set in target_cmd_size_check() as se_cmd->data_length.
1281abb85a9bSNicholas Bellinger 	 *
1282abb85a9bSNicholas Bellinger 	 * For this special case, fail the command and dump the immediate data
1283abb85a9bSNicholas Bellinger 	 * payload.
1284abb85a9bSNicholas Bellinger 	 */
1285abb85a9bSNicholas Bellinger 	if (cmd->first_burst_len > cmd->se_cmd.data_length) {
1286abb85a9bSNicholas Bellinger 		cmd->sense_reason = TCM_INVALID_CDB_FIELD;
1287abb85a9bSNicholas Bellinger 		goto after_immediate_data;
1288abb85a9bSNicholas Bellinger 	}
12893e1c81a9SNicholas Bellinger 
12903e1c81a9SNicholas Bellinger 	immed_ret = iscsit_handle_immediate_data(cmd, hdr,
12913e1c81a9SNicholas Bellinger 					cmd->first_burst_len);
1292e48354ceSNicholas Bellinger after_immediate_data:
1293e48354ceSNicholas Bellinger 	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) {
1294e48354ceSNicholas Bellinger 		/*
1295e48354ceSNicholas Bellinger 		 * A PDU/CmdSN carrying Immediate Data passed
1296e48354ceSNicholas Bellinger 		 * DataCRC, check against ExpCmdSN/MaxCmdSN if
1297e48354ceSNicholas Bellinger 		 * Immediate Bit is not set.
1298e48354ceSNicholas Bellinger 		 */
1299561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd,
1300561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
13019d86a2beSNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1302561bf158SNicholas Bellinger 			return -1;
1303e48354ceSNicholas Bellinger 
13049d86a2beSNicholas Bellinger 		if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1305561bf158SNicholas Bellinger 			int rc;
1306561bf158SNicholas Bellinger 
1307561bf158SNicholas Bellinger 			rc = iscsit_dump_data_payload(cmd->conn,
1308561bf158SNicholas Bellinger 						      cmd->first_burst_len, 1);
1309afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
1310561bf158SNicholas Bellinger 			return rc;
13113e1c81a9SNicholas Bellinger 		} else if (cmd->unsolicited_data)
13123e1c81a9SNicholas Bellinger 			iscsit_set_unsoliticed_dataout(cmd);
1313e48354ceSNicholas Bellinger 
1314e48354ceSNicholas Bellinger 	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
1315e48354ceSNicholas Bellinger 		/*
1316e48354ceSNicholas Bellinger 		 * Immediate Data failed DataCRC and ERL>=1,
1317e48354ceSNicholas Bellinger 		 * silently drop this PDU and let the initiator
1318e48354ceSNicholas Bellinger 		 * plug the CmdSN gap.
1319e48354ceSNicholas Bellinger 		 *
1320e48354ceSNicholas Bellinger 		 * FIXME: Send Unsolicited NOPIN with reserved
1321e48354ceSNicholas Bellinger 		 * TTT here to help the initiator figure out
1322e48354ceSNicholas Bellinger 		 * the missing CmdSN, although they should be
1323e48354ceSNicholas Bellinger 		 * intelligent enough to determine the missing
1324e48354ceSNicholas Bellinger 		 * CmdSN and issue a retry to plug the sequence.
1325e48354ceSNicholas Bellinger 		 */
1326e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_REMOVE;
13273e1c81a9SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, cmd->i_state);
1328e48354ceSNicholas Bellinger 	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */
1329e48354ceSNicholas Bellinger 		return -1;
1330e48354ceSNicholas Bellinger 
1331e48354ceSNicholas Bellinger 	return 0;
1332e48354ceSNicholas Bellinger }
1333e48354ceSNicholas Bellinger 
13343e1c81a9SNicholas Bellinger static int
13353e1c81a9SNicholas Bellinger iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
13363e1c81a9SNicholas Bellinger 			   unsigned char *buf)
13373e1c81a9SNicholas Bellinger {
13383e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
13393e1c81a9SNicholas Bellinger 	int rc, immed_data;
13403e1c81a9SNicholas Bellinger 	bool dump_payload = false;
13413e1c81a9SNicholas Bellinger 
13423e1c81a9SNicholas Bellinger 	rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
13433e1c81a9SNicholas Bellinger 	if (rc < 0)
1344561bf158SNicholas Bellinger 		return 0;
13453e1c81a9SNicholas Bellinger 	/*
13463e1c81a9SNicholas Bellinger 	 * Allocation iovecs needed for struct socket operations for
13473e1c81a9SNicholas Bellinger 	 * traditional iSCSI block I/O.
13483e1c81a9SNicholas Bellinger 	 */
13493e1c81a9SNicholas Bellinger 	if (iscsit_allocate_iovecs(cmd) < 0) {
1350b815fc12SMike Christie 		return iscsit_reject_cmd(cmd,
1351ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
13523e1c81a9SNicholas Bellinger 	}
13533e1c81a9SNicholas Bellinger 	immed_data = cmd->immediate_data;
13543e1c81a9SNicholas Bellinger 
13553e1c81a9SNicholas Bellinger 	rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
13563e1c81a9SNicholas Bellinger 	if (rc < 0)
13573e1c81a9SNicholas Bellinger 		return rc;
13583e1c81a9SNicholas Bellinger 	else if (rc > 0)
13593e1c81a9SNicholas Bellinger 		dump_payload = true;
13603e1c81a9SNicholas Bellinger 
13613e1c81a9SNicholas Bellinger 	if (!immed_data)
13623e1c81a9SNicholas Bellinger 		return 0;
13633e1c81a9SNicholas Bellinger 
13643e1c81a9SNicholas Bellinger 	return iscsit_get_immediate_data(cmd, hdr, dump_payload);
13653e1c81a9SNicholas Bellinger }
13663e1c81a9SNicholas Bellinger 
1367e48354ceSNicholas Bellinger static u32 iscsit_do_crypto_hash_sg(
136869110e3cSHerbert Xu 	struct ahash_request *hash,
1369e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
1370e48354ceSNicholas Bellinger 	u32 data_offset,
1371e48354ceSNicholas Bellinger 	u32 data_length,
1372e48354ceSNicholas Bellinger 	u32 padding,
1373e48354ceSNicholas Bellinger 	u8 *pad_bytes)
1374e48354ceSNicholas Bellinger {
1375e48354ceSNicholas Bellinger 	u32 data_crc;
1376e48354ceSNicholas Bellinger 	struct scatterlist *sg;
1377e48354ceSNicholas Bellinger 	unsigned int page_off;
1378e48354ceSNicholas Bellinger 
137969110e3cSHerbert Xu 	crypto_ahash_init(hash);
1380e48354ceSNicholas Bellinger 
1381e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
1382e48354ceSNicholas Bellinger 	page_off = cmd->first_data_sg_off;
1383e48354ceSNicholas Bellinger 
1384e48354ceSNicholas Bellinger 	while (data_length) {
1385aa75679cSAlexei Potashnik 		u32 cur_len = min_t(u32, data_length, (sg->length - page_off));
1386e48354ceSNicholas Bellinger 
138769110e3cSHerbert Xu 		ahash_request_set_crypt(hash, sg, NULL, cur_len);
138869110e3cSHerbert Xu 		crypto_ahash_update(hash);
1389e48354ceSNicholas Bellinger 
1390e48354ceSNicholas Bellinger 		data_length -= cur_len;
1391e48354ceSNicholas Bellinger 		page_off = 0;
1392aa75679cSAlexei Potashnik 		/* iscsit_map_iovec has already checked for invalid sg pointers */
1393aa75679cSAlexei Potashnik 		sg = sg_next(sg);
1394e48354ceSNicholas Bellinger 	}
1395e48354ceSNicholas Bellinger 
1396e48354ceSNicholas Bellinger 	if (padding) {
1397e48354ceSNicholas Bellinger 		struct scatterlist pad_sg;
1398e48354ceSNicholas Bellinger 
1399e48354ceSNicholas Bellinger 		sg_init_one(&pad_sg, pad_bytes, padding);
140069110e3cSHerbert Xu 		ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc,
140169110e3cSHerbert Xu 					padding);
140269110e3cSHerbert Xu 		crypto_ahash_finup(hash);
140369110e3cSHerbert Xu 	} else {
140469110e3cSHerbert Xu 		ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0);
140569110e3cSHerbert Xu 		crypto_ahash_final(hash);
1406e48354ceSNicholas Bellinger 	}
1407e48354ceSNicholas Bellinger 
1408e48354ceSNicholas Bellinger 	return data_crc;
1409e48354ceSNicholas Bellinger }
1410e48354ceSNicholas Bellinger 
1411e1dfb21fSBart Van Assche static void iscsit_do_crypto_hash_buf(struct ahash_request *hash,
1412e1dfb21fSBart Van Assche 	const void *buf, u32 payload_length, u32 padding,
1413e1dfb21fSBart Van Assche 	const void *pad_bytes, void *data_crc)
1414e48354ceSNicholas Bellinger {
141569110e3cSHerbert Xu 	struct scatterlist sg[2];
1416e48354ceSNicholas Bellinger 
141769110e3cSHerbert Xu 	sg_init_table(sg, ARRAY_SIZE(sg));
141869110e3cSHerbert Xu 	sg_set_buf(sg, buf, payload_length);
141969110e3cSHerbert Xu 	sg_set_buf(sg + 1, pad_bytes, padding);
1420e48354ceSNicholas Bellinger 
142169110e3cSHerbert Xu 	ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding);
1422e48354ceSNicholas Bellinger 
142369110e3cSHerbert Xu 	crypto_ahash_digest(hash);
1424e48354ceSNicholas Bellinger }
1425e48354ceSNicholas Bellinger 
14263e1c81a9SNicholas Bellinger int
14279a584bf9SVarun Prakash __iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
14289a584bf9SVarun Prakash 			   struct iscsi_cmd *cmd, u32 payload_length,
14299a584bf9SVarun Prakash 			   bool *success)
1430e48354ceSNicholas Bellinger {
14319a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
1432e48354ceSNicholas Bellinger 	struct se_cmd *se_cmd;
14333e1c81a9SNicholas Bellinger 	int rc;
1434e48354ceSNicholas Bellinger 
1435e48354ceSNicholas Bellinger 	/* iSCSI write */
143604f3b31bSNicholas Bellinger 	atomic_long_add(payload_length, &conn->sess->rx_data_octets);
1437e48354ceSNicholas Bellinger 
1438e48354ceSNicholas Bellinger 	pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
1439e48354ceSNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
14403e1c81a9SNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
1441e48354ceSNicholas Bellinger 		payload_length, conn->cid);
1442e48354ceSNicholas Bellinger 
1443e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
1444e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT after"
1445e48354ceSNicholas Bellinger 			" last DataOUT received, dumping payload\n",
1446e48354ceSNicholas Bellinger 			cmd->init_task_tag);
1447e48354ceSNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1448e48354ceSNicholas Bellinger 	}
1449e48354ceSNicholas Bellinger 
1450e48354ceSNicholas Bellinger 	if (cmd->data_direction != DMA_TO_DEVICE) {
1451e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT for a"
1452e48354ceSNicholas Bellinger 			" NON-WRITE command.\n", cmd->init_task_tag);
145397c99b47SNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1454e48354ceSNicholas Bellinger 	}
1455e48354ceSNicholas Bellinger 	se_cmd = &cmd->se_cmd;
1456e48354ceSNicholas Bellinger 	iscsit_mod_dataout_timer(cmd);
1457e48354ceSNicholas Bellinger 
145850e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->offset) + payload_length) > cmd->se_cmd.data_length) {
1459de3493aeSBart Van Assche 		pr_err("DataOut Offset: %u, Length %u greater than iSCSI Command EDTL %u, protocol error.\n",
1460de3493aeSBart Van Assche 		       be32_to_cpu(hdr->offset), payload_length,
1461de3493aeSBart Van Assche 		       cmd->se_cmd.data_length);
1462ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf);
1463e48354ceSNicholas Bellinger 	}
1464e48354ceSNicholas Bellinger 
1465e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data) {
1466e48354ceSNicholas Bellinger 		int dump_unsolicited_data = 0;
1467e48354ceSNicholas Bellinger 
1468e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->InitialR2T) {
1469e48354ceSNicholas Bellinger 			pr_err("Received unexpected unsolicited data"
1470e48354ceSNicholas Bellinger 				" while InitialR2T=Yes, protocol error.\n");
1471e48354ceSNicholas Bellinger 			transport_send_check_condition_and_sense(&cmd->se_cmd,
1472e48354ceSNicholas Bellinger 					TCM_UNEXPECTED_UNSOLICITED_DATA, 0);
1473e48354ceSNicholas Bellinger 			return -1;
1474e48354ceSNicholas Bellinger 		}
1475e48354ceSNicholas Bellinger 		/*
1476e48354ceSNicholas Bellinger 		 * Special case for dealing with Unsolicited DataOUT
1477e48354ceSNicholas Bellinger 		 * and Unsupported SAM WRITE Opcodes and SE resource allocation
1478e48354ceSNicholas Bellinger 		 * failures;
1479e48354ceSNicholas Bellinger 		 */
1480e48354ceSNicholas Bellinger 
1481e48354ceSNicholas Bellinger 		/* Something's amiss if we're not in WRITE_PENDING state... */
1482e48354ceSNicholas Bellinger 		WARN_ON(se_cmd->t_state != TRANSPORT_WRITE_PENDING);
1483de103c93SChristoph Hellwig 		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE))
1484e48354ceSNicholas Bellinger 			dump_unsolicited_data = 1;
1485e48354ceSNicholas Bellinger 
1486e48354ceSNicholas Bellinger 		if (dump_unsolicited_data) {
1487e48354ceSNicholas Bellinger 			/*
1488e48354ceSNicholas Bellinger 			 * Check if a delayed TASK_ABORTED status needs to
1489e48354ceSNicholas Bellinger 			 * be sent now if the ISCSI_FLAG_CMD_FINAL has been
14905a342521SBart Van Assche 			 * received with the unsolicited data out.
1491e48354ceSNicholas Bellinger 			 */
1492e48354ceSNicholas Bellinger 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
1493e48354ceSNicholas Bellinger 				iscsit_stop_dataout_timer(cmd);
1494e48354ceSNicholas Bellinger 
1495e48354ceSNicholas Bellinger 			transport_check_aborted_status(se_cmd,
1496e48354ceSNicholas Bellinger 					(hdr->flags & ISCSI_FLAG_CMD_FINAL));
1497e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1498e48354ceSNicholas Bellinger 		}
1499e48354ceSNicholas Bellinger 	} else {
1500e48354ceSNicholas Bellinger 		/*
1501e48354ceSNicholas Bellinger 		 * For the normal solicited data path:
1502e48354ceSNicholas Bellinger 		 *
1503e48354ceSNicholas Bellinger 		 * Check for a delayed TASK_ABORTED status and dump any
1504e48354ceSNicholas Bellinger 		 * incoming data out payload if one exists.  Also, when the
1505e48354ceSNicholas Bellinger 		 * ISCSI_FLAG_CMD_FINAL is set to denote the end of the current
1506e48354ceSNicholas Bellinger 		 * data out sequence, we decrement outstanding_r2ts.  Once
1507e48354ceSNicholas Bellinger 		 * outstanding_r2ts reaches zero, go ahead and send the delayed
1508e48354ceSNicholas Bellinger 		 * TASK_ABORTED status.
1509e48354ceSNicholas Bellinger 		 */
15107d680f3bSChristoph Hellwig 		if (se_cmd->transport_state & CMD_T_ABORTED) {
1511e48354ceSNicholas Bellinger 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
1512e48354ceSNicholas Bellinger 				if (--cmd->outstanding_r2ts < 1) {
1513e48354ceSNicholas Bellinger 					iscsit_stop_dataout_timer(cmd);
1514e48354ceSNicholas Bellinger 					transport_check_aborted_status(
1515e48354ceSNicholas Bellinger 							se_cmd, 1);
1516e48354ceSNicholas Bellinger 				}
1517e48354ceSNicholas Bellinger 
1518e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1519e48354ceSNicholas Bellinger 		}
1520e48354ceSNicholas Bellinger 	}
1521e48354ceSNicholas Bellinger 	/*
15220d5efb8aSBart Van Assche 	 * Perform DataSN, DataSequenceInOrder, DataPDUInOrder, and
1523e48354ceSNicholas Bellinger 	 * within-command recovery checks before receiving the payload.
1524e48354ceSNicholas Bellinger 	 */
15253e1c81a9SNicholas Bellinger 	rc = iscsit_check_pre_dataout(cmd, buf);
15263e1c81a9SNicholas Bellinger 	if (rc == DATAOUT_WITHIN_COMMAND_RECOVERY)
1527e48354ceSNicholas Bellinger 		return 0;
15283e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_CANNOT_RECOVER)
1529e48354ceSNicholas Bellinger 		return -1;
15309a584bf9SVarun Prakash 	*success = true;
15313e1c81a9SNicholas Bellinger 	return 0;
15323e1c81a9SNicholas Bellinger }
15339a584bf9SVarun Prakash EXPORT_SYMBOL(__iscsit_check_dataout_hdr);
15349a584bf9SVarun Prakash 
15359a584bf9SVarun Prakash int
15369a584bf9SVarun Prakash iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
15379a584bf9SVarun Prakash 			 struct iscsi_cmd **out_cmd)
15389a584bf9SVarun Prakash {
15399a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
15409a584bf9SVarun Prakash 	struct iscsi_cmd *cmd;
15419a584bf9SVarun Prakash 	u32 payload_length = ntoh24(hdr->dlength);
15429a584bf9SVarun Prakash 	int rc;
15439a584bf9SVarun Prakash 	bool success = false;
15449a584bf9SVarun Prakash 
15459a584bf9SVarun Prakash 	if (!payload_length) {
15469a584bf9SVarun Prakash 		pr_warn_ratelimited("DataOUT payload is ZERO, ignoring.\n");
15479a584bf9SVarun Prakash 		return 0;
15489a584bf9SVarun Prakash 	}
15499a584bf9SVarun Prakash 
15509a584bf9SVarun Prakash 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
15519a584bf9SVarun Prakash 		pr_err_ratelimited("DataSegmentLength: %u is greater than"
15529a584bf9SVarun Prakash 			" MaxXmitDataSegmentLength: %u\n", payload_length,
15539a584bf9SVarun Prakash 			conn->conn_ops->MaxXmitDataSegmentLength);
15549a584bf9SVarun Prakash 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf);
15559a584bf9SVarun Prakash 	}
15569a584bf9SVarun Prakash 
15579a584bf9SVarun Prakash 	cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, payload_length);
15589a584bf9SVarun Prakash 	if (!cmd)
15599a584bf9SVarun Prakash 		return 0;
15609a584bf9SVarun Prakash 
15619a584bf9SVarun Prakash 	rc = __iscsit_check_dataout_hdr(conn, buf, cmd, payload_length, &success);
15629a584bf9SVarun Prakash 
15639a584bf9SVarun Prakash 	if (success)
15649a584bf9SVarun Prakash 		*out_cmd = cmd;
15659a584bf9SVarun Prakash 
15669a584bf9SVarun Prakash 	return rc;
15679a584bf9SVarun Prakash }
15683e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_hdr);
15693e1c81a9SNicholas Bellinger 
15703e1c81a9SNicholas Bellinger static int
15713e1c81a9SNicholas Bellinger iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
15723e1c81a9SNicholas Bellinger 		   struct iscsi_data *hdr)
15733e1c81a9SNicholas Bellinger {
15743e1c81a9SNicholas Bellinger 	struct kvec *iov;
15753e1c81a9SNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0;
15763e1c81a9SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
15773e1c81a9SNicholas Bellinger 	int iov_ret, data_crc_failed = 0;
15783e1c81a9SNicholas Bellinger 
1579e48354ceSNicholas Bellinger 	rx_size += payload_length;
1580e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
1581e48354ceSNicholas Bellinger 
158250e5c87dSChristoph Hellwig 	iov_ret = iscsit_map_iovec(cmd, iov, be32_to_cpu(hdr->offset),
158350e5c87dSChristoph Hellwig 				   payload_length);
1584e48354ceSNicholas Bellinger 	if (iov_ret < 0)
1585e48354ceSNicholas Bellinger 		return -1;
1586e48354ceSNicholas Bellinger 
1587e48354ceSNicholas Bellinger 	iov_count += iov_ret;
1588e48354ceSNicholas Bellinger 
1589e48354ceSNicholas Bellinger 	padding = ((-payload_length) & 3);
1590e48354ceSNicholas Bellinger 	if (padding != 0) {
1591e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
1592e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
1593e48354ceSNicholas Bellinger 		rx_size += padding;
1594e48354ceSNicholas Bellinger 		pr_debug("Receiving %u padding bytes.\n", padding);
1595e48354ceSNicholas Bellinger 	}
1596e48354ceSNicholas Bellinger 
1597e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1598e48354ceSNicholas Bellinger 		iov[iov_count].iov_base = &checksum;
1599e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
1600e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
1601e48354ceSNicholas Bellinger 	}
1602e48354ceSNicholas Bellinger 
1603e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
1604e48354ceSNicholas Bellinger 
1605e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
1606e48354ceSNicholas Bellinger 
1607e48354ceSNicholas Bellinger 	if (rx_got != rx_size)
1608e48354ceSNicholas Bellinger 		return -1;
1609e48354ceSNicholas Bellinger 
1610e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1611e48354ceSNicholas Bellinger 		u32 data_crc;
1612e48354ceSNicholas Bellinger 
161369110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
161450e5c87dSChristoph Hellwig 						    be32_to_cpu(hdr->offset),
161550e5c87dSChristoph Hellwig 						    payload_length, padding,
1616e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
1617e48354ceSNicholas Bellinger 
1618e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
1619e48354ceSNicholas Bellinger 			pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
1620e48354ceSNicholas Bellinger 				" DataSN: 0x%08x, CRC32C DataDigest 0x%08x"
1621e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n",
1622e48354ceSNicholas Bellinger 				hdr->itt, hdr->offset, payload_length,
1623e48354ceSNicholas Bellinger 				hdr->datasn, checksum, data_crc);
1624e48354ceSNicholas Bellinger 			data_crc_failed = 1;
1625e48354ceSNicholas Bellinger 		} else {
1626e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
1627e48354ceSNicholas Bellinger 				" %u bytes of Data Out\n", checksum,
1628e48354ceSNicholas Bellinger 				payload_length);
1629e48354ceSNicholas Bellinger 		}
1630e48354ceSNicholas Bellinger 	}
16313e1c81a9SNicholas Bellinger 
16323e1c81a9SNicholas Bellinger 	return data_crc_failed;
16333e1c81a9SNicholas Bellinger }
16343e1c81a9SNicholas Bellinger 
16353e1c81a9SNicholas Bellinger int
16363e1c81a9SNicholas Bellinger iscsit_check_dataout_payload(struct iscsi_cmd *cmd, struct iscsi_data *hdr,
16373e1c81a9SNicholas Bellinger 			     bool data_crc_failed)
16383e1c81a9SNicholas Bellinger {
16393e1c81a9SNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
16403e1c81a9SNicholas Bellinger 	int rc, ooo_cmdsn;
1641e48354ceSNicholas Bellinger 	/*
1642e48354ceSNicholas Bellinger 	 * Increment post receive data and CRC values or perform
1643e48354ceSNicholas Bellinger 	 * within-command recovery.
1644e48354ceSNicholas Bellinger 	 */
16453e1c81a9SNicholas Bellinger 	rc = iscsit_check_post_dataout(cmd, (unsigned char *)hdr, data_crc_failed);
16463e1c81a9SNicholas Bellinger 	if ((rc == DATAOUT_NORMAL) || (rc == DATAOUT_WITHIN_COMMAND_RECOVERY))
1647e48354ceSNicholas Bellinger 		return 0;
16483e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_SEND_R2T) {
1649e48354ceSNicholas Bellinger 		iscsit_set_dataout_sequence_values(cmd);
16503e1c81a9SNicholas Bellinger 		conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
16513e1c81a9SNicholas Bellinger 	} else if (rc == DATAOUT_SEND_TO_TRANSPORT) {
1652e48354ceSNicholas Bellinger 		/*
1653e48354ceSNicholas Bellinger 		 * Handle extra special case for out of order
1654e48354ceSNicholas Bellinger 		 * Unsolicited Data Out.
1655e48354ceSNicholas Bellinger 		 */
1656e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
1657e48354ceSNicholas Bellinger 		ooo_cmdsn = (cmd->cmd_flags & ICF_OOO_CMDSN);
1658e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
1659e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
1660e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
1661e48354ceSNicholas Bellinger 
1662e48354ceSNicholas Bellinger 		iscsit_stop_dataout_timer(cmd);
166367441b68SChristoph Hellwig 		if (ooo_cmdsn)
166467441b68SChristoph Hellwig 			return 0;
166567441b68SChristoph Hellwig 		target_execute_cmd(&cmd->se_cmd);
166667441b68SChristoph Hellwig 		return 0;
1667e48354ceSNicholas Bellinger 	} else /* DATAOUT_CANNOT_RECOVER */
1668e48354ceSNicholas Bellinger 		return -1;
1669e48354ceSNicholas Bellinger 
1670e48354ceSNicholas Bellinger 	return 0;
1671e48354ceSNicholas Bellinger }
16723e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_payload);
1673e48354ceSNicholas Bellinger 
16743e1c81a9SNicholas Bellinger static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
16753e1c81a9SNicholas Bellinger {
1676dbcbc95cSNicholas Bellinger 	struct iscsi_cmd *cmd = NULL;
16773e1c81a9SNicholas Bellinger 	struct iscsi_data *hdr = (struct iscsi_data *)buf;
16783e1c81a9SNicholas Bellinger 	int rc;
16793e1c81a9SNicholas Bellinger 	bool data_crc_failed = false;
16803e1c81a9SNicholas Bellinger 
16813e1c81a9SNicholas Bellinger 	rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
16823e1c81a9SNicholas Bellinger 	if (rc < 0)
1683561bf158SNicholas Bellinger 		return 0;
16843e1c81a9SNicholas Bellinger 	else if (!cmd)
16853e1c81a9SNicholas Bellinger 		return 0;
16863e1c81a9SNicholas Bellinger 
16873e1c81a9SNicholas Bellinger 	rc = iscsit_get_dataout(conn, cmd, hdr);
16883e1c81a9SNicholas Bellinger 	if (rc < 0)
16893e1c81a9SNicholas Bellinger 		return rc;
16903e1c81a9SNicholas Bellinger 	else if (rc > 0)
16913e1c81a9SNicholas Bellinger 		data_crc_failed = true;
16923e1c81a9SNicholas Bellinger 
16933e1c81a9SNicholas Bellinger 	return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
16943e1c81a9SNicholas Bellinger }
16953e1c81a9SNicholas Bellinger 
1696778de368SNicholas Bellinger int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1697778de368SNicholas Bellinger 			 struct iscsi_nopout *hdr)
1698e48354ceSNicholas Bellinger {
1699778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1700e48354ceSNicholas Bellinger 
1701a3662605SArshad Hussain 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1702a3662605SArshad Hussain 		pr_err("NopOUT Flag's, Left Most Bit not set, protocol error.\n");
1703a3662605SArshad Hussain 		if (!cmd)
1704a3662605SArshad Hussain 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
1705a3662605SArshad Hussain 						 (unsigned char *)hdr);
1706a3662605SArshad Hussain 
1707a3662605SArshad Hussain 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1708a3662605SArshad Hussain 					 (unsigned char *)hdr);
1709a3662605SArshad Hussain 	}
1710a3662605SArshad Hussain 
171166c7db68SChristoph Hellwig 	if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1712e48354ceSNicholas Bellinger 		pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
1713e48354ceSNicholas Bellinger 			" not set, protocol error.\n");
171428aaa950SNicholas Bellinger 		if (!cmd)
171528aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
171628aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
171728aaa950SNicholas Bellinger 
1718ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1719ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1720e48354ceSNicholas Bellinger 	}
1721e48354ceSNicholas Bellinger 
172221f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1723e48354ceSNicholas Bellinger 		pr_err("NOPOUT Ping Data DataSegmentLength: %u is"
172421f5aa7eSNicholas Bellinger 			" greater than MaxXmitDataSegmentLength: %u, protocol"
1725e48354ceSNicholas Bellinger 			" error.\n", payload_length,
172621f5aa7eSNicholas Bellinger 			conn->conn_ops->MaxXmitDataSegmentLength);
172728aaa950SNicholas Bellinger 		if (!cmd)
172828aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
172928aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
173028aaa950SNicholas Bellinger 
1731ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1732ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1733e48354ceSNicholas Bellinger 	}
1734e48354ceSNicholas Bellinger 
17353e1c81a9SNicholas Bellinger 	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
1736e48354ceSNicholas Bellinger 		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
173766c7db68SChristoph Hellwig 		hdr->itt == RESERVED_ITT ? "Response" : "Request",
1738e48354ceSNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
1739e48354ceSNicholas Bellinger 		payload_length);
1740e48354ceSNicholas Bellinger 	/*
1741e48354ceSNicholas Bellinger 	 * This is not a response to a Unsolicited NopIN, which means
1742e48354ceSNicholas Bellinger 	 * it can either be a NOPOUT ping request (with a valid ITT),
1743e48354ceSNicholas Bellinger 	 * or a NOPOUT not requesting a NOPIN (with a reserved ITT).
1744e48354ceSNicholas Bellinger 	 * Either way, make sure we allocate an struct iscsi_cmd, as both
1745e48354ceSNicholas Bellinger 	 * can contain ping data.
1746e48354ceSNicholas Bellinger 	 */
174750e5c87dSChristoph Hellwig 	if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1748e48354ceSNicholas Bellinger 		cmd->iscsi_opcode	= ISCSI_OP_NOOP_OUT;
1749e48354ceSNicholas Bellinger 		cmd->i_state		= ISTATE_SEND_NOPIN;
1750e48354ceSNicholas Bellinger 		cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ?
1751e48354ceSNicholas Bellinger 						1 : 0);
1752e48354ceSNicholas Bellinger 		conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
1753e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag	= 0xFFFFFFFF;
175450e5c87dSChristoph Hellwig 		cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
175550e5c87dSChristoph Hellwig 		cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1756e48354ceSNicholas Bellinger 		cmd->data_direction	= DMA_NONE;
1757e48354ceSNicholas Bellinger 	}
1758e48354ceSNicholas Bellinger 
1759778de368SNicholas Bellinger 	return 0;
1760778de368SNicholas Bellinger }
1761778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_nop_out);
1762778de368SNicholas Bellinger 
1763778de368SNicholas Bellinger int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1764778de368SNicholas Bellinger 			   struct iscsi_nopout *hdr)
1765778de368SNicholas Bellinger {
1766778de368SNicholas Bellinger 	struct iscsi_cmd *cmd_p = NULL;
1767778de368SNicholas Bellinger 	int cmdsn_ret = 0;
1768778de368SNicholas Bellinger 	/*
1769778de368SNicholas Bellinger 	 * Initiator is expecting a NopIN ping reply..
1770778de368SNicholas Bellinger 	 */
1771778de368SNicholas Bellinger 	if (hdr->itt != RESERVED_ITT) {
17727cbfcc95SNicholas Bellinger 		if (!cmd)
17737cbfcc95SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
17747cbfcc95SNicholas Bellinger 						(unsigned char *)hdr);
1775778de368SNicholas Bellinger 
1776778de368SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
1777778de368SNicholas Bellinger 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1778778de368SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
1779778de368SNicholas Bellinger 
1780778de368SNicholas Bellinger 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1781778de368SNicholas Bellinger 
1782778de368SNicholas Bellinger 		if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1783778de368SNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
1784778de368SNicholas Bellinger 							 cmd->i_state);
1785778de368SNicholas Bellinger 			return 0;
1786778de368SNicholas Bellinger 		}
1787778de368SNicholas Bellinger 
1788561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1789561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
1790778de368SNicholas Bellinger                 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
1791778de368SNicholas Bellinger 			return 0;
1792778de368SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1793ba159914SNicholas Bellinger 			return -1;
1794778de368SNicholas Bellinger 
1795778de368SNicholas Bellinger 		return 0;
1796778de368SNicholas Bellinger 	}
1797778de368SNicholas Bellinger 	/*
1798778de368SNicholas Bellinger 	 * This was a response to a unsolicited NOPIN ping.
1799778de368SNicholas Bellinger 	 */
1800778de368SNicholas Bellinger 	if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
1801778de368SNicholas Bellinger 		cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
1802778de368SNicholas Bellinger 		if (!cmd_p)
1803778de368SNicholas Bellinger 			return -EINVAL;
1804778de368SNicholas Bellinger 
1805778de368SNicholas Bellinger 		iscsit_stop_nopin_response_timer(conn);
1806778de368SNicholas Bellinger 
1807778de368SNicholas Bellinger 		cmd_p->i_state = ISTATE_REMOVE;
1808778de368SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
1809778de368SNicholas Bellinger 
1810778de368SNicholas Bellinger 		iscsit_start_nopin_timer(conn);
1811778de368SNicholas Bellinger 		return 0;
1812778de368SNicholas Bellinger 	}
1813778de368SNicholas Bellinger 	/*
1814778de368SNicholas Bellinger 	 * Otherwise, initiator is not expecting a NOPIN is response.
1815778de368SNicholas Bellinger 	 * Just ignore for now.
1816778de368SNicholas Bellinger 	 */
18171a40f0a3SVarun Prakash 
18181a40f0a3SVarun Prakash 	if (cmd)
18191a40f0a3SVarun Prakash 		iscsit_free_cmd(cmd, false);
18201a40f0a3SVarun Prakash 
1821778de368SNicholas Bellinger         return 0;
1822778de368SNicholas Bellinger }
1823778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_nop_out);
1824778de368SNicholas Bellinger 
1825778de368SNicholas Bellinger static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1826778de368SNicholas Bellinger 				 unsigned char *buf)
1827778de368SNicholas Bellinger {
1828778de368SNicholas Bellinger 	unsigned char *ping_data = NULL;
1829778de368SNicholas Bellinger 	struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
1830778de368SNicholas Bellinger 	struct kvec *iov = NULL;
1831778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1832778de368SNicholas Bellinger 	int ret;
1833778de368SNicholas Bellinger 
1834778de368SNicholas Bellinger 	ret = iscsit_setup_nop_out(conn, cmd, hdr);
1835778de368SNicholas Bellinger 	if (ret < 0)
1836561bf158SNicholas Bellinger 		return 0;
1837778de368SNicholas Bellinger 	/*
1838778de368SNicholas Bellinger 	 * Handle NOP-OUT payload for traditional iSCSI sockets
1839778de368SNicholas Bellinger 	 */
184050e5c87dSChristoph Hellwig 	if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1841778de368SNicholas Bellinger 		u32 checksum, data_crc, padding = 0;
1842778de368SNicholas Bellinger 		int niov = 0, rx_got, rx_size = payload_length;
1843778de368SNicholas Bellinger 
1844e48354ceSNicholas Bellinger 		ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
1845e48354ceSNicholas Bellinger 		if (!ping_data) {
1846e48354ceSNicholas Bellinger 			ret = -1;
1847e48354ceSNicholas Bellinger 			goto out;
1848e48354ceSNicholas Bellinger 		}
1849e48354ceSNicholas Bellinger 
1850e48354ceSNicholas Bellinger 		iov = &cmd->iov_misc[0];
1851e48354ceSNicholas Bellinger 		iov[niov].iov_base	= ping_data;
1852e48354ceSNicholas Bellinger 		iov[niov++].iov_len	= payload_length;
1853e48354ceSNicholas Bellinger 
1854e48354ceSNicholas Bellinger 		padding = ((-payload_length) & 3);
1855e48354ceSNicholas Bellinger 		if (padding != 0) {
1856e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
1857e48354ceSNicholas Bellinger 				" for padding.\n", padding);
1858e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &cmd->pad_bytes;
1859e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= padding;
1860e48354ceSNicholas Bellinger 			rx_size += padding;
1861e48354ceSNicholas Bellinger 		}
1862e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1863e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
1864e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
1865e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
1866e48354ceSNicholas Bellinger 		}
1867e48354ceSNicholas Bellinger 
1868e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &cmd->iov_misc[0], niov, rx_size);
1869e48354ceSNicholas Bellinger 		if (rx_got != rx_size) {
1870e48354ceSNicholas Bellinger 			ret = -1;
1871e48354ceSNicholas Bellinger 			goto out;
1872e48354ceSNicholas Bellinger 		}
1873e48354ceSNicholas Bellinger 
1874e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1875e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data,
1876e1dfb21fSBart Van Assche 						  payload_length, padding,
1877e1dfb21fSBart Van Assche 						  cmd->pad_bytes, &data_crc);
1878e48354ceSNicholas Bellinger 
1879e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
1880e48354ceSNicholas Bellinger 				pr_err("Ping data CRC32C DataDigest"
1881e48354ceSNicholas Bellinger 				" 0x%08x does not match computed 0x%08x\n",
1882e48354ceSNicholas Bellinger 					checksum, data_crc);
1883e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
1884e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
1885e48354ceSNicholas Bellinger 					" NOPOUT Ping DataCRC failure while in"
1886e48354ceSNicholas Bellinger 						" ERL=0.\n");
1887e48354ceSNicholas Bellinger 					ret = -1;
1888e48354ceSNicholas Bellinger 					goto out;
1889e48354ceSNicholas Bellinger 				} else {
1890e48354ceSNicholas Bellinger 					/*
1891e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
1892e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
1893e48354ceSNicholas Bellinger 					 */
1894e48354ceSNicholas Bellinger 					pr_debug("Dropping NOPOUT"
1895e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
1896e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
1897e48354ceSNicholas Bellinger 					ret = 0;
1898e48354ceSNicholas Bellinger 					goto out;
1899e48354ceSNicholas Bellinger 				}
1900e48354ceSNicholas Bellinger 			} else {
1901e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
1902e48354ceSNicholas Bellinger 				" 0x%08x for %u bytes of ping data.\n",
1903e48354ceSNicholas Bellinger 					checksum, payload_length);
1904e48354ceSNicholas Bellinger 			}
1905e48354ceSNicholas Bellinger 		}
1906e48354ceSNicholas Bellinger 
1907e48354ceSNicholas Bellinger 		ping_data[payload_length] = '\0';
1908e48354ceSNicholas Bellinger 		/*
1909e48354ceSNicholas Bellinger 		 * Attach ping data to struct iscsi_cmd->buf_ptr.
1910e48354ceSNicholas Bellinger 		 */
19118359cf43SJörn Engel 		cmd->buf_ptr = ping_data;
1912e48354ceSNicholas Bellinger 		cmd->buf_ptr_size = payload_length;
1913e48354ceSNicholas Bellinger 
1914e48354ceSNicholas Bellinger 		pr_debug("Got %u bytes of NOPOUT ping"
1915e48354ceSNicholas Bellinger 			" data.\n", payload_length);
1916e48354ceSNicholas Bellinger 		pr_debug("Ping Data: \"%s\"\n", ping_data);
1917e48354ceSNicholas Bellinger 	}
1918e48354ceSNicholas Bellinger 
1919778de368SNicholas Bellinger 	return iscsit_process_nop_out(conn, cmd, hdr);
1920e48354ceSNicholas Bellinger out:
1921e48354ceSNicholas Bellinger 	if (cmd)
1922aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
1923778de368SNicholas Bellinger 
1924e48354ceSNicholas Bellinger 	kfree(ping_data);
1925e48354ceSNicholas Bellinger 	return ret;
1926e48354ceSNicholas Bellinger }
1927e48354ceSNicholas Bellinger 
1928e381fe9eSBart Van Assche static enum tcm_tmreq_table iscsit_convert_tmf(u8 iscsi_tmf)
1929e381fe9eSBart Van Assche {
1930e381fe9eSBart Van Assche 	switch (iscsi_tmf) {
1931e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK:
1932e381fe9eSBart Van Assche 		return TMR_ABORT_TASK;
1933e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
1934e381fe9eSBart Van Assche 		return TMR_ABORT_TASK_SET;
1935e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_ACA:
1936e381fe9eSBart Van Assche 		return TMR_CLEAR_ACA;
1937e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
1938e381fe9eSBart Van Assche 		return TMR_CLEAR_TASK_SET;
1939e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
1940e381fe9eSBart Van Assche 		return TMR_LUN_RESET;
1941e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
1942e381fe9eSBart Van Assche 		return TMR_TARGET_WARM_RESET;
1943e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
1944e381fe9eSBart Van Assche 		return TMR_TARGET_COLD_RESET;
1945e381fe9eSBart Van Assche 	default:
1946e381fe9eSBart Van Assche 		return TMR_UNKNOWN;
1947e381fe9eSBart Van Assche 	}
1948e381fe9eSBart Van Assche }
1949e381fe9eSBart Van Assche 
19503e1c81a9SNicholas Bellinger int
19513e1c81a9SNicholas Bellinger iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1952e48354ceSNicholas Bellinger 			   unsigned char *buf)
1953e48354ceSNicholas Bellinger {
1954e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr;
1955e48354ceSNicholas Bellinger 	struct iscsi_tmr_req *tmr_req;
1956e48354ceSNicholas Bellinger 	struct iscsi_tm *hdr;
1957186a9647SNicholas Bellinger 	int out_of_order_cmdsn = 0, ret;
195859b6986dSBart Van Assche 	u8 function, tcm_function = TMR_UNKNOWN;
1959e48354ceSNicholas Bellinger 
1960e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_tm *) buf;
1961e48354ceSNicholas Bellinger 	hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
1962e48354ceSNicholas Bellinger 	function = hdr->flags;
1963e48354ceSNicholas Bellinger 
1964e48354ceSNicholas Bellinger 	pr_debug("Got Task Management Request ITT: 0x%08x, CmdSN:"
1965e48354ceSNicholas Bellinger 		" 0x%08x, Function: 0x%02x, RefTaskTag: 0x%08x, RefCmdSN:"
1966e48354ceSNicholas Bellinger 		" 0x%08x, CID: %hu\n", hdr->itt, hdr->cmdsn, function,
1967e48354ceSNicholas Bellinger 		hdr->rtt, hdr->refcmdsn, conn->cid);
1968e48354ceSNicholas Bellinger 
1969e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
1970e48354ceSNicholas Bellinger 	    ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
197166c7db68SChristoph Hellwig 	     hdr->rtt != RESERVED_ITT)) {
1972e48354ceSNicholas Bellinger 		pr_err("RefTaskTag should be set to 0xFFFFFFFF.\n");
197366c7db68SChristoph Hellwig 		hdr->rtt = RESERVED_ITT;
1974e48354ceSNicholas Bellinger 	}
1975e48354ceSNicholas Bellinger 
1976e48354ceSNicholas Bellinger 	if ((function == ISCSI_TM_FUNC_TASK_REASSIGN) &&
1977e48354ceSNicholas Bellinger 			!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1978e48354ceSNicholas Bellinger 		pr_err("Task Management Request TASK_REASSIGN not"
1979e48354ceSNicholas Bellinger 			" issued as immediate command, bad iSCSI Initiator"
1980e48354ceSNicholas Bellinger 				"implementation\n");
1981ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1982ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1983e48354ceSNicholas Bellinger 	}
1984e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
198550e5c87dSChristoph Hellwig 	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
198650e5c87dSChristoph Hellwig 		hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
1987e48354ceSNicholas Bellinger 
1988d28b1169SAndy Grover 	cmd->data_direction = DMA_NONE;
19893829f381SMarkus Elfring 	cmd->tmr_req = kzalloc(sizeof(*cmd->tmr_req), GFP_KERNEL);
1990ae072726SNicholas Bellinger 	if (!cmd->tmr_req) {
1991ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1992d28b1169SAndy Grover 					     ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1993ba159914SNicholas Bellinger 					     buf);
1994ae072726SNicholas Bellinger 	}
1995ae072726SNicholas Bellinger 
1996ae072726SNicholas Bellinger 	transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
1997ae072726SNicholas Bellinger 			      conn->sess->se_sess, 0, DMA_NONE,
1998ae072726SNicholas Bellinger 			      TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
1999ae072726SNicholas Bellinger 
2000ae072726SNicholas Bellinger 	target_get_sess_cmd(&cmd->se_cmd, true);
2001d28b1169SAndy Grover 
2002d28b1169SAndy Grover 	/*
2003d28b1169SAndy Grover 	 * TASK_REASSIGN for ERL=2 / connection stays inside of
2004d28b1169SAndy Grover 	 * LIO-Target $FABRIC_MOD
2005d28b1169SAndy Grover 	 */
2006d28b1169SAndy Grover 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
2007e381fe9eSBart Van Assche 		tcm_function = iscsit_convert_tmf(function);
2008e381fe9eSBart Van Assche 		if (tcm_function == TMR_UNKNOWN) {
2009d28b1169SAndy Grover 			pr_err("Unknown iSCSI TMR Function:"
2010d28b1169SAndy Grover 			       " 0x%02x\n", function);
2011ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2012ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2013d28b1169SAndy Grover 		}
201459b6986dSBart Van Assche 	}
201559b6986dSBart Van Assche 	ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function,
201659b6986dSBart Van Assche 				 GFP_KERNEL);
2017d28b1169SAndy Grover 	if (ret < 0)
2018ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2019ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2020d28b1169SAndy Grover 
2021d28b1169SAndy Grover 	cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
2022d28b1169SAndy Grover 
2023e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_TMFUNC;
2024e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TASKMGTRSP;
2025e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2026e48354ceSNicholas Bellinger 	cmd->init_task_tag	= hdr->itt;
2027e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
202850e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
202950e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
2030e48354ceSNicholas Bellinger 	se_tmr			= cmd->se_cmd.se_tmr_req;
2031e48354ceSNicholas Bellinger 	tmr_req			= cmd->tmr_req;
2032e48354ceSNicholas Bellinger 	/*
2033e48354ceSNicholas Bellinger 	 * Locate the struct se_lun for all TMRs not related to ERL=2 TASK_REASSIGN
2034e48354ceSNicholas Bellinger 	 */
2035e48354ceSNicholas Bellinger 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
20364f26998aSAndy Grover 		ret = transport_lookup_tmr_lun(&cmd->se_cmd,
20374f26998aSAndy Grover 					       scsilun_to_int(&hdr->lun));
2038e48354ceSNicholas Bellinger 		if (ret < 0) {
2039e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_NO_LUN;
2040e48354ceSNicholas Bellinger 			goto attach;
2041e48354ceSNicholas Bellinger 		}
2042e48354ceSNicholas Bellinger 	}
2043e48354ceSNicholas Bellinger 
2044e48354ceSNicholas Bellinger 	switch (function) {
2045e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK:
2046e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_abort_task(cmd, buf);
2047de103c93SChristoph Hellwig 		if (se_tmr->response)
2048e48354ceSNicholas Bellinger 			goto attach;
2049e48354ceSNicholas Bellinger 		break;
2050e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
2051e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_ACA:
2052e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
2053e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
2054e48354ceSNicholas Bellinger 		break;
2055e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
2056e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) {
2057e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2058e48354ceSNicholas Bellinger 			goto attach;
2059e48354ceSNicholas Bellinger 		}
2060e48354ceSNicholas Bellinger 		break;
2061e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
2062e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) {
2063e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2064e48354ceSNicholas Bellinger 			goto attach;
2065e48354ceSNicholas Bellinger 		}
2066e48354ceSNicholas Bellinger 		break;
2067e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TASK_REASSIGN:
2068e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_task_reassign(cmd, buf);
2069e48354ceSNicholas Bellinger 		/*
2070e48354ceSNicholas Bellinger 		 * Perform sanity checks on the ExpDataSN only if the
2071e48354ceSNicholas Bellinger 		 * TASK_REASSIGN was successful.
2072e48354ceSNicholas Bellinger 		 */
2073de103c93SChristoph Hellwig 		if (se_tmr->response)
2074e48354ceSNicholas Bellinger 			break;
2075e48354ceSNicholas Bellinger 
2076e48354ceSNicholas Bellinger 		if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
2077ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2078ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_INVALID, buf);
2079e48354ceSNicholas Bellinger 		break;
2080e48354ceSNicholas Bellinger 	default:
2081e48354ceSNicholas Bellinger 		pr_err("Unknown TMR function: 0x%02x, protocol"
2082e48354ceSNicholas Bellinger 			" error.\n", function);
2083e48354ceSNicholas Bellinger 		se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED;
2084e48354ceSNicholas Bellinger 		goto attach;
2085e48354ceSNicholas Bellinger 	}
2086e48354ceSNicholas Bellinger 
2087e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
2088e48354ceSNicholas Bellinger 	    (se_tmr->response == ISCSI_TMF_RSP_COMPLETE))
2089e48354ceSNicholas Bellinger 		se_tmr->call_transport = 1;
2090e48354ceSNicholas Bellinger attach:
2091e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
20922fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2093e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2094e48354ceSNicholas Bellinger 
2095e48354ceSNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2096561bf158SNicholas Bellinger 		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
2097e48354ceSNicholas Bellinger 		if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
2098e48354ceSNicholas Bellinger 			out_of_order_cmdsn = 1;
20995a4c8666SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
2100e48354ceSNicholas Bellinger 			return 0;
21015a4c8666SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2102ba159914SNicholas Bellinger 			return -1;
2103e48354ceSNicholas Bellinger 	}
210450e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2105e48354ceSNicholas Bellinger 
21065a4c8666SNicholas Bellinger 	if (out_of_order_cmdsn || !(hdr->opcode & ISCSI_OP_IMMEDIATE))
2107e48354ceSNicholas Bellinger 		return 0;
2108e48354ceSNicholas Bellinger 	/*
2109e48354ceSNicholas Bellinger 	 * Found the referenced task, send to transport for processing.
2110e48354ceSNicholas Bellinger 	 */
2111e48354ceSNicholas Bellinger 	if (se_tmr->call_transport)
2112e48354ceSNicholas Bellinger 		return transport_generic_handle_tmr(&cmd->se_cmd);
2113e48354ceSNicholas Bellinger 
2114e48354ceSNicholas Bellinger 	/*
2115e48354ceSNicholas Bellinger 	 * Could not find the referenced LUN, task, or Task Management
2116e48354ceSNicholas Bellinger 	 * command not authorized or supported.  Change state and
2117e48354ceSNicholas Bellinger 	 * let the tx_thread send the response.
2118e48354ceSNicholas Bellinger 	 *
2119e48354ceSNicholas Bellinger 	 * For connection recovery, this is also the default action for
2120e48354ceSNicholas Bellinger 	 * TMR TASK_REASSIGN.
2121e48354ceSNicholas Bellinger 	 */
2122e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2123ae072726SNicholas Bellinger 	target_put_sess_cmd(&cmd->se_cmd);
2124e48354ceSNicholas Bellinger 	return 0;
2125e48354ceSNicholas Bellinger }
21263e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd);
2127e48354ceSNicholas Bellinger 
2128e48354ceSNicholas Bellinger /* #warning FIXME: Support Text Command parameters besides SendTargets */
212964534aa7SNicholas Bellinger int
213064534aa7SNicholas Bellinger iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
213164534aa7SNicholas Bellinger 		      struct iscsi_text *hdr)
2132e48354ceSNicholas Bellinger {
213364534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
2134e48354ceSNicholas Bellinger 
213521f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
2136e48354ceSNicholas Bellinger 		pr_err("Unable to accept text parameter length: %u"
213721f5aa7eSNicholas Bellinger 			"greater than MaxXmitDataSegmentLength %u.\n",
213821f5aa7eSNicholas Bellinger 		       payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
2139ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2140ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
2141e48354ceSNicholas Bellinger 	}
2142e48354ceSNicholas Bellinger 
2143122f8afcSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL) ||
2144122f8afcSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_TEXT_CONTINUE)) {
2145122f8afcSNicholas Bellinger 		pr_err("Multi sequence text commands currently not supported\n");
2146122f8afcSNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_CMD_NOT_SUPPORTED,
2147122f8afcSNicholas Bellinger 					(unsigned char *)hdr);
2148122f8afcSNicholas Bellinger 	}
2149122f8afcSNicholas Bellinger 
2150e48354ceSNicholas Bellinger 	pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
2151e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
2152e48354ceSNicholas Bellinger 		hdr->exp_statsn, payload_length);
2153e48354ceSNicholas Bellinger 
215464534aa7SNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_TEXT;
215564534aa7SNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TEXTRSP;
215664534aa7SNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
215764534aa7SNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
215864534aa7SNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
215964534aa7SNicholas Bellinger 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
216064534aa7SNicholas Bellinger 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
216164534aa7SNicholas Bellinger 	cmd->data_direction	= DMA_NONE;
2162ea8dc5b4SVarun Prakash 	kfree(cmd->text_in_ptr);
2163e4f4e801SSagi Grimberg 	cmd->text_in_ptr	= NULL;
216464534aa7SNicholas Bellinger 
216564534aa7SNicholas Bellinger 	return 0;
216664534aa7SNicholas Bellinger }
216764534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_text_cmd);
216864534aa7SNicholas Bellinger 
216964534aa7SNicholas Bellinger int
217064534aa7SNicholas Bellinger iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
217164534aa7SNicholas Bellinger 			struct iscsi_text *hdr)
217264534aa7SNicholas Bellinger {
21739864ca9dSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr;
217464534aa7SNicholas Bellinger 	int cmdsn_ret;
217564534aa7SNicholas Bellinger 
21769864ca9dSNicholas Bellinger 	if (!text_in) {
2177e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
2178e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
21799864ca9dSNicholas Bellinger 			pr_err("Unable to locate text_in buffer for sendtargets"
21809864ca9dSNicholas Bellinger 			       " discovery\n");
21819864ca9dSNicholas Bellinger 			goto reject;
21829864ca9dSNicholas Bellinger 		}
2183e4f4e801SSagi Grimberg 		goto empty_sendtargets;
2184e4f4e801SSagi Grimberg 	}
21859864ca9dSNicholas Bellinger 	if (strncmp("SendTargets", text_in, 11) != 0) {
21869864ca9dSNicholas Bellinger 		pr_err("Received Text Data that is not"
21879864ca9dSNicholas Bellinger 			" SendTargets, cannot continue.\n");
21889864ca9dSNicholas Bellinger 		goto reject;
21899864ca9dSNicholas Bellinger 	}
21909864ca9dSNicholas Bellinger 	text_ptr = strchr(text_in, '=');
21919864ca9dSNicholas Bellinger 	if (!text_ptr) {
21929864ca9dSNicholas Bellinger 		pr_err("No \"=\" separator found in Text Data,"
21939864ca9dSNicholas Bellinger 			"  cannot continue.\n");
21949864ca9dSNicholas Bellinger 		goto reject;
21959864ca9dSNicholas Bellinger 	}
21969864ca9dSNicholas Bellinger 	if (!strncmp("=All", text_ptr, 4)) {
21978060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_ALL;
21986665889cSNicholas Bellinger 	} else if (!strncmp("=iqn.", text_ptr, 5) ||
21996665889cSNicholas Bellinger 		   !strncmp("=eui.", text_ptr, 5)) {
22008060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_SINGLE;
22019864ca9dSNicholas Bellinger 	} else {
22029864ca9dSNicholas Bellinger 		pr_err("Unable to locate valid SendTargets=%s value\n", text_ptr);
22039864ca9dSNicholas Bellinger 		goto reject;
22049864ca9dSNicholas Bellinger 	}
22059864ca9dSNicholas Bellinger 
220664534aa7SNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
220764534aa7SNicholas Bellinger 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
220864534aa7SNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
220964534aa7SNicholas Bellinger 
2210e4f4e801SSagi Grimberg empty_sendtargets:
221164534aa7SNicholas Bellinger 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
221264534aa7SNicholas Bellinger 
221364534aa7SNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2214561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
2215561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
221664534aa7SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2217ba159914SNicholas Bellinger 			return -1;
2218ba159914SNicholas Bellinger 
221964534aa7SNicholas Bellinger 		return 0;
222064534aa7SNicholas Bellinger 	}
222164534aa7SNicholas Bellinger 
222264534aa7SNicholas Bellinger 	return iscsit_execute_cmd(cmd, 0);
22239864ca9dSNicholas Bellinger 
22249864ca9dSNicholas Bellinger reject:
2225ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2226ba159914SNicholas Bellinger 				 (unsigned char *)hdr);
222764534aa7SNicholas Bellinger }
222864534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_text_cmd);
222964534aa7SNicholas Bellinger 
223064534aa7SNicholas Bellinger static int
223164534aa7SNicholas Bellinger iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
223264534aa7SNicholas Bellinger 		       unsigned char *buf)
223364534aa7SNicholas Bellinger {
223464534aa7SNicholas Bellinger 	struct iscsi_text *hdr = (struct iscsi_text *)buf;
223564534aa7SNicholas Bellinger 	char *text_in = NULL;
223664534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
223764534aa7SNicholas Bellinger 	int rx_size, rc;
223864534aa7SNicholas Bellinger 
223964534aa7SNicholas Bellinger 	rc = iscsit_setup_text_cmd(conn, cmd, hdr);
224064534aa7SNicholas Bellinger 	if (rc < 0)
2241561bf158SNicholas Bellinger 		return 0;
224264534aa7SNicholas Bellinger 
224364534aa7SNicholas Bellinger 	rx_size = payload_length;
224464534aa7SNicholas Bellinger 	if (payload_length) {
224564534aa7SNicholas Bellinger 		u32 checksum = 0, data_crc = 0;
224664534aa7SNicholas Bellinger 		u32 padding = 0, pad_bytes = 0;
224764534aa7SNicholas Bellinger 		int niov = 0, rx_got;
224864534aa7SNicholas Bellinger 		struct kvec iov[3];
224964534aa7SNicholas Bellinger 
225064534aa7SNicholas Bellinger 		text_in = kzalloc(payload_length, GFP_KERNEL);
2251c46e22f1SMarkus Elfring 		if (!text_in)
225264534aa7SNicholas Bellinger 			goto reject;
2253c46e22f1SMarkus Elfring 
22549864ca9dSNicholas Bellinger 		cmd->text_in_ptr = text_in;
2255e48354ceSNicholas Bellinger 
2256e48354ceSNicholas Bellinger 		memset(iov, 0, 3 * sizeof(struct kvec));
2257e48354ceSNicholas Bellinger 		iov[niov].iov_base	= text_in;
225864534aa7SNicholas Bellinger 		iov[niov++].iov_len	= payload_length;
2259e48354ceSNicholas Bellinger 
2260e48354ceSNicholas Bellinger 		padding = ((-payload_length) & 3);
2261e48354ceSNicholas Bellinger 		if (padding != 0) {
226276f1928eSNicholas Bellinger 			iov[niov].iov_base = &pad_bytes;
2263e48354ceSNicholas Bellinger 			iov[niov++].iov_len  = padding;
2264e48354ceSNicholas Bellinger 			rx_size += padding;
2265e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
2266e48354ceSNicholas Bellinger 					" for padding.\n", padding);
2267e48354ceSNicholas Bellinger 		}
2268e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
2269e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
2270e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
2271e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
2272e48354ceSNicholas Bellinger 		}
2273e48354ceSNicholas Bellinger 
2274e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &iov[0], niov, rx_size);
227564534aa7SNicholas Bellinger 		if (rx_got != rx_size)
227664534aa7SNicholas Bellinger 			goto reject;
2277e48354ceSNicholas Bellinger 
2278e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
2279e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, text_in,
2280e1dfb21fSBart Van Assche 						  payload_length, padding,
2281e1dfb21fSBart Van Assche 						  &pad_bytes, &data_crc);
2282e48354ceSNicholas Bellinger 
2283e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
2284e48354ceSNicholas Bellinger 				pr_err("Text data CRC32C DataDigest"
2285e48354ceSNicholas Bellinger 					" 0x%08x does not match computed"
2286e48354ceSNicholas Bellinger 					" 0x%08x\n", checksum, data_crc);
2287e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2288e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
2289e48354ceSNicholas Bellinger 					" Text Data digest failure while in"
2290e48354ceSNicholas Bellinger 						" ERL=0.\n");
229164534aa7SNicholas Bellinger 					goto reject;
2292e48354ceSNicholas Bellinger 				} else {
2293e48354ceSNicholas Bellinger 					/*
2294e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
2295e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
2296e48354ceSNicholas Bellinger 					 */
2297e48354ceSNicholas Bellinger 					pr_debug("Dropping Text"
2298e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
2299e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
2300e48354ceSNicholas Bellinger 					kfree(text_in);
2301e48354ceSNicholas Bellinger 					return 0;
2302e48354ceSNicholas Bellinger 				}
2303e48354ceSNicholas Bellinger 			} else {
2304e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
2305e48354ceSNicholas Bellinger 					" 0x%08x for %u bytes of text data.\n",
230664534aa7SNicholas Bellinger 						checksum, payload_length);
2307e48354ceSNicholas Bellinger 			}
2308e48354ceSNicholas Bellinger 		}
230964534aa7SNicholas Bellinger 		text_in[payload_length - 1] = '\0';
2310e48354ceSNicholas Bellinger 		pr_debug("Successfully read %d bytes of text"
231164534aa7SNicholas Bellinger 				" data.\n", payload_length);
2312e48354ceSNicholas Bellinger 	}
2313e48354ceSNicholas Bellinger 
231464534aa7SNicholas Bellinger 	return iscsit_process_text_cmd(conn, cmd, hdr);
2315e48354ceSNicholas Bellinger 
231664534aa7SNicholas Bellinger reject:
23179864ca9dSNicholas Bellinger 	kfree(cmd->text_in_ptr);
23189864ca9dSNicholas Bellinger 	cmd->text_in_ptr = NULL;
2319ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
2320e48354ceSNicholas Bellinger }
2321e48354ceSNicholas Bellinger 
2322e48354ceSNicholas Bellinger int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2323e48354ceSNicholas Bellinger {
2324e48354ceSNicholas Bellinger 	struct iscsi_conn *conn_p;
2325e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2326e48354ceSNicholas Bellinger 
2327e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSESESSION on CID: %hu"
2328e48354ceSNicholas Bellinger 		" for SID: %u.\n", conn->cid, conn->sess->sid);
2329e48354ceSNicholas Bellinger 
2330e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
2331e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 1);
2332e48354ceSNicholas Bellinger 	conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2333e48354ceSNicholas Bellinger 
2334e48354ceSNicholas Bellinger 	iscsit_inc_conn_usage_count(conn);
2335e48354ceSNicholas Bellinger 	iscsit_inc_session_usage_count(sess);
2336e48354ceSNicholas Bellinger 
2337e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
2338e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &sess->sess_conn_list, conn_list) {
2339e48354ceSNicholas Bellinger 		if (conn_p->conn_state != TARG_CONN_STATE_LOGGED_IN)
2340e48354ceSNicholas Bellinger 			continue;
2341e48354ceSNicholas Bellinger 
2342e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2343e48354ceSNicholas Bellinger 		conn_p->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2344e48354ceSNicholas Bellinger 	}
2345e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
2346e48354ceSNicholas Bellinger 
2347e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2348e48354ceSNicholas Bellinger 
2349e48354ceSNicholas Bellinger 	return 0;
2350e48354ceSNicholas Bellinger }
2351e48354ceSNicholas Bellinger 
2352e48354ceSNicholas Bellinger int iscsit_logout_closeconnection(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2353e48354ceSNicholas Bellinger {
2354e48354ceSNicholas Bellinger 	struct iscsi_conn *l_conn;
2355e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2356e48354ceSNicholas Bellinger 
2357e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSECONNECTION for CID:"
2358e48354ceSNicholas Bellinger 		" %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2359e48354ceSNicholas Bellinger 
2360e48354ceSNicholas Bellinger 	/*
2361e48354ceSNicholas Bellinger 	 * A Logout Request with a CLOSECONNECTION reason code for a CID
2362e48354ceSNicholas Bellinger 	 * can arrive on a connection with a differing CID.
2363e48354ceSNicholas Bellinger 	 */
2364e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2365e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
2366e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2367e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2368e48354ceSNicholas Bellinger 
2369e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 1);
2370e48354ceSNicholas Bellinger 		conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_CONNECTION;
2371e48354ceSNicholas Bellinger 		iscsit_inc_conn_usage_count(conn);
2372e48354ceSNicholas Bellinger 
2373e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
2374e48354ceSNicholas Bellinger 	} else {
2375e48354ceSNicholas Bellinger 		/*
2376e48354ceSNicholas Bellinger 		 * Handle all different cid CLOSECONNECTION requests in
2377e48354ceSNicholas Bellinger 		 * iscsit_logout_post_handler_diffcid() as to give enough
2378e48354ceSNicholas Bellinger 		 * time for any non immediate command's CmdSN to be
2379e48354ceSNicholas Bellinger 		 * acknowledged on the connection in question.
2380e48354ceSNicholas Bellinger 		 *
2381e48354ceSNicholas Bellinger 		 * Here we simply make sure the CID is still around.
2382e48354ceSNicholas Bellinger 		 */
2383e48354ceSNicholas Bellinger 		l_conn = iscsit_get_conn_from_cid(sess,
2384e48354ceSNicholas Bellinger 				cmd->logout_cid);
2385e48354ceSNicholas Bellinger 		if (!l_conn) {
2386e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2387e48354ceSNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
2388e48354ceSNicholas Bellinger 					cmd->i_state);
2389e48354ceSNicholas Bellinger 			return 0;
2390e48354ceSNicholas Bellinger 		}
2391e48354ceSNicholas Bellinger 
2392e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(l_conn);
2393e48354ceSNicholas Bellinger 	}
2394e48354ceSNicholas Bellinger 
2395e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2396e48354ceSNicholas Bellinger 
2397e48354ceSNicholas Bellinger 	return 0;
2398e48354ceSNicholas Bellinger }
2399e48354ceSNicholas Bellinger 
2400e48354ceSNicholas Bellinger int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2401e48354ceSNicholas Bellinger {
2402e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2403e48354ceSNicholas Bellinger 
2404e48354ceSNicholas Bellinger 	pr_debug("Received explicit REMOVECONNFORRECOVERY logout for"
2405e48354ceSNicholas Bellinger 		" CID: %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2406e48354ceSNicholas Bellinger 
2407e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel != 2) {
2408e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2409e48354ceSNicholas Bellinger 			" while ERL!=2.\n");
2410e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED;
2411e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2412e48354ceSNicholas Bellinger 		return 0;
2413e48354ceSNicholas Bellinger 	}
2414e48354ceSNicholas Bellinger 
2415e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2416e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2417e48354ceSNicholas Bellinger 			" with CID: %hu on CID: %hu, implementation error.\n",
2418e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2419e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_CLEANUP_FAILED;
2420e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2421e48354ceSNicholas Bellinger 		return 0;
2422e48354ceSNicholas Bellinger 	}
2423e48354ceSNicholas Bellinger 
2424e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2425e48354ceSNicholas Bellinger 
2426e48354ceSNicholas Bellinger 	return 0;
2427e48354ceSNicholas Bellinger }
2428e48354ceSNicholas Bellinger 
24293e1c81a9SNicholas Bellinger int
24303e1c81a9SNicholas Bellinger iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2431e48354ceSNicholas Bellinger 			unsigned char *buf)
2432e48354ceSNicholas Bellinger {
2433e48354ceSNicholas Bellinger 	int cmdsn_ret, logout_remove = 0;
2434e48354ceSNicholas Bellinger 	u8 reason_code = 0;
2435e48354ceSNicholas Bellinger 	struct iscsi_logout *hdr;
2436e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn);
2437e48354ceSNicholas Bellinger 
2438e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_logout *) buf;
2439e48354ceSNicholas Bellinger 	reason_code		= (hdr->flags & 0x7f);
2440e48354ceSNicholas Bellinger 
2441e48354ceSNicholas Bellinger 	if (tiqn) {
2442e48354ceSNicholas Bellinger 		spin_lock(&tiqn->logout_stats.lock);
2443e48354ceSNicholas Bellinger 		if (reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION)
2444e48354ceSNicholas Bellinger 			tiqn->logout_stats.normal_logouts++;
2445e48354ceSNicholas Bellinger 		else
2446e48354ceSNicholas Bellinger 			tiqn->logout_stats.abnormal_logouts++;
2447e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->logout_stats.lock);
2448e48354ceSNicholas Bellinger 	}
2449e48354ceSNicholas Bellinger 
2450e48354ceSNicholas Bellinger 	pr_debug("Got Logout Request ITT: 0x%08x CmdSN: 0x%08x"
2451e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x Reason: 0x%02x CID: %hu on CID: %hu\n",
2452e48354ceSNicholas Bellinger 		hdr->itt, hdr->cmdsn, hdr->exp_statsn, reason_code,
2453e48354ceSNicholas Bellinger 		hdr->cid, conn->cid);
2454e48354ceSNicholas Bellinger 
2455e48354ceSNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
2456e48354ceSNicholas Bellinger 		pr_err("Received logout request on connection that"
2457e48354ceSNicholas Bellinger 			" is not in logged in state, ignoring request.\n");
2458aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
2459e48354ceSNicholas Bellinger 		return 0;
2460e48354ceSNicholas Bellinger 	}
2461e48354ceSNicholas Bellinger 
2462e48354ceSNicholas Bellinger 	cmd->iscsi_opcode       = ISCSI_OP_LOGOUT;
2463e48354ceSNicholas Bellinger 	cmd->i_state            = ISTATE_SEND_LOGOUTRSP;
2464e48354ceSNicholas Bellinger 	cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2465e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
2466e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag      = 0xFFFFFFFF;
246750e5c87dSChristoph Hellwig 	cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
246850e5c87dSChristoph Hellwig 	cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
246950e5c87dSChristoph Hellwig 	cmd->logout_cid         = be16_to_cpu(hdr->cid);
2470e48354ceSNicholas Bellinger 	cmd->logout_reason      = reason_code;
2471e48354ceSNicholas Bellinger 	cmd->data_direction     = DMA_NONE;
2472e48354ceSNicholas Bellinger 
2473e48354ceSNicholas Bellinger 	/*
2474e48354ceSNicholas Bellinger 	 * We need to sleep in these cases (by returning 1) until the Logout
2475e48354ceSNicholas Bellinger 	 * Response gets sent in the tx thread.
2476e48354ceSNicholas Bellinger 	 */
2477e48354ceSNicholas Bellinger 	if ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION) ||
2478e48354ceSNicholas Bellinger 	   ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) &&
247950e5c87dSChristoph Hellwig 	    be16_to_cpu(hdr->cid) == conn->cid))
2480e48354ceSNicholas Bellinger 		logout_remove = 1;
2481e48354ceSNicholas Bellinger 
2482e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
24832fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2484e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2485e48354ceSNicholas Bellinger 
2486e48354ceSNicholas Bellinger 	if (reason_code != ISCSI_LOGOUT_REASON_RECOVERY)
248750e5c87dSChristoph Hellwig 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2488e48354ceSNicholas Bellinger 
2489e48354ceSNicholas Bellinger 	/*
2490e48354ceSNicholas Bellinger 	 * Immediate commands are executed, well, immediately.
2491e48354ceSNicholas Bellinger 	 * Non-Immediate Logout Commands are executed in CmdSN order.
2492e48354ceSNicholas Bellinger 	 */
2493c6037cc5SAndy Grover 	if (cmd->immediate_cmd) {
2494e48354ceSNicholas Bellinger 		int ret = iscsit_execute_cmd(cmd, 0);
2495e48354ceSNicholas Bellinger 
2496e48354ceSNicholas Bellinger 		if (ret < 0)
2497e48354ceSNicholas Bellinger 			return ret;
2498e48354ceSNicholas Bellinger 	} else {
2499561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
2500ba159914SNicholas Bellinger 		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
2501e48354ceSNicholas Bellinger 			logout_remove = 0;
2502ba159914SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2503ba159914SNicholas Bellinger 			return -1;
2504e48354ceSNicholas Bellinger 	}
2505e48354ceSNicholas Bellinger 
2506e48354ceSNicholas Bellinger 	return logout_remove;
2507e48354ceSNicholas Bellinger }
25083e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_logout_cmd);
2509e48354ceSNicholas Bellinger 
2510d2faaefbSVarun Prakash int iscsit_handle_snack(
2511e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
2512e48354ceSNicholas Bellinger 	unsigned char *buf)
2513e48354ceSNicholas Bellinger {
2514e48354ceSNicholas Bellinger 	struct iscsi_snack *hdr;
2515e48354ceSNicholas Bellinger 
2516e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_snack *) buf;
2517e48354ceSNicholas Bellinger 	hdr->flags		&= ~ISCSI_FLAG_CMD_FINAL;
2518e48354ceSNicholas Bellinger 
2519e48354ceSNicholas Bellinger 	pr_debug("Got ISCSI_INIT_SNACK, ITT: 0x%08x, ExpStatSN:"
2520e48354ceSNicholas Bellinger 		" 0x%08x, Type: 0x%02x, BegRun: 0x%08x, RunLength: 0x%08x,"
2521e48354ceSNicholas Bellinger 		" CID: %hu\n", hdr->itt, hdr->exp_statsn, hdr->flags,
2522e48354ceSNicholas Bellinger 			hdr->begrun, hdr->runlength, conn->cid);
2523e48354ceSNicholas Bellinger 
2524e48354ceSNicholas Bellinger 	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2525e48354ceSNicholas Bellinger 		pr_err("Initiator sent SNACK request while in"
2526e48354ceSNicholas Bellinger 			" ErrorRecoveryLevel=0.\n");
2527ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2528ba159914SNicholas Bellinger 					 buf);
2529e48354ceSNicholas Bellinger 	}
2530e48354ceSNicholas Bellinger 	/*
2531e48354ceSNicholas Bellinger 	 * SNACK_DATA and SNACK_R2T are both 0,  so check which function to
2532e48354ceSNicholas Bellinger 	 * call from inside iscsi_send_recovery_datain_or_r2t().
2533e48354ceSNicholas Bellinger 	 */
2534e48354ceSNicholas Bellinger 	switch (hdr->flags & ISCSI_FLAG_SNACK_TYPE_MASK) {
2535e48354ceSNicholas Bellinger 	case 0:
2536e48354ceSNicholas Bellinger 		return iscsit_handle_recovery_datain_or_r2t(conn, buf,
253750e5c87dSChristoph Hellwig 			hdr->itt,
253850e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
253950e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
254050e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2541e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_STATUS:
254250e5c87dSChristoph Hellwig 		return iscsit_handle_status_snack(conn, hdr->itt,
254350e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
254450e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun), be32_to_cpu(hdr->runlength));
2545e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_DATA_ACK:
254650e5c87dSChristoph Hellwig 		return iscsit_handle_data_ack(conn, be32_to_cpu(hdr->ttt),
254750e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
254850e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2549e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_RDATA:
2550e48354ceSNicholas Bellinger 		/* FIXME: Support R-Data SNACK */
2551e48354ceSNicholas Bellinger 		pr_err("R-Data SNACK Not Supported.\n");
2552ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2553ba159914SNicholas Bellinger 					 buf);
2554e48354ceSNicholas Bellinger 	default:
2555e48354ceSNicholas Bellinger 		pr_err("Unknown SNACK type 0x%02x, protocol"
2556e48354ceSNicholas Bellinger 			" error.\n", hdr->flags & 0x0f);
2557ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2558ba159914SNicholas Bellinger 					 buf);
2559e48354ceSNicholas Bellinger 	}
2560e48354ceSNicholas Bellinger 
2561e48354ceSNicholas Bellinger 	return 0;
2562e48354ceSNicholas Bellinger }
2563d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_handle_snack);
2564e48354ceSNicholas Bellinger 
2565e48354ceSNicholas Bellinger static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn)
2566e48354ceSNicholas Bellinger {
2567e48354ceSNicholas Bellinger 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
2568e48354ceSNicholas Bellinger 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
2569e48354ceSNicholas Bellinger 		wait_for_completion_interruptible_timeout(
2570e48354ceSNicholas Bellinger 					&conn->rx_half_close_comp,
2571e48354ceSNicholas Bellinger 					ISCSI_RX_THREAD_TCP_TIMEOUT * HZ);
2572e48354ceSNicholas Bellinger 	}
2573e48354ceSNicholas Bellinger }
2574e48354ceSNicholas Bellinger 
2575e48354ceSNicholas Bellinger static int iscsit_handle_immediate_data(
2576e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
25773e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr,
2578e48354ceSNicholas Bellinger 	u32 length)
2579e48354ceSNicholas Bellinger {
2580e48354ceSNicholas Bellinger 	int iov_ret, rx_got = 0, rx_size = 0;
2581e48354ceSNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0;
2582e48354ceSNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
2583e48354ceSNicholas Bellinger 	struct kvec *iov;
2584e48354ceSNicholas Bellinger 
2585e48354ceSNicholas Bellinger 	iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, cmd->write_data_done, length);
2586e48354ceSNicholas Bellinger 	if (iov_ret < 0)
2587e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2588e48354ceSNicholas Bellinger 
2589e48354ceSNicholas Bellinger 	rx_size = length;
2590e48354ceSNicholas Bellinger 	iov_count = iov_ret;
2591e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
2592e48354ceSNicholas Bellinger 
2593e48354ceSNicholas Bellinger 	padding = ((-length) & 3);
2594e48354ceSNicholas Bellinger 	if (padding != 0) {
2595e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
2596e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
2597e48354ceSNicholas Bellinger 		rx_size += padding;
2598e48354ceSNicholas Bellinger 	}
2599e48354ceSNicholas Bellinger 
2600e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2601e48354ceSNicholas Bellinger 		iov[iov_count].iov_base		= &checksum;
2602e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len	= ISCSI_CRC_LEN;
2603e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
2604e48354ceSNicholas Bellinger 	}
2605e48354ceSNicholas Bellinger 
2606e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
2607e48354ceSNicholas Bellinger 
2608e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
2609e48354ceSNicholas Bellinger 
2610e48354ceSNicholas Bellinger 	if (rx_got != rx_size) {
2611e48354ceSNicholas Bellinger 		iscsit_rx_thread_wait_for_tcp(conn);
2612e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2613e48354ceSNicholas Bellinger 	}
2614e48354ceSNicholas Bellinger 
2615e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2616e48354ceSNicholas Bellinger 		u32 data_crc;
2617e48354ceSNicholas Bellinger 
261869110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
2619e48354ceSNicholas Bellinger 						    cmd->write_data_done, length, padding,
2620e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
2621e48354ceSNicholas Bellinger 
2622e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
2623e48354ceSNicholas Bellinger 			pr_err("ImmediateData CRC32C DataDigest 0x%08x"
2624e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n", checksum,
2625e48354ceSNicholas Bellinger 				data_crc);
2626e48354ceSNicholas Bellinger 
2627e48354ceSNicholas Bellinger 			if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2628e48354ceSNicholas Bellinger 				pr_err("Unable to recover from"
2629e48354ceSNicholas Bellinger 					" Immediate Data digest failure while"
2630e48354ceSNicholas Bellinger 					" in ERL=0.\n");
2631ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2632e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2633ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2634e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_CANNOT_RECOVER;
2635e48354ceSNicholas Bellinger 			} else {
2636ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2637e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2638ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2639e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
2640e48354ceSNicholas Bellinger 			}
2641e48354ceSNicholas Bellinger 		} else {
2642e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
2643e48354ceSNicholas Bellinger 				" %u bytes of Immediate Data\n", checksum,
2644e48354ceSNicholas Bellinger 				length);
2645e48354ceSNicholas Bellinger 		}
2646e48354ceSNicholas Bellinger 	}
2647e48354ceSNicholas Bellinger 
2648e48354ceSNicholas Bellinger 	cmd->write_data_done += length;
2649e48354ceSNicholas Bellinger 
2650ebf1d95cSAndy Grover 	if (cmd->write_data_done == cmd->se_cmd.data_length) {
2651e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
2652e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
2653e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
2654e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
2655e48354ceSNicholas Bellinger 	}
2656e48354ceSNicholas Bellinger 
2657e48354ceSNicholas Bellinger 	return IMMEDIATE_DATA_NORMAL_OPERATION;
2658e48354ceSNicholas Bellinger }
2659e48354ceSNicholas Bellinger 
2660e48354ceSNicholas Bellinger /*
2661e48354ceSNicholas Bellinger  *	Called with sess->conn_lock held.
2662e48354ceSNicholas Bellinger  */
2663e48354ceSNicholas Bellinger /* #warning iscsi_build_conn_drop_async_message() only sends out on connections
2664e48354ceSNicholas Bellinger 	with active network interface */
2665e48354ceSNicholas Bellinger static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn)
2666e48354ceSNicholas Bellinger {
2667e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
2668e48354ceSNicholas Bellinger 	struct iscsi_conn *conn_p;
2669d444edc6SNicholas Bellinger 	bool found = false;
2670e48354ceSNicholas Bellinger 
2671e48354ceSNicholas Bellinger 	/*
2672e48354ceSNicholas Bellinger 	 * Only send a Asynchronous Message on connections whos network
2673e48354ceSNicholas Bellinger 	 * interface is still functional.
2674e48354ceSNicholas Bellinger 	 */
2675e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &conn->sess->sess_conn_list, conn_list) {
2676e48354ceSNicholas Bellinger 		if (conn_p->conn_state == TARG_CONN_STATE_LOGGED_IN) {
2677e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn_p);
2678d444edc6SNicholas Bellinger 			found = true;
2679e48354ceSNicholas Bellinger 			break;
2680e48354ceSNicholas Bellinger 		}
2681e48354ceSNicholas Bellinger 	}
2682e48354ceSNicholas Bellinger 
2683d444edc6SNicholas Bellinger 	if (!found)
2684e48354ceSNicholas Bellinger 		return;
2685e48354ceSNicholas Bellinger 
2686676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn_p, TASK_RUNNING);
2687e48354ceSNicholas Bellinger 	if (!cmd) {
2688e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(conn_p);
2689e48354ceSNicholas Bellinger 		return;
2690e48354ceSNicholas Bellinger 	}
2691e48354ceSNicholas Bellinger 
2692e48354ceSNicholas Bellinger 	cmd->logout_cid = conn->cid;
2693e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2694e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_ASYNCMSG;
2695e48354ceSNicholas Bellinger 
2696e48354ceSNicholas Bellinger 	spin_lock_bh(&conn_p->cmd_lock);
26972fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn_p->conn_cmd_list);
2698e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn_p->cmd_lock);
2699e48354ceSNicholas Bellinger 
2700e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn_p, cmd->i_state);
2701e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn_p);
2702e48354ceSNicholas Bellinger }
2703e48354ceSNicholas Bellinger 
2704e48354ceSNicholas Bellinger static int iscsit_send_conn_drop_async_message(
2705e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
2706e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
2707e48354ceSNicholas Bellinger {
2708e48354ceSNicholas Bellinger 	struct iscsi_async *hdr;
2709e48354ceSNicholas Bellinger 
2710e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2711e48354ceSNicholas Bellinger 
2712e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_async *) cmd->pdu;
2713e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_ASYNC_EVENT;
2714e48354ceSNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
271566c7db68SChristoph Hellwig 	cmd->init_task_tag	= RESERVED_ITT;
2716e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
2717e48354ceSNicholas Bellinger 	put_unaligned_be64(0xFFFFFFFFFFFFFFFFULL, &hdr->rsvd4[0]);
2718e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2719e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2720e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2721109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2722e48354ceSNicholas Bellinger 	hdr->async_event	= ISCSI_ASYNC_MSG_DROPPING_CONNECTION;
2723e48354ceSNicholas Bellinger 	hdr->param1		= cpu_to_be16(cmd->logout_cid);
2724e48354ceSNicholas Bellinger 	hdr->param2		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait);
2725e48354ceSNicholas Bellinger 	hdr->param3		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Retain);
2726e48354ceSNicholas Bellinger 
2727e48354ceSNicholas Bellinger 	pr_debug("Sending Connection Dropped Async Message StatSN:"
2728e48354ceSNicholas Bellinger 		" 0x%08x, for CID: %hu on CID: %hu\n", cmd->stat_sn,
2729e48354ceSNicholas Bellinger 			cmd->logout_cid, conn->cid);
27302854bb23SVarun Prakash 
27312854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
2732e48354ceSNicholas Bellinger }
2733e48354ceSNicholas Bellinger 
27346f3c0e69SAndy Grover static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
27356f3c0e69SAndy Grover {
27366f3c0e69SAndy Grover 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
27376f3c0e69SAndy Grover 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
27386f3c0e69SAndy Grover 		wait_for_completion_interruptible_timeout(
27396f3c0e69SAndy Grover 					&conn->tx_half_close_comp,
27406f3c0e69SAndy Grover 					ISCSI_TX_THREAD_TCP_TIMEOUT * HZ);
27416f3c0e69SAndy Grover 	}
27426f3c0e69SAndy Grover }
27436f3c0e69SAndy Grover 
2744d2faaefbSVarun Prakash void
27452ec5a8c1SNicholas Bellinger iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
27462ec5a8c1SNicholas Bellinger 			struct iscsi_datain *datain, struct iscsi_data_rsp *hdr,
27472ec5a8c1SNicholas Bellinger 			bool set_statsn)
2748e48354ceSNicholas Bellinger {
27492ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_DATA_IN;
27502ec5a8c1SNicholas Bellinger 	hdr->flags		= datain->flags;
27512ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
27522ec5a8c1SNicholas Bellinger 		if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
27532ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
27542ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
27552ec5a8c1SNicholas Bellinger 		} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
27562ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
27572ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
27582ec5a8c1SNicholas Bellinger 		}
27592ec5a8c1SNicholas Bellinger 	}
27602ec5a8c1SNicholas Bellinger 	hton24(hdr->dlength, datain->length);
27612ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
27622ec5a8c1SNicholas Bellinger 		int_to_scsilun(cmd->se_cmd.orig_fe_lun,
27632ec5a8c1SNicholas Bellinger 				(struct scsi_lun *)&hdr->lun);
27642ec5a8c1SNicholas Bellinger 	else
27652ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
27662ec5a8c1SNicholas Bellinger 
27672ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
27682ec5a8c1SNicholas Bellinger 
27692ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
27702ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
27712ec5a8c1SNicholas Bellinger 	else
27722ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(0xFFFFFFFF);
27732ec5a8c1SNicholas Bellinger 	if (set_statsn)
27742ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(cmd->stat_sn);
27752ec5a8c1SNicholas Bellinger 	else
27762ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(0xFFFFFFFF);
27772ec5a8c1SNicholas Bellinger 
27782ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2779109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
27802ec5a8c1SNicholas Bellinger 	hdr->datasn		= cpu_to_be32(datain->data_sn);
27812ec5a8c1SNicholas Bellinger 	hdr->offset		= cpu_to_be32(datain->offset);
27822ec5a8c1SNicholas Bellinger 
27832ec5a8c1SNicholas Bellinger 	pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x,"
27842ec5a8c1SNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
27852ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
27862ec5a8c1SNicholas Bellinger 		ntohl(hdr->offset), datain->length, conn->cid);
27872ec5a8c1SNicholas Bellinger }
2788d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_datain_pdu);
27892ec5a8c1SNicholas Bellinger 
27902ec5a8c1SNicholas Bellinger static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
27912ec5a8c1SNicholas Bellinger {
27922ec5a8c1SNicholas Bellinger 	struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0];
2793e48354ceSNicholas Bellinger 	struct iscsi_datain datain;
2794e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
27952854bb23SVarun Prakash 	int eodr = 0, ret;
27962ec5a8c1SNicholas Bellinger 	bool set_statsn = false;
2797e48354ceSNicholas Bellinger 
2798e48354ceSNicholas Bellinger 	memset(&datain, 0, sizeof(struct iscsi_datain));
2799e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_values(cmd, &datain);
2800e48354ceSNicholas Bellinger 	if (!dr) {
2801e48354ceSNicholas Bellinger 		pr_err("iscsit_get_datain_values failed for ITT: 0x%08x\n",
2802e48354ceSNicholas Bellinger 				cmd->init_task_tag);
2803e48354ceSNicholas Bellinger 		return -1;
2804e48354ceSNicholas Bellinger 	}
2805e48354ceSNicholas Bellinger 	/*
2806e48354ceSNicholas Bellinger 	 * Be paranoid and double check the logic for now.
2807e48354ceSNicholas Bellinger 	 */
2808ebf1d95cSAndy Grover 	if ((datain.offset + datain.length) > cmd->se_cmd.data_length) {
2809e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x, datain.offset: %u and"
2810e48354ceSNicholas Bellinger 			" datain.length: %u exceeds cmd->data_length: %u\n",
2811e48354ceSNicholas Bellinger 			cmd->init_task_tag, datain.offset, datain.length,
2812ebf1d95cSAndy Grover 			cmd->se_cmd.data_length);
2813e48354ceSNicholas Bellinger 		return -1;
2814e48354ceSNicholas Bellinger 	}
2815e48354ceSNicholas Bellinger 
281604f3b31bSNicholas Bellinger 	atomic_long_add(datain.length, &conn->sess->tx_data_octets);
2817e48354ceSNicholas Bellinger 	/*
2818e48354ceSNicholas Bellinger 	 * Special case for successfully execution w/ both DATAIN
2819e48354ceSNicholas Bellinger 	 * and Sense Data.
2820e48354ceSNicholas Bellinger 	 */
2821e48354ceSNicholas Bellinger 	if ((datain.flags & ISCSI_FLAG_DATA_STATUS) &&
2822e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
2823e48354ceSNicholas Bellinger 		datain.flags &= ~ISCSI_FLAG_DATA_STATUS;
2824e48354ceSNicholas Bellinger 	else {
2825e48354ceSNicholas Bellinger 		if ((dr->dr_complete == DATAIN_COMPLETE_NORMAL) ||
2826e48354ceSNicholas Bellinger 		    (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
2827e48354ceSNicholas Bellinger 			iscsit_increment_maxcmdsn(cmd, conn->sess);
2828e48354ceSNicholas Bellinger 			cmd->stat_sn = conn->stat_sn++;
28292ec5a8c1SNicholas Bellinger 			set_statsn = true;
2830e48354ceSNicholas Bellinger 		} else if (dr->dr_complete ==
2831e48354ceSNicholas Bellinger 			   DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
28322ec5a8c1SNicholas Bellinger 			set_statsn = true;
2833e48354ceSNicholas Bellinger 	}
2834e48354ceSNicholas Bellinger 
28352ec5a8c1SNicholas Bellinger 	iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
2836e48354ceSNicholas Bellinger 
28372854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, dr, &datain, 0);
28382854bb23SVarun Prakash 	if (ret < 0)
28396f3c0e69SAndy Grover 		return ret;
28406f3c0e69SAndy Grover 
2841e48354ceSNicholas Bellinger 	if (dr->dr_complete) {
28426f3c0e69SAndy Grover 		eodr = (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ?
2843e48354ceSNicholas Bellinger 				2 : 1;
2844e48354ceSNicholas Bellinger 		iscsit_free_datain_req(cmd, dr);
2845e48354ceSNicholas Bellinger 	}
2846e48354ceSNicholas Bellinger 
28476f3c0e69SAndy Grover 	return eodr;
2848e48354ceSNicholas Bellinger }
2849e48354ceSNicholas Bellinger 
28502ec5a8c1SNicholas Bellinger int
28512ec5a8c1SNicholas Bellinger iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
28522ec5a8c1SNicholas Bellinger 			struct iscsi_logout_rsp *hdr)
2853e48354ceSNicholas Bellinger {
2854e48354ceSNicholas Bellinger 	struct iscsi_conn *logout_conn = NULL;
2855e48354ceSNicholas Bellinger 	struct iscsi_conn_recovery *cr = NULL;
2856e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2857e48354ceSNicholas Bellinger 	/*
2858e48354ceSNicholas Bellinger 	 * The actual shutting down of Sessions and/or Connections
2859e48354ceSNicholas Bellinger 	 * for CLOSESESSION and CLOSECONNECTION Logout Requests
2860e48354ceSNicholas Bellinger 	 * is done in scsi_logout_post_handler().
2861e48354ceSNicholas Bellinger 	 */
2862e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
2863e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
2864e48354ceSNicholas Bellinger 		pr_debug("iSCSI session logout successful, setting"
2865e48354ceSNicholas Bellinger 			" logout response to ISCSI_LOGOUT_SUCCESS.\n");
2866e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2867e48354ceSNicholas Bellinger 		break;
2868e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
2869e48354ceSNicholas Bellinger 		if (cmd->logout_response == ISCSI_LOGOUT_CID_NOT_FOUND)
2870e48354ceSNicholas Bellinger 			break;
2871e48354ceSNicholas Bellinger 		/*
2872e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2873e48354ceSNicholas Bellinger 		 * a matching logout CID -> local CID, the reference
2874e48354ceSNicholas Bellinger 		 * for the local CID will have been incremented in
2875e48354ceSNicholas Bellinger 		 * iscsi_logout_closeconnection().
2876e48354ceSNicholas Bellinger 		 *
2877e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2878e48354ceSNicholas Bellinger 		 * a different CID than the connection it arrived
2879e48354ceSNicholas Bellinger 		 * on, the connection responding to cmd->logout_cid
2880e48354ceSNicholas Bellinger 		 * is stopped in iscsit_logout_post_handler_diffcid().
2881e48354ceSNicholas Bellinger 		 */
2882e48354ceSNicholas Bellinger 
2883e48354ceSNicholas Bellinger 		pr_debug("iSCSI CID: %hu logout on CID: %hu"
2884e48354ceSNicholas Bellinger 			" successful.\n", cmd->logout_cid, conn->cid);
2885e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2886e48354ceSNicholas Bellinger 		break;
2887e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
2888e48354ceSNicholas Bellinger 		if ((cmd->logout_response == ISCSI_LOGOUT_RECOVERY_UNSUPPORTED) ||
2889e48354ceSNicholas Bellinger 		    (cmd->logout_response == ISCSI_LOGOUT_CLEANUP_FAILED))
2890e48354ceSNicholas Bellinger 			break;
2891e48354ceSNicholas Bellinger 		/*
2892e48354ceSNicholas Bellinger 		 * If the connection is still active from our point of view
2893e48354ceSNicholas Bellinger 		 * force connection recovery to occur.
2894e48354ceSNicholas Bellinger 		 */
2895e48354ceSNicholas Bellinger 		logout_conn = iscsit_get_conn_from_cid_rcfr(sess,
2896e48354ceSNicholas Bellinger 				cmd->logout_cid);
2897ee1b1b9cSAndy Grover 		if (logout_conn) {
2898e48354ceSNicholas Bellinger 			iscsit_connection_reinstatement_rcfr(logout_conn);
2899e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(logout_conn);
2900e48354ceSNicholas Bellinger 		}
2901e48354ceSNicholas Bellinger 
2902e48354ceSNicholas Bellinger 		cr = iscsit_get_inactive_connection_recovery_entry(
2903e48354ceSNicholas Bellinger 				conn->sess, cmd->logout_cid);
2904e48354ceSNicholas Bellinger 		if (!cr) {
2905e48354ceSNicholas Bellinger 			pr_err("Unable to locate CID: %hu for"
2906e48354ceSNicholas Bellinger 			" REMOVECONNFORRECOVERY Logout Request.\n",
2907e48354ceSNicholas Bellinger 				cmd->logout_cid);
2908e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2909e48354ceSNicholas Bellinger 			break;
2910e48354ceSNicholas Bellinger 		}
2911e48354ceSNicholas Bellinger 
2912e48354ceSNicholas Bellinger 		iscsit_discard_cr_cmds_by_expstatsn(cr, cmd->exp_stat_sn);
2913e48354ceSNicholas Bellinger 
2914e48354ceSNicholas Bellinger 		pr_debug("iSCSI REMOVECONNFORRECOVERY logout"
2915e48354ceSNicholas Bellinger 			" for recovery for CID: %hu on CID: %hu successful.\n",
2916e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2917e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2918e48354ceSNicholas Bellinger 		break;
2919e48354ceSNicholas Bellinger 	default:
2920e48354ceSNicholas Bellinger 		pr_err("Unknown cmd->logout_reason: 0x%02x\n",
2921e48354ceSNicholas Bellinger 				cmd->logout_reason);
2922e48354ceSNicholas Bellinger 		return -1;
2923e48354ceSNicholas Bellinger 	}
2924e48354ceSNicholas Bellinger 
2925e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_LOGOUT_RSP;
2926e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
2927e48354ceSNicholas Bellinger 	hdr->response		= cmd->logout_response;
292866c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
2929e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2930e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2931e48354ceSNicholas Bellinger 
2932e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
2933e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2934109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2935e48354ceSNicholas Bellinger 
29362ec5a8c1SNicholas Bellinger 	pr_debug("Built Logout Response ITT: 0x%08x StatSN:"
29372ec5a8c1SNicholas Bellinger 		" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
29382ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response,
29392ec5a8c1SNicholas Bellinger 		cmd->logout_cid, conn->cid);
29402ec5a8c1SNicholas Bellinger 
29412ec5a8c1SNicholas Bellinger 	return 0;
29422ec5a8c1SNicholas Bellinger }
29432ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_logout_rsp);
29442ec5a8c1SNicholas Bellinger 
29452ec5a8c1SNicholas Bellinger static int
29462ec5a8c1SNicholas Bellinger iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
29472ec5a8c1SNicholas Bellinger {
29482854bb23SVarun Prakash 	int rc;
29492ec5a8c1SNicholas Bellinger 
29502ec5a8c1SNicholas Bellinger 	rc = iscsit_build_logout_rsp(cmd, conn,
29512ec5a8c1SNicholas Bellinger 			(struct iscsi_logout_rsp *)&cmd->pdu[0]);
29522ec5a8c1SNicholas Bellinger 	if (rc < 0)
29532ec5a8c1SNicholas Bellinger 		return rc;
29542ec5a8c1SNicholas Bellinger 
29552854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
2956e48354ceSNicholas Bellinger }
2957e48354ceSNicholas Bellinger 
29582ec5a8c1SNicholas Bellinger void
29592ec5a8c1SNicholas Bellinger iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
29602ec5a8c1SNicholas Bellinger 		       struct iscsi_nopin *hdr, bool nopout_response)
29612ec5a8c1SNicholas Bellinger {
29622ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_NOOP_IN;
29632ec5a8c1SNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
29642ec5a8c1SNicholas Bellinger         hton24(hdr->dlength, cmd->buf_ptr_size);
29652ec5a8c1SNicholas Bellinger 	if (nopout_response)
29662ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
29672ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
29682ec5a8c1SNicholas Bellinger 	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
29692ec5a8c1SNicholas Bellinger 	cmd->stat_sn		= (nopout_response) ? conn->stat_sn++ :
29702ec5a8c1SNicholas Bellinger 				  conn->stat_sn;
29712ec5a8c1SNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
29722ec5a8c1SNicholas Bellinger 
29732ec5a8c1SNicholas Bellinger 	if (nopout_response)
29742ec5a8c1SNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, conn->sess);
29752ec5a8c1SNicholas Bellinger 
29762ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2977109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
29782ec5a8c1SNicholas Bellinger 
29792ec5a8c1SNicholas Bellinger 	pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
29802ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Length %u\n", (nopout_response) ?
29813fc6a642SColin Ian King 		"Solicited" : "Unsolicited", cmd->init_task_tag,
29822ec5a8c1SNicholas Bellinger 		cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
29832ec5a8c1SNicholas Bellinger }
29842ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_nopin_rsp);
29852ec5a8c1SNicholas Bellinger 
2986e48354ceSNicholas Bellinger /*
2987e48354ceSNicholas Bellinger  *	Unsolicited NOPIN, either requesting a response or not.
2988e48354ceSNicholas Bellinger  */
2989e48354ceSNicholas Bellinger static int iscsit_send_unsolicited_nopin(
2990e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
2991e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
2992e48354ceSNicholas Bellinger 	int want_response)
2993e48354ceSNicholas Bellinger {
29942ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
29952854bb23SVarun Prakash 	int ret;
2996e48354ceSNicholas Bellinger 
29972ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, false);
2998e48354ceSNicholas Bellinger 
2999e48354ceSNicholas Bellinger 	pr_debug("Sending Unsolicited NOPIN TTT: 0x%08x StatSN:"
3000e48354ceSNicholas Bellinger 		" 0x%08x CID: %hu\n", hdr->ttt, cmd->stat_sn, conn->cid);
3001e48354ceSNicholas Bellinger 
30022854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
30032854bb23SVarun Prakash 	if (ret < 0)
30046f3c0e69SAndy Grover 		return ret;
30056f3c0e69SAndy Grover 
30066f3c0e69SAndy Grover 	spin_lock_bh(&cmd->istate_lock);
30076f3c0e69SAndy Grover 	cmd->i_state = want_response ?
30086f3c0e69SAndy Grover 		ISTATE_SENT_NOPIN_WANT_RESPONSE : ISTATE_SENT_STATUS;
30096f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->istate_lock);
30106f3c0e69SAndy Grover 
3011e48354ceSNicholas Bellinger 	return 0;
3012e48354ceSNicholas Bellinger }
3013e48354ceSNicholas Bellinger 
30142ec5a8c1SNicholas Bellinger static int
30152ec5a8c1SNicholas Bellinger iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
3016e48354ceSNicholas Bellinger {
30172ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
30182ec5a8c1SNicholas Bellinger 
30192ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, true);
3020e48354ceSNicholas Bellinger 
3021e48354ceSNicholas Bellinger 	/*
3022e48354ceSNicholas Bellinger 	 * NOPOUT Ping Data is attached to struct iscsi_cmd->buf_ptr.
3023e48354ceSNicholas Bellinger 	 * NOPOUT DataSegmentLength is at struct iscsi_cmd->buf_ptr_size.
3024e48354ceSNicholas Bellinger 	 */
30252854bb23SVarun Prakash 	pr_debug("Echoing back %u bytes of ping data.\n", cmd->buf_ptr_size);
3026e48354ceSNicholas Bellinger 
30272854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
30282854bb23SVarun Prakash 						     cmd->buf_ptr,
30292854bb23SVarun Prakash 						     cmd->buf_ptr_size);
3030e48354ceSNicholas Bellinger }
3031e48354ceSNicholas Bellinger 
30326f3c0e69SAndy Grover static int iscsit_send_r2t(
3033e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
3034e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
3035e48354ceSNicholas Bellinger {
3036e48354ceSNicholas Bellinger 	struct iscsi_r2t *r2t;
3037e48354ceSNicholas Bellinger 	struct iscsi_r2t_rsp *hdr;
30386f3c0e69SAndy Grover 	int ret;
3039e48354ceSNicholas Bellinger 
3040e48354ceSNicholas Bellinger 	r2t = iscsit_get_r2t_from_list(cmd);
3041e48354ceSNicholas Bellinger 	if (!r2t)
3042e48354ceSNicholas Bellinger 		return -1;
3043e48354ceSNicholas Bellinger 
3044e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_r2t_rsp *) cmd->pdu;
3045e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3046e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_R2T;
3047e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3048e48354ceSNicholas Bellinger 	int_to_scsilun(cmd->se_cmd.orig_fe_lun,
3049e48354ceSNicholas Bellinger 			(struct scsi_lun *)&hdr->lun);
305066c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
30518567270dSVarun Prakash 	if (conn->conn_transport->iscsit_get_r2t_ttt)
30528567270dSVarun Prakash 		conn->conn_transport->iscsit_get_r2t_ttt(conn, cmd, r2t);
30538567270dSVarun Prakash 	else
3054c1e34b64SSagi Grimberg 		r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
3055e48354ceSNicholas Bellinger 	hdr->ttt		= cpu_to_be32(r2t->targ_xfer_tag);
3056e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(conn->stat_sn);
3057e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3058109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3059e48354ceSNicholas Bellinger 	hdr->r2tsn		= cpu_to_be32(r2t->r2t_sn);
3060e48354ceSNicholas Bellinger 	hdr->data_offset	= cpu_to_be32(r2t->offset);
3061e48354ceSNicholas Bellinger 	hdr->data_length	= cpu_to_be32(r2t->xfer_len);
3062e48354ceSNicholas Bellinger 
3063e48354ceSNicholas Bellinger 	pr_debug("Built %sR2T, ITT: 0x%08x, TTT: 0x%08x, StatSN:"
3064e48354ceSNicholas Bellinger 		" 0x%08x, R2TSN: 0x%08x, Offset: %u, DDTL: %u, CID: %hu\n",
3065e48354ceSNicholas Bellinger 		(!r2t->recovery_r2t) ? "" : "Recovery ", cmd->init_task_tag,
3066e48354ceSNicholas Bellinger 		r2t->targ_xfer_tag, ntohl(hdr->statsn), r2t->r2t_sn,
3067e48354ceSNicholas Bellinger 			r2t->offset, r2t->xfer_len, conn->cid);
3068e48354ceSNicholas Bellinger 
3069e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3070e48354ceSNicholas Bellinger 	r2t->sent_r2t = 1;
3071e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3072e48354ceSNicholas Bellinger 
30732854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
30746f3c0e69SAndy Grover 	if (ret < 0) {
30756f3c0e69SAndy Grover 		return ret;
30766f3c0e69SAndy Grover 	}
30776f3c0e69SAndy Grover 
30786f3c0e69SAndy Grover 	spin_lock_bh(&cmd->dataout_timeout_lock);
30796f3c0e69SAndy Grover 	iscsit_start_dataout_timer(cmd, conn);
30806f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->dataout_timeout_lock);
30816f3c0e69SAndy Grover 
3082e48354ceSNicholas Bellinger 	return 0;
3083e48354ceSNicholas Bellinger }
3084e48354ceSNicholas Bellinger 
3085e48354ceSNicholas Bellinger /*
30868b1e1244SAndy Grover  *	@recovery: If called from iscsi_task_reassign_complete_write() for
3087e48354ceSNicholas Bellinger  *		connection recovery.
3088e48354ceSNicholas Bellinger  */
3089e48354ceSNicholas Bellinger int iscsit_build_r2ts_for_cmd(
3090e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
30913e1c81a9SNicholas Bellinger 	struct iscsi_cmd *cmd,
30928b1e1244SAndy Grover 	bool recovery)
3093e48354ceSNicholas Bellinger {
3094e48354ceSNicholas Bellinger 	int first_r2t = 1;
3095e48354ceSNicholas Bellinger 	u32 offset = 0, xfer_len = 0;
3096e48354ceSNicholas Bellinger 
3097e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3098e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_SENT_LAST_R2T) {
3099e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->r2t_lock);
3100e48354ceSNicholas Bellinger 		return 0;
3101e48354ceSNicholas Bellinger 	}
3102e48354ceSNicholas Bellinger 
31038b1e1244SAndy Grover 	if (conn->sess->sess_ops->DataSequenceInOrder &&
31048b1e1244SAndy Grover 	    !recovery)
3105c6037cc5SAndy Grover 		cmd->r2t_offset = max(cmd->r2t_offset, cmd->write_data_done);
3106e48354ceSNicholas Bellinger 
3107e48354ceSNicholas Bellinger 	while (cmd->outstanding_r2ts < conn->sess->sess_ops->MaxOutstandingR2T) {
3108e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->DataSequenceInOrder) {
3109e48354ceSNicholas Bellinger 			offset = cmd->r2t_offset;
3110e48354ceSNicholas Bellinger 
31118b1e1244SAndy Grover 			if (first_r2t && recovery) {
31128b1e1244SAndy Grover 				int new_data_end = offset +
31138b1e1244SAndy Grover 					conn->sess->sess_ops->MaxBurstLength -
31148b1e1244SAndy Grover 					cmd->next_burst_len;
31158b1e1244SAndy Grover 
3116ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3117ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31188b1e1244SAndy Grover 				else
31198b1e1244SAndy Grover 					xfer_len =
31208b1e1244SAndy Grover 						conn->sess->sess_ops->MaxBurstLength -
31218b1e1244SAndy Grover 						cmd->next_burst_len;
3122e48354ceSNicholas Bellinger 			} else {
31238b1e1244SAndy Grover 				int new_data_end = offset +
3124e48354ceSNicholas Bellinger 					conn->sess->sess_ops->MaxBurstLength;
31258b1e1244SAndy Grover 
3126ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3127ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31288b1e1244SAndy Grover 				else
31298b1e1244SAndy Grover 					xfer_len = conn->sess->sess_ops->MaxBurstLength;
3130e48354ceSNicholas Bellinger 			}
3131e48354ceSNicholas Bellinger 			cmd->r2t_offset += xfer_len;
3132e48354ceSNicholas Bellinger 
3133ebf1d95cSAndy Grover 			if (cmd->r2t_offset == cmd->se_cmd.data_length)
3134e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3135e48354ceSNicholas Bellinger 		} else {
3136e48354ceSNicholas Bellinger 			struct iscsi_seq *seq;
3137e48354ceSNicholas Bellinger 
3138e48354ceSNicholas Bellinger 			seq = iscsit_get_seq_holder_for_r2t(cmd);
3139e48354ceSNicholas Bellinger 			if (!seq) {
3140e48354ceSNicholas Bellinger 				spin_unlock_bh(&cmd->r2t_lock);
3141e48354ceSNicholas Bellinger 				return -1;
3142e48354ceSNicholas Bellinger 			}
3143e48354ceSNicholas Bellinger 
3144e48354ceSNicholas Bellinger 			offset = seq->offset;
3145e48354ceSNicholas Bellinger 			xfer_len = seq->xfer_len;
3146e48354ceSNicholas Bellinger 
3147e48354ceSNicholas Bellinger 			if (cmd->seq_send_order == cmd->seq_count)
3148e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3149e48354ceSNicholas Bellinger 		}
3150e48354ceSNicholas Bellinger 		cmd->outstanding_r2ts++;
3151e48354ceSNicholas Bellinger 		first_r2t = 0;
3152e48354ceSNicholas Bellinger 
3153e48354ceSNicholas Bellinger 		if (iscsit_add_r2t_to_list(cmd, offset, xfer_len, 0, 0) < 0) {
3154e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->r2t_lock);
3155e48354ceSNicholas Bellinger 			return -1;
3156e48354ceSNicholas Bellinger 		}
3157e48354ceSNicholas Bellinger 
3158e48354ceSNicholas Bellinger 		if (cmd->cmd_flags & ICF_SENT_LAST_R2T)
3159e48354ceSNicholas Bellinger 			break;
3160e48354ceSNicholas Bellinger 	}
3161e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3162e48354ceSNicholas Bellinger 
3163e48354ceSNicholas Bellinger 	return 0;
3164e48354ceSNicholas Bellinger }
3165d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_r2ts_for_cmd);
3166e48354ceSNicholas Bellinger 
31672ec5a8c1SNicholas Bellinger void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
31682ec5a8c1SNicholas Bellinger 			bool inc_stat_sn, struct iscsi_scsi_rsp *hdr)
3169e48354ceSNicholas Bellinger {
31702ec5a8c1SNicholas Bellinger 	if (inc_stat_sn)
3171e48354ceSNicholas Bellinger 		cmd->stat_sn = conn->stat_sn++;
3172e48354ceSNicholas Bellinger 
317304f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->rsp_pdus);
3174e48354ceSNicholas Bellinger 
3175e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3176e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_CMD_RSP;
3177e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3178e48354ceSNicholas Bellinger 	if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
3179e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW;
31807e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3181e48354ceSNicholas Bellinger 	} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
3182e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
31837e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3184e48354ceSNicholas Bellinger 	}
3185e48354ceSNicholas Bellinger 	hdr->response		= cmd->iscsi_response;
3186e48354ceSNicholas Bellinger 	hdr->cmd_status		= cmd->se_cmd.scsi_status;
318766c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3188e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3189e48354ceSNicholas Bellinger 
3190e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3191e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3192109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3193e48354ceSNicholas Bellinger 
31942ec5a8c1SNicholas Bellinger 	pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
31952ec5a8c1SNicholas Bellinger 		" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
31962ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, cmd->se_cmd.scsi_status,
31972ec5a8c1SNicholas Bellinger 		cmd->se_cmd.scsi_status, conn->cid);
31982ec5a8c1SNicholas Bellinger }
31992ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_rsp_pdu);
32002ec5a8c1SNicholas Bellinger 
32012ec5a8c1SNicholas Bellinger static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
32022ec5a8c1SNicholas Bellinger {
32032ec5a8c1SNicholas Bellinger 	struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)&cmd->pdu[0];
32042ec5a8c1SNicholas Bellinger 	bool inc_stat_sn = (cmd->i_state == ISTATE_SEND_STATUS);
32052854bb23SVarun Prakash 	void *data_buf = NULL;
32062854bb23SVarun Prakash 	u32 padding = 0, data_buf_len = 0;
32072ec5a8c1SNicholas Bellinger 
32082ec5a8c1SNicholas Bellinger 	iscsit_build_rsp_pdu(cmd, conn, inc_stat_sn, hdr);
32092ec5a8c1SNicholas Bellinger 
3210e48354ceSNicholas Bellinger 	/*
3211e48354ceSNicholas Bellinger 	 * Attach SENSE DATA payload to iSCSI Response PDU
3212e48354ceSNicholas Bellinger 	 */
3213e48354ceSNicholas Bellinger 	if (cmd->se_cmd.sense_buffer &&
3214e48354ceSNicholas Bellinger 	   ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
3215e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
32169c58b7ddSRoland Dreier 		put_unaligned_be16(cmd->se_cmd.scsi_sense_length, cmd->sense_buffer);
32179c58b7ddSRoland Dreier 		cmd->se_cmd.scsi_sense_length += sizeof (__be16);
32189c58b7ddSRoland Dreier 
3219e48354ceSNicholas Bellinger 		padding		= -(cmd->se_cmd.scsi_sense_length) & 3;
322050e5c87dSChristoph Hellwig 		hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length);
32212854bb23SVarun Prakash 		data_buf = cmd->sense_buffer;
32222854bb23SVarun Prakash 		data_buf_len = cmd->se_cmd.scsi_sense_length + padding;
3223e48354ceSNicholas Bellinger 
3224e48354ceSNicholas Bellinger 		if (padding) {
32259c58b7ddSRoland Dreier 			memset(cmd->sense_buffer +
3226e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length, 0, padding);
3227e48354ceSNicholas Bellinger 			pr_debug("Adding %u bytes of padding to"
3228e48354ceSNicholas Bellinger 				" SENSE.\n", padding);
3229e48354ceSNicholas Bellinger 		}
3230e48354ceSNicholas Bellinger 
3231e48354ceSNicholas Bellinger 		pr_debug("Attaching SENSE DATA: %u bytes to iSCSI"
3232e48354ceSNicholas Bellinger 				" Response PDU\n",
3233e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length);
3234e48354ceSNicholas Bellinger 	}
3235e48354ceSNicholas Bellinger 
32362854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, data_buf,
32372854bb23SVarun Prakash 						     data_buf_len);
3238e48354ceSNicholas Bellinger }
3239e48354ceSNicholas Bellinger 
3240e48354ceSNicholas Bellinger static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr)
3241e48354ceSNicholas Bellinger {
3242e48354ceSNicholas Bellinger 	switch (se_tmr->response) {
3243e48354ceSNicholas Bellinger 	case TMR_FUNCTION_COMPLETE:
3244e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_COMPLETE;
3245e48354ceSNicholas Bellinger 	case TMR_TASK_DOES_NOT_EXIST:
3246e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_TASK;
3247e48354ceSNicholas Bellinger 	case TMR_LUN_DOES_NOT_EXIST:
3248e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_LUN;
3249e48354ceSNicholas Bellinger 	case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
3250e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NOT_SUPPORTED;
3251e48354ceSNicholas Bellinger 	case TMR_FUNCTION_REJECTED:
3252e48354ceSNicholas Bellinger 	default:
3253e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_REJECTED;
3254e48354ceSNicholas Bellinger 	}
3255e48354ceSNicholas Bellinger }
3256e48354ceSNicholas Bellinger 
32572ec5a8c1SNicholas Bellinger void
32582ec5a8c1SNicholas Bellinger iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
32592ec5a8c1SNicholas Bellinger 			  struct iscsi_tm_rsp *hdr)
3260e48354ceSNicholas Bellinger {
3261e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
3262e48354ceSNicholas Bellinger 
3263e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_TMFUNC_RSP;
32647ae0b103SNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
3265e48354ceSNicholas Bellinger 	hdr->response		= iscsit_convert_tcm_tmr_rsp(se_tmr);
326666c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3267e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3268e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3269e48354ceSNicholas Bellinger 
3270e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3271e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3272109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3273e48354ceSNicholas Bellinger 
32742ec5a8c1SNicholas Bellinger 	pr_debug("Built Task Management Response ITT: 0x%08x,"
32752ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
32762ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid);
32772ec5a8c1SNicholas Bellinger }
32782ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_task_mgt_rsp);
32792ec5a8c1SNicholas Bellinger 
32802ec5a8c1SNicholas Bellinger static int
32812ec5a8c1SNicholas Bellinger iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
32822ec5a8c1SNicholas Bellinger {
32832ec5a8c1SNicholas Bellinger 	struct iscsi_tm_rsp *hdr = (struct iscsi_tm_rsp *)&cmd->pdu[0];
32842ec5a8c1SNicholas Bellinger 
32852ec5a8c1SNicholas Bellinger 	iscsit_build_task_mgt_rsp(cmd, conn, hdr);
32862ec5a8c1SNicholas Bellinger 
32872854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
3288e48354ceSNicholas Bellinger }
3289e48354ceSNicholas Bellinger 
32902f9bc894SNicholas Bellinger static bool iscsit_check_inaddr_any(struct iscsi_np *np)
32912f9bc894SNicholas Bellinger {
32922f9bc894SNicholas Bellinger 	bool ret = false;
32932f9bc894SNicholas Bellinger 
32942f9bc894SNicholas Bellinger 	if (np->np_sockaddr.ss_family == AF_INET6) {
32952f9bc894SNicholas Bellinger 		const struct sockaddr_in6 sin6 = {
32962f9bc894SNicholas Bellinger 			.sin6_addr = IN6ADDR_ANY_INIT };
32972f9bc894SNicholas Bellinger 		struct sockaddr_in6 *sock_in6 =
32982f9bc894SNicholas Bellinger 			 (struct sockaddr_in6 *)&np->np_sockaddr;
32992f9bc894SNicholas Bellinger 
33002f9bc894SNicholas Bellinger 		if (!memcmp(sock_in6->sin6_addr.s6_addr,
33012f9bc894SNicholas Bellinger 				sin6.sin6_addr.s6_addr, 16))
33022f9bc894SNicholas Bellinger 			ret = true;
33032f9bc894SNicholas Bellinger 	} else {
33042f9bc894SNicholas Bellinger 		struct sockaddr_in * sock_in =
33052f9bc894SNicholas Bellinger 			(struct sockaddr_in *)&np->np_sockaddr;
33062f9bc894SNicholas Bellinger 
3307cea0b4ceSChristoph Hellwig 		if (sock_in->sin_addr.s_addr == htonl(INADDR_ANY))
33082f9bc894SNicholas Bellinger 			ret = true;
33092f9bc894SNicholas Bellinger 	}
33102f9bc894SNicholas Bellinger 
33112f9bc894SNicholas Bellinger 	return ret;
33122f9bc894SNicholas Bellinger }
33132f9bc894SNicholas Bellinger 
33148b1e1244SAndy Grover #define SENDTARGETS_BUF_LIMIT 32768U
33158b1e1244SAndy Grover 
331622c7aaa5SSagi Grimberg static int
331722c7aaa5SSagi Grimberg iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
3318e4f4e801SSagi Grimberg 				  enum iscsit_transport_type network_transport,
3319e4f4e801SSagi Grimberg 				  int skip_bytes, bool *completed)
3320e48354ceSNicholas Bellinger {
3321e48354ceSNicholas Bellinger 	char *payload = NULL;
3322e48354ceSNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
3323e48354ceSNicholas Bellinger 	struct iscsi_portal_group *tpg;
3324e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn;
3325e48354ceSNicholas Bellinger 	struct iscsi_tpg_np *tpg_np;
3326e48354ceSNicholas Bellinger 	int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
33272dd1d53fSThomas Glanzmann 	int target_name_printed;
33288b1e1244SAndy Grover 	unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
33296665889cSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
3330a6415cddSDavid Disseldorp 	bool active;
3331e48354ceSNicholas Bellinger 
3332be7dcfb6SSagi Grimberg 	buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength,
33338b1e1244SAndy Grover 			 SENDTARGETS_BUF_LIMIT);
3334e48354ceSNicholas Bellinger 
3335e48354ceSNicholas Bellinger 	payload = kzalloc(buffer_len, GFP_KERNEL);
3336c46e22f1SMarkus Elfring 	if (!payload)
3337e48354ceSNicholas Bellinger 		return -ENOMEM;
3338c46e22f1SMarkus Elfring 
33396665889cSNicholas Bellinger 	/*
33408060b8ddSAndy Grover 	 * Locate pointer to iqn./eui. string for ICF_SENDTARGETS_SINGLE
33416665889cSNicholas Bellinger 	 * explicit case..
33426665889cSNicholas Bellinger 	 */
33438060b8ddSAndy Grover 	if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) {
33446665889cSNicholas Bellinger 		text_ptr = strchr(text_in, '=');
33456665889cSNicholas Bellinger 		if (!text_ptr) {
33466665889cSNicholas Bellinger 			pr_err("Unable to locate '=' string in text_in:"
33476665889cSNicholas Bellinger 			       " %s\n", text_in);
33484f45d320SDan Carpenter 			kfree(payload);
33496665889cSNicholas Bellinger 			return -EINVAL;
33506665889cSNicholas Bellinger 		}
33516665889cSNicholas Bellinger 		/*
33526665889cSNicholas Bellinger 		 * Skip over '=' character..
33536665889cSNicholas Bellinger 		 */
33546665889cSNicholas Bellinger 		text_ptr += 1;
33556665889cSNicholas Bellinger 	}
3356e48354ceSNicholas Bellinger 
3357e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
3358e48354ceSNicholas Bellinger 	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
33598060b8ddSAndy Grover 		if ((cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) &&
33606665889cSNicholas Bellinger 		     strcmp(tiqn->tiqn, text_ptr)) {
33616665889cSNicholas Bellinger 			continue;
33626665889cSNicholas Bellinger 		}
33636665889cSNicholas Bellinger 
33642dd1d53fSThomas Glanzmann 		target_name_printed = 0;
3365e48354ceSNicholas Bellinger 
3366e48354ceSNicholas Bellinger 		spin_lock(&tiqn->tiqn_tpg_lock);
3367e48354ceSNicholas Bellinger 		list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
3368e48354ceSNicholas Bellinger 
33692dd1d53fSThomas Glanzmann 			/* If demo_mode_discovery=0 and generate_node_acls=0
33702dd1d53fSThomas Glanzmann 			 * (demo mode dislabed) do not return
33712dd1d53fSThomas Glanzmann 			 * TargetName+TargetAddress unless a NodeACL exists.
33722dd1d53fSThomas Glanzmann 			 */
33732dd1d53fSThomas Glanzmann 
33742dd1d53fSThomas Glanzmann 			if ((tpg->tpg_attrib.generate_node_acls == 0) &&
33752dd1d53fSThomas Glanzmann 			    (tpg->tpg_attrib.demo_mode_discovery == 0) &&
337621aaa23bSNicholas Bellinger 			    (!target_tpg_has_node_acl(&tpg->tpg_se_tpg,
33772dd1d53fSThomas Glanzmann 				cmd->conn->sess->sess_ops->InitiatorName))) {
33782dd1d53fSThomas Glanzmann 				continue;
33792dd1d53fSThomas Glanzmann 			}
33802dd1d53fSThomas Glanzmann 
3381e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_state_lock);
3382a6415cddSDavid Disseldorp 			active = (tpg->tpg_state == TPG_STATE_ACTIVE);
3383e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_state_lock);
3384a6415cddSDavid Disseldorp 
3385a6415cddSDavid Disseldorp 			if (!active && tpg->tpg_attrib.tpg_enabled_sendtargets)
3386e48354ceSNicholas Bellinger 				continue;
3387e48354ceSNicholas Bellinger 
3388e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_np_lock);
3389e48354ceSNicholas Bellinger 			list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
3390e48354ceSNicholas Bellinger 						tpg_np_list) {
33912f9bc894SNicholas Bellinger 				struct iscsi_np *np = tpg_np->tpg_np;
33922f9bc894SNicholas Bellinger 				bool inaddr_any = iscsit_check_inaddr_any(np);
339313a3cf08SAndy Grover 				struct sockaddr_storage *sockaddr;
33942f9bc894SNicholas Bellinger 
339522c7aaa5SSagi Grimberg 				if (np->np_network_transport != network_transport)
339622c7aaa5SSagi Grimberg 					continue;
339722c7aaa5SSagi Grimberg 
33982dd1d53fSThomas Glanzmann 				if (!target_name_printed) {
33992dd1d53fSThomas Glanzmann 					len = sprintf(buf, "TargetName=%s",
34002dd1d53fSThomas Glanzmann 						      tiqn->tiqn);
34012dd1d53fSThomas Glanzmann 					len += 1;
34022dd1d53fSThomas Glanzmann 
34032dd1d53fSThomas Glanzmann 					if ((len + payload_len) > buffer_len) {
34042dd1d53fSThomas Glanzmann 						spin_unlock(&tpg->tpg_np_lock);
34052dd1d53fSThomas Glanzmann 						spin_unlock(&tiqn->tiqn_tpg_lock);
34062dd1d53fSThomas Glanzmann 						end_of_buf = 1;
34072dd1d53fSThomas Glanzmann 						goto eob;
34082dd1d53fSThomas Glanzmann 					}
3409e4f4e801SSagi Grimberg 
3410e4f4e801SSagi Grimberg 					if (skip_bytes && len <= skip_bytes) {
3411e4f4e801SSagi Grimberg 						skip_bytes -= len;
3412e4f4e801SSagi Grimberg 					} else {
34132dd1d53fSThomas Glanzmann 						memcpy(payload + payload_len, buf, len);
34142dd1d53fSThomas Glanzmann 						payload_len += len;
34152dd1d53fSThomas Glanzmann 						target_name_printed = 1;
3416e4f4e801SSagi Grimberg 						if (len > skip_bytes)
3417e4f4e801SSagi Grimberg 							skip_bytes = 0;
3418e4f4e801SSagi Grimberg 					}
34192dd1d53fSThomas Glanzmann 				}
34202dd1d53fSThomas Glanzmann 
342169d75574SAndy Grover 				if (inaddr_any)
342269d75574SAndy Grover 					sockaddr = &conn->local_sockaddr;
34231997e625SAndy Grover 				else
342469d75574SAndy Grover 					sockaddr = &np->np_sockaddr;
34251997e625SAndy Grover 
342676c28f1fSAndy Grover 				len = sprintf(buf, "TargetAddress="
342776c28f1fSAndy Grover 					      "%pISpc,%hu",
342869d75574SAndy Grover 					      sockaddr,
3429e48354ceSNicholas Bellinger 					      tpg->tpgt);
3430e48354ceSNicholas Bellinger 				len += 1;
3431e48354ceSNicholas Bellinger 
3432e48354ceSNicholas Bellinger 				if ((len + payload_len) > buffer_len) {
3433e48354ceSNicholas Bellinger 					spin_unlock(&tpg->tpg_np_lock);
3434e48354ceSNicholas Bellinger 					spin_unlock(&tiqn->tiqn_tpg_lock);
3435e48354ceSNicholas Bellinger 					end_of_buf = 1;
3436e48354ceSNicholas Bellinger 					goto eob;
3437e48354ceSNicholas Bellinger 				}
3438e4f4e801SSagi Grimberg 
3439e4f4e801SSagi Grimberg 				if (skip_bytes && len <= skip_bytes) {
3440e4f4e801SSagi Grimberg 					skip_bytes -= len;
3441e4f4e801SSagi Grimberg 				} else {
34428359cf43SJörn Engel 					memcpy(payload + payload_len, buf, len);
3443e48354ceSNicholas Bellinger 					payload_len += len;
3444e4f4e801SSagi Grimberg 					if (len > skip_bytes)
3445e4f4e801SSagi Grimberg 						skip_bytes = 0;
3446e4f4e801SSagi Grimberg 				}
3447e48354ceSNicholas Bellinger 			}
3448e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_np_lock);
3449e48354ceSNicholas Bellinger 		}
3450e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_tpg_lock);
3451e48354ceSNicholas Bellinger eob:
3452e4f4e801SSagi Grimberg 		if (end_of_buf) {
3453e4f4e801SSagi Grimberg 			*completed = false;
3454e48354ceSNicholas Bellinger 			break;
3455e4f4e801SSagi Grimberg 		}
34566665889cSNicholas Bellinger 
34578060b8ddSAndy Grover 		if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE)
34586665889cSNicholas Bellinger 			break;
3459e48354ceSNicholas Bellinger 	}
3460e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
3461e48354ceSNicholas Bellinger 
3462e48354ceSNicholas Bellinger 	cmd->buf_ptr = payload;
3463e48354ceSNicholas Bellinger 
3464e48354ceSNicholas Bellinger 	return payload_len;
3465e48354ceSNicholas Bellinger }
3466e48354ceSNicholas Bellinger 
3467889c8a68SNicholas Bellinger int
3468889c8a68SNicholas Bellinger iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
346922c7aaa5SSagi Grimberg 		      struct iscsi_text_rsp *hdr,
347022c7aaa5SSagi Grimberg 		      enum iscsit_transport_type network_transport)
3471e48354ceSNicholas Bellinger {
3472889c8a68SNicholas Bellinger 	int text_length, padding;
3473e4f4e801SSagi Grimberg 	bool completed = true;
3474e48354ceSNicholas Bellinger 
3475e4f4e801SSagi Grimberg 	text_length = iscsit_build_sendtargets_response(cmd, network_transport,
3476e4f4e801SSagi Grimberg 							cmd->read_data_done,
3477e4f4e801SSagi Grimberg 							&completed);
3478e48354ceSNicholas Bellinger 	if (text_length < 0)
3479e48354ceSNicholas Bellinger 		return text_length;
3480e48354ceSNicholas Bellinger 
3481e4f4e801SSagi Grimberg 	if (completed) {
3482310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
3483e4f4e801SSagi Grimberg 	} else {
3484310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_TEXT_CONTINUE;
3485e4f4e801SSagi Grimberg 		cmd->read_data_done += text_length;
3486e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF)
3487e4f4e801SSagi Grimberg 			cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
3488e4f4e801SSagi Grimberg 	}
3489e4f4e801SSagi Grimberg 	hdr->opcode = ISCSI_OP_TEXT_RSP;
3490889c8a68SNicholas Bellinger 	padding = ((-text_length) & 3);
3491e48354ceSNicholas Bellinger 	hton24(hdr->dlength, text_length);
349266c7db68SChristoph Hellwig 	hdr->itt = cmd->init_task_tag;
3493e48354ceSNicholas Bellinger 	hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
3494e48354ceSNicholas Bellinger 	cmd->stat_sn = conn->stat_sn++;
3495e48354ceSNicholas Bellinger 	hdr->statsn = cpu_to_be32(cmd->stat_sn);
3496e48354ceSNicholas Bellinger 
3497e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3498e4f4e801SSagi Grimberg 	/*
3499e4f4e801SSagi Grimberg 	 * Reset maxcmdsn_inc in multi-part text payload exchanges to
3500e4f4e801SSagi Grimberg 	 * correctly increment MaxCmdSN for each response answering a
3501e4f4e801SSagi Grimberg 	 * non immediate text request with a valid CmdSN.
3502e4f4e801SSagi Grimberg 	 */
3503e4f4e801SSagi Grimberg 	cmd->maxcmdsn_inc = 0;
3504e48354ceSNicholas Bellinger 	hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
3505109e2381SRoland Dreier 	hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3506e48354ceSNicholas Bellinger 
3507e4f4e801SSagi Grimberg 	pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
3508e4f4e801SSagi Grimberg 		" Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
3509e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag, cmd->stat_sn, text_length, conn->cid,
3510e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_CMD_FINAL),
3511e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE));
3512e48354ceSNicholas Bellinger 
3513889c8a68SNicholas Bellinger 	return text_length + padding;
3514889c8a68SNicholas Bellinger }
3515889c8a68SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_text_rsp);
3516889c8a68SNicholas Bellinger 
3517889c8a68SNicholas Bellinger static int iscsit_send_text_rsp(
3518889c8a68SNicholas Bellinger 	struct iscsi_cmd *cmd,
3519889c8a68SNicholas Bellinger 	struct iscsi_conn *conn)
3520889c8a68SNicholas Bellinger {
3521889c8a68SNicholas Bellinger 	struct iscsi_text_rsp *hdr = (struct iscsi_text_rsp *)cmd->pdu;
35222854bb23SVarun Prakash 	int text_length;
3523889c8a68SNicholas Bellinger 
3524864e504aSVarun Prakash 	text_length = iscsit_build_text_rsp(cmd, conn, hdr,
3525864e504aSVarun Prakash 				conn->conn_transport->transport_type);
35262854bb23SVarun Prakash 	if (text_length < 0)
35272854bb23SVarun Prakash 		return text_length;
3528889c8a68SNicholas Bellinger 
35292854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35302854bb23SVarun Prakash 						     cmd->buf_ptr,
35312854bb23SVarun Prakash 						     text_length);
3532e48354ceSNicholas Bellinger }
3533e48354ceSNicholas Bellinger 
35342ec5a8c1SNicholas Bellinger void
35352ec5a8c1SNicholas Bellinger iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
35362ec5a8c1SNicholas Bellinger 		    struct iscsi_reject *hdr)
3537e48354ceSNicholas Bellinger {
3538e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_REJECT;
3539ba159914SNicholas Bellinger 	hdr->reason		= cmd->reject_reason;
3540e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3541e48354ceSNicholas Bellinger 	hton24(hdr->dlength, ISCSI_HDR_LEN);
354250e5c87dSChristoph Hellwig 	hdr->ffffffff		= cpu_to_be32(0xffffffff);
3543e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3544e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3545e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3546109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3547e48354ceSNicholas Bellinger 
35482ec5a8c1SNicholas Bellinger }
35492ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_reject);
3550e48354ceSNicholas Bellinger 
35512ec5a8c1SNicholas Bellinger static int iscsit_send_reject(
35522ec5a8c1SNicholas Bellinger 	struct iscsi_cmd *cmd,
35532ec5a8c1SNicholas Bellinger 	struct iscsi_conn *conn)
35542ec5a8c1SNicholas Bellinger {
3555bfbdb31dSNicholas Bellinger 	struct iscsi_reject *hdr = (struct iscsi_reject *)&cmd->pdu[0];
35562ec5a8c1SNicholas Bellinger 
3557bfbdb31dSNicholas Bellinger 	iscsit_build_reject(cmd, conn, hdr);
35582ec5a8c1SNicholas Bellinger 
3559e48354ceSNicholas Bellinger 	pr_debug("Built Reject PDU StatSN: 0x%08x, Reason: 0x%02x,"
3560e48354ceSNicholas Bellinger 		" CID: %hu\n", ntohl(hdr->statsn), hdr->reason, conn->cid);
3561e48354ceSNicholas Bellinger 
35622854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35632854bb23SVarun Prakash 						     cmd->buf_ptr,
35642854bb23SVarun Prakash 						     ISCSI_HDR_LEN);
3565e48354ceSNicholas Bellinger }
3566e48354ceSNicholas Bellinger 
3567e48354ceSNicholas Bellinger void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
3568e48354ceSNicholas Bellinger {
3569e48354ceSNicholas Bellinger 	int ord, cpu;
3570e48354ceSNicholas Bellinger 	/*
357188dcd2daSNicholas Bellinger 	 * bitmap_id is assigned from iscsit_global->ts_bitmap from
357288dcd2daSNicholas Bellinger 	 * within iscsit_start_kthreads()
3573e48354ceSNicholas Bellinger 	 *
357488dcd2daSNicholas Bellinger 	 * Here we use bitmap_id to determine which CPU that this
357588dcd2daSNicholas Bellinger 	 * iSCSI connection's RX/TX threads will be scheduled to
3576e48354ceSNicholas Bellinger 	 * execute upon.
3577e48354ceSNicholas Bellinger 	 */
357888dcd2daSNicholas Bellinger 	ord = conn->bitmap_id % cpumask_weight(cpu_online_mask);
3579e48354ceSNicholas Bellinger 	for_each_online_cpu(cpu) {
3580e48354ceSNicholas Bellinger 		if (ord-- == 0) {
3581e48354ceSNicholas Bellinger 			cpumask_set_cpu(cpu, conn->conn_cpumask);
3582e48354ceSNicholas Bellinger 			return;
3583e48354ceSNicholas Bellinger 		}
3584e48354ceSNicholas Bellinger 	}
3585e48354ceSNicholas Bellinger 	/*
3586e48354ceSNicholas Bellinger 	 * This should never be reached..
3587e48354ceSNicholas Bellinger 	 */
3588e48354ceSNicholas Bellinger 	dump_stack();
3589e48354ceSNicholas Bellinger 	cpumask_setall(conn->conn_cpumask);
3590e48354ceSNicholas Bellinger }
3591e48354ceSNicholas Bellinger 
3592d2faaefbSVarun Prakash int
35932ec5a8c1SNicholas Bellinger iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
3594e48354ceSNicholas Bellinger {
35952ec5a8c1SNicholas Bellinger 	int ret;
35962ec5a8c1SNicholas Bellinger 
35972ec5a8c1SNicholas Bellinger 	switch (state) {
35982ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_R2T:
35992ec5a8c1SNicholas Bellinger 		ret = iscsit_send_r2t(cmd, conn);
36002ec5a8c1SNicholas Bellinger 		if (ret < 0)
36012ec5a8c1SNicholas Bellinger 			goto err;
36022ec5a8c1SNicholas Bellinger 		break;
36032ec5a8c1SNicholas Bellinger 	case ISTATE_REMOVE:
36042ec5a8c1SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
36055159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
36062ec5a8c1SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
36072ec5a8c1SNicholas Bellinger 
3608aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
36092ec5a8c1SNicholas Bellinger 		break;
36102ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_WANT_RESPONSE:
36112ec5a8c1SNicholas Bellinger 		iscsit_mod_nopin_response_timer(conn);
36122ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 1);
36132ec5a8c1SNicholas Bellinger 		if (ret < 0)
36142ec5a8c1SNicholas Bellinger 			goto err;
36152ec5a8c1SNicholas Bellinger 		break;
36162ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_NO_RESPONSE:
36172ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 0);
36182ec5a8c1SNicholas Bellinger 		if (ret < 0)
36192ec5a8c1SNicholas Bellinger 			goto err;
36202ec5a8c1SNicholas Bellinger 		break;
36212ec5a8c1SNicholas Bellinger 	default:
36222ec5a8c1SNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
36232ec5a8c1SNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
36242ec5a8c1SNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag, state,
36252ec5a8c1SNicholas Bellinger 		       conn->cid);
36262ec5a8c1SNicholas Bellinger 		goto err;
36272ec5a8c1SNicholas Bellinger 	}
36282ec5a8c1SNicholas Bellinger 
36292ec5a8c1SNicholas Bellinger 	return 0;
36302ec5a8c1SNicholas Bellinger 
36312ec5a8c1SNicholas Bellinger err:
36322ec5a8c1SNicholas Bellinger 	return -1;
36332ec5a8c1SNicholas Bellinger }
3634d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_immediate_queue);
36352ec5a8c1SNicholas Bellinger 
36362ec5a8c1SNicholas Bellinger static int
36372ec5a8c1SNicholas Bellinger iscsit_handle_immediate_queue(struct iscsi_conn *conn)
36382ec5a8c1SNicholas Bellinger {
36392ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
36406f3c0e69SAndy Grover 	struct iscsi_queue_req *qr;
36416f3c0e69SAndy Grover 	struct iscsi_cmd *cmd;
3642e48354ceSNicholas Bellinger 	u8 state;
36436f3c0e69SAndy Grover 	int ret;
3644e48354ceSNicholas Bellinger 
3645c6037cc5SAndy Grover 	while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) {
3646e48354ceSNicholas Bellinger 		atomic_set(&conn->check_immediate_queue, 0);
3647e48354ceSNicholas Bellinger 		cmd = qr->cmd;
3648e48354ceSNicholas Bellinger 		state = qr->state;
3649e48354ceSNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
3650e48354ceSNicholas Bellinger 
36512ec5a8c1SNicholas Bellinger 		ret = t->iscsit_immediate_queue(conn, cmd, state);
36526f3c0e69SAndy Grover 		if (ret < 0)
36532ec5a8c1SNicholas Bellinger 			return ret;
3654e48354ceSNicholas Bellinger 	}
3655e48354ceSNicholas Bellinger 
36566f3c0e69SAndy Grover 	return 0;
3657e48354ceSNicholas Bellinger }
36586f3c0e69SAndy Grover 
3659d2faaefbSVarun Prakash int
36602ec5a8c1SNicholas Bellinger iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
36616f3c0e69SAndy Grover {
36626f3c0e69SAndy Grover 	int ret;
3663e48354ceSNicholas Bellinger 
3664e48354ceSNicholas Bellinger check_rsp_state:
3665e48354ceSNicholas Bellinger 	switch (state) {
3666e48354ceSNicholas Bellinger 	case ISTATE_SEND_DATAIN:
36672ec5a8c1SNicholas Bellinger 		ret = iscsit_send_datain(cmd, conn);
36686f3c0e69SAndy Grover 		if (ret < 0)
36696f3c0e69SAndy Grover 			goto err;
36706f3c0e69SAndy Grover 		else if (!ret)
36716f3c0e69SAndy Grover 			/* more drs */
36726f3c0e69SAndy Grover 			goto check_rsp_state;
36736f3c0e69SAndy Grover 		else if (ret == 1) {
36746f3c0e69SAndy Grover 			/* all done */
36756f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
36766f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SENT_STATUS;
3677e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->istate_lock);
3678fd3a9025SNicholas Bellinger 
3679fd3a9025SNicholas Bellinger 			if (atomic_read(&conn->check_immediate_queue))
3680fd3a9025SNicholas Bellinger 				return 1;
3681fd3a9025SNicholas Bellinger 
36822ec5a8c1SNicholas Bellinger 			return 0;
36836f3c0e69SAndy Grover 		} else if (ret == 2) {
36846f3c0e69SAndy Grover 			/* Still must send status,
36856f3c0e69SAndy Grover 			   SCF_TRANSPORT_TASK_SENSE was set */
36866f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
36876f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SEND_STATUS;
36886f3c0e69SAndy Grover 			spin_unlock_bh(&cmd->istate_lock);
36896f3c0e69SAndy Grover 			state = ISTATE_SEND_STATUS;
36906f3c0e69SAndy Grover 			goto check_rsp_state;
36916f3c0e69SAndy Grover 		}
36926f3c0e69SAndy Grover 
3693e48354ceSNicholas Bellinger 		break;
3694e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3695e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
36962ec5a8c1SNicholas Bellinger 		ret = iscsit_send_response(cmd, conn);
3697e48354ceSNicholas Bellinger 		break;
3698e48354ceSNicholas Bellinger 	case ISTATE_SEND_LOGOUTRSP:
36992ec5a8c1SNicholas Bellinger 		ret = iscsit_send_logout(cmd, conn);
3700e48354ceSNicholas Bellinger 		break;
3701e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3702e48354ceSNicholas Bellinger 		ret = iscsit_send_conn_drop_async_message(
3703e48354ceSNicholas Bellinger 			cmd, conn);
3704e48354ceSNicholas Bellinger 		break;
3705e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
37062ec5a8c1SNicholas Bellinger 		ret = iscsit_send_nopin(cmd, conn);
3707e48354ceSNicholas Bellinger 		break;
3708e48354ceSNicholas Bellinger 	case ISTATE_SEND_REJECT:
3709e48354ceSNicholas Bellinger 		ret = iscsit_send_reject(cmd, conn);
3710e48354ceSNicholas Bellinger 		break;
3711e48354ceSNicholas Bellinger 	case ISTATE_SEND_TASKMGTRSP:
3712e48354ceSNicholas Bellinger 		ret = iscsit_send_task_mgt_rsp(cmd, conn);
3713e48354ceSNicholas Bellinger 		if (ret != 0)
3714e48354ceSNicholas Bellinger 			break;
3715e48354ceSNicholas Bellinger 		ret = iscsit_tmr_post_handler(cmd, conn);
3716e48354ceSNicholas Bellinger 		if (ret != 0)
3717e48354ceSNicholas Bellinger 			iscsit_fall_back_to_erl0(conn->sess);
3718e48354ceSNicholas Bellinger 		break;
3719e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
3720e48354ceSNicholas Bellinger 		ret = iscsit_send_text_rsp(cmd, conn);
3721e48354ceSNicholas Bellinger 		break;
3722e48354ceSNicholas Bellinger 	default:
3723e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3724e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3725e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3726e48354ceSNicholas Bellinger 		       state, conn->cid);
37276f3c0e69SAndy Grover 		goto err;
3728e48354ceSNicholas Bellinger 	}
3729c6037cc5SAndy Grover 	if (ret < 0)
37306f3c0e69SAndy Grover 		goto err;
3731e48354ceSNicholas Bellinger 
3732e48354ceSNicholas Bellinger 	switch (state) {
37336f3c0e69SAndy Grover 	case ISTATE_SEND_LOGOUTRSP:
37346f3c0e69SAndy Grover 		if (!iscsit_logout_post_handler(cmd, conn))
373588dcd2daSNicholas Bellinger 			return -ECONNRESET;
37366f3c0e69SAndy Grover 		/* fall through */
3737e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3738e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3739e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
3740e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
3741e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
37426f3c0e69SAndy Grover 	case ISTATE_SEND_TASKMGTRSP:
3743ba159914SNicholas Bellinger 	case ISTATE_SEND_REJECT:
37446f3c0e69SAndy Grover 		spin_lock_bh(&cmd->istate_lock);
37456f3c0e69SAndy Grover 		cmd->i_state = ISTATE_SENT_STATUS;
37466f3c0e69SAndy Grover 		spin_unlock_bh(&cmd->istate_lock);
3747e48354ceSNicholas Bellinger 		break;
3748e48354ceSNicholas Bellinger 	default:
3749e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3750e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3751e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3752e48354ceSNicholas Bellinger 		       cmd->i_state, conn->cid);
37536f3c0e69SAndy Grover 		goto err;
3754e48354ceSNicholas Bellinger 	}
3755e48354ceSNicholas Bellinger 
3756e48354ceSNicholas Bellinger 	if (atomic_read(&conn->check_immediate_queue))
3757fd3a9025SNicholas Bellinger 		return 1;
37586f3c0e69SAndy Grover 
37596f3c0e69SAndy Grover 	return 0;
37606f3c0e69SAndy Grover 
37616f3c0e69SAndy Grover err:
37626f3c0e69SAndy Grover 	return -1;
37636f3c0e69SAndy Grover }
3764d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_response_queue);
37656f3c0e69SAndy Grover 
37662ec5a8c1SNicholas Bellinger static int iscsit_handle_response_queue(struct iscsi_conn *conn)
37672ec5a8c1SNicholas Bellinger {
37682ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
37692ec5a8c1SNicholas Bellinger 	struct iscsi_queue_req *qr;
37702ec5a8c1SNicholas Bellinger 	struct iscsi_cmd *cmd;
37712ec5a8c1SNicholas Bellinger 	u8 state;
37722ec5a8c1SNicholas Bellinger 	int ret;
37732ec5a8c1SNicholas Bellinger 
37742ec5a8c1SNicholas Bellinger 	while ((qr = iscsit_get_cmd_from_response_queue(conn))) {
37752ec5a8c1SNicholas Bellinger 		cmd = qr->cmd;
37762ec5a8c1SNicholas Bellinger 		state = qr->state;
37772ec5a8c1SNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
37782ec5a8c1SNicholas Bellinger 
37792ec5a8c1SNicholas Bellinger 		ret = t->iscsit_response_queue(conn, cmd, state);
37802ec5a8c1SNicholas Bellinger 		if (ret == 1 || ret < 0)
37812ec5a8c1SNicholas Bellinger 			return ret;
37822ec5a8c1SNicholas Bellinger 	}
37832ec5a8c1SNicholas Bellinger 
37842ec5a8c1SNicholas Bellinger 	return 0;
37852ec5a8c1SNicholas Bellinger }
37862ec5a8c1SNicholas Bellinger 
37876f3c0e69SAndy Grover int iscsi_target_tx_thread(void *arg)
37886f3c0e69SAndy Grover {
37896f3c0e69SAndy Grover 	int ret = 0;
379088dcd2daSNicholas Bellinger 	struct iscsi_conn *conn = arg;
37915e0cf5e6SJiang Yi 	bool conn_freed = false;
37925e0cf5e6SJiang Yi 
37936f3c0e69SAndy Grover 	/*
37946f3c0e69SAndy Grover 	 * Allow ourselves to be interrupted by SIGINT so that a
37956f3c0e69SAndy Grover 	 * connection recovery / failure event can be triggered externally.
37966f3c0e69SAndy Grover 	 */
37976f3c0e69SAndy Grover 	allow_signal(SIGINT);
37986f3c0e69SAndy Grover 
37996f3c0e69SAndy Grover 	while (!kthread_should_stop()) {
38006f3c0e69SAndy Grover 		/*
38016f3c0e69SAndy Grover 		 * Ensure that both TX and RX per connection kthreads
38026f3c0e69SAndy Grover 		 * are scheduled to run on the same CPU.
38036f3c0e69SAndy Grover 		 */
38046f3c0e69SAndy Grover 		iscsit_thread_check_cpumask(conn, current, 1);
38056f3c0e69SAndy Grover 
3806d5627acbSRoland Dreier 		wait_event_interruptible(conn->queues_wq,
380788dcd2daSNicholas Bellinger 					 !iscsit_conn_all_queues_empty(conn));
38086f3c0e69SAndy Grover 
380988dcd2daSNicholas Bellinger 		if (signal_pending(current))
38106f3c0e69SAndy Grover 			goto transport_err;
38116f3c0e69SAndy Grover 
3812fd3a9025SNicholas Bellinger get_immediate:
38132ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_immediate_queue(conn);
38146f3c0e69SAndy Grover 		if (ret < 0)
38156f3c0e69SAndy Grover 			goto transport_err;
38166f3c0e69SAndy Grover 
38172ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_response_queue(conn);
38185e0cf5e6SJiang Yi 		if (ret == 1) {
3819fd3a9025SNicholas Bellinger 			goto get_immediate;
38205e0cf5e6SJiang Yi 		} else if (ret == -ECONNRESET) {
38215e0cf5e6SJiang Yi 			conn_freed = true;
382288dcd2daSNicholas Bellinger 			goto out;
38235e0cf5e6SJiang Yi 		} else if (ret < 0) {
38246f3c0e69SAndy Grover 			goto transport_err;
3825e48354ceSNicholas Bellinger 		}
38265e0cf5e6SJiang Yi 	}
3827e48354ceSNicholas Bellinger 
3828e48354ceSNicholas Bellinger transport_err:
3829e5419865SNicholas Bellinger 	/*
3830e5419865SNicholas Bellinger 	 * Avoid the normal connection failure code-path if this connection
3831e5419865SNicholas Bellinger 	 * is still within LOGIN mode, and iscsi_np process context is
3832e5419865SNicholas Bellinger 	 * responsible for cleaning up the early connection failure.
3833e5419865SNicholas Bellinger 	 */
3834e5419865SNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
38355e0cf5e6SJiang Yi 		iscsit_take_action_for_connection_exit(conn, &conn_freed);
3836e48354ceSNicholas Bellinger out:
38375e0cf5e6SJiang Yi 	if (!conn_freed) {
38385e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
38395e0cf5e6SJiang Yi 			msleep(100);
38405e0cf5e6SJiang Yi 		}
38415e0cf5e6SJiang Yi 	}
3842e48354ceSNicholas Bellinger 	return 0;
3843e48354ceSNicholas Bellinger }
3844e48354ceSNicholas Bellinger 
38453e1c81a9SNicholas Bellinger static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
38463e1c81a9SNicholas Bellinger {
38473e1c81a9SNicholas Bellinger 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)buf;
38483e1c81a9SNicholas Bellinger 	struct iscsi_cmd *cmd;
38493e1c81a9SNicholas Bellinger 	int ret = 0;
38503e1c81a9SNicholas Bellinger 
38513e1c81a9SNicholas Bellinger 	switch (hdr->opcode & ISCSI_OPCODE_MASK) {
38523e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_CMD:
3853676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38543e1c81a9SNicholas Bellinger 		if (!cmd)
3855ba159914SNicholas Bellinger 			goto reject;
38563e1c81a9SNicholas Bellinger 
38573e1c81a9SNicholas Bellinger 		ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
38583e1c81a9SNicholas Bellinger 		break;
38593e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_DATA_OUT:
38603e1c81a9SNicholas Bellinger 		ret = iscsit_handle_data_out(conn, buf);
38613e1c81a9SNicholas Bellinger 		break;
38623e1c81a9SNicholas Bellinger 	case ISCSI_OP_NOOP_OUT:
38633e1c81a9SNicholas Bellinger 		cmd = NULL;
38643e1c81a9SNicholas Bellinger 		if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
3865676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38663e1c81a9SNicholas Bellinger 			if (!cmd)
3867ba159914SNicholas Bellinger 				goto reject;
38683e1c81a9SNicholas Bellinger 		}
38693e1c81a9SNicholas Bellinger 		ret = iscsit_handle_nop_out(conn, cmd, buf);
38703e1c81a9SNicholas Bellinger 		break;
38713e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_TMFUNC:
3872676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38733e1c81a9SNicholas Bellinger 		if (!cmd)
3874ba159914SNicholas Bellinger 			goto reject;
38753e1c81a9SNicholas Bellinger 
38763e1c81a9SNicholas Bellinger 		ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
38773e1c81a9SNicholas Bellinger 		break;
38783e1c81a9SNicholas Bellinger 	case ISCSI_OP_TEXT:
3879e4f4e801SSagi Grimberg 		if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
3880e4f4e801SSagi Grimberg 			cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
3881e4f4e801SSagi Grimberg 			if (!cmd)
3882e4f4e801SSagi Grimberg 				goto reject;
3883e4f4e801SSagi Grimberg 		} else {
3884676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
388564534aa7SNicholas Bellinger 			if (!cmd)
3886ba159914SNicholas Bellinger 				goto reject;
3887e4f4e801SSagi Grimberg 		}
388864534aa7SNicholas Bellinger 
388964534aa7SNicholas Bellinger 		ret = iscsit_handle_text_cmd(conn, cmd, buf);
38903e1c81a9SNicholas Bellinger 		break;
38913e1c81a9SNicholas Bellinger 	case ISCSI_OP_LOGOUT:
3892676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38933e1c81a9SNicholas Bellinger 		if (!cmd)
3894ba159914SNicholas Bellinger 			goto reject;
38953e1c81a9SNicholas Bellinger 
38963e1c81a9SNicholas Bellinger 		ret = iscsit_handle_logout_cmd(conn, cmd, buf);
38973e1c81a9SNicholas Bellinger 		if (ret > 0)
38983e1c81a9SNicholas Bellinger 			wait_for_completion_timeout(&conn->conn_logout_comp,
38993e1c81a9SNicholas Bellinger 					SECONDS_FOR_LOGOUT_COMP * HZ);
39003e1c81a9SNicholas Bellinger 		break;
39013e1c81a9SNicholas Bellinger 	case ISCSI_OP_SNACK:
39023e1c81a9SNicholas Bellinger 		ret = iscsit_handle_snack(conn, buf);
39033e1c81a9SNicholas Bellinger 		break;
39043e1c81a9SNicholas Bellinger 	default:
39053e1c81a9SNicholas Bellinger 		pr_err("Got unknown iSCSI OpCode: 0x%02x\n", hdr->opcode);
39063e1c81a9SNicholas Bellinger 		if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
39073e1c81a9SNicholas Bellinger 			pr_err("Cannot recover from unknown"
39083e1c81a9SNicholas Bellinger 			" opcode while ERL=0, closing iSCSI connection.\n");
39093e1c81a9SNicholas Bellinger 			return -1;
39103e1c81a9SNicholas Bellinger 		}
3911c04a6091SChristophe Vu-Brugier 		pr_err("Unable to recover from unknown opcode while OFMarker=No,"
3912c04a6091SChristophe Vu-Brugier 		       " closing iSCSI connection.\n");
3913c04a6091SChristophe Vu-Brugier 		ret = -1;
39143e1c81a9SNicholas Bellinger 		break;
39153e1c81a9SNicholas Bellinger 	}
39163e1c81a9SNicholas Bellinger 
39173e1c81a9SNicholas Bellinger 	return ret;
3918ba159914SNicholas Bellinger reject:
3919ba159914SNicholas Bellinger 	return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
39203e1c81a9SNicholas Bellinger }
39213e1c81a9SNicholas Bellinger 
3922ca82c2bdSNicholas Bellinger static bool iscsi_target_check_conn_state(struct iscsi_conn *conn)
3923ca82c2bdSNicholas Bellinger {
3924ca82c2bdSNicholas Bellinger 	bool ret;
3925ca82c2bdSNicholas Bellinger 
3926ca82c2bdSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
3927ca82c2bdSNicholas Bellinger 	ret = (conn->conn_state != TARG_CONN_STATE_LOGGED_IN);
3928ca82c2bdSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
3929ca82c2bdSNicholas Bellinger 
3930ca82c2bdSNicholas Bellinger 	return ret;
3931ca82c2bdSNicholas Bellinger }
3932ca82c2bdSNicholas Bellinger 
3933e8205ccaSVarun Prakash static void iscsit_get_rx_pdu(struct iscsi_conn *conn)
3934e48354ceSNicholas Bellinger {
3935e8205ccaSVarun Prakash 	int ret;
3936e48354ceSNicholas Bellinger 	u8 buffer[ISCSI_HDR_LEN], opcode;
3937e48354ceSNicholas Bellinger 	u32 checksum = 0, digest = 0;
3938e48354ceSNicholas Bellinger 	struct kvec iov;
39393e1c81a9SNicholas Bellinger 
3940e48354ceSNicholas Bellinger 	while (!kthread_should_stop()) {
3941e48354ceSNicholas Bellinger 		/*
3942e48354ceSNicholas Bellinger 		 * Ensure that both TX and RX per connection kthreads
3943e48354ceSNicholas Bellinger 		 * are scheduled to run on the same CPU.
3944e48354ceSNicholas Bellinger 		 */
3945e48354ceSNicholas Bellinger 		iscsit_thread_check_cpumask(conn, current, 0);
3946e48354ceSNicholas Bellinger 
3947e48354ceSNicholas Bellinger 		memset(buffer, 0, ISCSI_HDR_LEN);
3948e48354ceSNicholas Bellinger 		memset(&iov, 0, sizeof(struct kvec));
3949e48354ceSNicholas Bellinger 
3950e48354ceSNicholas Bellinger 		iov.iov_base	= buffer;
3951e48354ceSNicholas Bellinger 		iov.iov_len	= ISCSI_HDR_LEN;
3952e48354ceSNicholas Bellinger 
3953e48354ceSNicholas Bellinger 		ret = rx_data(conn, &iov, 1, ISCSI_HDR_LEN);
3954e48354ceSNicholas Bellinger 		if (ret != ISCSI_HDR_LEN) {
3955e48354ceSNicholas Bellinger 			iscsit_rx_thread_wait_for_tcp(conn);
3956e8205ccaSVarun Prakash 			return;
3957e48354ceSNicholas Bellinger 		}
3958e48354ceSNicholas Bellinger 
3959e48354ceSNicholas Bellinger 		if (conn->conn_ops->HeaderDigest) {
3960e48354ceSNicholas Bellinger 			iov.iov_base	= &digest;
3961e48354ceSNicholas Bellinger 			iov.iov_len	= ISCSI_CRC_LEN;
3962e48354ceSNicholas Bellinger 
3963e48354ceSNicholas Bellinger 			ret = rx_data(conn, &iov, 1, ISCSI_CRC_LEN);
3964e48354ceSNicholas Bellinger 			if (ret != ISCSI_CRC_LEN) {
3965e48354ceSNicholas Bellinger 				iscsit_rx_thread_wait_for_tcp(conn);
3966e8205ccaSVarun Prakash 				return;
3967e48354ceSNicholas Bellinger 			}
3968e48354ceSNicholas Bellinger 
3969e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer,
3970e1dfb21fSBart Van Assche 						  ISCSI_HDR_LEN, 0, NULL,
3971e1dfb21fSBart Van Assche 						  &checksum);
3972e48354ceSNicholas Bellinger 
3973e48354ceSNicholas Bellinger 			if (digest != checksum) {
3974e48354ceSNicholas Bellinger 				pr_err("HeaderDigest CRC32C failed,"
3975e48354ceSNicholas Bellinger 					" received 0x%08x, computed 0x%08x\n",
3976e48354ceSNicholas Bellinger 					digest, checksum);
3977e48354ceSNicholas Bellinger 				/*
3978e48354ceSNicholas Bellinger 				 * Set the PDU to 0xff so it will intentionally
3979e48354ceSNicholas Bellinger 				 * hit default in the switch below.
3980e48354ceSNicholas Bellinger 				 */
3981e48354ceSNicholas Bellinger 				memset(buffer, 0xff, ISCSI_HDR_LEN);
398204f3b31bSNicholas Bellinger 				atomic_long_inc(&conn->sess->conn_digest_errors);
3983e48354ceSNicholas Bellinger 			} else {
3984e48354ceSNicholas Bellinger 				pr_debug("Got HeaderDigest CRC32C"
3985e48354ceSNicholas Bellinger 						" 0x%08x\n", checksum);
3986e48354ceSNicholas Bellinger 			}
3987e48354ceSNicholas Bellinger 		}
3988e48354ceSNicholas Bellinger 
3989e48354ceSNicholas Bellinger 		if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT)
3990e8205ccaSVarun Prakash 			return;
3991e48354ceSNicholas Bellinger 
3992e48354ceSNicholas Bellinger 		opcode = buffer[0] & ISCSI_OPCODE_MASK;
3993e48354ceSNicholas Bellinger 
3994e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->SessionType &&
3995e48354ceSNicholas Bellinger 		   ((!(opcode & ISCSI_OP_TEXT)) ||
3996e48354ceSNicholas Bellinger 		    (!(opcode & ISCSI_OP_LOGOUT)))) {
3997e48354ceSNicholas Bellinger 			pr_err("Received illegal iSCSI Opcode: 0x%02x"
3998e48354ceSNicholas Bellinger 			" while in Discovery Session, rejecting.\n", opcode);
3999ba159914SNicholas Bellinger 			iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
4000ba159914SNicholas Bellinger 					  buffer);
4001e8205ccaSVarun Prakash 			return;
4002e48354ceSNicholas Bellinger 		}
4003e48354ceSNicholas Bellinger 
40043e1c81a9SNicholas Bellinger 		ret = iscsi_target_rx_opcode(conn, buffer);
40053e1c81a9SNicholas Bellinger 		if (ret < 0)
4006e8205ccaSVarun Prakash 			return;
4007e8205ccaSVarun Prakash 	}
4008e48354ceSNicholas Bellinger }
4009e48354ceSNicholas Bellinger 
4010e8205ccaSVarun Prakash int iscsi_target_rx_thread(void *arg)
4011e8205ccaSVarun Prakash {
4012e8205ccaSVarun Prakash 	int rc;
4013e8205ccaSVarun Prakash 	struct iscsi_conn *conn = arg;
40145e0cf5e6SJiang Yi 	bool conn_freed = false;
4015e8205ccaSVarun Prakash 
4016e8205ccaSVarun Prakash 	/*
4017e8205ccaSVarun Prakash 	 * Allow ourselves to be interrupted by SIGINT so that a
4018e8205ccaSVarun Prakash 	 * connection recovery / failure event can be triggered externally.
4019e8205ccaSVarun Prakash 	 */
4020e8205ccaSVarun Prakash 	allow_signal(SIGINT);
4021e8205ccaSVarun Prakash 	/*
4022e8205ccaSVarun Prakash 	 * Wait for iscsi_post_login_handler() to complete before allowing
4023e8205ccaSVarun Prakash 	 * incoming iscsi/tcp socket I/O, and/or failing the connection.
4024e8205ccaSVarun Prakash 	 */
4025e8205ccaSVarun Prakash 	rc = wait_for_completion_interruptible(&conn->rx_login_comp);
4026e8205ccaSVarun Prakash 	if (rc < 0 || iscsi_target_check_conn_state(conn))
40275e0cf5e6SJiang Yi 		goto out;
4028e8205ccaSVarun Prakash 
4029e8205ccaSVarun Prakash 	if (!conn->conn_transport->iscsit_get_rx_pdu)
4030e8205ccaSVarun Prakash 		return 0;
4031e8205ccaSVarun Prakash 
4032e8205ccaSVarun Prakash 	conn->conn_transport->iscsit_get_rx_pdu(conn);
4033e8205ccaSVarun Prakash 
4034e48354ceSNicholas Bellinger 	if (!signal_pending(current))
4035e48354ceSNicholas Bellinger 		atomic_set(&conn->transport_failed, 1);
40365e0cf5e6SJiang Yi 	iscsit_take_action_for_connection_exit(conn, &conn_freed);
40375e0cf5e6SJiang Yi 
40385e0cf5e6SJiang Yi out:
40395e0cf5e6SJiang Yi 	if (!conn_freed) {
40405e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
40415e0cf5e6SJiang Yi 			msleep(100);
40425e0cf5e6SJiang Yi 		}
40435e0cf5e6SJiang Yi 	}
40445e0cf5e6SJiang Yi 
4045e48354ceSNicholas Bellinger 	return 0;
4046e48354ceSNicholas Bellinger }
4047e48354ceSNicholas Bellinger 
4048e48354ceSNicholas Bellinger static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
4049e48354ceSNicholas Bellinger {
4050064cdd2dSNicholas Bellinger 	LIST_HEAD(tmp_list);
4051e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
4052e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4053e48354ceSNicholas Bellinger 	/*
4054e48354ceSNicholas Bellinger 	 * We expect this function to only ever be called from either RX or TX
4055e48354ceSNicholas Bellinger 	 * thread context via iscsit_close_connection() once the other context
4056e48354ceSNicholas Bellinger 	 * has been reset -> returned sleeping pre-handler state.
4057e48354ceSNicholas Bellinger 	 */
4058e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
4059064cdd2dSNicholas Bellinger 	list_splice_init(&conn->conn_cmd_list, &tmp_list);
4060e48354ceSNicholas Bellinger 
4061064cdd2dSNicholas Bellinger 	list_for_each_entry(cmd, &tmp_list, i_conn_node) {
4062064cdd2dSNicholas Bellinger 		struct se_cmd *se_cmd = &cmd->se_cmd;
4063e48354ceSNicholas Bellinger 
4064064cdd2dSNicholas Bellinger 		if (se_cmd->se_tfo != NULL) {
4065064cdd2dSNicholas Bellinger 			spin_lock(&se_cmd->t_state_lock);
4066064cdd2dSNicholas Bellinger 			se_cmd->transport_state |= CMD_T_FABRIC_STOP;
4067064cdd2dSNicholas Bellinger 			spin_unlock(&se_cmd->t_state_lock);
4068064cdd2dSNicholas Bellinger 		}
4069e48354ceSNicholas Bellinger 	}
4070e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4071064cdd2dSNicholas Bellinger 
4072064cdd2dSNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
4073064cdd2dSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
4074064cdd2dSNicholas Bellinger 
4075064cdd2dSNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, sess);
4076064cdd2dSNicholas Bellinger 		iscsit_free_cmd(cmd, true);
4077064cdd2dSNicholas Bellinger 
4078064cdd2dSNicholas Bellinger 	}
4079e48354ceSNicholas Bellinger }
4080e48354ceSNicholas Bellinger 
4081e48354ceSNicholas Bellinger static void iscsit_stop_timers_for_cmds(
4082e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4083e48354ceSNicholas Bellinger {
4084e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
4085e48354ceSNicholas Bellinger 
4086e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
40872fbb471eSAndy Grover 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
4088e48354ceSNicholas Bellinger 		if (cmd->data_direction == DMA_TO_DEVICE)
4089e48354ceSNicholas Bellinger 			iscsit_stop_dataout_timer(cmd);
4090e48354ceSNicholas Bellinger 	}
4091e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4092e48354ceSNicholas Bellinger }
4093e48354ceSNicholas Bellinger 
4094e48354ceSNicholas Bellinger int iscsit_close_connection(
4095e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4096e48354ceSNicholas Bellinger {
4097e48354ceSNicholas Bellinger 	int conn_logout = (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT);
4098e48354ceSNicholas Bellinger 	struct iscsi_session	*sess = conn->sess;
4099e48354ceSNicholas Bellinger 
4100e48354ceSNicholas Bellinger 	pr_debug("Closing iSCSI connection CID %hu on SID:"
4101e48354ceSNicholas Bellinger 		" %u\n", conn->cid, sess->sid);
4102e48354ceSNicholas Bellinger 	/*
4103b4869ee9SVarun Prakash 	 * Always up conn_logout_comp for the traditional TCP and HW_OFFLOAD
4104b4869ee9SVarun Prakash 	 * case just in case the RX Thread in iscsi_target_rx_opcode() is
4105b4869ee9SVarun Prakash 	 * sleeping and the logout response never got sent because the
4106b4869ee9SVarun Prakash 	 * connection failed.
4107f068fbc8SNicholas Bellinger 	 *
4108f068fbc8SNicholas Bellinger 	 * However for iser-target, isert_wait4logout() is using conn_logout_comp
4109f068fbc8SNicholas Bellinger 	 * to signal logout response TX interrupt completion.  Go ahead and skip
4110f068fbc8SNicholas Bellinger 	 * this for iser since isert_rx_opcode() does not wait on logout failure,
4111f068fbc8SNicholas Bellinger 	 * and to avoid iscsi_conn pointer dereference in iser-target code.
4112e48354ceSNicholas Bellinger 	 */
4113bd027d85SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown)
4114e48354ceSNicholas Bellinger 		complete(&conn->conn_logout_comp);
4115e48354ceSNicholas Bellinger 
411688dcd2daSNicholas Bellinger 	if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) {
411788dcd2daSNicholas Bellinger 		if (conn->tx_thread &&
411888dcd2daSNicholas Bellinger 		    cmpxchg(&conn->tx_thread_active, true, false)) {
411988dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->tx_thread, 1);
412088dcd2daSNicholas Bellinger 			kthread_stop(conn->tx_thread);
412188dcd2daSNicholas Bellinger 		}
412288dcd2daSNicholas Bellinger 	} else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) {
412388dcd2daSNicholas Bellinger 		if (conn->rx_thread &&
412488dcd2daSNicholas Bellinger 		    cmpxchg(&conn->rx_thread_active, true, false)) {
412588dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->rx_thread, 1);
412688dcd2daSNicholas Bellinger 			kthread_stop(conn->rx_thread);
412788dcd2daSNicholas Bellinger 		}
412888dcd2daSNicholas Bellinger 	}
412988dcd2daSNicholas Bellinger 
413088dcd2daSNicholas Bellinger 	spin_lock(&iscsit_global->ts_bitmap_lock);
413188dcd2daSNicholas Bellinger 	bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
413288dcd2daSNicholas Bellinger 			      get_order(1));
413388dcd2daSNicholas Bellinger 	spin_unlock(&iscsit_global->ts_bitmap_lock);
4134e48354ceSNicholas Bellinger 
4135e48354ceSNicholas Bellinger 	iscsit_stop_timers_for_cmds(conn);
4136e48354ceSNicholas Bellinger 	iscsit_stop_nopin_response_timer(conn);
4137e48354ceSNicholas Bellinger 	iscsit_stop_nopin_timer(conn);
4138defd8848SNicholas Bellinger 
4139defd8848SNicholas Bellinger 	if (conn->conn_transport->iscsit_wait_conn)
4140defd8848SNicholas Bellinger 		conn->conn_transport->iscsit_wait_conn(conn);
4141defd8848SNicholas Bellinger 
4142e48354ceSNicholas Bellinger 	/*
4143e48354ceSNicholas Bellinger 	 * During Connection recovery drop unacknowledged out of order
4144e48354ceSNicholas Bellinger 	 * commands for this connection, and prepare the other commands
414553c561dcSBart Van Assche 	 * for reallegiance.
4146e48354ceSNicholas Bellinger 	 *
4147e48354ceSNicholas Bellinger 	 * During normal operation clear the out of order commands (but
4148e48354ceSNicholas Bellinger 	 * do not free the struct iscsi_ooo_cmdsn's) and release all
4149e48354ceSNicholas Bellinger 	 * struct iscsi_cmds.
4150e48354ceSNicholas Bellinger 	 */
4151e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery)) {
4152e48354ceSNicholas Bellinger 		iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(conn);
415353c561dcSBart Van Assche 		iscsit_prepare_cmds_for_reallegiance(conn);
4154e48354ceSNicholas Bellinger 	} else {
4155e48354ceSNicholas Bellinger 		iscsit_clear_ooo_cmdsns_for_conn(conn);
4156e48354ceSNicholas Bellinger 		iscsit_release_commands_from_conn(conn);
4157e48354ceSNicholas Bellinger 	}
4158bbc05048SNicholas Bellinger 	iscsit_free_queue_reqs_for_conn(conn);
4159e48354ceSNicholas Bellinger 
4160e48354ceSNicholas Bellinger 	/*
4161e48354ceSNicholas Bellinger 	 * Handle decrementing session or connection usage count if
4162e48354ceSNicholas Bellinger 	 * a logout response was not able to be sent because the
4163e48354ceSNicholas Bellinger 	 * connection failed.  Fall back to Session Recovery here.
4164e48354ceSNicholas Bellinger 	 */
4165e48354ceSNicholas Bellinger 	if (atomic_read(&conn->conn_logout_remove)) {
4166e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_SESSION) {
4167e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4168e48354ceSNicholas Bellinger 			iscsit_dec_session_usage_count(sess);
4169e48354ceSNicholas Bellinger 		}
4170e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION)
4171e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4172e48354ceSNicholas Bellinger 
4173e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 0);
4174e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 0);
4175e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4176e48354ceSNicholas Bellinger 	}
4177e48354ceSNicholas Bellinger 
4178e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4179e48354ceSNicholas Bellinger 	list_del(&conn->conn_list);
4180e48354ceSNicholas Bellinger 
4181e48354ceSNicholas Bellinger 	/*
4182e48354ceSNicholas Bellinger 	 * Attempt to let the Initiator know this connection failed by
4183e48354ceSNicholas Bellinger 	 * sending an Connection Dropped Async Message on another
4184e48354ceSNicholas Bellinger 	 * active connection.
4185e48354ceSNicholas Bellinger 	 */
4186e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery))
4187e48354ceSNicholas Bellinger 		iscsit_build_conn_drop_async_message(conn);
4188e48354ceSNicholas Bellinger 
4189e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4190e48354ceSNicholas Bellinger 
4191e48354ceSNicholas Bellinger 	/*
4192e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection,
4193e48354ceSNicholas Bellinger 	 * up the connection reinstatement semaphore that is being blocked on
4194e48354ceSNicholas Bellinger 	 * in iscsit_cause_connection_reinstatement().
4195e48354ceSNicholas Bellinger 	 */
4196e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
4197e48354ceSNicholas Bellinger 	if (atomic_read(&conn->sleep_on_conn_wait_comp)) {
4198e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4199e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_comp);
4200e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4201e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4202e48354ceSNicholas Bellinger 	}
4203e48354ceSNicholas Bellinger 
4204e48354ceSNicholas Bellinger 	/*
4205e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection
4206e48354ceSNicholas Bellinger 	 * by receiving a REMOVECONNFORRECOVERY logout request, up the
4207e48354ceSNicholas Bellinger 	 * connection wait rcfr semaphore that is being blocked on
4208e48354ceSNicholas Bellinger 	 * an iscsit_connection_reinstatement_rcfr().
4209e48354ceSNicholas Bellinger 	 */
4210e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_wait_rcfr)) {
4211e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4212e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_rcfr_comp);
4213e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4214e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4215e48354ceSNicholas Bellinger 	}
4216e48354ceSNicholas Bellinger 	atomic_set(&conn->connection_reinstatement, 1);
4217e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
4218e48354ceSNicholas Bellinger 
4219e48354ceSNicholas Bellinger 	/*
4220e48354ceSNicholas Bellinger 	 * If any other processes are accessing this connection pointer we
4221e48354ceSNicholas Bellinger 	 * must wait until they have completed.
4222e48354ceSNicholas Bellinger 	 */
4223e48354ceSNicholas Bellinger 	iscsit_check_conn_usage_count(conn);
4224e48354ceSNicholas Bellinger 
422569110e3cSHerbert Xu 	ahash_request_free(conn->conn_tx_hash);
422669110e3cSHerbert Xu 	if (conn->conn_rx_hash) {
422769110e3cSHerbert Xu 		struct crypto_ahash *tfm;
422869110e3cSHerbert Xu 
422969110e3cSHerbert Xu 		tfm = crypto_ahash_reqtfm(conn->conn_rx_hash);
423069110e3cSHerbert Xu 		ahash_request_free(conn->conn_rx_hash);
423169110e3cSHerbert Xu 		crypto_free_ahash(tfm);
423269110e3cSHerbert Xu 	}
4233e48354ceSNicholas Bellinger 
4234e48354ceSNicholas Bellinger 	free_cpumask_var(conn->conn_cpumask);
4235e48354ceSNicholas Bellinger 
4236e48354ceSNicholas Bellinger 	kfree(conn->conn_ops);
4237e48354ceSNicholas Bellinger 	conn->conn_ops = NULL;
4238e48354ceSNicholas Bellinger 
4239bf6932f4SAl Viro 	if (conn->sock)
4240e48354ceSNicholas Bellinger 		sock_release(conn->sock);
4241baa4d64bSNicholas Bellinger 
4242baa4d64bSNicholas Bellinger 	if (conn->conn_transport->iscsit_free_conn)
4243baa4d64bSNicholas Bellinger 		conn->conn_transport->iscsit_free_conn(conn);
4244baa4d64bSNicholas Bellinger 
4245baa4d64bSNicholas Bellinger 	iscsit_put_transport(conn->conn_transport);
4246baa4d64bSNicholas Bellinger 
4247e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
4248e48354ceSNicholas Bellinger 	conn->conn_state = TARG_CONN_STATE_FREE;
4249e48354ceSNicholas Bellinger 	kfree(conn);
4250e48354ceSNicholas Bellinger 
4251e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4252e48354ceSNicholas Bellinger 	atomic_dec(&sess->nconn);
4253e48354ceSNicholas Bellinger 	pr_debug("Decremented iSCSI connection count to %hu from node:"
4254e48354ceSNicholas Bellinger 		" %s\n", atomic_read(&sess->nconn),
4255e48354ceSNicholas Bellinger 		sess->sess_ops->InitiatorName);
4256e48354ceSNicholas Bellinger 	/*
4257e48354ceSNicholas Bellinger 	 * Make sure that if one connection fails in an non ERL=2 iSCSI
4258e48354ceSNicholas Bellinger 	 * Session that they all fail.
4259e48354ceSNicholas Bellinger 	 */
4260e48354ceSNicholas Bellinger 	if ((sess->sess_ops->ErrorRecoveryLevel != 2) && !conn_logout &&
4261e48354ceSNicholas Bellinger 	     !atomic_read(&sess->session_logout))
4262e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4263e48354ceSNicholas Bellinger 
4264e48354ceSNicholas Bellinger 	/*
4265e48354ceSNicholas Bellinger 	 * If this was not the last connection in the session, and we are
4266e48354ceSNicholas Bellinger 	 * performing session reinstatement or falling back to ERL=0, call
4267e48354ceSNicholas Bellinger 	 * iscsit_stop_session() without sleeping to shutdown the other
4268e48354ceSNicholas Bellinger 	 * active connections.
4269e48354ceSNicholas Bellinger 	 */
4270e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4271e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_reinstatement) &&
4272e48354ceSNicholas Bellinger 		    !atomic_read(&sess->session_fall_back_to_erl0)) {
4273e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4274e48354ceSNicholas Bellinger 			return 0;
4275e48354ceSNicholas Bellinger 		}
4276e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_stop_active)) {
4277e48354ceSNicholas Bellinger 			atomic_set(&sess->session_stop_active, 1);
4278e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4279e48354ceSNicholas Bellinger 			iscsit_stop_session(sess, 0, 0);
4280e48354ceSNicholas Bellinger 			return 0;
4281e48354ceSNicholas Bellinger 		}
4282e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4283e48354ceSNicholas Bellinger 		return 0;
4284e48354ceSNicholas Bellinger 	}
4285e48354ceSNicholas Bellinger 
4286e48354ceSNicholas Bellinger 	/*
4287e48354ceSNicholas Bellinger 	 * If this was the last connection in the session and one of the
4288e48354ceSNicholas Bellinger 	 * following is occurring:
4289e48354ceSNicholas Bellinger 	 *
4290e48354ceSNicholas Bellinger 	 * Session Reinstatement is not being performed, and are falling back
4291e48354ceSNicholas Bellinger 	 * to ERL=0 call iscsit_close_session().
4292e48354ceSNicholas Bellinger 	 *
4293e48354ceSNicholas Bellinger 	 * Session Logout was requested.  iscsit_close_session() will be called
4294e48354ceSNicholas Bellinger 	 * elsewhere.
4295e48354ceSNicholas Bellinger 	 *
4296e48354ceSNicholas Bellinger 	 * Session Continuation is not being performed, start the Time2Retain
4297e48354ceSNicholas Bellinger 	 * handler and check if sleep_on_sess_wait_sem is active.
4298e48354ceSNicholas Bellinger 	 */
4299e48354ceSNicholas Bellinger 	if (!atomic_read(&sess->session_reinstatement) &&
4300e48354ceSNicholas Bellinger 	     atomic_read(&sess->session_fall_back_to_erl0)) {
4301e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
430244f33d0fSChristoph Hellwig 		iscsit_close_session(sess);
4303e48354ceSNicholas Bellinger 
4304e48354ceSNicholas Bellinger 		return 0;
4305e48354ceSNicholas Bellinger 	} else if (atomic_read(&sess->session_logout)) {
4306e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4307e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FREE;
4308e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4309e48354ceSNicholas Bellinger 
4310e48354ceSNicholas Bellinger 		if (atomic_read(&sess->sleep_on_sess_wait_comp))
4311e48354ceSNicholas Bellinger 			complete(&sess->session_wait_comp);
4312e48354ceSNicholas Bellinger 
4313e48354ceSNicholas Bellinger 		return 0;
4314e48354ceSNicholas Bellinger 	} else {
4315e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4316e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FAILED;
4317e48354ceSNicholas Bellinger 
4318e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_continuation)) {
4319e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4320e48354ceSNicholas Bellinger 			iscsit_start_time2retain_handler(sess);
4321e48354ceSNicholas Bellinger 		} else
4322e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4323e48354ceSNicholas Bellinger 
4324e48354ceSNicholas Bellinger 		if (atomic_read(&sess->sleep_on_sess_wait_comp))
4325e48354ceSNicholas Bellinger 			complete(&sess->session_wait_comp);
4326e48354ceSNicholas Bellinger 
4327e48354ceSNicholas Bellinger 		return 0;
4328e48354ceSNicholas Bellinger 	}
4329e48354ceSNicholas Bellinger }
4330e48354ceSNicholas Bellinger 
433144f33d0fSChristoph Hellwig /*
433244f33d0fSChristoph Hellwig  * If the iSCSI Session for the iSCSI Initiator Node exists,
433344f33d0fSChristoph Hellwig  * forcefully shutdown the iSCSI NEXUS.
433444f33d0fSChristoph Hellwig  */
4335e48354ceSNicholas Bellinger int iscsit_close_session(struct iscsi_session *sess)
4336e48354ceSNicholas Bellinger {
433760bfcf8eSAndy Grover 	struct iscsi_portal_group *tpg = sess->tpg;
4338e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4339e48354ceSNicholas Bellinger 
4340e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4341e48354ceSNicholas Bellinger 		pr_err("%d connection(s) still exist for iSCSI session"
4342e48354ceSNicholas Bellinger 			" to %s\n", atomic_read(&sess->nconn),
4343e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4344e48354ceSNicholas Bellinger 		BUG();
4345e48354ceSNicholas Bellinger 	}
4346e48354ceSNicholas Bellinger 
4347e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4348e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
4349e48354ceSNicholas Bellinger 	atomic_set(&sess->session_reinstatement, 1);
4350e48354ceSNicholas Bellinger 	iscsit_stop_time2retain_timer(sess);
4351e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4352e48354ceSNicholas Bellinger 
4353e48354ceSNicholas Bellinger 	/*
4354e48354ceSNicholas Bellinger 	 * transport_deregister_session_configfs() will clear the
4355e48354ceSNicholas Bellinger 	 * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context
4356e48354ceSNicholas Bellinger 	 * can be setting it again with __transport_register_session() in
4357e48354ceSNicholas Bellinger 	 * iscsi_post_login_handler() again after the iscsit_stop_session()
4358e48354ceSNicholas Bellinger 	 * completes in iscsi_np context.
4359e48354ceSNicholas Bellinger 	 */
4360e48354ceSNicholas Bellinger 	transport_deregister_session_configfs(sess->se_sess);
4361e48354ceSNicholas Bellinger 
4362e48354ceSNicholas Bellinger 	/*
4363e48354ceSNicholas Bellinger 	 * If any other processes are accessing this session pointer we must
4364e48354ceSNicholas Bellinger 	 * wait until they have completed.  If we are in an interrupt (the
4365e48354ceSNicholas Bellinger 	 * time2retain handler) and contain and active session usage count we
4366e48354ceSNicholas Bellinger 	 * restart the timer and exit.
4367e48354ceSNicholas Bellinger 	 */
4368e48354ceSNicholas Bellinger 	if (!in_interrupt()) {
4369e48354ceSNicholas Bellinger 		if (iscsit_check_session_usage_count(sess) == 1)
4370e48354ceSNicholas Bellinger 			iscsit_stop_session(sess, 1, 1);
4371e48354ceSNicholas Bellinger 	} else {
4372e48354ceSNicholas Bellinger 		if (iscsit_check_session_usage_count(sess) == 2) {
4373e48354ceSNicholas Bellinger 			atomic_set(&sess->session_logout, 0);
4374e48354ceSNicholas Bellinger 			iscsit_start_time2retain_handler(sess);
4375e48354ceSNicholas Bellinger 			return 0;
4376e48354ceSNicholas Bellinger 		}
4377e48354ceSNicholas Bellinger 	}
4378e48354ceSNicholas Bellinger 
4379e48354ceSNicholas Bellinger 	transport_deregister_session(sess->se_sess);
4380e48354ceSNicholas Bellinger 
4381e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel == 2)
4382e48354ceSNicholas Bellinger 		iscsit_free_connection_recovery_entires(sess);
4383e48354ceSNicholas Bellinger 
4384e48354ceSNicholas Bellinger 	iscsit_free_all_ooo_cmdsns(sess);
4385e48354ceSNicholas Bellinger 
4386e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4387e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4388e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FREE;
4389e48354ceSNicholas Bellinger 	pr_debug("Released iSCSI session from node: %s\n",
4390e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4391e48354ceSNicholas Bellinger 	tpg->nsessions--;
4392e48354ceSNicholas Bellinger 	if (tpg->tpg_tiqn)
4393e48354ceSNicholas Bellinger 		tpg->tpg_tiqn->tiqn_nsessions--;
4394e48354ceSNicholas Bellinger 
4395e48354ceSNicholas Bellinger 	pr_debug("Decremented number of active iSCSI Sessions on"
4396e48354ceSNicholas Bellinger 		" iSCSI TPG: %hu to %u\n", tpg->tpgt, tpg->nsessions);
4397e48354ceSNicholas Bellinger 
4398e48354ceSNicholas Bellinger 	spin_lock(&sess_idr_lock);
4399e48354ceSNicholas Bellinger 	idr_remove(&sess_idr, sess->session_index);
4400e48354ceSNicholas Bellinger 	spin_unlock(&sess_idr_lock);
4401e48354ceSNicholas Bellinger 
4402e48354ceSNicholas Bellinger 	kfree(sess->sess_ops);
4403e48354ceSNicholas Bellinger 	sess->sess_ops = NULL;
4404e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4405e48354ceSNicholas Bellinger 
4406e48354ceSNicholas Bellinger 	kfree(sess);
4407e48354ceSNicholas Bellinger 	return 0;
4408e48354ceSNicholas Bellinger }
4409e48354ceSNicholas Bellinger 
4410e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_closesession(
4411e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4412e48354ceSNicholas Bellinger {
4413e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4414007d038bSNicholas Bellinger 	int sleep = 1;
4415007d038bSNicholas Bellinger 	/*
4416007d038bSNicholas Bellinger 	 * Traditional iscsi/tcp will invoke this logic from TX thread
4417007d038bSNicholas Bellinger 	 * context during session logout, so clear tx_thread_active and
4418007d038bSNicholas Bellinger 	 * sleep if iscsit_close_connection() has not already occured.
4419007d038bSNicholas Bellinger 	 *
4420007d038bSNicholas Bellinger 	 * Since iser-target invokes this logic from it's own workqueue,
4421007d038bSNicholas Bellinger 	 * always sleep waiting for RX/TX thread shutdown to complete
4422007d038bSNicholas Bellinger 	 * within iscsit_close_connection().
4423007d038bSNicholas Bellinger 	 */
4424105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4425007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4426105fa2f4SNicholas Bellinger 		if (!sleep)
4427105fa2f4SNicholas Bellinger 			return;
4428105fa2f4SNicholas Bellinger 	}
4429e48354ceSNicholas Bellinger 
4430e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4431e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4432e48354ceSNicholas Bellinger 
4433e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
443488dcd2daSNicholas Bellinger 	iscsit_stop_session(sess, sleep, sleep);
4435e48354ceSNicholas Bellinger 	iscsit_dec_session_usage_count(sess);
443644f33d0fSChristoph Hellwig 	iscsit_close_session(sess);
4437e48354ceSNicholas Bellinger }
4438e48354ceSNicholas Bellinger 
4439e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_samecid(
4440e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4441e48354ceSNicholas Bellinger {
4442007d038bSNicholas Bellinger 	int sleep = 1;
4443007d038bSNicholas Bellinger 
4444105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4445007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4446105fa2f4SNicholas Bellinger 		if (!sleep)
4447105fa2f4SNicholas Bellinger 			return;
4448105fa2f4SNicholas Bellinger 	}
4449e48354ceSNicholas Bellinger 
4450e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4451e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4452e48354ceSNicholas Bellinger 
445388dcd2daSNicholas Bellinger 	iscsit_cause_connection_reinstatement(conn, sleep);
4454e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
4455e48354ceSNicholas Bellinger }
4456e48354ceSNicholas Bellinger 
4457e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_diffcid(
4458e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
4459e48354ceSNicholas Bellinger 	u16 cid)
4460e48354ceSNicholas Bellinger {
4461e48354ceSNicholas Bellinger 	struct iscsi_conn *l_conn;
4462e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4463b53b0d99SNicholas Bellinger 	bool conn_found = false;
4464e48354ceSNicholas Bellinger 
4465e48354ceSNicholas Bellinger 	if (!sess)
4466e48354ceSNicholas Bellinger 		return;
4467e48354ceSNicholas Bellinger 
4468e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4469e48354ceSNicholas Bellinger 	list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) {
4470e48354ceSNicholas Bellinger 		if (l_conn->cid == cid) {
4471e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(l_conn);
4472b53b0d99SNicholas Bellinger 			conn_found = true;
4473e48354ceSNicholas Bellinger 			break;
4474e48354ceSNicholas Bellinger 		}
4475e48354ceSNicholas Bellinger 	}
4476e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4477e48354ceSNicholas Bellinger 
4478b53b0d99SNicholas Bellinger 	if (!conn_found)
4479e48354ceSNicholas Bellinger 		return;
4480e48354ceSNicholas Bellinger 
4481e48354ceSNicholas Bellinger 	if (l_conn->sock)
4482e48354ceSNicholas Bellinger 		l_conn->sock->ops->shutdown(l_conn->sock, RCV_SHUTDOWN);
4483e48354ceSNicholas Bellinger 
4484e48354ceSNicholas Bellinger 	spin_lock_bh(&l_conn->state_lock);
4485e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
4486e48354ceSNicholas Bellinger 	l_conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
4487e48354ceSNicholas Bellinger 	spin_unlock_bh(&l_conn->state_lock);
4488e48354ceSNicholas Bellinger 
4489e48354ceSNicholas Bellinger 	iscsit_cause_connection_reinstatement(l_conn, 1);
4490e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(l_conn);
4491e48354ceSNicholas Bellinger }
4492e48354ceSNicholas Bellinger 
4493e48354ceSNicholas Bellinger /*
4494e48354ceSNicholas Bellinger  *	Return of 0 causes the TX thread to restart.
4495e48354ceSNicholas Bellinger  */
44962ec5a8c1SNicholas Bellinger int iscsit_logout_post_handler(
4497e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
4498e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4499e48354ceSNicholas Bellinger {
4500e48354ceSNicholas Bellinger 	int ret = 0;
4501e48354ceSNicholas Bellinger 
4502e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
4503e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
4504e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4505e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4506e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4507e48354ceSNicholas Bellinger 		default:
4508e48354ceSNicholas Bellinger 			iscsit_logout_post_handler_closesession(conn);
4509e48354ceSNicholas Bellinger 			break;
4510e48354ceSNicholas Bellinger 		}
4511e48354ceSNicholas Bellinger 		ret = 0;
4512e48354ceSNicholas Bellinger 		break;
4513e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
4514e48354ceSNicholas Bellinger 		if (conn->cid == cmd->logout_cid) {
4515e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4516e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4517e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4518e48354ceSNicholas Bellinger 			default:
4519e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_samecid(conn);
4520e48354ceSNicholas Bellinger 				break;
4521e48354ceSNicholas Bellinger 			}
4522e48354ceSNicholas Bellinger 			ret = 0;
4523e48354ceSNicholas Bellinger 		} else {
4524e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4525e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4526e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_diffcid(conn,
4527e48354ceSNicholas Bellinger 					cmd->logout_cid);
4528e48354ceSNicholas Bellinger 				break;
4529e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CID_NOT_FOUND:
4530e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4531e48354ceSNicholas Bellinger 			default:
4532e48354ceSNicholas Bellinger 				break;
4533e48354ceSNicholas Bellinger 			}
4534e48354ceSNicholas Bellinger 			ret = 1;
4535e48354ceSNicholas Bellinger 		}
4536e48354ceSNicholas Bellinger 		break;
4537e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
4538e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4539e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4540e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CID_NOT_FOUND:
4541e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
4542e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4543e48354ceSNicholas Bellinger 		default:
4544e48354ceSNicholas Bellinger 			break;
4545e48354ceSNicholas Bellinger 		}
4546e48354ceSNicholas Bellinger 		ret = 1;
4547e48354ceSNicholas Bellinger 		break;
4548e48354ceSNicholas Bellinger 	default:
4549e48354ceSNicholas Bellinger 		break;
4550e48354ceSNicholas Bellinger 
4551e48354ceSNicholas Bellinger 	}
4552e48354ceSNicholas Bellinger 	return ret;
4553e48354ceSNicholas Bellinger }
45542ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_logout_post_handler);
4555e48354ceSNicholas Bellinger 
4556e48354ceSNicholas Bellinger void iscsit_fail_session(struct iscsi_session *sess)
4557e48354ceSNicholas Bellinger {
4558e48354ceSNicholas Bellinger 	struct iscsi_conn *conn;
4559e48354ceSNicholas Bellinger 
4560e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4561e48354ceSNicholas Bellinger 	list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
4562e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
4563e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
4564e48354ceSNicholas Bellinger 	}
4565e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4566e48354ceSNicholas Bellinger 
4567e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4568e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FAILED;
4569e48354ceSNicholas Bellinger }
4570e48354ceSNicholas Bellinger 
4571e48354ceSNicholas Bellinger int iscsit_free_session(struct iscsi_session *sess)
4572e48354ceSNicholas Bellinger {
4573e48354ceSNicholas Bellinger 	u16 conn_count = atomic_read(&sess->nconn);
4574e48354ceSNicholas Bellinger 	struct iscsi_conn *conn, *conn_tmp = NULL;
4575e48354ceSNicholas Bellinger 	int is_last;
4576e48354ceSNicholas Bellinger 
4577e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4578e48354ceSNicholas Bellinger 	atomic_set(&sess->sleep_on_sess_wait_comp, 1);
4579e48354ceSNicholas Bellinger 
4580e48354ceSNicholas Bellinger 	list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
4581e48354ceSNicholas Bellinger 			conn_list) {
4582e48354ceSNicholas Bellinger 		if (conn_count == 0)
4583e48354ceSNicholas Bellinger 			break;
4584e48354ceSNicholas Bellinger 
4585e48354ceSNicholas Bellinger 		if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
4586e48354ceSNicholas Bellinger 			is_last = 1;
4587e48354ceSNicholas Bellinger 		} else {
4588e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn_tmp);
4589e48354ceSNicholas Bellinger 			is_last = 0;
4590e48354ceSNicholas Bellinger 		}
4591e48354ceSNicholas Bellinger 		iscsit_inc_conn_usage_count(conn);
4592e48354ceSNicholas Bellinger 
4593e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4594e48354ceSNicholas Bellinger 		iscsit_cause_connection_reinstatement(conn, 1);
4595e48354ceSNicholas Bellinger 		spin_lock_bh(&sess->conn_lock);
4596e48354ceSNicholas Bellinger 
4597e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(conn);
4598e48354ceSNicholas Bellinger 		if (is_last == 0)
4599e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn_tmp);
4600e48354ceSNicholas Bellinger 
4601e48354ceSNicholas Bellinger 		conn_count--;
4602e48354ceSNicholas Bellinger 	}
4603e48354ceSNicholas Bellinger 
4604e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4605e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4606e48354ceSNicholas Bellinger 		wait_for_completion(&sess->session_wait_comp);
4607e48354ceSNicholas Bellinger 	} else
4608e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4609e48354ceSNicholas Bellinger 
461044f33d0fSChristoph Hellwig 	iscsit_close_session(sess);
4611e48354ceSNicholas Bellinger 	return 0;
4612e48354ceSNicholas Bellinger }
4613e48354ceSNicholas Bellinger 
4614e48354ceSNicholas Bellinger void iscsit_stop_session(
4615e48354ceSNicholas Bellinger 	struct iscsi_session *sess,
4616e48354ceSNicholas Bellinger 	int session_sleep,
4617e48354ceSNicholas Bellinger 	int connection_sleep)
4618e48354ceSNicholas Bellinger {
4619e48354ceSNicholas Bellinger 	u16 conn_count = atomic_read(&sess->nconn);
4620e48354ceSNicholas Bellinger 	struct iscsi_conn *conn, *conn_tmp = NULL;
4621e48354ceSNicholas Bellinger 	int is_last;
4622e48354ceSNicholas Bellinger 
4623e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4624e48354ceSNicholas Bellinger 	if (session_sleep)
4625e48354ceSNicholas Bellinger 		atomic_set(&sess->sleep_on_sess_wait_comp, 1);
4626e48354ceSNicholas Bellinger 
4627e48354ceSNicholas Bellinger 	if (connection_sleep) {
4628e48354ceSNicholas Bellinger 		list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
4629e48354ceSNicholas Bellinger 				conn_list) {
4630e48354ceSNicholas Bellinger 			if (conn_count == 0)
4631e48354ceSNicholas Bellinger 				break;
4632e48354ceSNicholas Bellinger 
4633e48354ceSNicholas Bellinger 			if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
4634e48354ceSNicholas Bellinger 				is_last = 1;
4635e48354ceSNicholas Bellinger 			} else {
4636e48354ceSNicholas Bellinger 				iscsit_inc_conn_usage_count(conn_tmp);
4637e48354ceSNicholas Bellinger 				is_last = 0;
4638e48354ceSNicholas Bellinger 			}
4639e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn);
4640e48354ceSNicholas Bellinger 
4641e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4642e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 1);
4643e48354ceSNicholas Bellinger 			spin_lock_bh(&sess->conn_lock);
4644e48354ceSNicholas Bellinger 
4645e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4646e48354ceSNicholas Bellinger 			if (is_last == 0)
4647e48354ceSNicholas Bellinger 				iscsit_dec_conn_usage_count(conn_tmp);
4648e48354ceSNicholas Bellinger 			conn_count--;
4649e48354ceSNicholas Bellinger 		}
4650e48354ceSNicholas Bellinger 	} else {
4651e48354ceSNicholas Bellinger 		list_for_each_entry(conn, &sess->sess_conn_list, conn_list)
4652e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 0);
4653e48354ceSNicholas Bellinger 	}
4654e48354ceSNicholas Bellinger 
4655e48354ceSNicholas Bellinger 	if (session_sleep && atomic_read(&sess->nconn)) {
4656e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4657e48354ceSNicholas Bellinger 		wait_for_completion(&sess->session_wait_comp);
4658e48354ceSNicholas Bellinger 	} else
4659e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4660e48354ceSNicholas Bellinger }
4661e48354ceSNicholas Bellinger 
4662e48354ceSNicholas Bellinger int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
4663e48354ceSNicholas Bellinger {
4664e48354ceSNicholas Bellinger 	struct iscsi_session *sess;
4665e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4666e48354ceSNicholas Bellinger 	struct se_session *se_sess, *se_sess_tmp;
4667417c20a9SNicholas Bellinger 	LIST_HEAD(free_list);
4668e48354ceSNicholas Bellinger 	int session_count = 0;
4669e48354ceSNicholas Bellinger 
4670e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4671e48354ceSNicholas Bellinger 	if (tpg->nsessions && !force) {
4672e48354ceSNicholas Bellinger 		spin_unlock_bh(&se_tpg->session_lock);
4673e48354ceSNicholas Bellinger 		return -1;
4674e48354ceSNicholas Bellinger 	}
4675e48354ceSNicholas Bellinger 
4676e48354ceSNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
4677e48354ceSNicholas Bellinger 			sess_list) {
4678e48354ceSNicholas Bellinger 		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
4679e48354ceSNicholas Bellinger 
4680e48354ceSNicholas Bellinger 		spin_lock(&sess->conn_lock);
4681e48354ceSNicholas Bellinger 		if (atomic_read(&sess->session_fall_back_to_erl0) ||
4682e48354ceSNicholas Bellinger 		    atomic_read(&sess->session_logout) ||
4683e48354ceSNicholas Bellinger 		    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
4684e48354ceSNicholas Bellinger 			spin_unlock(&sess->conn_lock);
4685e48354ceSNicholas Bellinger 			continue;
4686e48354ceSNicholas Bellinger 		}
4687e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 1);
4688197b806aSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4689e48354ceSNicholas Bellinger 		spin_unlock(&sess->conn_lock);
4690e48354ceSNicholas Bellinger 
4691417c20a9SNicholas Bellinger 		list_move_tail(&se_sess->sess_list, &free_list);
4692e48354ceSNicholas Bellinger 	}
4693e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4694e48354ceSNicholas Bellinger 
4695417c20a9SNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) {
4696417c20a9SNicholas Bellinger 		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
4697417c20a9SNicholas Bellinger 
4698417c20a9SNicholas Bellinger 		iscsit_free_session(sess);
4699417c20a9SNicholas Bellinger 		session_count++;
4700417c20a9SNicholas Bellinger 	}
4701417c20a9SNicholas Bellinger 
4702e48354ceSNicholas Bellinger 	pr_debug("Released %d iSCSI Session(s) from Target Portal"
4703e48354ceSNicholas Bellinger 			" Group: %hu\n", session_count, tpg->tpgt);
4704e48354ceSNicholas Bellinger 	return 0;
4705e48354ceSNicholas Bellinger }
4706e48354ceSNicholas Bellinger 
4707e48354ceSNicholas Bellinger MODULE_DESCRIPTION("iSCSI-Target Driver for mainline target infrastructure");
4708e48354ceSNicholas Bellinger MODULE_VERSION("4.1.x");
4709e48354ceSNicholas Bellinger MODULE_AUTHOR("nab@Linux-iSCSI.org");
4710e48354ceSNicholas Bellinger MODULE_LICENSE("GPL");
4711e48354ceSNicholas Bellinger 
4712e48354ceSNicholas Bellinger module_init(iscsi_target_init_module);
4713e48354ceSNicholas Bellinger module_exit(iscsi_target_cleanup_module);
4714