1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e48354ceSNicholas Bellinger /*******************************************************************************
3e48354ceSNicholas Bellinger  * This file contains main functions related to the iSCSI Target Core Driver.
4e48354ceSNicholas Bellinger  *
54c76251eSNicholas Bellinger  * (c) Copyright 2007-2013 Datera, Inc.
6e48354ceSNicholas Bellinger  *
7e48354ceSNicholas Bellinger  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
8e48354ceSNicholas Bellinger  *
9e48354ceSNicholas Bellinger  ******************************************************************************/
10e48354ceSNicholas Bellinger 
1169110e3cSHerbert Xu #include <crypto/hash.h>
12e48354ceSNicholas Bellinger #include <linux/string.h>
13e48354ceSNicholas Bellinger #include <linux/kthread.h>
14e48354ceSNicholas Bellinger #include <linux/completion.h>
15827509e3SPaul Gortmaker #include <linux/module.h>
165538d294SDavid S. Miller #include <linux/vmalloc.h>
1740401530SAl Viro #include <linux/idr.h>
188dcf07beSBart Van Assche #include <linux/delay.h>
193f07c014SIngo Molnar #include <linux/sched/signal.h>
20e48354ceSNicholas Bellinger #include <asm/unaligned.h>
217bfca0cfSSagi Grimberg #include <linux/inet.h>
228dcf07beSBart Van Assche #include <net/ipv6.h>
23ba929992SBart Van Assche #include <scsi/scsi_proto.h>
24e48354ceSNicholas Bellinger #include <scsi/iscsi_proto.h>
25d28b1169SAndy Grover #include <scsi/scsi_tcq.h>
26e48354ceSNicholas Bellinger #include <target/target_core_base.h>
27c4795fb2SChristoph Hellwig #include <target/target_core_fabric.h>
28e48354ceSNicholas Bellinger 
2967f091f2SSagi Grimberg #include <target/iscsi/iscsi_target_core.h>
30e48354ceSNicholas Bellinger #include "iscsi_target_parameters.h"
31e48354ceSNicholas Bellinger #include "iscsi_target_seq_pdu_list.h"
32e48354ceSNicholas Bellinger #include "iscsi_target_datain_values.h"
33e48354ceSNicholas Bellinger #include "iscsi_target_erl0.h"
34e48354ceSNicholas Bellinger #include "iscsi_target_erl1.h"
35e48354ceSNicholas Bellinger #include "iscsi_target_erl2.h"
36e48354ceSNicholas Bellinger #include "iscsi_target_login.h"
37e48354ceSNicholas Bellinger #include "iscsi_target_tmr.h"
38e48354ceSNicholas Bellinger #include "iscsi_target_tpg.h"
39e48354ceSNicholas Bellinger #include "iscsi_target_util.h"
40e48354ceSNicholas Bellinger #include "iscsi_target.h"
41e48354ceSNicholas Bellinger #include "iscsi_target_device.h"
4267f091f2SSagi Grimberg #include <target/iscsi/iscsi_target_stat.h>
43e48354ceSNicholas Bellinger 
44baa4d64bSNicholas Bellinger #include <target/iscsi/iscsi_transport.h>
45baa4d64bSNicholas Bellinger 
46e48354ceSNicholas Bellinger static LIST_HEAD(g_tiqn_list);
47e48354ceSNicholas Bellinger static LIST_HEAD(g_np_list);
48e48354ceSNicholas Bellinger static DEFINE_SPINLOCK(tiqn_lock);
49ee291e63SAndy Grover static DEFINE_MUTEX(np_lock);
50e48354ceSNicholas Bellinger 
51e48354ceSNicholas Bellinger static struct idr tiqn_idr;
5231ff0ceeSMatthew Wilcox DEFINE_IDA(sess_ida);
53e48354ceSNicholas Bellinger struct mutex auth_id_lock;
54e48354ceSNicholas Bellinger 
55e48354ceSNicholas Bellinger struct iscsit_global *iscsit_global;
56e48354ceSNicholas Bellinger 
57e48354ceSNicholas Bellinger struct kmem_cache *lio_qr_cache;
58e48354ceSNicholas Bellinger struct kmem_cache *lio_dr_cache;
59e48354ceSNicholas Bellinger struct kmem_cache *lio_ooo_cache;
60e48354ceSNicholas Bellinger struct kmem_cache *lio_r2t_cache;
61e48354ceSNicholas Bellinger 
62e48354ceSNicholas Bellinger static int iscsit_handle_immediate_data(struct iscsi_cmd *,
632ec5a8c1SNicholas Bellinger 			struct iscsi_scsi_req *, u32);
64e48354ceSNicholas Bellinger 
65e48354ceSNicholas Bellinger struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf)
66e48354ceSNicholas Bellinger {
67e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = NULL;
68e48354ceSNicholas Bellinger 
69e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
70e48354ceSNicholas Bellinger 	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
71e48354ceSNicholas Bellinger 		if (!strcmp(tiqn->tiqn, buf)) {
72e48354ceSNicholas Bellinger 
73e48354ceSNicholas Bellinger 			spin_lock(&tiqn->tiqn_state_lock);
74e48354ceSNicholas Bellinger 			if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
75e48354ceSNicholas Bellinger 				tiqn->tiqn_access_count++;
76e48354ceSNicholas Bellinger 				spin_unlock(&tiqn->tiqn_state_lock);
77e48354ceSNicholas Bellinger 				spin_unlock(&tiqn_lock);
78e48354ceSNicholas Bellinger 				return tiqn;
79e48354ceSNicholas Bellinger 			}
80e48354ceSNicholas Bellinger 			spin_unlock(&tiqn->tiqn_state_lock);
81e48354ceSNicholas Bellinger 		}
82e48354ceSNicholas Bellinger 	}
83e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
84e48354ceSNicholas Bellinger 
85e48354ceSNicholas Bellinger 	return NULL;
86e48354ceSNicholas Bellinger }
87e48354ceSNicholas Bellinger 
88e48354ceSNicholas Bellinger static int iscsit_set_tiqn_shutdown(struct iscsi_tiqn *tiqn)
89e48354ceSNicholas Bellinger {
90e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
91e48354ceSNicholas Bellinger 	if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
92e48354ceSNicholas Bellinger 		tiqn->tiqn_state = TIQN_STATE_SHUTDOWN;
93e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_state_lock);
94e48354ceSNicholas Bellinger 		return 0;
95e48354ceSNicholas Bellinger 	}
96e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
97e48354ceSNicholas Bellinger 
98e48354ceSNicholas Bellinger 	return -1;
99e48354ceSNicholas Bellinger }
100e48354ceSNicholas Bellinger 
101e48354ceSNicholas Bellinger void iscsit_put_tiqn_for_login(struct iscsi_tiqn *tiqn)
102e48354ceSNicholas Bellinger {
103e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
104e48354ceSNicholas Bellinger 	tiqn->tiqn_access_count--;
105e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
106e48354ceSNicholas Bellinger }
107e48354ceSNicholas Bellinger 
108e48354ceSNicholas Bellinger /*
109e48354ceSNicholas Bellinger  * Note that IQN formatting is expected to be done in userspace, and
110e48354ceSNicholas Bellinger  * no explict IQN format checks are done here.
111e48354ceSNicholas Bellinger  */
112e48354ceSNicholas Bellinger struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf)
113e48354ceSNicholas Bellinger {
114e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = NULL;
115e48354ceSNicholas Bellinger 	int ret;
116e48354ceSNicholas Bellinger 
1178f50c7f5SDan Carpenter 	if (strlen(buf) >= ISCSI_IQN_LEN) {
118e48354ceSNicholas Bellinger 		pr_err("Target IQN exceeds %d bytes\n",
119e48354ceSNicholas Bellinger 				ISCSI_IQN_LEN);
120e48354ceSNicholas Bellinger 		return ERR_PTR(-EINVAL);
121e48354ceSNicholas Bellinger 	}
122e48354ceSNicholas Bellinger 
1233829f381SMarkus Elfring 	tiqn = kzalloc(sizeof(*tiqn), GFP_KERNEL);
124c46e22f1SMarkus Elfring 	if (!tiqn)
125e48354ceSNicholas Bellinger 		return ERR_PTR(-ENOMEM);
126e48354ceSNicholas Bellinger 
127e48354ceSNicholas Bellinger 	sprintf(tiqn->tiqn, "%s", buf);
128e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&tiqn->tiqn_list);
129e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&tiqn->tiqn_tpg_list);
130e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->tiqn_state_lock);
131e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->tiqn_tpg_lock);
132e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->sess_err_stats.lock);
133e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->login_stats.lock);
134e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->logout_stats.lock);
135e48354ceSNicholas Bellinger 
136e48354ceSNicholas Bellinger 	tiqn->tiqn_state = TIQN_STATE_ACTIVE;
137e48354ceSNicholas Bellinger 
138c9365bd0STejun Heo 	idr_preload(GFP_KERNEL);
139e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
140c9365bd0STejun Heo 
141c9365bd0STejun Heo 	ret = idr_alloc(&tiqn_idr, NULL, 0, 0, GFP_NOWAIT);
142e48354ceSNicholas Bellinger 	if (ret < 0) {
143c9365bd0STejun Heo 		pr_err("idr_alloc() failed for tiqn->tiqn_index\n");
144e48354ceSNicholas Bellinger 		spin_unlock(&tiqn_lock);
145c9365bd0STejun Heo 		idr_preload_end();
146e48354ceSNicholas Bellinger 		kfree(tiqn);
147e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
148e48354ceSNicholas Bellinger 	}
149c9365bd0STejun Heo 	tiqn->tiqn_index = ret;
150e48354ceSNicholas Bellinger 	list_add_tail(&tiqn->tiqn_list, &g_tiqn_list);
151c9365bd0STejun Heo 
152e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
153c9365bd0STejun Heo 	idr_preload_end();
154e48354ceSNicholas Bellinger 
155e48354ceSNicholas Bellinger 	pr_debug("CORE[0] - Added iSCSI Target IQN: %s\n", tiqn->tiqn);
156e48354ceSNicholas Bellinger 
157e48354ceSNicholas Bellinger 	return tiqn;
158e48354ceSNicholas Bellinger 
159e48354ceSNicholas Bellinger }
160e48354ceSNicholas Bellinger 
161e48354ceSNicholas Bellinger static void iscsit_wait_for_tiqn(struct iscsi_tiqn *tiqn)
162e48354ceSNicholas Bellinger {
163e48354ceSNicholas Bellinger 	/*
164e48354ceSNicholas Bellinger 	 * Wait for accesses to said struct iscsi_tiqn to end.
165e48354ceSNicholas Bellinger 	 */
166e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
167e48354ceSNicholas Bellinger 	while (tiqn->tiqn_access_count != 0) {
168e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_state_lock);
169e48354ceSNicholas Bellinger 		msleep(10);
170e48354ceSNicholas Bellinger 		spin_lock(&tiqn->tiqn_state_lock);
171e48354ceSNicholas Bellinger 	}
172e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
173e48354ceSNicholas Bellinger }
174e48354ceSNicholas Bellinger 
175e48354ceSNicholas Bellinger void iscsit_del_tiqn(struct iscsi_tiqn *tiqn)
176e48354ceSNicholas Bellinger {
177e48354ceSNicholas Bellinger 	/*
178e48354ceSNicholas Bellinger 	 * iscsit_set_tiqn_shutdown sets tiqn->tiqn_state = TIQN_STATE_SHUTDOWN
179e48354ceSNicholas Bellinger 	 * while holding tiqn->tiqn_state_lock.  This means that all subsequent
180e48354ceSNicholas Bellinger 	 * attempts to access this struct iscsi_tiqn will fail from both transport
181e48354ceSNicholas Bellinger 	 * fabric and control code paths.
182e48354ceSNicholas Bellinger 	 */
183e48354ceSNicholas Bellinger 	if (iscsit_set_tiqn_shutdown(tiqn) < 0) {
184e48354ceSNicholas Bellinger 		pr_err("iscsit_set_tiqn_shutdown() failed\n");
185e48354ceSNicholas Bellinger 		return;
186e48354ceSNicholas Bellinger 	}
187e48354ceSNicholas Bellinger 
188e48354ceSNicholas Bellinger 	iscsit_wait_for_tiqn(tiqn);
189e48354ceSNicholas Bellinger 
190e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
191e48354ceSNicholas Bellinger 	list_del(&tiqn->tiqn_list);
192e48354ceSNicholas Bellinger 	idr_remove(&tiqn_idr, tiqn->tiqn_index);
193e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
194e48354ceSNicholas Bellinger 
195e48354ceSNicholas Bellinger 	pr_debug("CORE[0] - Deleted iSCSI Target IQN: %s\n",
196e48354ceSNicholas Bellinger 			tiqn->tiqn);
197e48354ceSNicholas Bellinger 	kfree(tiqn);
198e48354ceSNicholas Bellinger }
199e48354ceSNicholas Bellinger 
200e48354ceSNicholas Bellinger int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
201e48354ceSNicholas Bellinger {
202e48354ceSNicholas Bellinger 	int ret;
203e48354ceSNicholas Bellinger 	/*
204e48354ceSNicholas Bellinger 	 * Determine if the network portal is accepting storage traffic.
205e48354ceSNicholas Bellinger 	 */
206e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
207e48354ceSNicholas Bellinger 	if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
208e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
209e48354ceSNicholas Bellinger 		return -1;
210e48354ceSNicholas Bellinger 	}
211e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
212e48354ceSNicholas Bellinger 	/*
213e48354ceSNicholas Bellinger 	 * Determine if the portal group is accepting storage traffic.
214e48354ceSNicholas Bellinger 	 */
215e48354ceSNicholas Bellinger 	spin_lock_bh(&tpg->tpg_state_lock);
216e48354ceSNicholas Bellinger 	if (tpg->tpg_state != TPG_STATE_ACTIVE) {
217e48354ceSNicholas Bellinger 		spin_unlock_bh(&tpg->tpg_state_lock);
218e48354ceSNicholas Bellinger 		return -1;
219e48354ceSNicholas Bellinger 	}
220e48354ceSNicholas Bellinger 	spin_unlock_bh(&tpg->tpg_state_lock);
221e48354ceSNicholas Bellinger 
222e48354ceSNicholas Bellinger 	/*
223e48354ceSNicholas Bellinger 	 * Here we serialize access across the TIQN+TPG Tuple.
224e48354ceSNicholas Bellinger 	 */
225a91eb7d9SNicholas Bellinger 	ret = down_interruptible(&tpg->np_login_sem);
226ee7619f2SNicholas Bellinger 	if (ret != 0)
227e48354ceSNicholas Bellinger 		return -1;
228e48354ceSNicholas Bellinger 
229a91eb7d9SNicholas Bellinger 	spin_lock_bh(&tpg->tpg_state_lock);
230a91eb7d9SNicholas Bellinger 	if (tpg->tpg_state != TPG_STATE_ACTIVE) {
231a91eb7d9SNicholas Bellinger 		spin_unlock_bh(&tpg->tpg_state_lock);
232a91eb7d9SNicholas Bellinger 		up(&tpg->np_login_sem);
233a91eb7d9SNicholas Bellinger 		return -1;
234a91eb7d9SNicholas Bellinger 	}
235a91eb7d9SNicholas Bellinger 	spin_unlock_bh(&tpg->tpg_state_lock);
236e48354ceSNicholas Bellinger 
237e48354ceSNicholas Bellinger 	return 0;
238e48354ceSNicholas Bellinger }
239e48354ceSNicholas Bellinger 
240a91eb7d9SNicholas Bellinger void iscsit_login_kref_put(struct kref *kref)
241a91eb7d9SNicholas Bellinger {
242a91eb7d9SNicholas Bellinger 	struct iscsi_tpg_np *tpg_np = container_of(kref,
243a91eb7d9SNicholas Bellinger 				struct iscsi_tpg_np, tpg_np_kref);
244a91eb7d9SNicholas Bellinger 
245a91eb7d9SNicholas Bellinger 	complete(&tpg_np->tpg_np_comp);
246a91eb7d9SNicholas Bellinger }
247a91eb7d9SNicholas Bellinger 
248a91eb7d9SNicholas Bellinger int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg,
249a91eb7d9SNicholas Bellinger 		       struct iscsi_tpg_np *tpg_np)
250e48354ceSNicholas Bellinger {
251e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
252e48354ceSNicholas Bellinger 
253a91eb7d9SNicholas Bellinger 	up(&tpg->np_login_sem);
254e48354ceSNicholas Bellinger 
255a91eb7d9SNicholas Bellinger 	if (tpg_np)
256a91eb7d9SNicholas Bellinger 		kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
257e48354ceSNicholas Bellinger 
258e48354ceSNicholas Bellinger 	if (tiqn)
259e48354ceSNicholas Bellinger 		iscsit_put_tiqn_for_login(tiqn);
260e48354ceSNicholas Bellinger 
261e48354ceSNicholas Bellinger 	return 0;
262e48354ceSNicholas Bellinger }
263e48354ceSNicholas Bellinger 
26405b96892SNicholas Bellinger bool iscsit_check_np_match(
26513a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
26605b96892SNicholas Bellinger 	struct iscsi_np *np,
267e48354ceSNicholas Bellinger 	int network_transport)
268e48354ceSNicholas Bellinger {
269e48354ceSNicholas Bellinger 	struct sockaddr_in *sock_in, *sock_in_e;
270e48354ceSNicholas Bellinger 	struct sockaddr_in6 *sock_in6, *sock_in6_e;
27105b96892SNicholas Bellinger 	bool ip_match = false;
27269d75574SAndy Grover 	u16 port, port_e;
273e48354ceSNicholas Bellinger 
27405b96892SNicholas Bellinger 	if (sockaddr->ss_family == AF_INET6) {
27505b96892SNicholas Bellinger 		sock_in6 = (struct sockaddr_in6 *)sockaddr;
27605b96892SNicholas Bellinger 		sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;
27705b96892SNicholas Bellinger 
27805b96892SNicholas Bellinger 		if (!memcmp(&sock_in6->sin6_addr.in6_u,
27905b96892SNicholas Bellinger 			    &sock_in6_e->sin6_addr.in6_u,
28005b96892SNicholas Bellinger 			    sizeof(struct in6_addr)))
28105b96892SNicholas Bellinger 			ip_match = true;
28205b96892SNicholas Bellinger 
28305b96892SNicholas Bellinger 		port = ntohs(sock_in6->sin6_port);
28469d75574SAndy Grover 		port_e = ntohs(sock_in6_e->sin6_port);
28505b96892SNicholas Bellinger 	} else {
28605b96892SNicholas Bellinger 		sock_in = (struct sockaddr_in *)sockaddr;
28705b96892SNicholas Bellinger 		sock_in_e = (struct sockaddr_in *)&np->np_sockaddr;
28805b96892SNicholas Bellinger 
28905b96892SNicholas Bellinger 		if (sock_in->sin_addr.s_addr == sock_in_e->sin_addr.s_addr)
29005b96892SNicholas Bellinger 			ip_match = true;
29105b96892SNicholas Bellinger 
29205b96892SNicholas Bellinger 		port = ntohs(sock_in->sin_port);
29369d75574SAndy Grover 		port_e = ntohs(sock_in_e->sin_port);
29405b96892SNicholas Bellinger 	}
29505b96892SNicholas Bellinger 
29669d75574SAndy Grover 	if (ip_match && (port_e == port) &&
29705b96892SNicholas Bellinger 	    (np->np_network_transport == network_transport))
29805b96892SNicholas Bellinger 		return true;
29905b96892SNicholas Bellinger 
30005b96892SNicholas Bellinger 	return false;
30105b96892SNicholas Bellinger }
30205b96892SNicholas Bellinger 
30305b96892SNicholas Bellinger static struct iscsi_np *iscsit_get_np(
30413a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
30505b96892SNicholas Bellinger 	int network_transport)
30605b96892SNicholas Bellinger {
30705b96892SNicholas Bellinger 	struct iscsi_np *np;
30805b96892SNicholas Bellinger 	bool match;
30905b96892SNicholas Bellinger 
310618baaf7SBart Van Assche 	lockdep_assert_held(&np_lock);
311618baaf7SBart Van Assche 
312e48354ceSNicholas Bellinger 	list_for_each_entry(np, &g_np_list, np_list) {
313ee291e63SAndy Grover 		spin_lock_bh(&np->np_thread_lock);
314e48354ceSNicholas Bellinger 		if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
315ee291e63SAndy Grover 			spin_unlock_bh(&np->np_thread_lock);
316e48354ceSNicholas Bellinger 			continue;
317e48354ceSNicholas Bellinger 		}
318e48354ceSNicholas Bellinger 
31905b96892SNicholas Bellinger 		match = iscsit_check_np_match(sockaddr, np, network_transport);
3200bcc297eSChristophe Vu-Brugier 		if (match) {
321e48354ceSNicholas Bellinger 			/*
322e48354ceSNicholas Bellinger 			 * Increment the np_exports reference count now to
323e48354ceSNicholas Bellinger 			 * prevent iscsit_del_np() below from being called
324e48354ceSNicholas Bellinger 			 * while iscsi_tpg_add_network_portal() is called.
325e48354ceSNicholas Bellinger 			 */
326e48354ceSNicholas Bellinger 			np->np_exports++;
327ee291e63SAndy Grover 			spin_unlock_bh(&np->np_thread_lock);
328e48354ceSNicholas Bellinger 			return np;
329e48354ceSNicholas Bellinger 		}
330ee291e63SAndy Grover 		spin_unlock_bh(&np->np_thread_lock);
331e48354ceSNicholas Bellinger 	}
332e48354ceSNicholas Bellinger 
333e48354ceSNicholas Bellinger 	return NULL;
334e48354ceSNicholas Bellinger }
335e48354ceSNicholas Bellinger 
336e48354ceSNicholas Bellinger struct iscsi_np *iscsit_add_np(
33713a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
338e48354ceSNicholas Bellinger 	int network_transport)
339e48354ceSNicholas Bellinger {
340e48354ceSNicholas Bellinger 	struct iscsi_np *np;
341e48354ceSNicholas Bellinger 	int ret;
342ee291e63SAndy Grover 
343ee291e63SAndy Grover 	mutex_lock(&np_lock);
344ee291e63SAndy Grover 
345e48354ceSNicholas Bellinger 	/*
346e48354ceSNicholas Bellinger 	 * Locate the existing struct iscsi_np if already active..
347e48354ceSNicholas Bellinger 	 */
348e48354ceSNicholas Bellinger 	np = iscsit_get_np(sockaddr, network_transport);
349ee291e63SAndy Grover 	if (np) {
350ee291e63SAndy Grover 		mutex_unlock(&np_lock);
351e48354ceSNicholas Bellinger 		return np;
352ee291e63SAndy Grover 	}
353e48354ceSNicholas Bellinger 
3543829f381SMarkus Elfring 	np = kzalloc(sizeof(*np), GFP_KERNEL);
355e48354ceSNicholas Bellinger 	if (!np) {
356ee291e63SAndy Grover 		mutex_unlock(&np_lock);
357e48354ceSNicholas Bellinger 		return ERR_PTR(-ENOMEM);
358e48354ceSNicholas Bellinger 	}
359e48354ceSNicholas Bellinger 
360e48354ceSNicholas Bellinger 	np->np_flags |= NPF_IP_NETWORK;
361e48354ceSNicholas Bellinger 	np->np_network_transport = network_transport;
362e48354ceSNicholas Bellinger 	spin_lock_init(&np->np_thread_lock);
363e48354ceSNicholas Bellinger 	init_completion(&np->np_restart_comp);
364e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&np->np_list);
365e48354ceSNicholas Bellinger 
366f7c9564aSKees Cook 	timer_setup(&np->np_login_timer, iscsi_handle_login_thread_timeout, 0);
3678a47aa9dSBart Van Assche 
368e48354ceSNicholas Bellinger 	ret = iscsi_target_setup_login_socket(np, sockaddr);
369e48354ceSNicholas Bellinger 	if (ret != 0) {
370e48354ceSNicholas Bellinger 		kfree(np);
371ee291e63SAndy Grover 		mutex_unlock(&np_lock);
372e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
373e48354ceSNicholas Bellinger 	}
374e48354ceSNicholas Bellinger 
375e48354ceSNicholas Bellinger 	np->np_thread = kthread_run(iscsi_target_login_thread, np, "iscsi_np");
376e48354ceSNicholas Bellinger 	if (IS_ERR(np->np_thread)) {
377e48354ceSNicholas Bellinger 		pr_err("Unable to create kthread: iscsi_np\n");
378e48354ceSNicholas Bellinger 		ret = PTR_ERR(np->np_thread);
379e48354ceSNicholas Bellinger 		kfree(np);
380ee291e63SAndy Grover 		mutex_unlock(&np_lock);
381e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
382e48354ceSNicholas Bellinger 	}
383e48354ceSNicholas Bellinger 	/*
384e48354ceSNicholas Bellinger 	 * Increment the np_exports reference count now to prevent
385e48354ceSNicholas Bellinger 	 * iscsit_del_np() below from being run while a new call to
386e48354ceSNicholas Bellinger 	 * iscsi_tpg_add_network_portal() for a matching iscsi_np is
387e48354ceSNicholas Bellinger 	 * active.  We don't need to hold np->np_thread_lock at this
388e48354ceSNicholas Bellinger 	 * point because iscsi_np has not been added to g_np_list yet.
389e48354ceSNicholas Bellinger 	 */
390e48354ceSNicholas Bellinger 	np->np_exports = 1;
391ee291e63SAndy Grover 	np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
392e48354ceSNicholas Bellinger 
393e48354ceSNicholas Bellinger 	list_add_tail(&np->np_list, &g_np_list);
394ee291e63SAndy Grover 	mutex_unlock(&np_lock);
395e48354ceSNicholas Bellinger 
39669d75574SAndy Grover 	pr_debug("CORE[0] - Added Network Portal: %pISpc on %s\n",
39769d75574SAndy Grover 		&np->np_sockaddr, np->np_transport->name);
398e48354ceSNicholas Bellinger 
399e48354ceSNicholas Bellinger 	return np;
400e48354ceSNicholas Bellinger }
401e48354ceSNicholas Bellinger 
402e48354ceSNicholas Bellinger int iscsit_reset_np_thread(
403e48354ceSNicholas Bellinger 	struct iscsi_np *np,
404e48354ceSNicholas Bellinger 	struct iscsi_tpg_np *tpg_np,
405a91eb7d9SNicholas Bellinger 	struct iscsi_portal_group *tpg,
406a91eb7d9SNicholas Bellinger 	bool shutdown)
407e48354ceSNicholas Bellinger {
408e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
409e48354ceSNicholas Bellinger 	if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) {
410e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
411e48354ceSNicholas Bellinger 		return 0;
412e48354ceSNicholas Bellinger 	}
413e48354ceSNicholas Bellinger 	np->np_thread_state = ISCSI_NP_THREAD_RESET;
414978d13d6SNicholas Bellinger 	atomic_inc(&np->np_reset_count);
415e48354ceSNicholas Bellinger 
416e48354ceSNicholas Bellinger 	if (np->np_thread) {
417e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
418e48354ceSNicholas Bellinger 		send_sig(SIGINT, np->np_thread, 1);
419e48354ceSNicholas Bellinger 		wait_for_completion(&np->np_restart_comp);
420e48354ceSNicholas Bellinger 		spin_lock_bh(&np->np_thread_lock);
421e48354ceSNicholas Bellinger 	}
422e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
423e48354ceSNicholas Bellinger 
424a91eb7d9SNicholas Bellinger 	if (tpg_np && shutdown) {
425a91eb7d9SNicholas Bellinger 		kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
426a91eb7d9SNicholas Bellinger 
427a91eb7d9SNicholas Bellinger 		wait_for_completion(&tpg_np->tpg_np_comp);
428a91eb7d9SNicholas Bellinger 	}
429a91eb7d9SNicholas Bellinger 
430e48354ceSNicholas Bellinger 	return 0;
431e48354ceSNicholas Bellinger }
432e48354ceSNicholas Bellinger 
433baa4d64bSNicholas Bellinger static void iscsit_free_np(struct iscsi_np *np)
434e48354ceSNicholas Bellinger {
435bf6932f4SAl Viro 	if (np->np_socket)
436e48354ceSNicholas Bellinger 		sock_release(np->np_socket);
437e48354ceSNicholas Bellinger }
438e48354ceSNicholas Bellinger 
439e48354ceSNicholas Bellinger int iscsit_del_np(struct iscsi_np *np)
440e48354ceSNicholas Bellinger {
441e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
442e48354ceSNicholas Bellinger 	np->np_exports--;
443e48354ceSNicholas Bellinger 	if (np->np_exports) {
4442363d196SNicholas Bellinger 		np->enabled = true;
445e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
446e48354ceSNicholas Bellinger 		return 0;
447e48354ceSNicholas Bellinger 	}
448e48354ceSNicholas Bellinger 	np->np_thread_state = ISCSI_NP_THREAD_SHUTDOWN;
449e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
450e48354ceSNicholas Bellinger 
451e48354ceSNicholas Bellinger 	if (np->np_thread) {
452e48354ceSNicholas Bellinger 		/*
453e48354ceSNicholas Bellinger 		 * We need to send the signal to wakeup Linux/Net
454e48354ceSNicholas Bellinger 		 * which may be sleeping in sock_accept()..
455e48354ceSNicholas Bellinger 		 */
456e48354ceSNicholas Bellinger 		send_sig(SIGINT, np->np_thread, 1);
457e48354ceSNicholas Bellinger 		kthread_stop(np->np_thread);
458db6077fdSNicholas Bellinger 		np->np_thread = NULL;
459e48354ceSNicholas Bellinger 	}
460baa4d64bSNicholas Bellinger 
461baa4d64bSNicholas Bellinger 	np->np_transport->iscsit_free_np(np);
462e48354ceSNicholas Bellinger 
463ee291e63SAndy Grover 	mutex_lock(&np_lock);
464e48354ceSNicholas Bellinger 	list_del(&np->np_list);
465ee291e63SAndy Grover 	mutex_unlock(&np_lock);
466e48354ceSNicholas Bellinger 
46769d75574SAndy Grover 	pr_debug("CORE[0] - Removed Network Portal: %pISpc on %s\n",
46869d75574SAndy Grover 		&np->np_sockaddr, np->np_transport->name);
469e48354ceSNicholas Bellinger 
470baa4d64bSNicholas Bellinger 	iscsit_put_transport(np->np_transport);
471e48354ceSNicholas Bellinger 	kfree(np);
472e48354ceSNicholas Bellinger 	return 0;
473e48354ceSNicholas Bellinger }
474e48354ceSNicholas Bellinger 
475e8205ccaSVarun Prakash static void iscsit_get_rx_pdu(struct iscsi_conn *);
4762ec5a8c1SNicholas Bellinger 
477d2faaefbSVarun Prakash int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
4782ec5a8c1SNicholas Bellinger {
479a4467018SNicholas Bellinger 	return iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
4802ec5a8c1SNicholas Bellinger }
481d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_queue_rsp);
4822ec5a8c1SNicholas Bellinger 
483d2faaefbSVarun Prakash void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
484131e6abcSNicholas Bellinger {
485131e6abcSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
486064cdd2dSNicholas Bellinger 	if (!list_empty(&cmd->i_conn_node) &&
487064cdd2dSNicholas Bellinger 	    !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
488131e6abcSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
489131e6abcSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
490131e6abcSNicholas Bellinger 
4914412a671SBart Van Assche 	__iscsit_free_cmd(cmd, true);
492131e6abcSNicholas Bellinger }
493d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_aborted_task);
494131e6abcSNicholas Bellinger 
4952854bb23SVarun Prakash static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *,
496e1dfb21fSBart Van Assche 				      u32, u32, const void *, void *);
4972854bb23SVarun Prakash static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *);
4982854bb23SVarun Prakash 
4992854bb23SVarun Prakash static int
5002854bb23SVarun Prakash iscsit_xmit_nondatain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
5012854bb23SVarun Prakash 			  const void *data_buf, u32 data_buf_len)
5022854bb23SVarun Prakash {
5032854bb23SVarun Prakash 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)cmd->pdu;
5042854bb23SVarun Prakash 	struct kvec *iov;
5052854bb23SVarun Prakash 	u32 niov = 0, tx_size = ISCSI_HDR_LEN;
5062854bb23SVarun Prakash 	int ret;
5072854bb23SVarun Prakash 
5082854bb23SVarun Prakash 	iov = &cmd->iov_misc[0];
5092854bb23SVarun Prakash 	iov[niov].iov_base	= cmd->pdu;
5102854bb23SVarun Prakash 	iov[niov++].iov_len	= ISCSI_HDR_LEN;
5112854bb23SVarun Prakash 
5122854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5132854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5142854bb23SVarun Prakash 
5152854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr,
5162854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
517e1dfb21fSBart Van Assche 					  header_digest);
5182854bb23SVarun Prakash 
5192854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
5202854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
5212854bb23SVarun Prakash 		pr_debug("Attaching CRC32C HeaderDigest"
5222854bb23SVarun Prakash 			 " to opcode 0x%x 0x%08x\n",
5232854bb23SVarun Prakash 			 hdr->opcode, *header_digest);
5242854bb23SVarun Prakash 	}
5252854bb23SVarun Prakash 
5262854bb23SVarun Prakash 	if (data_buf_len) {
5272854bb23SVarun Prakash 		u32 padding = ((-data_buf_len) & 3);
5282854bb23SVarun Prakash 
5292854bb23SVarun Prakash 		iov[niov].iov_base	= (void *)data_buf;
5302854bb23SVarun Prakash 		iov[niov++].iov_len	= data_buf_len;
5312854bb23SVarun Prakash 		tx_size += data_buf_len;
5322854bb23SVarun Prakash 
5332854bb23SVarun Prakash 		if (padding != 0) {
5342854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->pad_bytes;
5352854bb23SVarun Prakash 			iov[niov++].iov_len = padding;
5362854bb23SVarun Prakash 			tx_size += padding;
5372854bb23SVarun Prakash 			pr_debug("Attaching %u additional"
5382854bb23SVarun Prakash 				 " padding bytes.\n", padding);
5392854bb23SVarun Prakash 		}
5402854bb23SVarun Prakash 
5412854bb23SVarun Prakash 		if (conn->conn_ops->DataDigest) {
5422854bb23SVarun Prakash 			iscsit_do_crypto_hash_buf(conn->conn_tx_hash,
5432854bb23SVarun Prakash 						  data_buf, data_buf_len,
544e1dfb21fSBart Van Assche 						  padding, &cmd->pad_bytes,
545e1dfb21fSBart Van Assche 						  &cmd->data_crc);
5462854bb23SVarun Prakash 
5472854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->data_crc;
5482854bb23SVarun Prakash 			iov[niov++].iov_len = ISCSI_CRC_LEN;
5492854bb23SVarun Prakash 			tx_size += ISCSI_CRC_LEN;
5502854bb23SVarun Prakash 			pr_debug("Attached DataDigest for %u"
5512854bb23SVarun Prakash 				 " bytes opcode 0x%x, CRC 0x%08x\n",
5522854bb23SVarun Prakash 				 data_buf_len, hdr->opcode, cmd->data_crc);
5532854bb23SVarun Prakash 		}
5542854bb23SVarun Prakash 	}
5552854bb23SVarun Prakash 
5562854bb23SVarun Prakash 	cmd->iov_misc_count = niov;
5572854bb23SVarun Prakash 	cmd->tx_size = tx_size;
5582854bb23SVarun Prakash 
5592854bb23SVarun Prakash 	ret = iscsit_send_tx_data(cmd, conn, 1);
5602854bb23SVarun Prakash 	if (ret < 0) {
5612854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
5622854bb23SVarun Prakash 		return ret;
5632854bb23SVarun Prakash 	}
5642854bb23SVarun Prakash 
5652854bb23SVarun Prakash 	return 0;
5662854bb23SVarun Prakash }
5672854bb23SVarun Prakash 
5682e39f1c9SBart Van Assche static int iscsit_map_iovec(struct iscsi_cmd *cmd, struct kvec *iov, int nvec,
5692e39f1c9SBart Van Assche 			    u32 data_offset, u32 data_length);
5702854bb23SVarun Prakash static void iscsit_unmap_iovec(struct iscsi_cmd *);
5712854bb23SVarun Prakash static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsi_cmd *,
5722854bb23SVarun Prakash 				    u32, u32, u32, u8 *);
5732854bb23SVarun Prakash static int
5742854bb23SVarun Prakash iscsit_xmit_datain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
5752854bb23SVarun Prakash 		       const struct iscsi_datain *datain)
5762854bb23SVarun Prakash {
5772854bb23SVarun Prakash 	struct kvec *iov;
5782854bb23SVarun Prakash 	u32 iov_count = 0, tx_size = 0;
5792854bb23SVarun Prakash 	int ret, iov_ret;
5802854bb23SVarun Prakash 
5812854bb23SVarun Prakash 	iov = &cmd->iov_data[0];
5822854bb23SVarun Prakash 	iov[iov_count].iov_base	= cmd->pdu;
5832854bb23SVarun Prakash 	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
5842854bb23SVarun Prakash 	tx_size += ISCSI_HDR_LEN;
5852854bb23SVarun Prakash 
5862854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5872854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5882854bb23SVarun Prakash 
5892854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu,
5902854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
591e1dfb21fSBart Van Assche 					  header_digest);
5922854bb23SVarun Prakash 
5932854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
5942854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
5952854bb23SVarun Prakash 
5962854bb23SVarun Prakash 		pr_debug("Attaching CRC32 HeaderDigest for DataIN PDU 0x%08x\n",
5972854bb23SVarun Prakash 			 *header_digest);
5982854bb23SVarun Prakash 	}
5992854bb23SVarun Prakash 
6002e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[iov_count],
6012e39f1c9SBart Van Assche 				   cmd->orig_iov_data_count - (iov_count + 2),
6022854bb23SVarun Prakash 				   datain->offset, datain->length);
6032854bb23SVarun Prakash 	if (iov_ret < 0)
6042854bb23SVarun Prakash 		return -1;
6052854bb23SVarun Prakash 
6062854bb23SVarun Prakash 	iov_count += iov_ret;
6072854bb23SVarun Prakash 	tx_size += datain->length;
6082854bb23SVarun Prakash 
6092854bb23SVarun Prakash 	cmd->padding = ((-datain->length) & 3);
6102854bb23SVarun Prakash 	if (cmd->padding) {
6112854bb23SVarun Prakash 		iov[iov_count].iov_base		= cmd->pad_bytes;
6122854bb23SVarun Prakash 		iov[iov_count++].iov_len	= cmd->padding;
6132854bb23SVarun Prakash 		tx_size += cmd->padding;
6142854bb23SVarun Prakash 
6152854bb23SVarun Prakash 		pr_debug("Attaching %u padding bytes\n", cmd->padding);
6162854bb23SVarun Prakash 	}
6172854bb23SVarun Prakash 
6182854bb23SVarun Prakash 	if (conn->conn_ops->DataDigest) {
6192854bb23SVarun Prakash 		cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash,
6202854bb23SVarun Prakash 							 cmd, datain->offset,
6212854bb23SVarun Prakash 							 datain->length,
6222854bb23SVarun Prakash 							 cmd->padding,
6232854bb23SVarun Prakash 							 cmd->pad_bytes);
6242854bb23SVarun Prakash 
6252854bb23SVarun Prakash 		iov[iov_count].iov_base	= &cmd->data_crc;
6262854bb23SVarun Prakash 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
6272854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
6282854bb23SVarun Prakash 
6292854bb23SVarun Prakash 		pr_debug("Attached CRC32C DataDigest %d bytes, crc 0x%08x\n",
6302854bb23SVarun Prakash 			 datain->length + cmd->padding, cmd->data_crc);
6312854bb23SVarun Prakash 	}
6322854bb23SVarun Prakash 
6332854bb23SVarun Prakash 	cmd->iov_data_count = iov_count;
6342854bb23SVarun Prakash 	cmd->tx_size = tx_size;
6352854bb23SVarun Prakash 
6362854bb23SVarun Prakash 	ret = iscsit_fe_sendpage_sg(cmd, conn);
6372854bb23SVarun Prakash 
6382854bb23SVarun Prakash 	iscsit_unmap_iovec(cmd);
6392854bb23SVarun Prakash 
6402854bb23SVarun Prakash 	if (ret < 0) {
6412854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
6422854bb23SVarun Prakash 		return ret;
6432854bb23SVarun Prakash 	}
6442854bb23SVarun Prakash 
6452854bb23SVarun Prakash 	return 0;
6462854bb23SVarun Prakash }
6472854bb23SVarun Prakash 
6482854bb23SVarun Prakash static int iscsit_xmit_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
6492854bb23SVarun Prakash 			   struct iscsi_datain_req *dr, const void *buf,
6502854bb23SVarun Prakash 			   u32 buf_len)
6512854bb23SVarun Prakash {
6522854bb23SVarun Prakash 	if (dr)
6532854bb23SVarun Prakash 		return iscsit_xmit_datain_pdu(conn, cmd, buf);
6542854bb23SVarun Prakash 	else
6552854bb23SVarun Prakash 		return iscsit_xmit_nondatain_pdu(conn, cmd, buf, buf_len);
6562854bb23SVarun Prakash }
6572854bb23SVarun Prakash 
658e70beee7SNicholas Bellinger static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
659e70beee7SNicholas Bellinger {
660e70beee7SNicholas Bellinger 	return TARGET_PROT_NORMAL;
661e70beee7SNicholas Bellinger }
662e70beee7SNicholas Bellinger 
663baa4d64bSNicholas Bellinger static struct iscsit_transport iscsi_target_transport = {
664baa4d64bSNicholas Bellinger 	.name			= "iSCSI/TCP",
665baa4d64bSNicholas Bellinger 	.transport_type		= ISCSI_TCP,
666bd027d85SNicholas Bellinger 	.rdma_shutdown		= false,
667baa4d64bSNicholas Bellinger 	.owner			= NULL,
668baa4d64bSNicholas Bellinger 	.iscsit_setup_np	= iscsit_setup_np,
669baa4d64bSNicholas Bellinger 	.iscsit_accept_np	= iscsit_accept_np,
670baa4d64bSNicholas Bellinger 	.iscsit_free_np		= iscsit_free_np,
671baa4d64bSNicholas Bellinger 	.iscsit_get_login_rx	= iscsit_get_login_rx,
672baa4d64bSNicholas Bellinger 	.iscsit_put_login_tx	= iscsit_put_login_tx,
6733e1c81a9SNicholas Bellinger 	.iscsit_get_dataout	= iscsit_build_r2ts_for_cmd,
6742ec5a8c1SNicholas Bellinger 	.iscsit_immediate_queue	= iscsit_immediate_queue,
6752ec5a8c1SNicholas Bellinger 	.iscsit_response_queue	= iscsit_response_queue,
6762ec5a8c1SNicholas Bellinger 	.iscsit_queue_data_in	= iscsit_queue_rsp,
6772ec5a8c1SNicholas Bellinger 	.iscsit_queue_status	= iscsit_queue_rsp,
678131e6abcSNicholas Bellinger 	.iscsit_aborted_task	= iscsit_aborted_task,
6792854bb23SVarun Prakash 	.iscsit_xmit_pdu	= iscsit_xmit_pdu,
680e8205ccaSVarun Prakash 	.iscsit_get_rx_pdu	= iscsit_get_rx_pdu,
681e70beee7SNicholas Bellinger 	.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
682baa4d64bSNicholas Bellinger };
683baa4d64bSNicholas Bellinger 
684e48354ceSNicholas Bellinger static int __init iscsi_target_init_module(void)
685e48354ceSNicholas Bellinger {
68688dcd2daSNicholas Bellinger 	int ret = 0, size;
687e48354ceSNicholas Bellinger 
688e48354ceSNicholas Bellinger 	pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
6893829f381SMarkus Elfring 	iscsit_global = kzalloc(sizeof(*iscsit_global), GFP_KERNEL);
690c46e22f1SMarkus Elfring 	if (!iscsit_global)
691e48354ceSNicholas Bellinger 		return -1;
692c46e22f1SMarkus Elfring 
69388dcd2daSNicholas Bellinger 	spin_lock_init(&iscsit_global->ts_bitmap_lock);
694e48354ceSNicholas Bellinger 	mutex_init(&auth_id_lock);
695e48354ceSNicholas Bellinger 	idr_init(&tiqn_idr);
696e48354ceSNicholas Bellinger 
6979ac8928eSChristoph Hellwig 	ret = target_register_template(&iscsi_ops);
6989ac8928eSChristoph Hellwig 	if (ret)
699e48354ceSNicholas Bellinger 		goto out;
700e48354ceSNicholas Bellinger 
70188dcd2daSNicholas Bellinger 	size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
70288dcd2daSNicholas Bellinger 	iscsit_global->ts_bitmap = vzalloc(size);
703c46e22f1SMarkus Elfring 	if (!iscsit_global->ts_bitmap)
704e48354ceSNicholas Bellinger 		goto configfs_out;
705e48354ceSNicholas Bellinger 
706e48354ceSNicholas Bellinger 	lio_qr_cache = kmem_cache_create("lio_qr_cache",
707e48354ceSNicholas Bellinger 			sizeof(struct iscsi_queue_req),
708e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_queue_req), 0, NULL);
709e48354ceSNicholas Bellinger 	if (!lio_qr_cache) {
710621a4367SLeo Zhang 		pr_err("Unable to kmem_cache_create() for"
711e48354ceSNicholas Bellinger 				" lio_qr_cache\n");
71288dcd2daSNicholas Bellinger 		goto bitmap_out;
713e48354ceSNicholas Bellinger 	}
714e48354ceSNicholas Bellinger 
715e48354ceSNicholas Bellinger 	lio_dr_cache = kmem_cache_create("lio_dr_cache",
716e48354ceSNicholas Bellinger 			sizeof(struct iscsi_datain_req),
717e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_datain_req), 0, NULL);
718e48354ceSNicholas Bellinger 	if (!lio_dr_cache) {
719e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
720e48354ceSNicholas Bellinger 				" lio_dr_cache\n");
721e48354ceSNicholas Bellinger 		goto qr_out;
722e48354ceSNicholas Bellinger 	}
723e48354ceSNicholas Bellinger 
724e48354ceSNicholas Bellinger 	lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
725e48354ceSNicholas Bellinger 			sizeof(struct iscsi_ooo_cmdsn),
726e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_ooo_cmdsn), 0, NULL);
727e48354ceSNicholas Bellinger 	if (!lio_ooo_cache) {
728e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
729e48354ceSNicholas Bellinger 				" lio_ooo_cache\n");
730e48354ceSNicholas Bellinger 		goto dr_out;
731e48354ceSNicholas Bellinger 	}
732e48354ceSNicholas Bellinger 
733e48354ceSNicholas Bellinger 	lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
734e48354ceSNicholas Bellinger 			sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
735e48354ceSNicholas Bellinger 			0, NULL);
736e48354ceSNicholas Bellinger 	if (!lio_r2t_cache) {
737e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
738e48354ceSNicholas Bellinger 				" lio_r2t_cache\n");
739e48354ceSNicholas Bellinger 		goto ooo_out;
740e48354ceSNicholas Bellinger 	}
741e48354ceSNicholas Bellinger 
742baa4d64bSNicholas Bellinger 	iscsit_register_transport(&iscsi_target_transport);
743baa4d64bSNicholas Bellinger 
744e48354ceSNicholas Bellinger 	if (iscsit_load_discovery_tpg() < 0)
745e48354ceSNicholas Bellinger 		goto r2t_out;
746e48354ceSNicholas Bellinger 
747e48354ceSNicholas Bellinger 	return ret;
748e48354ceSNicholas Bellinger r2t_out:
7497f2c53bbSLino Sanfilippo 	iscsit_unregister_transport(&iscsi_target_transport);
750e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
751e48354ceSNicholas Bellinger ooo_out:
752e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
753e48354ceSNicholas Bellinger dr_out:
754e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
755e48354ceSNicholas Bellinger qr_out:
756e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
75788dcd2daSNicholas Bellinger bitmap_out:
75888dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
759e48354ceSNicholas Bellinger configfs_out:
7609ac8928eSChristoph Hellwig 	/* XXX: this probably wants it to be it's own unwind step.. */
7619ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7629ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
7639ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
764e48354ceSNicholas Bellinger out:
765e48354ceSNicholas Bellinger 	kfree(iscsit_global);
766e48354ceSNicholas Bellinger 	return -ENOMEM;
767e48354ceSNicholas Bellinger }
768e48354ceSNicholas Bellinger 
769e48354ceSNicholas Bellinger static void __exit iscsi_target_cleanup_module(void)
770e48354ceSNicholas Bellinger {
771e48354ceSNicholas Bellinger 	iscsit_release_discovery_tpg();
772baa4d64bSNicholas Bellinger 	iscsit_unregister_transport(&iscsi_target_transport);
773e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
774e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
775e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
776e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
777e48354ceSNicholas Bellinger 
7789ac8928eSChristoph Hellwig 	/*
7799ac8928eSChristoph Hellwig 	 * Shutdown discovery sessions and disable discovery TPG
7809ac8928eSChristoph Hellwig 	 */
7819ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7829ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
783e48354ceSNicholas Bellinger 
7849ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
785e48354ceSNicholas Bellinger 
78688dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
787e48354ceSNicholas Bellinger 	kfree(iscsit_global);
788e48354ceSNicholas Bellinger }
789e48354ceSNicholas Bellinger 
790d2faaefbSVarun Prakash int iscsit_add_reject(
791ba159914SNicholas Bellinger 	struct iscsi_conn *conn,
792e48354ceSNicholas Bellinger 	u8 reason,
793ba159914SNicholas Bellinger 	unsigned char *buf)
794e48354ceSNicholas Bellinger {
795e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
796e48354ceSNicholas Bellinger 
797676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
798e48354ceSNicholas Bellinger 	if (!cmd)
799e48354ceSNicholas Bellinger 		return -1;
800e48354ceSNicholas Bellinger 
801e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
802ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
803e48354ceSNicholas Bellinger 
8041c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
805e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
806e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
807aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
808e48354ceSNicholas Bellinger 		return -1;
809e48354ceSNicholas Bellinger 	}
810e48354ceSNicholas Bellinger 
811e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
8122fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
813e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
814e48354ceSNicholas Bellinger 
815e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
816e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
817e48354ceSNicholas Bellinger 
818e48354ceSNicholas Bellinger 	return -1;
819e48354ceSNicholas Bellinger }
820d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_add_reject);
821e48354ceSNicholas Bellinger 
822ba159914SNicholas Bellinger static int iscsit_add_reject_from_cmd(
823ba159914SNicholas Bellinger 	struct iscsi_cmd *cmd,
824e48354ceSNicholas Bellinger 	u8 reason,
825ba159914SNicholas Bellinger 	bool add_to_conn,
826ba159914SNicholas Bellinger 	unsigned char *buf)
827e48354ceSNicholas Bellinger {
828e48354ceSNicholas Bellinger 	struct iscsi_conn *conn;
829cfe2b621SBart Van Assche 	const bool do_put = cmd->se_cmd.se_tfo != NULL;
830e48354ceSNicholas Bellinger 
831e48354ceSNicholas Bellinger 	if (!cmd->conn) {
832e48354ceSNicholas Bellinger 		pr_err("cmd->conn is NULL for ITT: 0x%08x\n",
833e48354ceSNicholas Bellinger 				cmd->init_task_tag);
834e48354ceSNicholas Bellinger 		return -1;
835e48354ceSNicholas Bellinger 	}
836e48354ceSNicholas Bellinger 	conn = cmd->conn;
837e48354ceSNicholas Bellinger 
838e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
839ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
840e48354ceSNicholas Bellinger 
8411c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
842e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
843e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
844aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
845e48354ceSNicholas Bellinger 		return -1;
846e48354ceSNicholas Bellinger 	}
847e48354ceSNicholas Bellinger 
848e48354ceSNicholas Bellinger 	if (add_to_conn) {
849e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
8502fbb471eSAndy Grover 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
851e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
852e48354ceSNicholas Bellinger 	}
853e48354ceSNicholas Bellinger 
854e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
855e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
8563e1c81a9SNicholas Bellinger 	/*
8573e1c81a9SNicholas Bellinger 	 * Perform the kref_put now if se_cmd has already been setup by
8583e1c81a9SNicholas Bellinger 	 * scsit_setup_scsi_cmd()
8593e1c81a9SNicholas Bellinger 	 */
860cfe2b621SBart Van Assche 	if (do_put) {
8613e1c81a9SNicholas Bellinger 		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
862afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
8633e1c81a9SNicholas Bellinger 	}
864e48354ceSNicholas Bellinger 	return -1;
865e48354ceSNicholas Bellinger }
866ba159914SNicholas Bellinger 
867ba159914SNicholas Bellinger static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason,
868ba159914SNicholas Bellinger 				 unsigned char *buf)
869ba159914SNicholas Bellinger {
870ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, true, buf);
871ba159914SNicholas Bellinger }
872ba159914SNicholas Bellinger 
873ba159914SNicholas Bellinger int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf)
874ba159914SNicholas Bellinger {
875ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, false, buf);
876ba159914SNicholas Bellinger }
877d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_reject_cmd);
878e48354ceSNicholas Bellinger 
879e48354ceSNicholas Bellinger /*
880e48354ceSNicholas Bellinger  * Map some portion of the allocated scatterlist to an iovec, suitable for
881bfb79eacSAndy Grover  * kernel sockets to copy data in/out.
882e48354ceSNicholas Bellinger  */
8832e39f1c9SBart Van Assche static int iscsit_map_iovec(struct iscsi_cmd *cmd, struct kvec *iov, int nvec,
8842e39f1c9SBart Van Assche 			    u32 data_offset, u32 data_length)
885e48354ceSNicholas Bellinger {
8862e39f1c9SBart Van Assche 	u32 i = 0, orig_data_length = data_length;
887e48354ceSNicholas Bellinger 	struct scatterlist *sg;
888e48354ceSNicholas Bellinger 	unsigned int page_off;
889e48354ceSNicholas Bellinger 
890e48354ceSNicholas Bellinger 	/*
891bfb79eacSAndy Grover 	 * We know each entry in t_data_sg contains a page.
892e48354ceSNicholas Bellinger 	 */
8932b16509cSImran Haider 	u32 ent = data_offset / PAGE_SIZE;
8942b16509cSImran Haider 
8952e39f1c9SBart Van Assche 	if (!data_length)
8962e39f1c9SBart Van Assche 		return 0;
8972e39f1c9SBart Van Assche 
8982b16509cSImran Haider 	if (ent >= cmd->se_cmd.t_data_nents) {
8992b16509cSImran Haider 		pr_err("Initial page entry out-of-bounds\n");
9002e39f1c9SBart Van Assche 		goto overflow;
9012b16509cSImran Haider 	}
9022b16509cSImran Haider 
9032b16509cSImran Haider 	sg = &cmd->se_cmd.t_data_sg[ent];
904e48354ceSNicholas Bellinger 	page_off = (data_offset % PAGE_SIZE);
905e48354ceSNicholas Bellinger 
906e48354ceSNicholas Bellinger 	cmd->first_data_sg = sg;
907e48354ceSNicholas Bellinger 	cmd->first_data_sg_off = page_off;
908e48354ceSNicholas Bellinger 
909e48354ceSNicholas Bellinger 	while (data_length) {
9102e39f1c9SBart Van Assche 		u32 cur_len;
9112e39f1c9SBart Van Assche 
9122e39f1c9SBart Van Assche 		if (WARN_ON_ONCE(!sg || i >= nvec))
9132e39f1c9SBart Van Assche 			goto overflow;
9142e39f1c9SBart Van Assche 
9152e39f1c9SBart Van Assche 		cur_len = min_t(u32, data_length, sg->length - page_off);
916e48354ceSNicholas Bellinger 
917e48354ceSNicholas Bellinger 		iov[i].iov_base = kmap(sg_page(sg)) + sg->offset + page_off;
918e48354ceSNicholas Bellinger 		iov[i].iov_len = cur_len;
919e48354ceSNicholas Bellinger 
920e48354ceSNicholas Bellinger 		data_length -= cur_len;
921e48354ceSNicholas Bellinger 		page_off = 0;
922e48354ceSNicholas Bellinger 		sg = sg_next(sg);
923e48354ceSNicholas Bellinger 		i++;
924e48354ceSNicholas Bellinger 	}
925e48354ceSNicholas Bellinger 
926e48354ceSNicholas Bellinger 	cmd->kmapped_nents = i;
927e48354ceSNicholas Bellinger 
928e48354ceSNicholas Bellinger 	return i;
9292e39f1c9SBart Van Assche 
9302e39f1c9SBart Van Assche overflow:
9312e39f1c9SBart Van Assche 	pr_err("offset %d + length %d overflow; %d/%d; sg-list:\n",
9322e39f1c9SBart Van Assche 	       data_offset, orig_data_length, i, nvec);
9332e39f1c9SBart Van Assche 	for_each_sg(cmd->se_cmd.t_data_sg, sg,
9342e39f1c9SBart Van Assche 		    cmd->se_cmd.t_data_nents, i) {
9352e39f1c9SBart Van Assche 		pr_err("[%d] off %d len %d\n",
9362e39f1c9SBart Van Assche 		       i, sg->offset, sg->length);
9372e39f1c9SBart Van Assche 	}
9382e39f1c9SBart Van Assche 	return -1;
939e48354ceSNicholas Bellinger }
940e48354ceSNicholas Bellinger 
941e48354ceSNicholas Bellinger static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)
942e48354ceSNicholas Bellinger {
943e48354ceSNicholas Bellinger 	u32 i;
944e48354ceSNicholas Bellinger 	struct scatterlist *sg;
945e48354ceSNicholas Bellinger 
946e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
947e48354ceSNicholas Bellinger 
948e48354ceSNicholas Bellinger 	for (i = 0; i < cmd->kmapped_nents; i++)
949e48354ceSNicholas Bellinger 		kunmap(sg_page(&sg[i]));
950e48354ceSNicholas Bellinger }
951e48354ceSNicholas Bellinger 
952e48354ceSNicholas Bellinger static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
953e48354ceSNicholas Bellinger {
954f56cbbb4SNicholas Bellinger 	LIST_HEAD(ack_list);
955f56cbbb4SNicholas Bellinger 	struct iscsi_cmd *cmd, *cmd_p;
956e48354ceSNicholas Bellinger 
957e48354ceSNicholas Bellinger 	conn->exp_statsn = exp_statsn;
958e48354ceSNicholas Bellinger 
9593e1c81a9SNicholas Bellinger 	if (conn->sess->sess_ops->RDMAExtensions)
9603e1c81a9SNicholas Bellinger 		return;
9613e1c81a9SNicholas Bellinger 
962e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
963f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
964e48354ceSNicholas Bellinger 		spin_lock(&cmd->istate_lock);
965e48354ceSNicholas Bellinger 		if ((cmd->i_state == ISTATE_SENT_STATUS) &&
96664c13330SSteve Hodgson 		    iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
967e48354ceSNicholas Bellinger 			cmd->i_state = ISTATE_REMOVE;
968e48354ceSNicholas Bellinger 			spin_unlock(&cmd->istate_lock);
969f56cbbb4SNicholas Bellinger 			list_move_tail(&cmd->i_conn_node, &ack_list);
970e48354ceSNicholas Bellinger 			continue;
971e48354ceSNicholas Bellinger 		}
972e48354ceSNicholas Bellinger 		spin_unlock(&cmd->istate_lock);
973e48354ceSNicholas Bellinger 	}
974e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
975f56cbbb4SNicholas Bellinger 
976f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
9775159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
978f56cbbb4SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
979f56cbbb4SNicholas Bellinger 	}
980e48354ceSNicholas Bellinger }
981e48354ceSNicholas Bellinger 
982e48354ceSNicholas Bellinger static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
983e48354ceSNicholas Bellinger {
984f80e8ed3SNicholas Bellinger 	u32 iov_count = max(1UL, DIV_ROUND_UP(cmd->se_cmd.data_length, PAGE_SIZE));
985e48354ceSNicholas Bellinger 
986c0427f15SChristoph Hellwig 	iov_count += ISCSI_IOV_DATA_BUFFER;
987f1725110SMarkus Elfring 	cmd->iov_data = kcalloc(iov_count, sizeof(*cmd->iov_data), GFP_KERNEL);
988c46e22f1SMarkus Elfring 	if (!cmd->iov_data)
989e48354ceSNicholas Bellinger 		return -ENOMEM;
990e48354ceSNicholas Bellinger 
991e48354ceSNicholas Bellinger 	cmd->orig_iov_data_count = iov_count;
992e48354ceSNicholas Bellinger 	return 0;
993e48354ceSNicholas Bellinger }
994e48354ceSNicholas Bellinger 
9953e1c81a9SNicholas Bellinger int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
996e48354ceSNicholas Bellinger 			  unsigned char *buf)
997e48354ceSNicholas Bellinger {
9983e1c81a9SNicholas Bellinger 	int data_direction, payload_length;
999e48354ceSNicholas Bellinger 	struct iscsi_scsi_req *hdr;
1000d28b1169SAndy Grover 	int iscsi_task_attr;
1001d28b1169SAndy Grover 	int sam_task_attr;
1002e48354ceSNicholas Bellinger 
100304f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->cmd_pdus);
1004e48354ceSNicholas Bellinger 
1005e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_scsi_req *) buf;
1006e48354ceSNicholas Bellinger 	payload_length		= ntoh24(hdr->dlength);
1007e48354ceSNicholas Bellinger 
1008e48354ceSNicholas Bellinger 	/* FIXME; Add checks for AdditionalHeaderSegment */
1009e48354ceSNicholas Bellinger 
1010e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_WRITE) &&
1011e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1012e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
1013e48354ceSNicholas Bellinger 				" not set. Bad iSCSI Initiator.\n");
1014ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1015ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1016e48354ceSNicholas Bellinger 	}
1017e48354ceSNicholas Bellinger 
1018e48354ceSNicholas Bellinger 	if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
1019e48354ceSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
1020e48354ceSNicholas Bellinger 		/*
10214454b66cSNicholas Bellinger 		 * From RFC-3720 Section 10.3.1:
10224454b66cSNicholas Bellinger 		 *
10234454b66cSNicholas Bellinger 		 * "Either or both of R and W MAY be 1 when either the
10244454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length and/or Bidirectional Read
10254454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length are 0"
10264454b66cSNicholas Bellinger 		 *
10274454b66cSNicholas Bellinger 		 * For this case, go ahead and clear the unnecssary bits
10284454b66cSNicholas Bellinger 		 * to avoid any confusion with ->data_direction.
1029e48354ceSNicholas Bellinger 		 */
1030e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_READ;
1031e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
1032e48354ceSNicholas Bellinger 
10334454b66cSNicholas Bellinger 		pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
1034e48354ceSNicholas Bellinger 			" set when Expected Data Transfer Length is 0 for"
10354454b66cSNicholas Bellinger 			" CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
1036e48354ceSNicholas Bellinger 	}
1037e48354ceSNicholas Bellinger 
1038e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
1039e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
1040e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
1041e48354ceSNicholas Bellinger 			" MUST be set if Expected Data Transfer Length is not 0."
1042e48354ceSNicholas Bellinger 			" Bad iSCSI Initiator\n");
1043ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1044ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1045e48354ceSNicholas Bellinger 	}
1046e48354ceSNicholas Bellinger 
1047e48354ceSNicholas Bellinger 	if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
1048e48354ceSNicholas Bellinger 	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
1049e48354ceSNicholas Bellinger 		pr_err("Bidirectional operations not supported!\n");
1050ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1051ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1052e48354ceSNicholas Bellinger 	}
1053e48354ceSNicholas Bellinger 
1054e48354ceSNicholas Bellinger 	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1055e48354ceSNicholas Bellinger 		pr_err("Illegally set Immediate Bit in iSCSI Initiator"
1056e48354ceSNicholas Bellinger 				" Scsi Command PDU.\n");
1057ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1058ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1059e48354ceSNicholas Bellinger 	}
1060e48354ceSNicholas Bellinger 
1061e48354ceSNicholas Bellinger 	if (payload_length && !conn->sess->sess_ops->ImmediateData) {
1062e48354ceSNicholas Bellinger 		pr_err("ImmediateData=No but DataSegmentLength=%u,"
1063e48354ceSNicholas Bellinger 			" protocol error.\n", payload_length);
1064ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1065ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1066e48354ceSNicholas Bellinger 	}
1067e48354ceSNicholas Bellinger 
106850e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->data_length) == payload_length) &&
1069e48354ceSNicholas Bellinger 	    (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
1070e48354ceSNicholas Bellinger 		pr_err("Expected Data Transfer Length and Length of"
1071e48354ceSNicholas Bellinger 			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
1072e48354ceSNicholas Bellinger 			" bit is not set protocol error\n");
1073ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1074ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1075e48354ceSNicholas Bellinger 	}
1076e48354ceSNicholas Bellinger 
107750e5c87dSChristoph Hellwig 	if (payload_length > be32_to_cpu(hdr->data_length)) {
1078e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1079e48354ceSNicholas Bellinger 			" EDTL: %u, protocol error.\n", payload_length,
1080e48354ceSNicholas Bellinger 				hdr->data_length);
1081ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1082ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1083e48354ceSNicholas Bellinger 	}
1084e48354ceSNicholas Bellinger 
108521f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1086e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
108721f5aa7eSNicholas Bellinger 			" MaxXmitDataSegmentLength: %u, protocol error.\n",
108821f5aa7eSNicholas Bellinger 			payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
1089ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1090ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1091e48354ceSNicholas Bellinger 	}
1092e48354ceSNicholas Bellinger 
1093e48354ceSNicholas Bellinger 	if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
1094e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1095e48354ceSNicholas Bellinger 			" FirstBurstLength: %u, protocol error.\n",
1096e48354ceSNicholas Bellinger 			payload_length, conn->sess->sess_ops->FirstBurstLength);
1097ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1098ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1099e48354ceSNicholas Bellinger 	}
1100e48354ceSNicholas Bellinger 
1101e48354ceSNicholas Bellinger 	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
1102e48354ceSNicholas Bellinger 			 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE :
1103e48354ceSNicholas Bellinger 			  DMA_NONE;
1104e48354ceSNicholas Bellinger 
1105d28b1169SAndy Grover 	cmd->data_direction = data_direction;
1106d28b1169SAndy Grover 	iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK;
1107d28b1169SAndy Grover 	/*
1108d28b1169SAndy Grover 	 * Figure out the SAM Task Attribute for the incoming SCSI CDB
1109d28b1169SAndy Grover 	 */
1110d28b1169SAndy Grover 	if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
1111d28b1169SAndy Grover 	    (iscsi_task_attr == ISCSI_ATTR_SIMPLE))
111268d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1113d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
111468d81f40SChristoph Hellwig 		sam_task_attr = TCM_ORDERED_TAG;
1115d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
111668d81f40SChristoph Hellwig 		sam_task_attr = TCM_HEAD_TAG;
1117d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ACA)
111868d81f40SChristoph Hellwig 		sam_task_attr = TCM_ACA_TAG;
1119d28b1169SAndy Grover 	else {
1120d28b1169SAndy Grover 		pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
112168d81f40SChristoph Hellwig 			" TCM_SIMPLE_TAG\n", iscsi_task_attr);
112268d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1123d28b1169SAndy Grover 	}
1124d28b1169SAndy Grover 
1125e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_CMD;
1126e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_NEW_CMD;
1127e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
1128e48354ceSNicholas Bellinger 	cmd->immediate_data	= (payload_length) ? 1 : 0;
1129e48354ceSNicholas Bellinger 	cmd->unsolicited_data	= ((!(hdr->flags & ISCSI_FLAG_CMD_FINAL) &&
1130e48354ceSNicholas Bellinger 				     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) ? 1 : 0);
1131e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data)
1132e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;
1133e48354ceSNicholas Bellinger 
1134e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
11359547308bSAlexei Potashnik 	if (hdr->flags & ISCSI_FLAG_CMD_READ)
1136c1e34b64SSagi Grimberg 		cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
11379547308bSAlexei Potashnik 	else
1138e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag = 0xFFFFFFFF;
113950e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
114050e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1141e48354ceSNicholas Bellinger 	cmd->first_burst_len	= payload_length;
1142e48354ceSNicholas Bellinger 
11433e1c81a9SNicholas Bellinger 	if (!conn->sess->sess_ops->RDMAExtensions &&
11443e1c81a9SNicholas Bellinger 	     cmd->data_direction == DMA_FROM_DEVICE) {
1145e48354ceSNicholas Bellinger 		struct iscsi_datain_req *dr;
1146e48354ceSNicholas Bellinger 
1147e48354ceSNicholas Bellinger 		dr = iscsit_allocate_datain_req();
1148e48354ceSNicholas Bellinger 		if (!dr)
1149ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1150ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1151e48354ceSNicholas Bellinger 
1152e48354ceSNicholas Bellinger 		iscsit_attach_datain_req(cmd, dr);
1153e48354ceSNicholas Bellinger 	}
1154e48354ceSNicholas Bellinger 
1155e48354ceSNicholas Bellinger 	/*
1156065ca1e4SAndy Grover 	 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
1157065ca1e4SAndy Grover 	 */
11589ac8928eSChristoph Hellwig 	transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
115950e5c87dSChristoph Hellwig 			conn->sess->se_sess, be32_to_cpu(hdr->data_length),
116050e5c87dSChristoph Hellwig 			cmd->data_direction, sam_task_attr,
1161a36840d8SSudhakar Panneerselvam 			cmd->sense_buffer + 2, scsilun_to_int(&hdr->lun));
1162065ca1e4SAndy Grover 
1163065ca1e4SAndy Grover 	pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
1164065ca1e4SAndy Grover 		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
11653e1c81a9SNicholas Bellinger 		hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
11663e1c81a9SNicholas Bellinger 		conn->cid);
11673e1c81a9SNicholas Bellinger 
1168807b9515SBart Van Assche 	target_get_sess_cmd(&cmd->se_cmd, true);
1169065ca1e4SAndy Grover 
11709e95fb80SSudhakar Panneerselvam 	cmd->sense_reason = target_cmd_init_cdb(&cmd->se_cmd, hdr->cdb);
1171de103c93SChristoph Hellwig 	if (cmd->sense_reason) {
1172de103c93SChristoph Hellwig 		if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
1173ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1174ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1175de103c93SChristoph Hellwig 		}
1176de103c93SChristoph Hellwig 
1177de103c93SChristoph Hellwig 		goto attach_cmd;
1178de103c93SChristoph Hellwig 	}
1179de103c93SChristoph Hellwig 
11809e95fb80SSudhakar Panneerselvam 	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd);
11819e95fb80SSudhakar Panneerselvam 	if (cmd->sense_reason)
11829e95fb80SSudhakar Panneerselvam 		goto attach_cmd;
11839e95fb80SSudhakar Panneerselvam 
11849e95fb80SSudhakar Panneerselvam 	/* only used for printks or comparing with ->ref_task_tag */
11859e95fb80SSudhakar Panneerselvam 	cmd->se_cmd.tag = (__force u32)cmd->init_task_tag;
1186987db587SSudhakar Panneerselvam 	cmd->sense_reason = target_cmd_parse_cdb(&cmd->se_cmd);
11879e95fb80SSudhakar Panneerselvam 	if (cmd->sense_reason)
11889e95fb80SSudhakar Panneerselvam 		goto attach_cmd;
11899e95fb80SSudhakar Panneerselvam 
1190de103c93SChristoph Hellwig 	if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
1191ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1192ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1193e48354ceSNicholas Bellinger 	}
1194e48354ceSNicholas Bellinger 
1195e48354ceSNicholas Bellinger attach_cmd:
1196e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
11972fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1198e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
1199e48354ceSNicholas Bellinger 	/*
1200e48354ceSNicholas Bellinger 	 * Check if we need to delay processing because of ALUA
1201e48354ceSNicholas Bellinger 	 * Active/NonOptimized primary access state..
1202e48354ceSNicholas Bellinger 	 */
1203e48354ceSNicholas Bellinger 	core_alua_check_nonop_delay(&cmd->se_cmd);
1204bfb79eacSAndy Grover 
12053e1c81a9SNicholas Bellinger 	return 0;
1206de103c93SChristoph Hellwig }
12073e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_scsi_cmd);
1208de103c93SChristoph Hellwig 
12090300b114SBart Van Assche void iscsit_set_unsolicited_dataout(struct iscsi_cmd *cmd)
12103e1c81a9SNicholas Bellinger {
12113e1c81a9SNicholas Bellinger 	iscsit_set_dataout_sequence_values(cmd);
12123e1c81a9SNicholas Bellinger 
12133e1c81a9SNicholas Bellinger 	spin_lock_bh(&cmd->dataout_timeout_lock);
12143e1c81a9SNicholas Bellinger 	iscsit_start_dataout_timer(cmd, cmd->conn);
12153e1c81a9SNicholas Bellinger 	spin_unlock_bh(&cmd->dataout_timeout_lock);
12163e1c81a9SNicholas Bellinger }
12170300b114SBart Van Assche EXPORT_SYMBOL(iscsit_set_unsolicited_dataout);
12183e1c81a9SNicholas Bellinger 
12193e1c81a9SNicholas Bellinger int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
12203e1c81a9SNicholas Bellinger 			    struct iscsi_scsi_req *hdr)
12213e1c81a9SNicholas Bellinger {
12223e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0;
1223e48354ceSNicholas Bellinger 	/*
1224e48354ceSNicholas Bellinger 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
1225e48354ceSNicholas Bellinger 	 * the Immediate Bit is not set, and no Immediate
1226e48354ceSNicholas Bellinger 	 * Data is attached.
1227e48354ceSNicholas Bellinger 	 *
1228e48354ceSNicholas Bellinger 	 * A PDU/CmdSN carrying Immediate Data can only
1229e48354ceSNicholas Bellinger 	 * be processed after the DataCRC has passed.
1230e48354ceSNicholas Bellinger 	 * If the DataCRC fails, the CmdSN MUST NOT
1231e48354ceSNicholas Bellinger 	 * be acknowledged. (See below)
1232e48354ceSNicholas Bellinger 	 */
1233e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
1234561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1235561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
1236561bf158SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1237561bf158SNicholas Bellinger 			return -1;
1238561bf158SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1239afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
12403e1c81a9SNicholas Bellinger 			return 0;
12413e1c81a9SNicholas Bellinger 		}
1242e48354ceSNicholas Bellinger 	}
1243e48354ceSNicholas Bellinger 
124450e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1245e48354ceSNicholas Bellinger 
1246e48354ceSNicholas Bellinger 	/*
1247e48354ceSNicholas Bellinger 	 * If no Immediate Data is attached, it's OK to return now.
1248e48354ceSNicholas Bellinger 	 */
1249e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
12503e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason && cmd->unsolicited_data)
12510300b114SBart Van Assche 			iscsit_set_unsolicited_dataout(cmd);
12523e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason)
12533e1c81a9SNicholas Bellinger 			return 0;
1254e48354ceSNicholas Bellinger 
1255afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
1256e48354ceSNicholas Bellinger 		return 0;
1257e48354ceSNicholas Bellinger 	}
1258e48354ceSNicholas Bellinger 
1259e48354ceSNicholas Bellinger 	/*
12603e1c81a9SNicholas Bellinger 	 * Early CHECK_CONDITIONs with ImmediateData never make it to command
12613e1c81a9SNicholas Bellinger 	 * execution.  These exceptions are processed in CmdSN order using
12623e1c81a9SNicholas Bellinger 	 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
1263e48354ceSNicholas Bellinger 	 */
12648fa4011eSBart Van Assche 	if (cmd->sense_reason)
12653e1c81a9SNicholas Bellinger 		return 1;
1266e48354ceSNicholas Bellinger 	/*
1267e48354ceSNicholas Bellinger 	 * Call directly into transport_generic_new_cmd() to perform
1268e48354ceSNicholas Bellinger 	 * the backend memory allocation.
1269e48354ceSNicholas Bellinger 	 */
1270de103c93SChristoph Hellwig 	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
1271561bf158SNicholas Bellinger 	if (cmd->sense_reason)
12723e1c81a9SNicholas Bellinger 		return 1;
1273e48354ceSNicholas Bellinger 
12743e1c81a9SNicholas Bellinger 	return 0;
12753e1c81a9SNicholas Bellinger }
12763e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_scsi_cmd);
12773e1c81a9SNicholas Bellinger 
12783e1c81a9SNicholas Bellinger static int
12793e1c81a9SNicholas Bellinger iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
12803e1c81a9SNicholas Bellinger 			  bool dump_payload)
12813e1c81a9SNicholas Bellinger {
12823e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
12834b3766ecSBart Van Assche 	int rc;
12844b3766ecSBart Van Assche 
12853e1c81a9SNicholas Bellinger 	/*
12863e1c81a9SNicholas Bellinger 	 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
12873e1c81a9SNicholas Bellinger 	 */
12884b3766ecSBart Van Assche 	if (dump_payload) {
12894b3766ecSBart Van Assche 		u32 length = min(cmd->se_cmd.data_length - cmd->write_data_done,
12904b3766ecSBart Van Assche 				 cmd->first_burst_len);
12913e1c81a9SNicholas Bellinger 
12924b3766ecSBart Van Assche 		pr_debug("Dumping min(%d - %d, %d) = %d bytes of immediate data\n",
12934b3766ecSBart Van Assche 			 cmd->se_cmd.data_length, cmd->write_data_done,
12944b3766ecSBart Van Assche 			 cmd->first_burst_len, length);
12954b3766ecSBart Van Assche 		rc = iscsit_dump_data_payload(cmd->conn, length, 1);
12964b3766ecSBart Van Assche 		pr_debug("Finished dumping immediate data\n");
12974b3766ecSBart Van Assche 		if (rc < 0)
12984b3766ecSBart Van Assche 			immed_ret = IMMEDIATE_DATA_CANNOT_RECOVER;
12994b3766ecSBart Van Assche 	} else {
13003e1c81a9SNicholas Bellinger 		immed_ret = iscsit_handle_immediate_data(cmd, hdr,
13013e1c81a9SNicholas Bellinger 							 cmd->first_burst_len);
13024b3766ecSBart Van Assche 	}
13034b3766ecSBart Van Assche 
1304e48354ceSNicholas Bellinger 	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) {
1305e48354ceSNicholas Bellinger 		/*
1306e48354ceSNicholas Bellinger 		 * A PDU/CmdSN carrying Immediate Data passed
1307e48354ceSNicholas Bellinger 		 * DataCRC, check against ExpCmdSN/MaxCmdSN if
1308e48354ceSNicholas Bellinger 		 * Immediate Bit is not set.
1309e48354ceSNicholas Bellinger 		 */
1310561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd,
1311561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
13129d86a2beSNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1313561bf158SNicholas Bellinger 			return -1;
1314e48354ceSNicholas Bellinger 
13159d86a2beSNicholas Bellinger 		if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1316afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
13174b3766ecSBart Van Assche 
13184b3766ecSBart Van Assche 			return 0;
13193e1c81a9SNicholas Bellinger 		} else if (cmd->unsolicited_data)
13200300b114SBart Van Assche 			iscsit_set_unsolicited_dataout(cmd);
1321e48354ceSNicholas Bellinger 
1322e48354ceSNicholas Bellinger 	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
1323e48354ceSNicholas Bellinger 		/*
1324e48354ceSNicholas Bellinger 		 * Immediate Data failed DataCRC and ERL>=1,
1325e48354ceSNicholas Bellinger 		 * silently drop this PDU and let the initiator
1326e48354ceSNicholas Bellinger 		 * plug the CmdSN gap.
1327e48354ceSNicholas Bellinger 		 *
1328e48354ceSNicholas Bellinger 		 * FIXME: Send Unsolicited NOPIN with reserved
1329e48354ceSNicholas Bellinger 		 * TTT here to help the initiator figure out
1330e48354ceSNicholas Bellinger 		 * the missing CmdSN, although they should be
1331e48354ceSNicholas Bellinger 		 * intelligent enough to determine the missing
1332e48354ceSNicholas Bellinger 		 * CmdSN and issue a retry to plug the sequence.
1333e48354ceSNicholas Bellinger 		 */
1334e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_REMOVE;
13353e1c81a9SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, cmd->i_state);
1336e48354ceSNicholas Bellinger 	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */
1337e48354ceSNicholas Bellinger 		return -1;
1338e48354ceSNicholas Bellinger 
1339e48354ceSNicholas Bellinger 	return 0;
1340e48354ceSNicholas Bellinger }
1341e48354ceSNicholas Bellinger 
13423e1c81a9SNicholas Bellinger static int
13433e1c81a9SNicholas Bellinger iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
13443e1c81a9SNicholas Bellinger 			   unsigned char *buf)
13453e1c81a9SNicholas Bellinger {
13463e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
13473e1c81a9SNicholas Bellinger 	int rc, immed_data;
13483e1c81a9SNicholas Bellinger 	bool dump_payload = false;
13493e1c81a9SNicholas Bellinger 
13503e1c81a9SNicholas Bellinger 	rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
13513e1c81a9SNicholas Bellinger 	if (rc < 0)
1352561bf158SNicholas Bellinger 		return 0;
13533e1c81a9SNicholas Bellinger 	/*
13543e1c81a9SNicholas Bellinger 	 * Allocation iovecs needed for struct socket operations for
13553e1c81a9SNicholas Bellinger 	 * traditional iSCSI block I/O.
13563e1c81a9SNicholas Bellinger 	 */
13573e1c81a9SNicholas Bellinger 	if (iscsit_allocate_iovecs(cmd) < 0) {
1358b815fc12SMike Christie 		return iscsit_reject_cmd(cmd,
1359ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
13603e1c81a9SNicholas Bellinger 	}
13613e1c81a9SNicholas Bellinger 	immed_data = cmd->immediate_data;
13623e1c81a9SNicholas Bellinger 
13633e1c81a9SNicholas Bellinger 	rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
13643e1c81a9SNicholas Bellinger 	if (rc < 0)
13653e1c81a9SNicholas Bellinger 		return rc;
13663e1c81a9SNicholas Bellinger 	else if (rc > 0)
13673e1c81a9SNicholas Bellinger 		dump_payload = true;
13683e1c81a9SNicholas Bellinger 
13693e1c81a9SNicholas Bellinger 	if (!immed_data)
13703e1c81a9SNicholas Bellinger 		return 0;
13713e1c81a9SNicholas Bellinger 
13723e1c81a9SNicholas Bellinger 	return iscsit_get_immediate_data(cmd, hdr, dump_payload);
13733e1c81a9SNicholas Bellinger }
13743e1c81a9SNicholas Bellinger 
1375e48354ceSNicholas Bellinger static u32 iscsit_do_crypto_hash_sg(
137669110e3cSHerbert Xu 	struct ahash_request *hash,
1377e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
1378e48354ceSNicholas Bellinger 	u32 data_offset,
1379e48354ceSNicholas Bellinger 	u32 data_length,
1380e48354ceSNicholas Bellinger 	u32 padding,
1381e48354ceSNicholas Bellinger 	u8 *pad_bytes)
1382e48354ceSNicholas Bellinger {
1383e48354ceSNicholas Bellinger 	u32 data_crc;
1384e48354ceSNicholas Bellinger 	struct scatterlist *sg;
1385e48354ceSNicholas Bellinger 	unsigned int page_off;
1386e48354ceSNicholas Bellinger 
138769110e3cSHerbert Xu 	crypto_ahash_init(hash);
1388e48354ceSNicholas Bellinger 
1389e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
1390e48354ceSNicholas Bellinger 	page_off = cmd->first_data_sg_off;
1391e48354ceSNicholas Bellinger 
13925528d031SVarun Prakash 	if (data_length && page_off) {
13935528d031SVarun Prakash 		struct scatterlist first_sg;
13945528d031SVarun Prakash 		u32 len = min_t(u32, data_length, sg->length - page_off);
13955528d031SVarun Prakash 
13965528d031SVarun Prakash 		sg_init_table(&first_sg, 1);
13975528d031SVarun Prakash 		sg_set_page(&first_sg, sg_page(sg), len, sg->offset + page_off);
13985528d031SVarun Prakash 
13995528d031SVarun Prakash 		ahash_request_set_crypt(hash, &first_sg, NULL, len);
14005528d031SVarun Prakash 		crypto_ahash_update(hash);
14015528d031SVarun Prakash 
14025528d031SVarun Prakash 		data_length -= len;
14035528d031SVarun Prakash 		sg = sg_next(sg);
14045528d031SVarun Prakash 	}
14055528d031SVarun Prakash 
1406e48354ceSNicholas Bellinger 	while (data_length) {
14075528d031SVarun Prakash 		u32 cur_len = min_t(u32, data_length, sg->length);
1408e48354ceSNicholas Bellinger 
140969110e3cSHerbert Xu 		ahash_request_set_crypt(hash, sg, NULL, cur_len);
141069110e3cSHerbert Xu 		crypto_ahash_update(hash);
1411e48354ceSNicholas Bellinger 
1412e48354ceSNicholas Bellinger 		data_length -= cur_len;
1413aa75679cSAlexei Potashnik 		/* iscsit_map_iovec has already checked for invalid sg pointers */
1414aa75679cSAlexei Potashnik 		sg = sg_next(sg);
1415e48354ceSNicholas Bellinger 	}
1416e48354ceSNicholas Bellinger 
1417e48354ceSNicholas Bellinger 	if (padding) {
1418e48354ceSNicholas Bellinger 		struct scatterlist pad_sg;
1419e48354ceSNicholas Bellinger 
1420e48354ceSNicholas Bellinger 		sg_init_one(&pad_sg, pad_bytes, padding);
142169110e3cSHerbert Xu 		ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc,
142269110e3cSHerbert Xu 					padding);
142369110e3cSHerbert Xu 		crypto_ahash_finup(hash);
142469110e3cSHerbert Xu 	} else {
142569110e3cSHerbert Xu 		ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0);
142669110e3cSHerbert Xu 		crypto_ahash_final(hash);
1427e48354ceSNicholas Bellinger 	}
1428e48354ceSNicholas Bellinger 
1429e48354ceSNicholas Bellinger 	return data_crc;
1430e48354ceSNicholas Bellinger }
1431e48354ceSNicholas Bellinger 
1432e1dfb21fSBart Van Assche static void iscsit_do_crypto_hash_buf(struct ahash_request *hash,
1433e1dfb21fSBart Van Assche 	const void *buf, u32 payload_length, u32 padding,
1434e1dfb21fSBart Van Assche 	const void *pad_bytes, void *data_crc)
1435e48354ceSNicholas Bellinger {
143669110e3cSHerbert Xu 	struct scatterlist sg[2];
1437e48354ceSNicholas Bellinger 
143869110e3cSHerbert Xu 	sg_init_table(sg, ARRAY_SIZE(sg));
143969110e3cSHerbert Xu 	sg_set_buf(sg, buf, payload_length);
1440679fcae4SLaura Abbott 	if (padding)
144169110e3cSHerbert Xu 		sg_set_buf(sg + 1, pad_bytes, padding);
1442e48354ceSNicholas Bellinger 
144369110e3cSHerbert Xu 	ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding);
1444e48354ceSNicholas Bellinger 
144569110e3cSHerbert Xu 	crypto_ahash_digest(hash);
1446e48354ceSNicholas Bellinger }
1447e48354ceSNicholas Bellinger 
14483e1c81a9SNicholas Bellinger int
14499a584bf9SVarun Prakash __iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
14509a584bf9SVarun Prakash 			   struct iscsi_cmd *cmd, u32 payload_length,
14519a584bf9SVarun Prakash 			   bool *success)
1452e48354ceSNicholas Bellinger {
14539a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
1454e48354ceSNicholas Bellinger 	struct se_cmd *se_cmd;
14553e1c81a9SNicholas Bellinger 	int rc;
1456e48354ceSNicholas Bellinger 
1457e48354ceSNicholas Bellinger 	/* iSCSI write */
145804f3b31bSNicholas Bellinger 	atomic_long_add(payload_length, &conn->sess->rx_data_octets);
1459e48354ceSNicholas Bellinger 
1460e48354ceSNicholas Bellinger 	pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
1461e48354ceSNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
14623e1c81a9SNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
1463e48354ceSNicholas Bellinger 		payload_length, conn->cid);
1464e48354ceSNicholas Bellinger 
1465e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
1466e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT after"
1467e48354ceSNicholas Bellinger 			" last DataOUT received, dumping payload\n",
1468e48354ceSNicholas Bellinger 			cmd->init_task_tag);
1469e48354ceSNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1470e48354ceSNicholas Bellinger 	}
1471e48354ceSNicholas Bellinger 
1472e48354ceSNicholas Bellinger 	if (cmd->data_direction != DMA_TO_DEVICE) {
1473e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT for a"
1474e48354ceSNicholas Bellinger 			" NON-WRITE command.\n", cmd->init_task_tag);
147597c99b47SNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1476e48354ceSNicholas Bellinger 	}
1477e48354ceSNicholas Bellinger 	se_cmd = &cmd->se_cmd;
1478e48354ceSNicholas Bellinger 	iscsit_mod_dataout_timer(cmd);
1479e48354ceSNicholas Bellinger 
148050e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->offset) + payload_length) > cmd->se_cmd.data_length) {
1481de3493aeSBart Van Assche 		pr_err("DataOut Offset: %u, Length %u greater than iSCSI Command EDTL %u, protocol error.\n",
1482de3493aeSBart Van Assche 		       be32_to_cpu(hdr->offset), payload_length,
1483de3493aeSBart Van Assche 		       cmd->se_cmd.data_length);
1484ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf);
1485e48354ceSNicholas Bellinger 	}
1486e48354ceSNicholas Bellinger 
1487e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data) {
1488e48354ceSNicholas Bellinger 		int dump_unsolicited_data = 0;
1489e48354ceSNicholas Bellinger 
1490e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->InitialR2T) {
1491e48354ceSNicholas Bellinger 			pr_err("Received unexpected unsolicited data"
1492e48354ceSNicholas Bellinger 				" while InitialR2T=Yes, protocol error.\n");
1493e48354ceSNicholas Bellinger 			transport_send_check_condition_and_sense(&cmd->se_cmd,
1494e48354ceSNicholas Bellinger 					TCM_UNEXPECTED_UNSOLICITED_DATA, 0);
1495e48354ceSNicholas Bellinger 			return -1;
1496e48354ceSNicholas Bellinger 		}
1497e48354ceSNicholas Bellinger 		/*
1498e48354ceSNicholas Bellinger 		 * Special case for dealing with Unsolicited DataOUT
1499e48354ceSNicholas Bellinger 		 * and Unsupported SAM WRITE Opcodes and SE resource allocation
1500e48354ceSNicholas Bellinger 		 * failures;
1501e48354ceSNicholas Bellinger 		 */
1502e48354ceSNicholas Bellinger 
1503e48354ceSNicholas Bellinger 		/* Something's amiss if we're not in WRITE_PENDING state... */
1504e48354ceSNicholas Bellinger 		WARN_ON(se_cmd->t_state != TRANSPORT_WRITE_PENDING);
1505de103c93SChristoph Hellwig 		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE))
1506e48354ceSNicholas Bellinger 			dump_unsolicited_data = 1;
1507e48354ceSNicholas Bellinger 
1508e48354ceSNicholas Bellinger 		if (dump_unsolicited_data) {
1509e48354ceSNicholas Bellinger 			/*
1510e48354ceSNicholas Bellinger 			 * Check if a delayed TASK_ABORTED status needs to
1511e48354ceSNicholas Bellinger 			 * be sent now if the ISCSI_FLAG_CMD_FINAL has been
15125a342521SBart Van Assche 			 * received with the unsolicited data out.
1513e48354ceSNicholas Bellinger 			 */
1514e48354ceSNicholas Bellinger 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
1515e48354ceSNicholas Bellinger 				iscsit_stop_dataout_timer(cmd);
1516e48354ceSNicholas Bellinger 
1517e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1518e48354ceSNicholas Bellinger 		}
1519e48354ceSNicholas Bellinger 	} else {
1520e48354ceSNicholas Bellinger 		/*
1521e48354ceSNicholas Bellinger 		 * For the normal solicited data path:
1522e48354ceSNicholas Bellinger 		 *
1523e48354ceSNicholas Bellinger 		 * Check for a delayed TASK_ABORTED status and dump any
1524e48354ceSNicholas Bellinger 		 * incoming data out payload if one exists.  Also, when the
1525e48354ceSNicholas Bellinger 		 * ISCSI_FLAG_CMD_FINAL is set to denote the end of the current
1526e48354ceSNicholas Bellinger 		 * data out sequence, we decrement outstanding_r2ts.  Once
1527e48354ceSNicholas Bellinger 		 * outstanding_r2ts reaches zero, go ahead and send the delayed
1528e48354ceSNicholas Bellinger 		 * TASK_ABORTED status.
1529e48354ceSNicholas Bellinger 		 */
15307d680f3bSChristoph Hellwig 		if (se_cmd->transport_state & CMD_T_ABORTED) {
1531aaa00cc9SBart Van Assche 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL &&
1532aaa00cc9SBart Van Assche 			    --cmd->outstanding_r2ts < 1)
1533e48354ceSNicholas Bellinger 				iscsit_stop_dataout_timer(cmd);
1534e48354ceSNicholas Bellinger 
1535e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1536e48354ceSNicholas Bellinger 		}
1537e48354ceSNicholas Bellinger 	}
1538e48354ceSNicholas Bellinger 	/*
15390d5efb8aSBart Van Assche 	 * Perform DataSN, DataSequenceInOrder, DataPDUInOrder, and
1540e48354ceSNicholas Bellinger 	 * within-command recovery checks before receiving the payload.
1541e48354ceSNicholas Bellinger 	 */
15423e1c81a9SNicholas Bellinger 	rc = iscsit_check_pre_dataout(cmd, buf);
15433e1c81a9SNicholas Bellinger 	if (rc == DATAOUT_WITHIN_COMMAND_RECOVERY)
1544e48354ceSNicholas Bellinger 		return 0;
15453e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_CANNOT_RECOVER)
1546e48354ceSNicholas Bellinger 		return -1;
15479a584bf9SVarun Prakash 	*success = true;
15483e1c81a9SNicholas Bellinger 	return 0;
15493e1c81a9SNicholas Bellinger }
15509a584bf9SVarun Prakash EXPORT_SYMBOL(__iscsit_check_dataout_hdr);
15519a584bf9SVarun Prakash 
15529a584bf9SVarun Prakash int
15539a584bf9SVarun Prakash iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
15549a584bf9SVarun Prakash 			 struct iscsi_cmd **out_cmd)
15559a584bf9SVarun Prakash {
15569a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
15579a584bf9SVarun Prakash 	struct iscsi_cmd *cmd;
15589a584bf9SVarun Prakash 	u32 payload_length = ntoh24(hdr->dlength);
15599a584bf9SVarun Prakash 	int rc;
15609a584bf9SVarun Prakash 	bool success = false;
15619a584bf9SVarun Prakash 
15629a584bf9SVarun Prakash 	if (!payload_length) {
15639a584bf9SVarun Prakash 		pr_warn_ratelimited("DataOUT payload is ZERO, ignoring.\n");
15649a584bf9SVarun Prakash 		return 0;
15659a584bf9SVarun Prakash 	}
15669a584bf9SVarun Prakash 
15679a584bf9SVarun Prakash 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
15689a584bf9SVarun Prakash 		pr_err_ratelimited("DataSegmentLength: %u is greater than"
15699a584bf9SVarun Prakash 			" MaxXmitDataSegmentLength: %u\n", payload_length,
15709a584bf9SVarun Prakash 			conn->conn_ops->MaxXmitDataSegmentLength);
15719a584bf9SVarun Prakash 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf);
15729a584bf9SVarun Prakash 	}
15739a584bf9SVarun Prakash 
15749a584bf9SVarun Prakash 	cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, payload_length);
15759a584bf9SVarun Prakash 	if (!cmd)
15769a584bf9SVarun Prakash 		return 0;
15779a584bf9SVarun Prakash 
15789a584bf9SVarun Prakash 	rc = __iscsit_check_dataout_hdr(conn, buf, cmd, payload_length, &success);
15799a584bf9SVarun Prakash 
15809a584bf9SVarun Prakash 	if (success)
15819a584bf9SVarun Prakash 		*out_cmd = cmd;
15829a584bf9SVarun Prakash 
15839a584bf9SVarun Prakash 	return rc;
15849a584bf9SVarun Prakash }
15853e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_hdr);
15863e1c81a9SNicholas Bellinger 
15873e1c81a9SNicholas Bellinger static int
15883e1c81a9SNicholas Bellinger iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
15893e1c81a9SNicholas Bellinger 		   struct iscsi_data *hdr)
15903e1c81a9SNicholas Bellinger {
15913e1c81a9SNicholas Bellinger 	struct kvec *iov;
15923e1c81a9SNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0;
15930ca650c1SBart Van Assche 	u32 payload_length;
15943e1c81a9SNicholas Bellinger 	int iov_ret, data_crc_failed = 0;
15953e1c81a9SNicholas Bellinger 
15960ca650c1SBart Van Assche 	payload_length = min_t(u32, cmd->se_cmd.data_length,
15970ca650c1SBart Van Assche 			       ntoh24(hdr->dlength));
1598e48354ceSNicholas Bellinger 	rx_size += payload_length;
1599e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
1600e48354ceSNicholas Bellinger 
16012e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, iov, cmd->orig_iov_data_count - 2,
16022e39f1c9SBart Van Assche 				   be32_to_cpu(hdr->offset), payload_length);
1603e48354ceSNicholas Bellinger 	if (iov_ret < 0)
1604e48354ceSNicholas Bellinger 		return -1;
1605e48354ceSNicholas Bellinger 
1606e48354ceSNicholas Bellinger 	iov_count += iov_ret;
1607e48354ceSNicholas Bellinger 
1608e48354ceSNicholas Bellinger 	padding = ((-payload_length) & 3);
1609e48354ceSNicholas Bellinger 	if (padding != 0) {
1610e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
1611e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
1612e48354ceSNicholas Bellinger 		rx_size += padding;
1613e48354ceSNicholas Bellinger 		pr_debug("Receiving %u padding bytes.\n", padding);
1614e48354ceSNicholas Bellinger 	}
1615e48354ceSNicholas Bellinger 
1616e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1617e48354ceSNicholas Bellinger 		iov[iov_count].iov_base = &checksum;
1618e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
1619e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
1620e48354ceSNicholas Bellinger 	}
1621e48354ceSNicholas Bellinger 
16222e39f1c9SBart Van Assche 	WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count);
1623e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
1624e48354ceSNicholas Bellinger 
1625e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
1626e48354ceSNicholas Bellinger 
1627e48354ceSNicholas Bellinger 	if (rx_got != rx_size)
1628e48354ceSNicholas Bellinger 		return -1;
1629e48354ceSNicholas Bellinger 
1630e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1631e48354ceSNicholas Bellinger 		u32 data_crc;
1632e48354ceSNicholas Bellinger 
163369110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
163450e5c87dSChristoph Hellwig 						    be32_to_cpu(hdr->offset),
163550e5c87dSChristoph Hellwig 						    payload_length, padding,
1636e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
1637e48354ceSNicholas Bellinger 
1638e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
1639e48354ceSNicholas Bellinger 			pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
1640e48354ceSNicholas Bellinger 				" DataSN: 0x%08x, CRC32C DataDigest 0x%08x"
1641e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n",
1642e48354ceSNicholas Bellinger 				hdr->itt, hdr->offset, payload_length,
1643e48354ceSNicholas Bellinger 				hdr->datasn, checksum, data_crc);
1644e48354ceSNicholas Bellinger 			data_crc_failed = 1;
1645e48354ceSNicholas Bellinger 		} else {
1646e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
1647e48354ceSNicholas Bellinger 				" %u bytes of Data Out\n", checksum,
1648e48354ceSNicholas Bellinger 				payload_length);
1649e48354ceSNicholas Bellinger 		}
1650e48354ceSNicholas Bellinger 	}
16513e1c81a9SNicholas Bellinger 
16523e1c81a9SNicholas Bellinger 	return data_crc_failed;
16533e1c81a9SNicholas Bellinger }
16543e1c81a9SNicholas Bellinger 
16553e1c81a9SNicholas Bellinger int
16563e1c81a9SNicholas Bellinger iscsit_check_dataout_payload(struct iscsi_cmd *cmd, struct iscsi_data *hdr,
16573e1c81a9SNicholas Bellinger 			     bool data_crc_failed)
16583e1c81a9SNicholas Bellinger {
16593e1c81a9SNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
16603e1c81a9SNicholas Bellinger 	int rc, ooo_cmdsn;
1661e48354ceSNicholas Bellinger 	/*
1662e48354ceSNicholas Bellinger 	 * Increment post receive data and CRC values or perform
1663e48354ceSNicholas Bellinger 	 * within-command recovery.
1664e48354ceSNicholas Bellinger 	 */
16653e1c81a9SNicholas Bellinger 	rc = iscsit_check_post_dataout(cmd, (unsigned char *)hdr, data_crc_failed);
16663e1c81a9SNicholas Bellinger 	if ((rc == DATAOUT_NORMAL) || (rc == DATAOUT_WITHIN_COMMAND_RECOVERY))
1667e48354ceSNicholas Bellinger 		return 0;
16683e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_SEND_R2T) {
1669e48354ceSNicholas Bellinger 		iscsit_set_dataout_sequence_values(cmd);
16703e1c81a9SNicholas Bellinger 		conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
16713e1c81a9SNicholas Bellinger 	} else if (rc == DATAOUT_SEND_TO_TRANSPORT) {
1672e48354ceSNicholas Bellinger 		/*
1673e48354ceSNicholas Bellinger 		 * Handle extra special case for out of order
1674e48354ceSNicholas Bellinger 		 * Unsolicited Data Out.
1675e48354ceSNicholas Bellinger 		 */
1676e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
1677e48354ceSNicholas Bellinger 		ooo_cmdsn = (cmd->cmd_flags & ICF_OOO_CMDSN);
1678e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
1679e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
1680e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
1681e48354ceSNicholas Bellinger 
1682e48354ceSNicholas Bellinger 		iscsit_stop_dataout_timer(cmd);
168367441b68SChristoph Hellwig 		if (ooo_cmdsn)
168467441b68SChristoph Hellwig 			return 0;
168567441b68SChristoph Hellwig 		target_execute_cmd(&cmd->se_cmd);
168667441b68SChristoph Hellwig 		return 0;
1687e48354ceSNicholas Bellinger 	} else /* DATAOUT_CANNOT_RECOVER */
1688e48354ceSNicholas Bellinger 		return -1;
1689e48354ceSNicholas Bellinger 
1690e48354ceSNicholas Bellinger 	return 0;
1691e48354ceSNicholas Bellinger }
16923e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_payload);
1693e48354ceSNicholas Bellinger 
16943e1c81a9SNicholas Bellinger static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
16953e1c81a9SNicholas Bellinger {
1696dbcbc95cSNicholas Bellinger 	struct iscsi_cmd *cmd = NULL;
16973e1c81a9SNicholas Bellinger 	struct iscsi_data *hdr = (struct iscsi_data *)buf;
16983e1c81a9SNicholas Bellinger 	int rc;
16993e1c81a9SNicholas Bellinger 	bool data_crc_failed = false;
17003e1c81a9SNicholas Bellinger 
17013e1c81a9SNicholas Bellinger 	rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
17023e1c81a9SNicholas Bellinger 	if (rc < 0)
1703561bf158SNicholas Bellinger 		return 0;
17043e1c81a9SNicholas Bellinger 	else if (!cmd)
17053e1c81a9SNicholas Bellinger 		return 0;
17063e1c81a9SNicholas Bellinger 
17073e1c81a9SNicholas Bellinger 	rc = iscsit_get_dataout(conn, cmd, hdr);
17083e1c81a9SNicholas Bellinger 	if (rc < 0)
17093e1c81a9SNicholas Bellinger 		return rc;
17103e1c81a9SNicholas Bellinger 	else if (rc > 0)
17113e1c81a9SNicholas Bellinger 		data_crc_failed = true;
17123e1c81a9SNicholas Bellinger 
17133e1c81a9SNicholas Bellinger 	return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
17143e1c81a9SNicholas Bellinger }
17153e1c81a9SNicholas Bellinger 
1716778de368SNicholas Bellinger int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1717778de368SNicholas Bellinger 			 struct iscsi_nopout *hdr)
1718e48354ceSNicholas Bellinger {
1719778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1720e48354ceSNicholas Bellinger 
1721a3662605SArshad Hussain 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1722a3662605SArshad Hussain 		pr_err("NopOUT Flag's, Left Most Bit not set, protocol error.\n");
1723a3662605SArshad Hussain 		if (!cmd)
1724a3662605SArshad Hussain 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
1725a3662605SArshad Hussain 						 (unsigned char *)hdr);
1726a3662605SArshad Hussain 
1727a3662605SArshad Hussain 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1728a3662605SArshad Hussain 					 (unsigned char *)hdr);
1729a3662605SArshad Hussain 	}
1730a3662605SArshad Hussain 
173166c7db68SChristoph Hellwig 	if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1732e48354ceSNicholas Bellinger 		pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
1733e48354ceSNicholas Bellinger 			" not set, protocol error.\n");
173428aaa950SNicholas Bellinger 		if (!cmd)
173528aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
173628aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
173728aaa950SNicholas Bellinger 
1738ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1739ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1740e48354ceSNicholas Bellinger 	}
1741e48354ceSNicholas Bellinger 
174221f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1743e48354ceSNicholas Bellinger 		pr_err("NOPOUT Ping Data DataSegmentLength: %u is"
174421f5aa7eSNicholas Bellinger 			" greater than MaxXmitDataSegmentLength: %u, protocol"
1745e48354ceSNicholas Bellinger 			" error.\n", payload_length,
174621f5aa7eSNicholas Bellinger 			conn->conn_ops->MaxXmitDataSegmentLength);
174728aaa950SNicholas Bellinger 		if (!cmd)
174828aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
174928aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
175028aaa950SNicholas Bellinger 
1751ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1752ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1753e48354ceSNicholas Bellinger 	}
1754e48354ceSNicholas Bellinger 
17553e1c81a9SNicholas Bellinger 	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
1756e48354ceSNicholas Bellinger 		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
175766c7db68SChristoph Hellwig 		hdr->itt == RESERVED_ITT ? "Response" : "Request",
1758e48354ceSNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
1759e48354ceSNicholas Bellinger 		payload_length);
1760e48354ceSNicholas Bellinger 	/*
1761e48354ceSNicholas Bellinger 	 * This is not a response to a Unsolicited NopIN, which means
1762e48354ceSNicholas Bellinger 	 * it can either be a NOPOUT ping request (with a valid ITT),
1763e48354ceSNicholas Bellinger 	 * or a NOPOUT not requesting a NOPIN (with a reserved ITT).
1764e48354ceSNicholas Bellinger 	 * Either way, make sure we allocate an struct iscsi_cmd, as both
1765e48354ceSNicholas Bellinger 	 * can contain ping data.
1766e48354ceSNicholas Bellinger 	 */
176750e5c87dSChristoph Hellwig 	if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1768e48354ceSNicholas Bellinger 		cmd->iscsi_opcode	= ISCSI_OP_NOOP_OUT;
1769e48354ceSNicholas Bellinger 		cmd->i_state		= ISTATE_SEND_NOPIN;
1770e48354ceSNicholas Bellinger 		cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ?
1771e48354ceSNicholas Bellinger 						1 : 0);
1772e48354ceSNicholas Bellinger 		conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
1773e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag	= 0xFFFFFFFF;
177450e5c87dSChristoph Hellwig 		cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
177550e5c87dSChristoph Hellwig 		cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1776e48354ceSNicholas Bellinger 		cmd->data_direction	= DMA_NONE;
1777e48354ceSNicholas Bellinger 	}
1778e48354ceSNicholas Bellinger 
1779778de368SNicholas Bellinger 	return 0;
1780778de368SNicholas Bellinger }
1781778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_nop_out);
1782778de368SNicholas Bellinger 
1783778de368SNicholas Bellinger int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1784778de368SNicholas Bellinger 			   struct iscsi_nopout *hdr)
1785778de368SNicholas Bellinger {
1786778de368SNicholas Bellinger 	struct iscsi_cmd *cmd_p = NULL;
1787778de368SNicholas Bellinger 	int cmdsn_ret = 0;
1788778de368SNicholas Bellinger 	/*
1789778de368SNicholas Bellinger 	 * Initiator is expecting a NopIN ping reply..
1790778de368SNicholas Bellinger 	 */
1791778de368SNicholas Bellinger 	if (hdr->itt != RESERVED_ITT) {
17927cbfcc95SNicholas Bellinger 		if (!cmd)
17937cbfcc95SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
17947cbfcc95SNicholas Bellinger 						(unsigned char *)hdr);
1795778de368SNicholas Bellinger 
1796778de368SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
1797778de368SNicholas Bellinger 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1798778de368SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
1799778de368SNicholas Bellinger 
1800778de368SNicholas Bellinger 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1801778de368SNicholas Bellinger 
1802778de368SNicholas Bellinger 		if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1803778de368SNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
1804778de368SNicholas Bellinger 							 cmd->i_state);
1805778de368SNicholas Bellinger 			return 0;
1806778de368SNicholas Bellinger 		}
1807778de368SNicholas Bellinger 
1808561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1809561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
1810778de368SNicholas Bellinger                 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
1811778de368SNicholas Bellinger 			return 0;
1812778de368SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1813ba159914SNicholas Bellinger 			return -1;
1814778de368SNicholas Bellinger 
1815778de368SNicholas Bellinger 		return 0;
1816778de368SNicholas Bellinger 	}
1817778de368SNicholas Bellinger 	/*
1818778de368SNicholas Bellinger 	 * This was a response to a unsolicited NOPIN ping.
1819778de368SNicholas Bellinger 	 */
1820778de368SNicholas Bellinger 	if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
1821778de368SNicholas Bellinger 		cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
1822778de368SNicholas Bellinger 		if (!cmd_p)
1823778de368SNicholas Bellinger 			return -EINVAL;
1824778de368SNicholas Bellinger 
1825778de368SNicholas Bellinger 		iscsit_stop_nopin_response_timer(conn);
1826778de368SNicholas Bellinger 
1827778de368SNicholas Bellinger 		cmd_p->i_state = ISTATE_REMOVE;
1828778de368SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
1829778de368SNicholas Bellinger 
1830778de368SNicholas Bellinger 		iscsit_start_nopin_timer(conn);
1831778de368SNicholas Bellinger 		return 0;
1832778de368SNicholas Bellinger 	}
1833778de368SNicholas Bellinger 	/*
1834778de368SNicholas Bellinger 	 * Otherwise, initiator is not expecting a NOPIN is response.
1835778de368SNicholas Bellinger 	 * Just ignore for now.
1836778de368SNicholas Bellinger 	 */
18371a40f0a3SVarun Prakash 
18381a40f0a3SVarun Prakash 	if (cmd)
18391a40f0a3SVarun Prakash 		iscsit_free_cmd(cmd, false);
18401a40f0a3SVarun Prakash 
1841778de368SNicholas Bellinger         return 0;
1842778de368SNicholas Bellinger }
1843778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_nop_out);
1844778de368SNicholas Bellinger 
1845778de368SNicholas Bellinger static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1846778de368SNicholas Bellinger 				 unsigned char *buf)
1847778de368SNicholas Bellinger {
1848778de368SNicholas Bellinger 	unsigned char *ping_data = NULL;
1849778de368SNicholas Bellinger 	struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
1850778de368SNicholas Bellinger 	struct kvec *iov = NULL;
1851778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1852778de368SNicholas Bellinger 	int ret;
1853778de368SNicholas Bellinger 
1854778de368SNicholas Bellinger 	ret = iscsit_setup_nop_out(conn, cmd, hdr);
1855778de368SNicholas Bellinger 	if (ret < 0)
1856561bf158SNicholas Bellinger 		return 0;
1857778de368SNicholas Bellinger 	/*
1858778de368SNicholas Bellinger 	 * Handle NOP-OUT payload for traditional iSCSI sockets
1859778de368SNicholas Bellinger 	 */
186050e5c87dSChristoph Hellwig 	if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1861778de368SNicholas Bellinger 		u32 checksum, data_crc, padding = 0;
1862778de368SNicholas Bellinger 		int niov = 0, rx_got, rx_size = payload_length;
1863778de368SNicholas Bellinger 
1864e48354ceSNicholas Bellinger 		ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
1865e48354ceSNicholas Bellinger 		if (!ping_data) {
1866e48354ceSNicholas Bellinger 			ret = -1;
1867e48354ceSNicholas Bellinger 			goto out;
1868e48354ceSNicholas Bellinger 		}
1869e48354ceSNicholas Bellinger 
1870e48354ceSNicholas Bellinger 		iov = &cmd->iov_misc[0];
1871e48354ceSNicholas Bellinger 		iov[niov].iov_base	= ping_data;
1872e48354ceSNicholas Bellinger 		iov[niov++].iov_len	= payload_length;
1873e48354ceSNicholas Bellinger 
1874e48354ceSNicholas Bellinger 		padding = ((-payload_length) & 3);
1875e48354ceSNicholas Bellinger 		if (padding != 0) {
1876e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
1877e48354ceSNicholas Bellinger 				" for padding.\n", padding);
1878e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &cmd->pad_bytes;
1879e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= padding;
1880e48354ceSNicholas Bellinger 			rx_size += padding;
1881e48354ceSNicholas Bellinger 		}
1882e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1883e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
1884e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
1885e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
1886e48354ceSNicholas Bellinger 		}
1887e48354ceSNicholas Bellinger 
18882e39f1c9SBart Van Assche 		WARN_ON_ONCE(niov > ARRAY_SIZE(cmd->iov_misc));
1889e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &cmd->iov_misc[0], niov, rx_size);
1890e48354ceSNicholas Bellinger 		if (rx_got != rx_size) {
1891e48354ceSNicholas Bellinger 			ret = -1;
1892e48354ceSNicholas Bellinger 			goto out;
1893e48354ceSNicholas Bellinger 		}
1894e48354ceSNicholas Bellinger 
1895e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1896e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data,
1897e1dfb21fSBart Van Assche 						  payload_length, padding,
1898e1dfb21fSBart Van Assche 						  cmd->pad_bytes, &data_crc);
1899e48354ceSNicholas Bellinger 
1900e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
1901e48354ceSNicholas Bellinger 				pr_err("Ping data CRC32C DataDigest"
1902e48354ceSNicholas Bellinger 				" 0x%08x does not match computed 0x%08x\n",
1903e48354ceSNicholas Bellinger 					checksum, data_crc);
1904e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
1905e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
1906e48354ceSNicholas Bellinger 					" NOPOUT Ping DataCRC failure while in"
1907e48354ceSNicholas Bellinger 						" ERL=0.\n");
1908e48354ceSNicholas Bellinger 					ret = -1;
1909e48354ceSNicholas Bellinger 					goto out;
1910e48354ceSNicholas Bellinger 				} else {
1911e48354ceSNicholas Bellinger 					/*
1912e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
1913e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
1914e48354ceSNicholas Bellinger 					 */
1915e48354ceSNicholas Bellinger 					pr_debug("Dropping NOPOUT"
1916e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
1917e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
1918e48354ceSNicholas Bellinger 					ret = 0;
1919e48354ceSNicholas Bellinger 					goto out;
1920e48354ceSNicholas Bellinger 				}
1921e48354ceSNicholas Bellinger 			} else {
1922e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
1923e48354ceSNicholas Bellinger 				" 0x%08x for %u bytes of ping data.\n",
1924e48354ceSNicholas Bellinger 					checksum, payload_length);
1925e48354ceSNicholas Bellinger 			}
1926e48354ceSNicholas Bellinger 		}
1927e48354ceSNicholas Bellinger 
1928e48354ceSNicholas Bellinger 		ping_data[payload_length] = '\0';
1929e48354ceSNicholas Bellinger 		/*
1930e48354ceSNicholas Bellinger 		 * Attach ping data to struct iscsi_cmd->buf_ptr.
1931e48354ceSNicholas Bellinger 		 */
19328359cf43SJörn Engel 		cmd->buf_ptr = ping_data;
1933e48354ceSNicholas Bellinger 		cmd->buf_ptr_size = payload_length;
1934e48354ceSNicholas Bellinger 
1935e48354ceSNicholas Bellinger 		pr_debug("Got %u bytes of NOPOUT ping"
1936e48354ceSNicholas Bellinger 			" data.\n", payload_length);
1937e48354ceSNicholas Bellinger 		pr_debug("Ping Data: \"%s\"\n", ping_data);
1938e48354ceSNicholas Bellinger 	}
1939e48354ceSNicholas Bellinger 
1940778de368SNicholas Bellinger 	return iscsit_process_nop_out(conn, cmd, hdr);
1941e48354ceSNicholas Bellinger out:
1942e48354ceSNicholas Bellinger 	if (cmd)
1943aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
1944778de368SNicholas Bellinger 
1945e48354ceSNicholas Bellinger 	kfree(ping_data);
1946e48354ceSNicholas Bellinger 	return ret;
1947e48354ceSNicholas Bellinger }
1948e48354ceSNicholas Bellinger 
1949e381fe9eSBart Van Assche static enum tcm_tmreq_table iscsit_convert_tmf(u8 iscsi_tmf)
1950e381fe9eSBart Van Assche {
1951e381fe9eSBart Van Assche 	switch (iscsi_tmf) {
1952e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK:
1953e381fe9eSBart Van Assche 		return TMR_ABORT_TASK;
1954e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
1955e381fe9eSBart Van Assche 		return TMR_ABORT_TASK_SET;
1956e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_ACA:
1957e381fe9eSBart Van Assche 		return TMR_CLEAR_ACA;
1958e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
1959e381fe9eSBart Van Assche 		return TMR_CLEAR_TASK_SET;
1960e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
1961e381fe9eSBart Van Assche 		return TMR_LUN_RESET;
1962e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
1963e381fe9eSBart Van Assche 		return TMR_TARGET_WARM_RESET;
1964e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
1965e381fe9eSBart Van Assche 		return TMR_TARGET_COLD_RESET;
1966e381fe9eSBart Van Assche 	default:
1967e381fe9eSBart Van Assche 		return TMR_UNKNOWN;
1968e381fe9eSBart Van Assche 	}
1969e381fe9eSBart Van Assche }
1970e381fe9eSBart Van Assche 
19713e1c81a9SNicholas Bellinger int
19723e1c81a9SNicholas Bellinger iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1973e48354ceSNicholas Bellinger 			   unsigned char *buf)
1974e48354ceSNicholas Bellinger {
1975e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr;
1976e48354ceSNicholas Bellinger 	struct iscsi_tmr_req *tmr_req;
1977e48354ceSNicholas Bellinger 	struct iscsi_tm *hdr;
1978186a9647SNicholas Bellinger 	int out_of_order_cmdsn = 0, ret;
197959b6986dSBart Van Assche 	u8 function, tcm_function = TMR_UNKNOWN;
1980e48354ceSNicholas Bellinger 
1981e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_tm *) buf;
1982e48354ceSNicholas Bellinger 	hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
1983e48354ceSNicholas Bellinger 	function = hdr->flags;
1984e48354ceSNicholas Bellinger 
1985e48354ceSNicholas Bellinger 	pr_debug("Got Task Management Request ITT: 0x%08x, CmdSN:"
1986e48354ceSNicholas Bellinger 		" 0x%08x, Function: 0x%02x, RefTaskTag: 0x%08x, RefCmdSN:"
1987e48354ceSNicholas Bellinger 		" 0x%08x, CID: %hu\n", hdr->itt, hdr->cmdsn, function,
1988e48354ceSNicholas Bellinger 		hdr->rtt, hdr->refcmdsn, conn->cid);
1989e48354ceSNicholas Bellinger 
1990e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
1991e48354ceSNicholas Bellinger 	    ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
199266c7db68SChristoph Hellwig 	     hdr->rtt != RESERVED_ITT)) {
1993e48354ceSNicholas Bellinger 		pr_err("RefTaskTag should be set to 0xFFFFFFFF.\n");
199466c7db68SChristoph Hellwig 		hdr->rtt = RESERVED_ITT;
1995e48354ceSNicholas Bellinger 	}
1996e48354ceSNicholas Bellinger 
1997e48354ceSNicholas Bellinger 	if ((function == ISCSI_TM_FUNC_TASK_REASSIGN) &&
1998e48354ceSNicholas Bellinger 			!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1999e48354ceSNicholas Bellinger 		pr_err("Task Management Request TASK_REASSIGN not"
2000e48354ceSNicholas Bellinger 			" issued as immediate command, bad iSCSI Initiator"
2001e48354ceSNicholas Bellinger 				"implementation\n");
2002ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2003ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
2004e48354ceSNicholas Bellinger 	}
2005e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
200650e5c87dSChristoph Hellwig 	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
200750e5c87dSChristoph Hellwig 		hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
2008e48354ceSNicholas Bellinger 
2009d28b1169SAndy Grover 	cmd->data_direction = DMA_NONE;
20103829f381SMarkus Elfring 	cmd->tmr_req = kzalloc(sizeof(*cmd->tmr_req), GFP_KERNEL);
2011ae072726SNicholas Bellinger 	if (!cmd->tmr_req) {
2012ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2013d28b1169SAndy Grover 					     ISCSI_REASON_BOOKMARK_NO_RESOURCES,
2014ba159914SNicholas Bellinger 					     buf);
2015ae072726SNicholas Bellinger 	}
2016ae072726SNicholas Bellinger 
2017ae072726SNicholas Bellinger 	transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
2018ae072726SNicholas Bellinger 			      conn->sess->se_sess, 0, DMA_NONE,
2019a36840d8SSudhakar Panneerselvam 			      TCM_SIMPLE_TAG, cmd->sense_buffer + 2,
2020a36840d8SSudhakar Panneerselvam 			      scsilun_to_int(&hdr->lun));
2021ae072726SNicholas Bellinger 
2022807b9515SBart Van Assche 	target_get_sess_cmd(&cmd->se_cmd, true);
2023d28b1169SAndy Grover 
2024d28b1169SAndy Grover 	/*
2025d28b1169SAndy Grover 	 * TASK_REASSIGN for ERL=2 / connection stays inside of
2026d28b1169SAndy Grover 	 * LIO-Target $FABRIC_MOD
2027d28b1169SAndy Grover 	 */
2028d28b1169SAndy Grover 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
2029e381fe9eSBart Van Assche 		tcm_function = iscsit_convert_tmf(function);
2030e381fe9eSBart Van Assche 		if (tcm_function == TMR_UNKNOWN) {
2031d28b1169SAndy Grover 			pr_err("Unknown iSCSI TMR Function:"
2032d28b1169SAndy Grover 			       " 0x%02x\n", function);
2033ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2034ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2035d28b1169SAndy Grover 		}
203659b6986dSBart Van Assche 	}
203759b6986dSBart Van Assche 	ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function,
203859b6986dSBart Van Assche 				 GFP_KERNEL);
2039d28b1169SAndy Grover 	if (ret < 0)
2040ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2041ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2042d28b1169SAndy Grover 
2043d28b1169SAndy Grover 	cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
2044d28b1169SAndy Grover 
2045e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_TMFUNC;
2046e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TASKMGTRSP;
2047e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2048e48354ceSNicholas Bellinger 	cmd->init_task_tag	= hdr->itt;
2049e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
205050e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
205150e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
2052e48354ceSNicholas Bellinger 	se_tmr			= cmd->se_cmd.se_tmr_req;
2053e48354ceSNicholas Bellinger 	tmr_req			= cmd->tmr_req;
2054e48354ceSNicholas Bellinger 	/*
2055e48354ceSNicholas Bellinger 	 * Locate the struct se_lun for all TMRs not related to ERL=2 TASK_REASSIGN
2056e48354ceSNicholas Bellinger 	 */
2057e48354ceSNicholas Bellinger 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
2058a36840d8SSudhakar Panneerselvam 		ret = transport_lookup_tmr_lun(&cmd->se_cmd);
2059e48354ceSNicholas Bellinger 		if (ret < 0) {
2060e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_NO_LUN;
2061e48354ceSNicholas Bellinger 			goto attach;
2062e48354ceSNicholas Bellinger 		}
2063e48354ceSNicholas Bellinger 	}
2064e48354ceSNicholas Bellinger 
2065e48354ceSNicholas Bellinger 	switch (function) {
2066e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK:
2067e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_abort_task(cmd, buf);
2068de103c93SChristoph Hellwig 		if (se_tmr->response)
2069e48354ceSNicholas Bellinger 			goto attach;
2070e48354ceSNicholas Bellinger 		break;
2071e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
2072e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_ACA:
2073e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
2074e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
2075e48354ceSNicholas Bellinger 		break;
2076e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
2077e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) {
2078e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2079e48354ceSNicholas Bellinger 			goto attach;
2080e48354ceSNicholas Bellinger 		}
2081e48354ceSNicholas Bellinger 		break;
2082e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
2083e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) {
2084e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2085e48354ceSNicholas Bellinger 			goto attach;
2086e48354ceSNicholas Bellinger 		}
2087e48354ceSNicholas Bellinger 		break;
2088e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TASK_REASSIGN:
2089e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_task_reassign(cmd, buf);
2090e48354ceSNicholas Bellinger 		/*
2091e48354ceSNicholas Bellinger 		 * Perform sanity checks on the ExpDataSN only if the
2092e48354ceSNicholas Bellinger 		 * TASK_REASSIGN was successful.
2093e48354ceSNicholas Bellinger 		 */
2094de103c93SChristoph Hellwig 		if (se_tmr->response)
2095e48354ceSNicholas Bellinger 			break;
2096e48354ceSNicholas Bellinger 
2097e48354ceSNicholas Bellinger 		if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
2098ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2099ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_INVALID, buf);
2100e48354ceSNicholas Bellinger 		break;
2101e48354ceSNicholas Bellinger 	default:
2102e48354ceSNicholas Bellinger 		pr_err("Unknown TMR function: 0x%02x, protocol"
2103e48354ceSNicholas Bellinger 			" error.\n", function);
2104e48354ceSNicholas Bellinger 		se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED;
2105e48354ceSNicholas Bellinger 		goto attach;
2106e48354ceSNicholas Bellinger 	}
2107e48354ceSNicholas Bellinger 
2108e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
2109e48354ceSNicholas Bellinger 	    (se_tmr->response == ISCSI_TMF_RSP_COMPLETE))
2110e48354ceSNicholas Bellinger 		se_tmr->call_transport = 1;
2111e48354ceSNicholas Bellinger attach:
2112e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
21132fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2114e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2115e48354ceSNicholas Bellinger 
2116e48354ceSNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2117561bf158SNicholas Bellinger 		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
21183fc9fb13SNicholas Bellinger 		if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) {
2119e48354ceSNicholas Bellinger 			out_of_order_cmdsn = 1;
21203fc9fb13SNicholas Bellinger 		} else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
21213fc9fb13SNicholas Bellinger 			target_put_sess_cmd(&cmd->se_cmd);
2122e48354ceSNicholas Bellinger 			return 0;
21233fc9fb13SNicholas Bellinger 		} else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
2124ba159914SNicholas Bellinger 			return -1;
2125e48354ceSNicholas Bellinger 		}
21263fc9fb13SNicholas Bellinger 	}
212750e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2128e48354ceSNicholas Bellinger 
21295a4c8666SNicholas Bellinger 	if (out_of_order_cmdsn || !(hdr->opcode & ISCSI_OP_IMMEDIATE))
2130e48354ceSNicholas Bellinger 		return 0;
2131e48354ceSNicholas Bellinger 	/*
2132e48354ceSNicholas Bellinger 	 * Found the referenced task, send to transport for processing.
2133e48354ceSNicholas Bellinger 	 */
2134e48354ceSNicholas Bellinger 	if (se_tmr->call_transport)
2135e48354ceSNicholas Bellinger 		return transport_generic_handle_tmr(&cmd->se_cmd);
2136e48354ceSNicholas Bellinger 
2137e48354ceSNicholas Bellinger 	/*
2138e48354ceSNicholas Bellinger 	 * Could not find the referenced LUN, task, or Task Management
2139e48354ceSNicholas Bellinger 	 * command not authorized or supported.  Change state and
2140e48354ceSNicholas Bellinger 	 * let the tx_thread send the response.
2141e48354ceSNicholas Bellinger 	 *
2142e48354ceSNicholas Bellinger 	 * For connection recovery, this is also the default action for
2143e48354ceSNicholas Bellinger 	 * TMR TASK_REASSIGN.
2144e48354ceSNicholas Bellinger 	 */
2145e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2146ae072726SNicholas Bellinger 	target_put_sess_cmd(&cmd->se_cmd);
2147e48354ceSNicholas Bellinger 	return 0;
2148e48354ceSNicholas Bellinger }
21493e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd);
2150e48354ceSNicholas Bellinger 
2151e48354ceSNicholas Bellinger /* #warning FIXME: Support Text Command parameters besides SendTargets */
215264534aa7SNicholas Bellinger int
215364534aa7SNicholas Bellinger iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
215464534aa7SNicholas Bellinger 		      struct iscsi_text *hdr)
2155e48354ceSNicholas Bellinger {
215664534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
2157e48354ceSNicholas Bellinger 
215821f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
2159e48354ceSNicholas Bellinger 		pr_err("Unable to accept text parameter length: %u"
216021f5aa7eSNicholas Bellinger 			"greater than MaxXmitDataSegmentLength %u.\n",
216121f5aa7eSNicholas Bellinger 		       payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
2162ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2163ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
2164e48354ceSNicholas Bellinger 	}
2165e48354ceSNicholas Bellinger 
2166122f8afcSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL) ||
2167122f8afcSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_TEXT_CONTINUE)) {
2168122f8afcSNicholas Bellinger 		pr_err("Multi sequence text commands currently not supported\n");
2169122f8afcSNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_CMD_NOT_SUPPORTED,
2170122f8afcSNicholas Bellinger 					(unsigned char *)hdr);
2171122f8afcSNicholas Bellinger 	}
2172122f8afcSNicholas Bellinger 
2173e48354ceSNicholas Bellinger 	pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
2174e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
2175e48354ceSNicholas Bellinger 		hdr->exp_statsn, payload_length);
2176e48354ceSNicholas Bellinger 
217764534aa7SNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_TEXT;
217864534aa7SNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TEXTRSP;
217964534aa7SNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
218064534aa7SNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
218164534aa7SNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
218264534aa7SNicholas Bellinger 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
218364534aa7SNicholas Bellinger 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
218464534aa7SNicholas Bellinger 	cmd->data_direction	= DMA_NONE;
2185ea8dc5b4SVarun Prakash 	kfree(cmd->text_in_ptr);
2186e4f4e801SSagi Grimberg 	cmd->text_in_ptr	= NULL;
218764534aa7SNicholas Bellinger 
218864534aa7SNicholas Bellinger 	return 0;
218964534aa7SNicholas Bellinger }
219064534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_text_cmd);
219164534aa7SNicholas Bellinger 
219264534aa7SNicholas Bellinger int
219364534aa7SNicholas Bellinger iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
219464534aa7SNicholas Bellinger 			struct iscsi_text *hdr)
219564534aa7SNicholas Bellinger {
21969864ca9dSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr;
219764534aa7SNicholas Bellinger 	int cmdsn_ret;
219864534aa7SNicholas Bellinger 
21999864ca9dSNicholas Bellinger 	if (!text_in) {
2200e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
2201e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
22029864ca9dSNicholas Bellinger 			pr_err("Unable to locate text_in buffer for sendtargets"
22039864ca9dSNicholas Bellinger 			       " discovery\n");
22049864ca9dSNicholas Bellinger 			goto reject;
22059864ca9dSNicholas Bellinger 		}
2206e4f4e801SSagi Grimberg 		goto empty_sendtargets;
2207e4f4e801SSagi Grimberg 	}
220895f8f6a9SDavid Disseldorp 	if (strncmp("SendTargets=", text_in, 12) != 0) {
22099864ca9dSNicholas Bellinger 		pr_err("Received Text Data that is not"
22109864ca9dSNicholas Bellinger 			" SendTargets, cannot continue.\n");
22119864ca9dSNicholas Bellinger 		goto reject;
22129864ca9dSNicholas Bellinger 	}
221395f8f6a9SDavid Disseldorp 	/* '=' confirmed in strncmp */
22149864ca9dSNicholas Bellinger 	text_ptr = strchr(text_in, '=');
221595f8f6a9SDavid Disseldorp 	BUG_ON(!text_ptr);
221695f8f6a9SDavid Disseldorp 	if (!strncmp("=All", text_ptr, 5)) {
22178060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_ALL;
22186665889cSNicholas Bellinger 	} else if (!strncmp("=iqn.", text_ptr, 5) ||
22196665889cSNicholas Bellinger 		   !strncmp("=eui.", text_ptr, 5)) {
22208060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_SINGLE;
22219864ca9dSNicholas Bellinger 	} else {
222295f8f6a9SDavid Disseldorp 		pr_err("Unable to locate valid SendTargets%s value\n",
222395f8f6a9SDavid Disseldorp 		       text_ptr);
22249864ca9dSNicholas Bellinger 		goto reject;
22259864ca9dSNicholas Bellinger 	}
22269864ca9dSNicholas Bellinger 
222764534aa7SNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
222864534aa7SNicholas Bellinger 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
222964534aa7SNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
223064534aa7SNicholas Bellinger 
2231e4f4e801SSagi Grimberg empty_sendtargets:
223264534aa7SNicholas Bellinger 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
223364534aa7SNicholas Bellinger 
223464534aa7SNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2235561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
2236561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
223764534aa7SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2238ba159914SNicholas Bellinger 			return -1;
2239ba159914SNicholas Bellinger 
224064534aa7SNicholas Bellinger 		return 0;
224164534aa7SNicholas Bellinger 	}
224264534aa7SNicholas Bellinger 
224364534aa7SNicholas Bellinger 	return iscsit_execute_cmd(cmd, 0);
22449864ca9dSNicholas Bellinger 
22459864ca9dSNicholas Bellinger reject:
2246ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2247ba159914SNicholas Bellinger 				 (unsigned char *)hdr);
224864534aa7SNicholas Bellinger }
224964534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_text_cmd);
225064534aa7SNicholas Bellinger 
225164534aa7SNicholas Bellinger static int
225264534aa7SNicholas Bellinger iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
225364534aa7SNicholas Bellinger 		       unsigned char *buf)
225464534aa7SNicholas Bellinger {
225564534aa7SNicholas Bellinger 	struct iscsi_text *hdr = (struct iscsi_text *)buf;
225664534aa7SNicholas Bellinger 	char *text_in = NULL;
225764534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
225864534aa7SNicholas Bellinger 	int rx_size, rc;
225964534aa7SNicholas Bellinger 
226064534aa7SNicholas Bellinger 	rc = iscsit_setup_text_cmd(conn, cmd, hdr);
226164534aa7SNicholas Bellinger 	if (rc < 0)
2262561bf158SNicholas Bellinger 		return 0;
226364534aa7SNicholas Bellinger 
226464534aa7SNicholas Bellinger 	rx_size = payload_length;
226564534aa7SNicholas Bellinger 	if (payload_length) {
226664534aa7SNicholas Bellinger 		u32 checksum = 0, data_crc = 0;
226747eefdedSBart Van Assche 		u32 padding = 0;
226864534aa7SNicholas Bellinger 		int niov = 0, rx_got;
226947eefdedSBart Van Assche 		struct kvec iov[2];
227064534aa7SNicholas Bellinger 
227147eefdedSBart Van Assche 		rx_size = ALIGN(payload_length, 4);
227247eefdedSBart Van Assche 		text_in = kzalloc(rx_size, GFP_KERNEL);
2273c46e22f1SMarkus Elfring 		if (!text_in)
227464534aa7SNicholas Bellinger 			goto reject;
2275c46e22f1SMarkus Elfring 
22769864ca9dSNicholas Bellinger 		cmd->text_in_ptr = text_in;
2277e48354ceSNicholas Bellinger 
227847eefdedSBart Van Assche 		memset(iov, 0, sizeof(iov));
2279e48354ceSNicholas Bellinger 		iov[niov].iov_base	= text_in;
228047eefdedSBart Van Assche 		iov[niov++].iov_len	= rx_size;
2281e48354ceSNicholas Bellinger 
228247eefdedSBart Van Assche 		padding = rx_size - payload_length;
228347eefdedSBart Van Assche 		if (padding)
2284e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
2285e48354ceSNicholas Bellinger 					" for padding.\n", padding);
2286e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
2287e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
2288e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
2289e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
2290e48354ceSNicholas Bellinger 		}
2291e48354ceSNicholas Bellinger 
22922e39f1c9SBart Van Assche 		WARN_ON_ONCE(niov > ARRAY_SIZE(iov));
2293e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &iov[0], niov, rx_size);
229464534aa7SNicholas Bellinger 		if (rx_got != rx_size)
229564534aa7SNicholas Bellinger 			goto reject;
2296e48354ceSNicholas Bellinger 
2297e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
229847eefdedSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash,
229947eefdedSBart Van Assche 						  text_in, rx_size, 0, NULL,
230047eefdedSBart Van Assche 						  &data_crc);
2301e48354ceSNicholas Bellinger 
2302e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
2303e48354ceSNicholas Bellinger 				pr_err("Text data CRC32C DataDigest"
2304e48354ceSNicholas Bellinger 					" 0x%08x does not match computed"
2305e48354ceSNicholas Bellinger 					" 0x%08x\n", checksum, data_crc);
2306e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2307e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
2308e48354ceSNicholas Bellinger 					" Text Data digest failure while in"
2309e48354ceSNicholas Bellinger 						" ERL=0.\n");
231064534aa7SNicholas Bellinger 					goto reject;
2311e48354ceSNicholas Bellinger 				} else {
2312e48354ceSNicholas Bellinger 					/*
2313e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
2314e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
2315e48354ceSNicholas Bellinger 					 */
2316e48354ceSNicholas Bellinger 					pr_debug("Dropping Text"
2317e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
2318e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
2319e48354ceSNicholas Bellinger 					kfree(text_in);
2320e48354ceSNicholas Bellinger 					return 0;
2321e48354ceSNicholas Bellinger 				}
2322e48354ceSNicholas Bellinger 			} else {
2323e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
2324e48354ceSNicholas Bellinger 					" 0x%08x for %u bytes of text data.\n",
232564534aa7SNicholas Bellinger 						checksum, payload_length);
2326e48354ceSNicholas Bellinger 			}
2327e48354ceSNicholas Bellinger 		}
232864534aa7SNicholas Bellinger 		text_in[payload_length - 1] = '\0';
2329e48354ceSNicholas Bellinger 		pr_debug("Successfully read %d bytes of text"
233064534aa7SNicholas Bellinger 				" data.\n", payload_length);
2331e48354ceSNicholas Bellinger 	}
2332e48354ceSNicholas Bellinger 
233364534aa7SNicholas Bellinger 	return iscsit_process_text_cmd(conn, cmd, hdr);
2334e48354ceSNicholas Bellinger 
233564534aa7SNicholas Bellinger reject:
23369864ca9dSNicholas Bellinger 	kfree(cmd->text_in_ptr);
23379864ca9dSNicholas Bellinger 	cmd->text_in_ptr = NULL;
2338ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
2339e48354ceSNicholas Bellinger }
2340e48354ceSNicholas Bellinger 
2341e48354ceSNicholas Bellinger int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2342e48354ceSNicholas Bellinger {
2343e48354ceSNicholas Bellinger 	struct iscsi_conn *conn_p;
2344e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2345e48354ceSNicholas Bellinger 
2346e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSESESSION on CID: %hu"
2347e48354ceSNicholas Bellinger 		" for SID: %u.\n", conn->cid, conn->sess->sid);
2348e48354ceSNicholas Bellinger 
2349e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
2350e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 1);
2351e48354ceSNicholas Bellinger 	conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2352e48354ceSNicholas Bellinger 
2353e48354ceSNicholas Bellinger 	iscsit_inc_conn_usage_count(conn);
2354e48354ceSNicholas Bellinger 	iscsit_inc_session_usage_count(sess);
2355e48354ceSNicholas Bellinger 
2356e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
2357e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &sess->sess_conn_list, conn_list) {
2358e48354ceSNicholas Bellinger 		if (conn_p->conn_state != TARG_CONN_STATE_LOGGED_IN)
2359e48354ceSNicholas Bellinger 			continue;
2360e48354ceSNicholas Bellinger 
2361e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2362e48354ceSNicholas Bellinger 		conn_p->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2363e48354ceSNicholas Bellinger 	}
2364e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
2365e48354ceSNicholas Bellinger 
2366e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2367e48354ceSNicholas Bellinger 
2368e48354ceSNicholas Bellinger 	return 0;
2369e48354ceSNicholas Bellinger }
2370e48354ceSNicholas Bellinger 
2371e48354ceSNicholas Bellinger int iscsit_logout_closeconnection(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2372e48354ceSNicholas Bellinger {
2373e48354ceSNicholas Bellinger 	struct iscsi_conn *l_conn;
2374e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2375e48354ceSNicholas Bellinger 
2376e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSECONNECTION for CID:"
2377e48354ceSNicholas Bellinger 		" %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2378e48354ceSNicholas Bellinger 
2379e48354ceSNicholas Bellinger 	/*
2380e48354ceSNicholas Bellinger 	 * A Logout Request with a CLOSECONNECTION reason code for a CID
2381e48354ceSNicholas Bellinger 	 * can arrive on a connection with a differing CID.
2382e48354ceSNicholas Bellinger 	 */
2383e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2384e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
2385e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2386e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2387e48354ceSNicholas Bellinger 
2388e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 1);
2389e48354ceSNicholas Bellinger 		conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_CONNECTION;
2390e48354ceSNicholas Bellinger 		iscsit_inc_conn_usage_count(conn);
2391e48354ceSNicholas Bellinger 
2392e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
2393e48354ceSNicholas Bellinger 	} else {
2394e48354ceSNicholas Bellinger 		/*
2395e48354ceSNicholas Bellinger 		 * Handle all different cid CLOSECONNECTION requests in
2396e48354ceSNicholas Bellinger 		 * iscsit_logout_post_handler_diffcid() as to give enough
2397e48354ceSNicholas Bellinger 		 * time for any non immediate command's CmdSN to be
2398e48354ceSNicholas Bellinger 		 * acknowledged on the connection in question.
2399e48354ceSNicholas Bellinger 		 *
2400e48354ceSNicholas Bellinger 		 * Here we simply make sure the CID is still around.
2401e48354ceSNicholas Bellinger 		 */
2402e48354ceSNicholas Bellinger 		l_conn = iscsit_get_conn_from_cid(sess,
2403e48354ceSNicholas Bellinger 				cmd->logout_cid);
2404e48354ceSNicholas Bellinger 		if (!l_conn) {
2405e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2406e48354ceSNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
2407e48354ceSNicholas Bellinger 					cmd->i_state);
2408e48354ceSNicholas Bellinger 			return 0;
2409e48354ceSNicholas Bellinger 		}
2410e48354ceSNicholas Bellinger 
2411e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(l_conn);
2412e48354ceSNicholas Bellinger 	}
2413e48354ceSNicholas Bellinger 
2414e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2415e48354ceSNicholas Bellinger 
2416e48354ceSNicholas Bellinger 	return 0;
2417e48354ceSNicholas Bellinger }
2418e48354ceSNicholas Bellinger 
2419e48354ceSNicholas Bellinger int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2420e48354ceSNicholas Bellinger {
2421e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2422e48354ceSNicholas Bellinger 
2423e48354ceSNicholas Bellinger 	pr_debug("Received explicit REMOVECONNFORRECOVERY logout for"
2424e48354ceSNicholas Bellinger 		" CID: %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2425e48354ceSNicholas Bellinger 
2426e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel != 2) {
2427e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2428e48354ceSNicholas Bellinger 			" while ERL!=2.\n");
2429e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED;
2430e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2431e48354ceSNicholas Bellinger 		return 0;
2432e48354ceSNicholas Bellinger 	}
2433e48354ceSNicholas Bellinger 
2434e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2435e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2436e48354ceSNicholas Bellinger 			" with CID: %hu on CID: %hu, implementation error.\n",
2437e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2438e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_CLEANUP_FAILED;
2439e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2440e48354ceSNicholas Bellinger 		return 0;
2441e48354ceSNicholas Bellinger 	}
2442e48354ceSNicholas Bellinger 
2443e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2444e48354ceSNicholas Bellinger 
2445e48354ceSNicholas Bellinger 	return 0;
2446e48354ceSNicholas Bellinger }
2447e48354ceSNicholas Bellinger 
24483e1c81a9SNicholas Bellinger int
24493e1c81a9SNicholas Bellinger iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2450e48354ceSNicholas Bellinger 			unsigned char *buf)
2451e48354ceSNicholas Bellinger {
2452e48354ceSNicholas Bellinger 	int cmdsn_ret, logout_remove = 0;
2453e48354ceSNicholas Bellinger 	u8 reason_code = 0;
2454e48354ceSNicholas Bellinger 	struct iscsi_logout *hdr;
2455e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn);
2456e48354ceSNicholas Bellinger 
2457e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_logout *) buf;
2458e48354ceSNicholas Bellinger 	reason_code		= (hdr->flags & 0x7f);
2459e48354ceSNicholas Bellinger 
2460e48354ceSNicholas Bellinger 	if (tiqn) {
2461e48354ceSNicholas Bellinger 		spin_lock(&tiqn->logout_stats.lock);
2462e48354ceSNicholas Bellinger 		if (reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION)
2463e48354ceSNicholas Bellinger 			tiqn->logout_stats.normal_logouts++;
2464e48354ceSNicholas Bellinger 		else
2465e48354ceSNicholas Bellinger 			tiqn->logout_stats.abnormal_logouts++;
2466e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->logout_stats.lock);
2467e48354ceSNicholas Bellinger 	}
2468e48354ceSNicholas Bellinger 
2469e48354ceSNicholas Bellinger 	pr_debug("Got Logout Request ITT: 0x%08x CmdSN: 0x%08x"
2470e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x Reason: 0x%02x CID: %hu on CID: %hu\n",
2471e48354ceSNicholas Bellinger 		hdr->itt, hdr->cmdsn, hdr->exp_statsn, reason_code,
2472e48354ceSNicholas Bellinger 		hdr->cid, conn->cid);
2473e48354ceSNicholas Bellinger 
2474e48354ceSNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
2475e48354ceSNicholas Bellinger 		pr_err("Received logout request on connection that"
2476e48354ceSNicholas Bellinger 			" is not in logged in state, ignoring request.\n");
2477aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
2478e48354ceSNicholas Bellinger 		return 0;
2479e48354ceSNicholas Bellinger 	}
2480e48354ceSNicholas Bellinger 
2481e48354ceSNicholas Bellinger 	cmd->iscsi_opcode       = ISCSI_OP_LOGOUT;
2482e48354ceSNicholas Bellinger 	cmd->i_state            = ISTATE_SEND_LOGOUTRSP;
2483e48354ceSNicholas Bellinger 	cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2484e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
2485e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag      = 0xFFFFFFFF;
248650e5c87dSChristoph Hellwig 	cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
248750e5c87dSChristoph Hellwig 	cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
248850e5c87dSChristoph Hellwig 	cmd->logout_cid         = be16_to_cpu(hdr->cid);
2489e48354ceSNicholas Bellinger 	cmd->logout_reason      = reason_code;
2490e48354ceSNicholas Bellinger 	cmd->data_direction     = DMA_NONE;
2491e48354ceSNicholas Bellinger 
2492e48354ceSNicholas Bellinger 	/*
2493e48354ceSNicholas Bellinger 	 * We need to sleep in these cases (by returning 1) until the Logout
2494e48354ceSNicholas Bellinger 	 * Response gets sent in the tx thread.
2495e48354ceSNicholas Bellinger 	 */
2496e48354ceSNicholas Bellinger 	if ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION) ||
2497e48354ceSNicholas Bellinger 	   ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) &&
249850e5c87dSChristoph Hellwig 	    be16_to_cpu(hdr->cid) == conn->cid))
2499e48354ceSNicholas Bellinger 		logout_remove = 1;
2500e48354ceSNicholas Bellinger 
2501e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
25022fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2503e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2504e48354ceSNicholas Bellinger 
2505e48354ceSNicholas Bellinger 	if (reason_code != ISCSI_LOGOUT_REASON_RECOVERY)
250650e5c87dSChristoph Hellwig 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2507e48354ceSNicholas Bellinger 
2508e48354ceSNicholas Bellinger 	/*
2509e48354ceSNicholas Bellinger 	 * Immediate commands are executed, well, immediately.
2510e48354ceSNicholas Bellinger 	 * Non-Immediate Logout Commands are executed in CmdSN order.
2511e48354ceSNicholas Bellinger 	 */
2512c6037cc5SAndy Grover 	if (cmd->immediate_cmd) {
2513e48354ceSNicholas Bellinger 		int ret = iscsit_execute_cmd(cmd, 0);
2514e48354ceSNicholas Bellinger 
2515e48354ceSNicholas Bellinger 		if (ret < 0)
2516e48354ceSNicholas Bellinger 			return ret;
2517e48354ceSNicholas Bellinger 	} else {
2518561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
2519ba159914SNicholas Bellinger 		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
2520e48354ceSNicholas Bellinger 			logout_remove = 0;
2521ba159914SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2522ba159914SNicholas Bellinger 			return -1;
2523e48354ceSNicholas Bellinger 	}
2524e48354ceSNicholas Bellinger 
2525e48354ceSNicholas Bellinger 	return logout_remove;
2526e48354ceSNicholas Bellinger }
25273e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_logout_cmd);
2528e48354ceSNicholas Bellinger 
2529d2faaefbSVarun Prakash int iscsit_handle_snack(
2530e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
2531e48354ceSNicholas Bellinger 	unsigned char *buf)
2532e48354ceSNicholas Bellinger {
2533e48354ceSNicholas Bellinger 	struct iscsi_snack *hdr;
2534e48354ceSNicholas Bellinger 
2535e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_snack *) buf;
2536e48354ceSNicholas Bellinger 	hdr->flags		&= ~ISCSI_FLAG_CMD_FINAL;
2537e48354ceSNicholas Bellinger 
2538e48354ceSNicholas Bellinger 	pr_debug("Got ISCSI_INIT_SNACK, ITT: 0x%08x, ExpStatSN:"
2539e48354ceSNicholas Bellinger 		" 0x%08x, Type: 0x%02x, BegRun: 0x%08x, RunLength: 0x%08x,"
2540e48354ceSNicholas Bellinger 		" CID: %hu\n", hdr->itt, hdr->exp_statsn, hdr->flags,
2541e48354ceSNicholas Bellinger 			hdr->begrun, hdr->runlength, conn->cid);
2542e48354ceSNicholas Bellinger 
2543e48354ceSNicholas Bellinger 	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2544e48354ceSNicholas Bellinger 		pr_err("Initiator sent SNACK request while in"
2545e48354ceSNicholas Bellinger 			" ErrorRecoveryLevel=0.\n");
2546ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2547ba159914SNicholas Bellinger 					 buf);
2548e48354ceSNicholas Bellinger 	}
2549e48354ceSNicholas Bellinger 	/*
2550e48354ceSNicholas Bellinger 	 * SNACK_DATA and SNACK_R2T are both 0,  so check which function to
2551e48354ceSNicholas Bellinger 	 * call from inside iscsi_send_recovery_datain_or_r2t().
2552e48354ceSNicholas Bellinger 	 */
2553e48354ceSNicholas Bellinger 	switch (hdr->flags & ISCSI_FLAG_SNACK_TYPE_MASK) {
2554e48354ceSNicholas Bellinger 	case 0:
2555e48354ceSNicholas Bellinger 		return iscsit_handle_recovery_datain_or_r2t(conn, buf,
255650e5c87dSChristoph Hellwig 			hdr->itt,
255750e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
255850e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
255950e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2560e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_STATUS:
256150e5c87dSChristoph Hellwig 		return iscsit_handle_status_snack(conn, hdr->itt,
256250e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
256350e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun), be32_to_cpu(hdr->runlength));
2564e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_DATA_ACK:
256550e5c87dSChristoph Hellwig 		return iscsit_handle_data_ack(conn, be32_to_cpu(hdr->ttt),
256650e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
256750e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2568e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_RDATA:
2569e48354ceSNicholas Bellinger 		/* FIXME: Support R-Data SNACK */
2570e48354ceSNicholas Bellinger 		pr_err("R-Data SNACK Not Supported.\n");
2571ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2572ba159914SNicholas Bellinger 					 buf);
2573e48354ceSNicholas Bellinger 	default:
2574e48354ceSNicholas Bellinger 		pr_err("Unknown SNACK type 0x%02x, protocol"
2575e48354ceSNicholas Bellinger 			" error.\n", hdr->flags & 0x0f);
2576ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2577ba159914SNicholas Bellinger 					 buf);
2578e48354ceSNicholas Bellinger 	}
2579e48354ceSNicholas Bellinger 
2580e48354ceSNicholas Bellinger 	return 0;
2581e48354ceSNicholas Bellinger }
2582d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_handle_snack);
2583e48354ceSNicholas Bellinger 
2584e48354ceSNicholas Bellinger static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn)
2585e48354ceSNicholas Bellinger {
2586e48354ceSNicholas Bellinger 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
2587e48354ceSNicholas Bellinger 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
2588e48354ceSNicholas Bellinger 		wait_for_completion_interruptible_timeout(
2589e48354ceSNicholas Bellinger 					&conn->rx_half_close_comp,
2590e48354ceSNicholas Bellinger 					ISCSI_RX_THREAD_TCP_TIMEOUT * HZ);
2591e48354ceSNicholas Bellinger 	}
2592e48354ceSNicholas Bellinger }
2593e48354ceSNicholas Bellinger 
2594e48354ceSNicholas Bellinger static int iscsit_handle_immediate_data(
2595e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
25963e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr,
2597e48354ceSNicholas Bellinger 	u32 length)
2598e48354ceSNicholas Bellinger {
2599e48354ceSNicholas Bellinger 	int iov_ret, rx_got = 0, rx_size = 0;
2600e48354ceSNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0;
2601e48354ceSNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
2602e48354ceSNicholas Bellinger 	struct kvec *iov;
26030ca650c1SBart Van Assche 	void *overflow_buf = NULL;
2604e48354ceSNicholas Bellinger 
26050ca650c1SBart Van Assche 	BUG_ON(cmd->write_data_done > cmd->se_cmd.data_length);
26060ca650c1SBart Van Assche 	rx_size = min(cmd->se_cmd.data_length - cmd->write_data_done, length);
26072e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, cmd->iov_data,
26082e39f1c9SBart Van Assche 				   cmd->orig_iov_data_count - 2,
26092e39f1c9SBart Van Assche 				   cmd->write_data_done, rx_size);
2610e48354ceSNicholas Bellinger 	if (iov_ret < 0)
2611e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2612e48354ceSNicholas Bellinger 
2613e48354ceSNicholas Bellinger 	iov_count = iov_ret;
2614e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
26150ca650c1SBart Van Assche 	if (rx_size < length) {
26160ca650c1SBart Van Assche 		/*
26170ca650c1SBart Van Assche 		 * Special case: length of immediate data exceeds the data
26180ca650c1SBart Van Assche 		 * buffer size derived from the CDB.
26190ca650c1SBart Van Assche 		 */
26200ca650c1SBart Van Assche 		overflow_buf = kmalloc(length - rx_size, GFP_KERNEL);
26210ca650c1SBart Van Assche 		if (!overflow_buf) {
26220ca650c1SBart Van Assche 			iscsit_unmap_iovec(cmd);
26230ca650c1SBart Van Assche 			return IMMEDIATE_DATA_CANNOT_RECOVER;
26240ca650c1SBart Van Assche 		}
26250ca650c1SBart Van Assche 		cmd->overflow_buf = overflow_buf;
26260ca650c1SBart Van Assche 		iov[iov_count].iov_base = overflow_buf;
26270ca650c1SBart Van Assche 		iov[iov_count].iov_len = length - rx_size;
26280ca650c1SBart Van Assche 		iov_count++;
26290ca650c1SBart Van Assche 		rx_size = length;
26300ca650c1SBart Van Assche 	}
2631e48354ceSNicholas Bellinger 
2632e48354ceSNicholas Bellinger 	padding = ((-length) & 3);
2633e48354ceSNicholas Bellinger 	if (padding != 0) {
2634e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
2635e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
2636e48354ceSNicholas Bellinger 		rx_size += padding;
2637e48354ceSNicholas Bellinger 	}
2638e48354ceSNicholas Bellinger 
2639e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2640e48354ceSNicholas Bellinger 		iov[iov_count].iov_base		= &checksum;
2641e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len	= ISCSI_CRC_LEN;
2642e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
2643e48354ceSNicholas Bellinger 	}
2644e48354ceSNicholas Bellinger 
26452e39f1c9SBart Van Assche 	WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count);
2646e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
2647e48354ceSNicholas Bellinger 
2648e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
2649e48354ceSNicholas Bellinger 
2650e48354ceSNicholas Bellinger 	if (rx_got != rx_size) {
2651e48354ceSNicholas Bellinger 		iscsit_rx_thread_wait_for_tcp(conn);
2652e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2653e48354ceSNicholas Bellinger 	}
2654e48354ceSNicholas Bellinger 
2655e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2656e48354ceSNicholas Bellinger 		u32 data_crc;
2657e48354ceSNicholas Bellinger 
265869110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
2659e48354ceSNicholas Bellinger 						    cmd->write_data_done, length, padding,
2660e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
2661e48354ceSNicholas Bellinger 
2662e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
2663e48354ceSNicholas Bellinger 			pr_err("ImmediateData CRC32C DataDigest 0x%08x"
2664e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n", checksum,
2665e48354ceSNicholas Bellinger 				data_crc);
2666e48354ceSNicholas Bellinger 
2667e48354ceSNicholas Bellinger 			if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2668e48354ceSNicholas Bellinger 				pr_err("Unable to recover from"
2669e48354ceSNicholas Bellinger 					" Immediate Data digest failure while"
2670e48354ceSNicholas Bellinger 					" in ERL=0.\n");
2671ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2672e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2673ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2674e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_CANNOT_RECOVER;
2675e48354ceSNicholas Bellinger 			} else {
2676ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2677e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2678ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2679e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
2680e48354ceSNicholas Bellinger 			}
2681e48354ceSNicholas Bellinger 		} else {
2682e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
2683e48354ceSNicholas Bellinger 				" %u bytes of Immediate Data\n", checksum,
2684e48354ceSNicholas Bellinger 				length);
2685e48354ceSNicholas Bellinger 		}
2686e48354ceSNicholas Bellinger 	}
2687e48354ceSNicholas Bellinger 
2688e48354ceSNicholas Bellinger 	cmd->write_data_done += length;
2689e48354ceSNicholas Bellinger 
2690ebf1d95cSAndy Grover 	if (cmd->write_data_done == cmd->se_cmd.data_length) {
2691e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
2692e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
2693e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
2694e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
2695e48354ceSNicholas Bellinger 	}
2696e48354ceSNicholas Bellinger 
2697e48354ceSNicholas Bellinger 	return IMMEDIATE_DATA_NORMAL_OPERATION;
2698e48354ceSNicholas Bellinger }
2699e48354ceSNicholas Bellinger 
2700e48354ceSNicholas Bellinger /* #warning iscsi_build_conn_drop_async_message() only sends out on connections
2701e48354ceSNicholas Bellinger 	with active network interface */
2702e48354ceSNicholas Bellinger static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn)
2703e48354ceSNicholas Bellinger {
2704e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
2705e48354ceSNicholas Bellinger 	struct iscsi_conn *conn_p;
2706d444edc6SNicholas Bellinger 	bool found = false;
2707e48354ceSNicholas Bellinger 
2708618baaf7SBart Van Assche 	lockdep_assert_held(&conn->sess->conn_lock);
2709618baaf7SBart Van Assche 
2710e48354ceSNicholas Bellinger 	/*
2711e48354ceSNicholas Bellinger 	 * Only send a Asynchronous Message on connections whos network
2712e48354ceSNicholas Bellinger 	 * interface is still functional.
2713e48354ceSNicholas Bellinger 	 */
2714e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &conn->sess->sess_conn_list, conn_list) {
2715e48354ceSNicholas Bellinger 		if (conn_p->conn_state == TARG_CONN_STATE_LOGGED_IN) {
2716e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn_p);
2717d444edc6SNicholas Bellinger 			found = true;
2718e48354ceSNicholas Bellinger 			break;
2719e48354ceSNicholas Bellinger 		}
2720e48354ceSNicholas Bellinger 	}
2721e48354ceSNicholas Bellinger 
2722d444edc6SNicholas Bellinger 	if (!found)
2723e48354ceSNicholas Bellinger 		return;
2724e48354ceSNicholas Bellinger 
2725676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn_p, TASK_RUNNING);
2726e48354ceSNicholas Bellinger 	if (!cmd) {
2727e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(conn_p);
2728e48354ceSNicholas Bellinger 		return;
2729e48354ceSNicholas Bellinger 	}
2730e48354ceSNicholas Bellinger 
2731e48354ceSNicholas Bellinger 	cmd->logout_cid = conn->cid;
2732e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2733e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_ASYNCMSG;
2734e48354ceSNicholas Bellinger 
2735e48354ceSNicholas Bellinger 	spin_lock_bh(&conn_p->cmd_lock);
27362fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn_p->conn_cmd_list);
2737e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn_p->cmd_lock);
2738e48354ceSNicholas Bellinger 
2739e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn_p, cmd->i_state);
2740e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn_p);
2741e48354ceSNicholas Bellinger }
2742e48354ceSNicholas Bellinger 
2743e48354ceSNicholas Bellinger static int iscsit_send_conn_drop_async_message(
2744e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
2745e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
2746e48354ceSNicholas Bellinger {
2747e48354ceSNicholas Bellinger 	struct iscsi_async *hdr;
2748e48354ceSNicholas Bellinger 
2749e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2750e48354ceSNicholas Bellinger 
2751e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_async *) cmd->pdu;
2752e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_ASYNC_EVENT;
2753e48354ceSNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
275466c7db68SChristoph Hellwig 	cmd->init_task_tag	= RESERVED_ITT;
2755e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
2756e48354ceSNicholas Bellinger 	put_unaligned_be64(0xFFFFFFFFFFFFFFFFULL, &hdr->rsvd4[0]);
2757e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2758e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2759e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2760109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2761e48354ceSNicholas Bellinger 	hdr->async_event	= ISCSI_ASYNC_MSG_DROPPING_CONNECTION;
2762e48354ceSNicholas Bellinger 	hdr->param1		= cpu_to_be16(cmd->logout_cid);
2763e48354ceSNicholas Bellinger 	hdr->param2		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait);
2764e48354ceSNicholas Bellinger 	hdr->param3		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Retain);
2765e48354ceSNicholas Bellinger 
2766e48354ceSNicholas Bellinger 	pr_debug("Sending Connection Dropped Async Message StatSN:"
2767e48354ceSNicholas Bellinger 		" 0x%08x, for CID: %hu on CID: %hu\n", cmd->stat_sn,
2768e48354ceSNicholas Bellinger 			cmd->logout_cid, conn->cid);
27692854bb23SVarun Prakash 
27702854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
2771e48354ceSNicholas Bellinger }
2772e48354ceSNicholas Bellinger 
27736f3c0e69SAndy Grover static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
27746f3c0e69SAndy Grover {
27756f3c0e69SAndy Grover 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
27766f3c0e69SAndy Grover 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
27776f3c0e69SAndy Grover 		wait_for_completion_interruptible_timeout(
27786f3c0e69SAndy Grover 					&conn->tx_half_close_comp,
27796f3c0e69SAndy Grover 					ISCSI_TX_THREAD_TCP_TIMEOUT * HZ);
27806f3c0e69SAndy Grover 	}
27816f3c0e69SAndy Grover }
27826f3c0e69SAndy Grover 
2783d2faaefbSVarun Prakash void
27842ec5a8c1SNicholas Bellinger iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
27852ec5a8c1SNicholas Bellinger 			struct iscsi_datain *datain, struct iscsi_data_rsp *hdr,
27862ec5a8c1SNicholas Bellinger 			bool set_statsn)
2787e48354ceSNicholas Bellinger {
27882ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_DATA_IN;
27892ec5a8c1SNicholas Bellinger 	hdr->flags		= datain->flags;
27902ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
27912ec5a8c1SNicholas Bellinger 		if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
27922ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
27932ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
27942ec5a8c1SNicholas Bellinger 		} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
27952ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
27962ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
27972ec5a8c1SNicholas Bellinger 		}
27982ec5a8c1SNicholas Bellinger 	}
27992ec5a8c1SNicholas Bellinger 	hton24(hdr->dlength, datain->length);
28002ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
28012ec5a8c1SNicholas Bellinger 		int_to_scsilun(cmd->se_cmd.orig_fe_lun,
28022ec5a8c1SNicholas Bellinger 				(struct scsi_lun *)&hdr->lun);
28032ec5a8c1SNicholas Bellinger 	else
28042ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
28052ec5a8c1SNicholas Bellinger 
28062ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
28072ec5a8c1SNicholas Bellinger 
28082ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
28092ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
28102ec5a8c1SNicholas Bellinger 	else
28112ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(0xFFFFFFFF);
28122ec5a8c1SNicholas Bellinger 	if (set_statsn)
28132ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(cmd->stat_sn);
28142ec5a8c1SNicholas Bellinger 	else
28152ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(0xFFFFFFFF);
28162ec5a8c1SNicholas Bellinger 
28172ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2818109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
28192ec5a8c1SNicholas Bellinger 	hdr->datasn		= cpu_to_be32(datain->data_sn);
28202ec5a8c1SNicholas Bellinger 	hdr->offset		= cpu_to_be32(datain->offset);
28212ec5a8c1SNicholas Bellinger 
28222ec5a8c1SNicholas Bellinger 	pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x,"
28232ec5a8c1SNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
28242ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
28252ec5a8c1SNicholas Bellinger 		ntohl(hdr->offset), datain->length, conn->cid);
28262ec5a8c1SNicholas Bellinger }
2827d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_datain_pdu);
28282ec5a8c1SNicholas Bellinger 
28292ec5a8c1SNicholas Bellinger static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
28302ec5a8c1SNicholas Bellinger {
28312ec5a8c1SNicholas Bellinger 	struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0];
2832e48354ceSNicholas Bellinger 	struct iscsi_datain datain;
2833e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
28342854bb23SVarun Prakash 	int eodr = 0, ret;
28352ec5a8c1SNicholas Bellinger 	bool set_statsn = false;
2836e48354ceSNicholas Bellinger 
2837e48354ceSNicholas Bellinger 	memset(&datain, 0, sizeof(struct iscsi_datain));
2838e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_values(cmd, &datain);
2839e48354ceSNicholas Bellinger 	if (!dr) {
2840e48354ceSNicholas Bellinger 		pr_err("iscsit_get_datain_values failed for ITT: 0x%08x\n",
2841e48354ceSNicholas Bellinger 				cmd->init_task_tag);
2842e48354ceSNicholas Bellinger 		return -1;
2843e48354ceSNicholas Bellinger 	}
2844e48354ceSNicholas Bellinger 	/*
2845e48354ceSNicholas Bellinger 	 * Be paranoid and double check the logic for now.
2846e48354ceSNicholas Bellinger 	 */
2847ebf1d95cSAndy Grover 	if ((datain.offset + datain.length) > cmd->se_cmd.data_length) {
2848e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x, datain.offset: %u and"
2849e48354ceSNicholas Bellinger 			" datain.length: %u exceeds cmd->data_length: %u\n",
2850e48354ceSNicholas Bellinger 			cmd->init_task_tag, datain.offset, datain.length,
2851ebf1d95cSAndy Grover 			cmd->se_cmd.data_length);
2852e48354ceSNicholas Bellinger 		return -1;
2853e48354ceSNicholas Bellinger 	}
2854e48354ceSNicholas Bellinger 
285504f3b31bSNicholas Bellinger 	atomic_long_add(datain.length, &conn->sess->tx_data_octets);
2856e48354ceSNicholas Bellinger 	/*
2857e48354ceSNicholas Bellinger 	 * Special case for successfully execution w/ both DATAIN
2858e48354ceSNicholas Bellinger 	 * and Sense Data.
2859e48354ceSNicholas Bellinger 	 */
2860e48354ceSNicholas Bellinger 	if ((datain.flags & ISCSI_FLAG_DATA_STATUS) &&
2861e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
2862e48354ceSNicholas Bellinger 		datain.flags &= ~ISCSI_FLAG_DATA_STATUS;
2863e48354ceSNicholas Bellinger 	else {
2864e48354ceSNicholas Bellinger 		if ((dr->dr_complete == DATAIN_COMPLETE_NORMAL) ||
2865e48354ceSNicholas Bellinger 		    (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
2866e48354ceSNicholas Bellinger 			iscsit_increment_maxcmdsn(cmd, conn->sess);
2867e48354ceSNicholas Bellinger 			cmd->stat_sn = conn->stat_sn++;
28682ec5a8c1SNicholas Bellinger 			set_statsn = true;
2869e48354ceSNicholas Bellinger 		} else if (dr->dr_complete ==
2870e48354ceSNicholas Bellinger 			   DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
28712ec5a8c1SNicholas Bellinger 			set_statsn = true;
2872e48354ceSNicholas Bellinger 	}
2873e48354ceSNicholas Bellinger 
28742ec5a8c1SNicholas Bellinger 	iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
2875e48354ceSNicholas Bellinger 
28762854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, dr, &datain, 0);
28772854bb23SVarun Prakash 	if (ret < 0)
28786f3c0e69SAndy Grover 		return ret;
28796f3c0e69SAndy Grover 
2880e48354ceSNicholas Bellinger 	if (dr->dr_complete) {
28816f3c0e69SAndy Grover 		eodr = (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ?
2882e48354ceSNicholas Bellinger 				2 : 1;
2883e48354ceSNicholas Bellinger 		iscsit_free_datain_req(cmd, dr);
2884e48354ceSNicholas Bellinger 	}
2885e48354ceSNicholas Bellinger 
28866f3c0e69SAndy Grover 	return eodr;
2887e48354ceSNicholas Bellinger }
2888e48354ceSNicholas Bellinger 
28892ec5a8c1SNicholas Bellinger int
28902ec5a8c1SNicholas Bellinger iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
28912ec5a8c1SNicholas Bellinger 			struct iscsi_logout_rsp *hdr)
2892e48354ceSNicholas Bellinger {
2893e48354ceSNicholas Bellinger 	struct iscsi_conn *logout_conn = NULL;
2894e48354ceSNicholas Bellinger 	struct iscsi_conn_recovery *cr = NULL;
2895e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2896e48354ceSNicholas Bellinger 	/*
2897e48354ceSNicholas Bellinger 	 * The actual shutting down of Sessions and/or Connections
2898e48354ceSNicholas Bellinger 	 * for CLOSESESSION and CLOSECONNECTION Logout Requests
2899e48354ceSNicholas Bellinger 	 * is done in scsi_logout_post_handler().
2900e48354ceSNicholas Bellinger 	 */
2901e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
2902e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
2903e48354ceSNicholas Bellinger 		pr_debug("iSCSI session logout successful, setting"
2904e48354ceSNicholas Bellinger 			" logout response to ISCSI_LOGOUT_SUCCESS.\n");
2905e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2906e48354ceSNicholas Bellinger 		break;
2907e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
2908e48354ceSNicholas Bellinger 		if (cmd->logout_response == ISCSI_LOGOUT_CID_NOT_FOUND)
2909e48354ceSNicholas Bellinger 			break;
2910e48354ceSNicholas Bellinger 		/*
2911e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2912e48354ceSNicholas Bellinger 		 * a matching logout CID -> local CID, the reference
2913e48354ceSNicholas Bellinger 		 * for the local CID will have been incremented in
2914e48354ceSNicholas Bellinger 		 * iscsi_logout_closeconnection().
2915e48354ceSNicholas Bellinger 		 *
2916e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2917e48354ceSNicholas Bellinger 		 * a different CID than the connection it arrived
2918e48354ceSNicholas Bellinger 		 * on, the connection responding to cmd->logout_cid
2919e48354ceSNicholas Bellinger 		 * is stopped in iscsit_logout_post_handler_diffcid().
2920e48354ceSNicholas Bellinger 		 */
2921e48354ceSNicholas Bellinger 
2922e48354ceSNicholas Bellinger 		pr_debug("iSCSI CID: %hu logout on CID: %hu"
2923e48354ceSNicholas Bellinger 			" successful.\n", cmd->logout_cid, conn->cid);
2924e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2925e48354ceSNicholas Bellinger 		break;
2926e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
2927e48354ceSNicholas Bellinger 		if ((cmd->logout_response == ISCSI_LOGOUT_RECOVERY_UNSUPPORTED) ||
2928e48354ceSNicholas Bellinger 		    (cmd->logout_response == ISCSI_LOGOUT_CLEANUP_FAILED))
2929e48354ceSNicholas Bellinger 			break;
2930e48354ceSNicholas Bellinger 		/*
2931e48354ceSNicholas Bellinger 		 * If the connection is still active from our point of view
2932e48354ceSNicholas Bellinger 		 * force connection recovery to occur.
2933e48354ceSNicholas Bellinger 		 */
2934e48354ceSNicholas Bellinger 		logout_conn = iscsit_get_conn_from_cid_rcfr(sess,
2935e48354ceSNicholas Bellinger 				cmd->logout_cid);
2936ee1b1b9cSAndy Grover 		if (logout_conn) {
2937e48354ceSNicholas Bellinger 			iscsit_connection_reinstatement_rcfr(logout_conn);
2938e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(logout_conn);
2939e48354ceSNicholas Bellinger 		}
2940e48354ceSNicholas Bellinger 
2941e48354ceSNicholas Bellinger 		cr = iscsit_get_inactive_connection_recovery_entry(
2942e48354ceSNicholas Bellinger 				conn->sess, cmd->logout_cid);
2943e48354ceSNicholas Bellinger 		if (!cr) {
2944e48354ceSNicholas Bellinger 			pr_err("Unable to locate CID: %hu for"
2945e48354ceSNicholas Bellinger 			" REMOVECONNFORRECOVERY Logout Request.\n",
2946e48354ceSNicholas Bellinger 				cmd->logout_cid);
2947e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2948e48354ceSNicholas Bellinger 			break;
2949e48354ceSNicholas Bellinger 		}
2950e48354ceSNicholas Bellinger 
2951e48354ceSNicholas Bellinger 		iscsit_discard_cr_cmds_by_expstatsn(cr, cmd->exp_stat_sn);
2952e48354ceSNicholas Bellinger 
2953e48354ceSNicholas Bellinger 		pr_debug("iSCSI REMOVECONNFORRECOVERY logout"
2954e48354ceSNicholas Bellinger 			" for recovery for CID: %hu on CID: %hu successful.\n",
2955e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2956e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2957e48354ceSNicholas Bellinger 		break;
2958e48354ceSNicholas Bellinger 	default:
2959e48354ceSNicholas Bellinger 		pr_err("Unknown cmd->logout_reason: 0x%02x\n",
2960e48354ceSNicholas Bellinger 				cmd->logout_reason);
2961e48354ceSNicholas Bellinger 		return -1;
2962e48354ceSNicholas Bellinger 	}
2963e48354ceSNicholas Bellinger 
2964e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_LOGOUT_RSP;
2965e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
2966e48354ceSNicholas Bellinger 	hdr->response		= cmd->logout_response;
296766c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
2968e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2969e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2970e48354ceSNicholas Bellinger 
2971e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
2972e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2973109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2974e48354ceSNicholas Bellinger 
29752ec5a8c1SNicholas Bellinger 	pr_debug("Built Logout Response ITT: 0x%08x StatSN:"
29762ec5a8c1SNicholas Bellinger 		" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
29772ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response,
29782ec5a8c1SNicholas Bellinger 		cmd->logout_cid, conn->cid);
29792ec5a8c1SNicholas Bellinger 
29802ec5a8c1SNicholas Bellinger 	return 0;
29812ec5a8c1SNicholas Bellinger }
29822ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_logout_rsp);
29832ec5a8c1SNicholas Bellinger 
29842ec5a8c1SNicholas Bellinger static int
29852ec5a8c1SNicholas Bellinger iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
29862ec5a8c1SNicholas Bellinger {
29872854bb23SVarun Prakash 	int rc;
29882ec5a8c1SNicholas Bellinger 
29892ec5a8c1SNicholas Bellinger 	rc = iscsit_build_logout_rsp(cmd, conn,
29902ec5a8c1SNicholas Bellinger 			(struct iscsi_logout_rsp *)&cmd->pdu[0]);
29912ec5a8c1SNicholas Bellinger 	if (rc < 0)
29922ec5a8c1SNicholas Bellinger 		return rc;
29932ec5a8c1SNicholas Bellinger 
29942854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
2995e48354ceSNicholas Bellinger }
2996e48354ceSNicholas Bellinger 
29972ec5a8c1SNicholas Bellinger void
29982ec5a8c1SNicholas Bellinger iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
29992ec5a8c1SNicholas Bellinger 		       struct iscsi_nopin *hdr, bool nopout_response)
30002ec5a8c1SNicholas Bellinger {
30012ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_NOOP_IN;
30022ec5a8c1SNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
30032ec5a8c1SNicholas Bellinger         hton24(hdr->dlength, cmd->buf_ptr_size);
30042ec5a8c1SNicholas Bellinger 	if (nopout_response)
30052ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
30062ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
30072ec5a8c1SNicholas Bellinger 	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
30082ec5a8c1SNicholas Bellinger 	cmd->stat_sn		= (nopout_response) ? conn->stat_sn++ :
30092ec5a8c1SNicholas Bellinger 				  conn->stat_sn;
30102ec5a8c1SNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
30112ec5a8c1SNicholas Bellinger 
30122ec5a8c1SNicholas Bellinger 	if (nopout_response)
30132ec5a8c1SNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, conn->sess);
30142ec5a8c1SNicholas Bellinger 
30152ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3016109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
30172ec5a8c1SNicholas Bellinger 
30182ec5a8c1SNicholas Bellinger 	pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
30192ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Length %u\n", (nopout_response) ?
30203fc6a642SColin Ian King 		"Solicited" : "Unsolicited", cmd->init_task_tag,
30212ec5a8c1SNicholas Bellinger 		cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
30222ec5a8c1SNicholas Bellinger }
30232ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_nopin_rsp);
30242ec5a8c1SNicholas Bellinger 
3025e48354ceSNicholas Bellinger /*
3026e48354ceSNicholas Bellinger  *	Unsolicited NOPIN, either requesting a response or not.
3027e48354ceSNicholas Bellinger  */
3028e48354ceSNicholas Bellinger static int iscsit_send_unsolicited_nopin(
3029e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
3030e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
3031e48354ceSNicholas Bellinger 	int want_response)
3032e48354ceSNicholas Bellinger {
30332ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
30342854bb23SVarun Prakash 	int ret;
3035e48354ceSNicholas Bellinger 
30362ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, false);
3037e48354ceSNicholas Bellinger 
3038e48354ceSNicholas Bellinger 	pr_debug("Sending Unsolicited NOPIN TTT: 0x%08x StatSN:"
3039e48354ceSNicholas Bellinger 		" 0x%08x CID: %hu\n", hdr->ttt, cmd->stat_sn, conn->cid);
3040e48354ceSNicholas Bellinger 
30412854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
30422854bb23SVarun Prakash 	if (ret < 0)
30436f3c0e69SAndy Grover 		return ret;
30446f3c0e69SAndy Grover 
30456f3c0e69SAndy Grover 	spin_lock_bh(&cmd->istate_lock);
30466f3c0e69SAndy Grover 	cmd->i_state = want_response ?
30476f3c0e69SAndy Grover 		ISTATE_SENT_NOPIN_WANT_RESPONSE : ISTATE_SENT_STATUS;
30486f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->istate_lock);
30496f3c0e69SAndy Grover 
3050e48354ceSNicholas Bellinger 	return 0;
3051e48354ceSNicholas Bellinger }
3052e48354ceSNicholas Bellinger 
30532ec5a8c1SNicholas Bellinger static int
30542ec5a8c1SNicholas Bellinger iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
3055e48354ceSNicholas Bellinger {
30562ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
30572ec5a8c1SNicholas Bellinger 
30582ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, true);
3059e48354ceSNicholas Bellinger 
3060e48354ceSNicholas Bellinger 	/*
3061e48354ceSNicholas Bellinger 	 * NOPOUT Ping Data is attached to struct iscsi_cmd->buf_ptr.
3062e48354ceSNicholas Bellinger 	 * NOPOUT DataSegmentLength is at struct iscsi_cmd->buf_ptr_size.
3063e48354ceSNicholas Bellinger 	 */
30642854bb23SVarun Prakash 	pr_debug("Echoing back %u bytes of ping data.\n", cmd->buf_ptr_size);
3065e48354ceSNicholas Bellinger 
30662854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
30672854bb23SVarun Prakash 						     cmd->buf_ptr,
30682854bb23SVarun Prakash 						     cmd->buf_ptr_size);
3069e48354ceSNicholas Bellinger }
3070e48354ceSNicholas Bellinger 
30716f3c0e69SAndy Grover static int iscsit_send_r2t(
3072e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
3073e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
3074e48354ceSNicholas Bellinger {
3075e48354ceSNicholas Bellinger 	struct iscsi_r2t *r2t;
3076e48354ceSNicholas Bellinger 	struct iscsi_r2t_rsp *hdr;
30776f3c0e69SAndy Grover 	int ret;
3078e48354ceSNicholas Bellinger 
3079e48354ceSNicholas Bellinger 	r2t = iscsit_get_r2t_from_list(cmd);
3080e48354ceSNicholas Bellinger 	if (!r2t)
3081e48354ceSNicholas Bellinger 		return -1;
3082e48354ceSNicholas Bellinger 
3083e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_r2t_rsp *) cmd->pdu;
3084e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3085e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_R2T;
3086e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3087e48354ceSNicholas Bellinger 	int_to_scsilun(cmd->se_cmd.orig_fe_lun,
3088e48354ceSNicholas Bellinger 			(struct scsi_lun *)&hdr->lun);
308966c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
30908567270dSVarun Prakash 	if (conn->conn_transport->iscsit_get_r2t_ttt)
30918567270dSVarun Prakash 		conn->conn_transport->iscsit_get_r2t_ttt(conn, cmd, r2t);
30928567270dSVarun Prakash 	else
3093c1e34b64SSagi Grimberg 		r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
3094e48354ceSNicholas Bellinger 	hdr->ttt		= cpu_to_be32(r2t->targ_xfer_tag);
3095e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(conn->stat_sn);
3096e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3097109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3098e48354ceSNicholas Bellinger 	hdr->r2tsn		= cpu_to_be32(r2t->r2t_sn);
3099e48354ceSNicholas Bellinger 	hdr->data_offset	= cpu_to_be32(r2t->offset);
3100e48354ceSNicholas Bellinger 	hdr->data_length	= cpu_to_be32(r2t->xfer_len);
3101e48354ceSNicholas Bellinger 
3102e48354ceSNicholas Bellinger 	pr_debug("Built %sR2T, ITT: 0x%08x, TTT: 0x%08x, StatSN:"
3103e48354ceSNicholas Bellinger 		" 0x%08x, R2TSN: 0x%08x, Offset: %u, DDTL: %u, CID: %hu\n",
3104e48354ceSNicholas Bellinger 		(!r2t->recovery_r2t) ? "" : "Recovery ", cmd->init_task_tag,
3105e48354ceSNicholas Bellinger 		r2t->targ_xfer_tag, ntohl(hdr->statsn), r2t->r2t_sn,
3106e48354ceSNicholas Bellinger 			r2t->offset, r2t->xfer_len, conn->cid);
3107e48354ceSNicholas Bellinger 
3108e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3109e48354ceSNicholas Bellinger 	r2t->sent_r2t = 1;
3110e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3111e48354ceSNicholas Bellinger 
31122854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
31136f3c0e69SAndy Grover 	if (ret < 0) {
31146f3c0e69SAndy Grover 		return ret;
31156f3c0e69SAndy Grover 	}
31166f3c0e69SAndy Grover 
31176f3c0e69SAndy Grover 	spin_lock_bh(&cmd->dataout_timeout_lock);
31186f3c0e69SAndy Grover 	iscsit_start_dataout_timer(cmd, conn);
31196f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->dataout_timeout_lock);
31206f3c0e69SAndy Grover 
3121e48354ceSNicholas Bellinger 	return 0;
3122e48354ceSNicholas Bellinger }
3123e48354ceSNicholas Bellinger 
3124e48354ceSNicholas Bellinger /*
31258b1e1244SAndy Grover  *	@recovery: If called from iscsi_task_reassign_complete_write() for
3126e48354ceSNicholas Bellinger  *		connection recovery.
3127e48354ceSNicholas Bellinger  */
3128e48354ceSNicholas Bellinger int iscsit_build_r2ts_for_cmd(
3129e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
31303e1c81a9SNicholas Bellinger 	struct iscsi_cmd *cmd,
31318b1e1244SAndy Grover 	bool recovery)
3132e48354ceSNicholas Bellinger {
3133e48354ceSNicholas Bellinger 	int first_r2t = 1;
3134e48354ceSNicholas Bellinger 	u32 offset = 0, xfer_len = 0;
3135e48354ceSNicholas Bellinger 
3136e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3137e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_SENT_LAST_R2T) {
3138e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->r2t_lock);
3139e48354ceSNicholas Bellinger 		return 0;
3140e48354ceSNicholas Bellinger 	}
3141e48354ceSNicholas Bellinger 
31428b1e1244SAndy Grover 	if (conn->sess->sess_ops->DataSequenceInOrder &&
31438b1e1244SAndy Grover 	    !recovery)
3144c6037cc5SAndy Grover 		cmd->r2t_offset = max(cmd->r2t_offset, cmd->write_data_done);
3145e48354ceSNicholas Bellinger 
3146e48354ceSNicholas Bellinger 	while (cmd->outstanding_r2ts < conn->sess->sess_ops->MaxOutstandingR2T) {
3147e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->DataSequenceInOrder) {
3148e48354ceSNicholas Bellinger 			offset = cmd->r2t_offset;
3149e48354ceSNicholas Bellinger 
31508b1e1244SAndy Grover 			if (first_r2t && recovery) {
31518b1e1244SAndy Grover 				int new_data_end = offset +
31528b1e1244SAndy Grover 					conn->sess->sess_ops->MaxBurstLength -
31538b1e1244SAndy Grover 					cmd->next_burst_len;
31548b1e1244SAndy Grover 
3155ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3156ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31578b1e1244SAndy Grover 				else
31588b1e1244SAndy Grover 					xfer_len =
31598b1e1244SAndy Grover 						conn->sess->sess_ops->MaxBurstLength -
31608b1e1244SAndy Grover 						cmd->next_burst_len;
3161e48354ceSNicholas Bellinger 			} else {
31628b1e1244SAndy Grover 				int new_data_end = offset +
3163e48354ceSNicholas Bellinger 					conn->sess->sess_ops->MaxBurstLength;
31648b1e1244SAndy Grover 
3165ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3166ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31678b1e1244SAndy Grover 				else
31688b1e1244SAndy Grover 					xfer_len = conn->sess->sess_ops->MaxBurstLength;
3169e48354ceSNicholas Bellinger 			}
317096e8e26dSBart Van Assche 
317196e8e26dSBart Van Assche 			if ((s32)xfer_len < 0) {
317296e8e26dSBart Van Assche 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
317396e8e26dSBart Van Assche 				break;
317496e8e26dSBart Van Assche 			}
317596e8e26dSBart Van Assche 
3176e48354ceSNicholas Bellinger 			cmd->r2t_offset += xfer_len;
3177e48354ceSNicholas Bellinger 
3178ebf1d95cSAndy Grover 			if (cmd->r2t_offset == cmd->se_cmd.data_length)
3179e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3180e48354ceSNicholas Bellinger 		} else {
3181e48354ceSNicholas Bellinger 			struct iscsi_seq *seq;
3182e48354ceSNicholas Bellinger 
3183e48354ceSNicholas Bellinger 			seq = iscsit_get_seq_holder_for_r2t(cmd);
3184e48354ceSNicholas Bellinger 			if (!seq) {
3185e48354ceSNicholas Bellinger 				spin_unlock_bh(&cmd->r2t_lock);
3186e48354ceSNicholas Bellinger 				return -1;
3187e48354ceSNicholas Bellinger 			}
3188e48354ceSNicholas Bellinger 
3189e48354ceSNicholas Bellinger 			offset = seq->offset;
3190e48354ceSNicholas Bellinger 			xfer_len = seq->xfer_len;
3191e48354ceSNicholas Bellinger 
3192e48354ceSNicholas Bellinger 			if (cmd->seq_send_order == cmd->seq_count)
3193e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3194e48354ceSNicholas Bellinger 		}
3195e48354ceSNicholas Bellinger 		cmd->outstanding_r2ts++;
3196e48354ceSNicholas Bellinger 		first_r2t = 0;
3197e48354ceSNicholas Bellinger 
3198e48354ceSNicholas Bellinger 		if (iscsit_add_r2t_to_list(cmd, offset, xfer_len, 0, 0) < 0) {
3199e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->r2t_lock);
3200e48354ceSNicholas Bellinger 			return -1;
3201e48354ceSNicholas Bellinger 		}
3202e48354ceSNicholas Bellinger 
3203e48354ceSNicholas Bellinger 		if (cmd->cmd_flags & ICF_SENT_LAST_R2T)
3204e48354ceSNicholas Bellinger 			break;
3205e48354ceSNicholas Bellinger 	}
3206e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3207e48354ceSNicholas Bellinger 
3208e48354ceSNicholas Bellinger 	return 0;
3209e48354ceSNicholas Bellinger }
3210d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_r2ts_for_cmd);
3211e48354ceSNicholas Bellinger 
32122ec5a8c1SNicholas Bellinger void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
32132ec5a8c1SNicholas Bellinger 			bool inc_stat_sn, struct iscsi_scsi_rsp *hdr)
3214e48354ceSNicholas Bellinger {
32152ec5a8c1SNicholas Bellinger 	if (inc_stat_sn)
3216e48354ceSNicholas Bellinger 		cmd->stat_sn = conn->stat_sn++;
3217e48354ceSNicholas Bellinger 
321804f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->rsp_pdus);
3219e48354ceSNicholas Bellinger 
3220e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3221e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_CMD_RSP;
3222e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3223e48354ceSNicholas Bellinger 	if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
3224e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW;
32257e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3226e48354ceSNicholas Bellinger 	} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
3227e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
32287e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3229e48354ceSNicholas Bellinger 	}
3230e48354ceSNicholas Bellinger 	hdr->response		= cmd->iscsi_response;
3231e48354ceSNicholas Bellinger 	hdr->cmd_status		= cmd->se_cmd.scsi_status;
323266c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3233e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3234e48354ceSNicholas Bellinger 
3235e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3236e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3237109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3238e48354ceSNicholas Bellinger 
32392ec5a8c1SNicholas Bellinger 	pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
32402ec5a8c1SNicholas Bellinger 		" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
32412ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, cmd->se_cmd.scsi_status,
32422ec5a8c1SNicholas Bellinger 		cmd->se_cmd.scsi_status, conn->cid);
32432ec5a8c1SNicholas Bellinger }
32442ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_rsp_pdu);
32452ec5a8c1SNicholas Bellinger 
32462ec5a8c1SNicholas Bellinger static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
32472ec5a8c1SNicholas Bellinger {
32482ec5a8c1SNicholas Bellinger 	struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)&cmd->pdu[0];
32492ec5a8c1SNicholas Bellinger 	bool inc_stat_sn = (cmd->i_state == ISTATE_SEND_STATUS);
32502854bb23SVarun Prakash 	void *data_buf = NULL;
32512854bb23SVarun Prakash 	u32 padding = 0, data_buf_len = 0;
32522ec5a8c1SNicholas Bellinger 
32532ec5a8c1SNicholas Bellinger 	iscsit_build_rsp_pdu(cmd, conn, inc_stat_sn, hdr);
32542ec5a8c1SNicholas Bellinger 
3255e48354ceSNicholas Bellinger 	/*
3256e48354ceSNicholas Bellinger 	 * Attach SENSE DATA payload to iSCSI Response PDU
3257e48354ceSNicholas Bellinger 	 */
3258e48354ceSNicholas Bellinger 	if (cmd->se_cmd.sense_buffer &&
3259e48354ceSNicholas Bellinger 	   ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
3260e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
32619c58b7ddSRoland Dreier 		put_unaligned_be16(cmd->se_cmd.scsi_sense_length, cmd->sense_buffer);
32629c58b7ddSRoland Dreier 		cmd->se_cmd.scsi_sense_length += sizeof (__be16);
32639c58b7ddSRoland Dreier 
3264e48354ceSNicholas Bellinger 		padding		= -(cmd->se_cmd.scsi_sense_length) & 3;
326550e5c87dSChristoph Hellwig 		hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length);
32662854bb23SVarun Prakash 		data_buf = cmd->sense_buffer;
32672854bb23SVarun Prakash 		data_buf_len = cmd->se_cmd.scsi_sense_length + padding;
3268e48354ceSNicholas Bellinger 
3269e48354ceSNicholas Bellinger 		if (padding) {
32709c58b7ddSRoland Dreier 			memset(cmd->sense_buffer +
3271e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length, 0, padding);
3272e48354ceSNicholas Bellinger 			pr_debug("Adding %u bytes of padding to"
3273e48354ceSNicholas Bellinger 				" SENSE.\n", padding);
3274e48354ceSNicholas Bellinger 		}
3275e48354ceSNicholas Bellinger 
3276e48354ceSNicholas Bellinger 		pr_debug("Attaching SENSE DATA: %u bytes to iSCSI"
3277e48354ceSNicholas Bellinger 				" Response PDU\n",
3278e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length);
3279e48354ceSNicholas Bellinger 	}
3280e48354ceSNicholas Bellinger 
32812854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, data_buf,
32822854bb23SVarun Prakash 						     data_buf_len);
3283e48354ceSNicholas Bellinger }
3284e48354ceSNicholas Bellinger 
3285e48354ceSNicholas Bellinger static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr)
3286e48354ceSNicholas Bellinger {
3287e48354ceSNicholas Bellinger 	switch (se_tmr->response) {
3288e48354ceSNicholas Bellinger 	case TMR_FUNCTION_COMPLETE:
3289e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_COMPLETE;
3290e48354ceSNicholas Bellinger 	case TMR_TASK_DOES_NOT_EXIST:
3291e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_TASK;
3292e48354ceSNicholas Bellinger 	case TMR_LUN_DOES_NOT_EXIST:
3293e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_LUN;
3294e48354ceSNicholas Bellinger 	case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
3295e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NOT_SUPPORTED;
3296e48354ceSNicholas Bellinger 	case TMR_FUNCTION_REJECTED:
3297e48354ceSNicholas Bellinger 	default:
3298e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_REJECTED;
3299e48354ceSNicholas Bellinger 	}
3300e48354ceSNicholas Bellinger }
3301e48354ceSNicholas Bellinger 
33022ec5a8c1SNicholas Bellinger void
33032ec5a8c1SNicholas Bellinger iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
33042ec5a8c1SNicholas Bellinger 			  struct iscsi_tm_rsp *hdr)
3305e48354ceSNicholas Bellinger {
3306e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
3307e48354ceSNicholas Bellinger 
3308e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_TMFUNC_RSP;
33097ae0b103SNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
3310e48354ceSNicholas Bellinger 	hdr->response		= iscsit_convert_tcm_tmr_rsp(se_tmr);
331166c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3312e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3313e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3314e48354ceSNicholas Bellinger 
3315e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3316e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3317109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3318e48354ceSNicholas Bellinger 
33192ec5a8c1SNicholas Bellinger 	pr_debug("Built Task Management Response ITT: 0x%08x,"
33202ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
33212ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid);
33222ec5a8c1SNicholas Bellinger }
33232ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_task_mgt_rsp);
33242ec5a8c1SNicholas Bellinger 
33252ec5a8c1SNicholas Bellinger static int
33262ec5a8c1SNicholas Bellinger iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
33272ec5a8c1SNicholas Bellinger {
33282ec5a8c1SNicholas Bellinger 	struct iscsi_tm_rsp *hdr = (struct iscsi_tm_rsp *)&cmd->pdu[0];
33292ec5a8c1SNicholas Bellinger 
33302ec5a8c1SNicholas Bellinger 	iscsit_build_task_mgt_rsp(cmd, conn, hdr);
33312ec5a8c1SNicholas Bellinger 
33322854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
3333e48354ceSNicholas Bellinger }
3334e48354ceSNicholas Bellinger 
33358b1e1244SAndy Grover #define SENDTARGETS_BUF_LIMIT 32768U
33368b1e1244SAndy Grover 
333722c7aaa5SSagi Grimberg static int
333822c7aaa5SSagi Grimberg iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
3339e4f4e801SSagi Grimberg 				  enum iscsit_transport_type network_transport,
3340e4f4e801SSagi Grimberg 				  int skip_bytes, bool *completed)
3341e48354ceSNicholas Bellinger {
3342e48354ceSNicholas Bellinger 	char *payload = NULL;
3343e48354ceSNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
3344e48354ceSNicholas Bellinger 	struct iscsi_portal_group *tpg;
3345e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn;
3346e48354ceSNicholas Bellinger 	struct iscsi_tpg_np *tpg_np;
3347e48354ceSNicholas Bellinger 	int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
33482dd1d53fSThomas Glanzmann 	int target_name_printed;
33498b1e1244SAndy Grover 	unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
33506665889cSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
3351a6415cddSDavid Disseldorp 	bool active;
3352e48354ceSNicholas Bellinger 
3353be7dcfb6SSagi Grimberg 	buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength,
33548b1e1244SAndy Grover 			 SENDTARGETS_BUF_LIMIT);
3355e48354ceSNicholas Bellinger 
3356e48354ceSNicholas Bellinger 	payload = kzalloc(buffer_len, GFP_KERNEL);
3357c46e22f1SMarkus Elfring 	if (!payload)
3358e48354ceSNicholas Bellinger 		return -ENOMEM;
3359c46e22f1SMarkus Elfring 
33606665889cSNicholas Bellinger 	/*
33618060b8ddSAndy Grover 	 * Locate pointer to iqn./eui. string for ICF_SENDTARGETS_SINGLE
33626665889cSNicholas Bellinger 	 * explicit case..
33636665889cSNicholas Bellinger 	 */
33648060b8ddSAndy Grover 	if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) {
33656665889cSNicholas Bellinger 		text_ptr = strchr(text_in, '=');
33666665889cSNicholas Bellinger 		if (!text_ptr) {
33676665889cSNicholas Bellinger 			pr_err("Unable to locate '=' string in text_in:"
33686665889cSNicholas Bellinger 			       " %s\n", text_in);
33694f45d320SDan Carpenter 			kfree(payload);
33706665889cSNicholas Bellinger 			return -EINVAL;
33716665889cSNicholas Bellinger 		}
33726665889cSNicholas Bellinger 		/*
33736665889cSNicholas Bellinger 		 * Skip over '=' character..
33746665889cSNicholas Bellinger 		 */
33756665889cSNicholas Bellinger 		text_ptr += 1;
33766665889cSNicholas Bellinger 	}
3377e48354ceSNicholas Bellinger 
3378e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
3379e48354ceSNicholas Bellinger 	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
33808060b8ddSAndy Grover 		if ((cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) &&
33816665889cSNicholas Bellinger 		     strcmp(tiqn->tiqn, text_ptr)) {
33826665889cSNicholas Bellinger 			continue;
33836665889cSNicholas Bellinger 		}
33846665889cSNicholas Bellinger 
33852dd1d53fSThomas Glanzmann 		target_name_printed = 0;
3386e48354ceSNicholas Bellinger 
3387e48354ceSNicholas Bellinger 		spin_lock(&tiqn->tiqn_tpg_lock);
3388e48354ceSNicholas Bellinger 		list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
3389e48354ceSNicholas Bellinger 
33902dd1d53fSThomas Glanzmann 			/* If demo_mode_discovery=0 and generate_node_acls=0
33912dd1d53fSThomas Glanzmann 			 * (demo mode dislabed) do not return
33922dd1d53fSThomas Glanzmann 			 * TargetName+TargetAddress unless a NodeACL exists.
33932dd1d53fSThomas Glanzmann 			 */
33942dd1d53fSThomas Glanzmann 
33952dd1d53fSThomas Glanzmann 			if ((tpg->tpg_attrib.generate_node_acls == 0) &&
33962dd1d53fSThomas Glanzmann 			    (tpg->tpg_attrib.demo_mode_discovery == 0) &&
339721aaa23bSNicholas Bellinger 			    (!target_tpg_has_node_acl(&tpg->tpg_se_tpg,
33982dd1d53fSThomas Glanzmann 				cmd->conn->sess->sess_ops->InitiatorName))) {
33992dd1d53fSThomas Glanzmann 				continue;
34002dd1d53fSThomas Glanzmann 			}
34012dd1d53fSThomas Glanzmann 
3402e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_state_lock);
3403a6415cddSDavid Disseldorp 			active = (tpg->tpg_state == TPG_STATE_ACTIVE);
3404e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_state_lock);
3405a6415cddSDavid Disseldorp 
3406a6415cddSDavid Disseldorp 			if (!active && tpg->tpg_attrib.tpg_enabled_sendtargets)
3407e48354ceSNicholas Bellinger 				continue;
3408e48354ceSNicholas Bellinger 
3409e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_np_lock);
3410e48354ceSNicholas Bellinger 			list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
3411e48354ceSNicholas Bellinger 						tpg_np_list) {
34122f9bc894SNicholas Bellinger 				struct iscsi_np *np = tpg_np->tpg_np;
341313a3cf08SAndy Grover 				struct sockaddr_storage *sockaddr;
34142f9bc894SNicholas Bellinger 
341522c7aaa5SSagi Grimberg 				if (np->np_network_transport != network_transport)
341622c7aaa5SSagi Grimberg 					continue;
341722c7aaa5SSagi Grimberg 
34182dd1d53fSThomas Glanzmann 				if (!target_name_printed) {
34192dd1d53fSThomas Glanzmann 					len = sprintf(buf, "TargetName=%s",
34202dd1d53fSThomas Glanzmann 						      tiqn->tiqn);
34212dd1d53fSThomas Glanzmann 					len += 1;
34222dd1d53fSThomas Glanzmann 
34232dd1d53fSThomas Glanzmann 					if ((len + payload_len) > buffer_len) {
34242dd1d53fSThomas Glanzmann 						spin_unlock(&tpg->tpg_np_lock);
34252dd1d53fSThomas Glanzmann 						spin_unlock(&tiqn->tiqn_tpg_lock);
34262dd1d53fSThomas Glanzmann 						end_of_buf = 1;
34272dd1d53fSThomas Glanzmann 						goto eob;
34282dd1d53fSThomas Glanzmann 					}
3429e4f4e801SSagi Grimberg 
3430e4f4e801SSagi Grimberg 					if (skip_bytes && len <= skip_bytes) {
3431e4f4e801SSagi Grimberg 						skip_bytes -= len;
3432e4f4e801SSagi Grimberg 					} else {
34332dd1d53fSThomas Glanzmann 						memcpy(payload + payload_len, buf, len);
34342dd1d53fSThomas Glanzmann 						payload_len += len;
34352dd1d53fSThomas Glanzmann 						target_name_printed = 1;
3436e4f4e801SSagi Grimberg 						if (len > skip_bytes)
3437e4f4e801SSagi Grimberg 							skip_bytes = 0;
3438e4f4e801SSagi Grimberg 					}
34392dd1d53fSThomas Glanzmann 				}
34402dd1d53fSThomas Glanzmann 
34417bfca0cfSSagi Grimberg 				if (inet_addr_is_any((struct sockaddr *)&np->np_sockaddr))
344269d75574SAndy Grover 					sockaddr = &conn->local_sockaddr;
34431997e625SAndy Grover 				else
344469d75574SAndy Grover 					sockaddr = &np->np_sockaddr;
34451997e625SAndy Grover 
344676c28f1fSAndy Grover 				len = sprintf(buf, "TargetAddress="
344776c28f1fSAndy Grover 					      "%pISpc,%hu",
344869d75574SAndy Grover 					      sockaddr,
3449e48354ceSNicholas Bellinger 					      tpg->tpgt);
3450e48354ceSNicholas Bellinger 				len += 1;
3451e48354ceSNicholas Bellinger 
3452e48354ceSNicholas Bellinger 				if ((len + payload_len) > buffer_len) {
3453e48354ceSNicholas Bellinger 					spin_unlock(&tpg->tpg_np_lock);
3454e48354ceSNicholas Bellinger 					spin_unlock(&tiqn->tiqn_tpg_lock);
3455e48354ceSNicholas Bellinger 					end_of_buf = 1;
3456e48354ceSNicholas Bellinger 					goto eob;
3457e48354ceSNicholas Bellinger 				}
3458e4f4e801SSagi Grimberg 
3459e4f4e801SSagi Grimberg 				if (skip_bytes && len <= skip_bytes) {
3460e4f4e801SSagi Grimberg 					skip_bytes -= len;
3461e4f4e801SSagi Grimberg 				} else {
34628359cf43SJörn Engel 					memcpy(payload + payload_len, buf, len);
3463e48354ceSNicholas Bellinger 					payload_len += len;
3464e4f4e801SSagi Grimberg 					if (len > skip_bytes)
3465e4f4e801SSagi Grimberg 						skip_bytes = 0;
3466e4f4e801SSagi Grimberg 				}
3467e48354ceSNicholas Bellinger 			}
3468e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_np_lock);
3469e48354ceSNicholas Bellinger 		}
3470e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_tpg_lock);
3471e48354ceSNicholas Bellinger eob:
3472e4f4e801SSagi Grimberg 		if (end_of_buf) {
3473e4f4e801SSagi Grimberg 			*completed = false;
3474e48354ceSNicholas Bellinger 			break;
3475e4f4e801SSagi Grimberg 		}
34766665889cSNicholas Bellinger 
34778060b8ddSAndy Grover 		if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE)
34786665889cSNicholas Bellinger 			break;
3479e48354ceSNicholas Bellinger 	}
3480e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
3481e48354ceSNicholas Bellinger 
3482e48354ceSNicholas Bellinger 	cmd->buf_ptr = payload;
3483e48354ceSNicholas Bellinger 
3484e48354ceSNicholas Bellinger 	return payload_len;
3485e48354ceSNicholas Bellinger }
3486e48354ceSNicholas Bellinger 
3487889c8a68SNicholas Bellinger int
3488889c8a68SNicholas Bellinger iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
348922c7aaa5SSagi Grimberg 		      struct iscsi_text_rsp *hdr,
349022c7aaa5SSagi Grimberg 		      enum iscsit_transport_type network_transport)
3491e48354ceSNicholas Bellinger {
3492889c8a68SNicholas Bellinger 	int text_length, padding;
3493e4f4e801SSagi Grimberg 	bool completed = true;
3494e48354ceSNicholas Bellinger 
3495e4f4e801SSagi Grimberg 	text_length = iscsit_build_sendtargets_response(cmd, network_transport,
3496e4f4e801SSagi Grimberg 							cmd->read_data_done,
3497e4f4e801SSagi Grimberg 							&completed);
3498e48354ceSNicholas Bellinger 	if (text_length < 0)
3499e48354ceSNicholas Bellinger 		return text_length;
3500e48354ceSNicholas Bellinger 
3501e4f4e801SSagi Grimberg 	if (completed) {
3502310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
3503e4f4e801SSagi Grimberg 	} else {
3504310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_TEXT_CONTINUE;
3505e4f4e801SSagi Grimberg 		cmd->read_data_done += text_length;
3506e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF)
3507e4f4e801SSagi Grimberg 			cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
3508e4f4e801SSagi Grimberg 	}
3509e4f4e801SSagi Grimberg 	hdr->opcode = ISCSI_OP_TEXT_RSP;
3510889c8a68SNicholas Bellinger 	padding = ((-text_length) & 3);
3511e48354ceSNicholas Bellinger 	hton24(hdr->dlength, text_length);
351266c7db68SChristoph Hellwig 	hdr->itt = cmd->init_task_tag;
3513e48354ceSNicholas Bellinger 	hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
3514e48354ceSNicholas Bellinger 	cmd->stat_sn = conn->stat_sn++;
3515e48354ceSNicholas Bellinger 	hdr->statsn = cpu_to_be32(cmd->stat_sn);
3516e48354ceSNicholas Bellinger 
3517e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3518e4f4e801SSagi Grimberg 	/*
3519e4f4e801SSagi Grimberg 	 * Reset maxcmdsn_inc in multi-part text payload exchanges to
3520e4f4e801SSagi Grimberg 	 * correctly increment MaxCmdSN for each response answering a
3521e4f4e801SSagi Grimberg 	 * non immediate text request with a valid CmdSN.
3522e4f4e801SSagi Grimberg 	 */
3523e4f4e801SSagi Grimberg 	cmd->maxcmdsn_inc = 0;
3524e48354ceSNicholas Bellinger 	hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
3525109e2381SRoland Dreier 	hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3526e48354ceSNicholas Bellinger 
3527e4f4e801SSagi Grimberg 	pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
3528e4f4e801SSagi Grimberg 		" Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
3529e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag, cmd->stat_sn, text_length, conn->cid,
3530e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_CMD_FINAL),
3531e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE));
3532e48354ceSNicholas Bellinger 
3533889c8a68SNicholas Bellinger 	return text_length + padding;
3534889c8a68SNicholas Bellinger }
3535889c8a68SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_text_rsp);
3536889c8a68SNicholas Bellinger 
3537889c8a68SNicholas Bellinger static int iscsit_send_text_rsp(
3538889c8a68SNicholas Bellinger 	struct iscsi_cmd *cmd,
3539889c8a68SNicholas Bellinger 	struct iscsi_conn *conn)
3540889c8a68SNicholas Bellinger {
3541889c8a68SNicholas Bellinger 	struct iscsi_text_rsp *hdr = (struct iscsi_text_rsp *)cmd->pdu;
35422854bb23SVarun Prakash 	int text_length;
3543889c8a68SNicholas Bellinger 
3544864e504aSVarun Prakash 	text_length = iscsit_build_text_rsp(cmd, conn, hdr,
3545864e504aSVarun Prakash 				conn->conn_transport->transport_type);
35462854bb23SVarun Prakash 	if (text_length < 0)
35472854bb23SVarun Prakash 		return text_length;
3548889c8a68SNicholas Bellinger 
35492854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35502854bb23SVarun Prakash 						     cmd->buf_ptr,
35512854bb23SVarun Prakash 						     text_length);
3552e48354ceSNicholas Bellinger }
3553e48354ceSNicholas Bellinger 
35542ec5a8c1SNicholas Bellinger void
35552ec5a8c1SNicholas Bellinger iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
35562ec5a8c1SNicholas Bellinger 		    struct iscsi_reject *hdr)
3557e48354ceSNicholas Bellinger {
3558e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_REJECT;
3559ba159914SNicholas Bellinger 	hdr->reason		= cmd->reject_reason;
3560e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3561e48354ceSNicholas Bellinger 	hton24(hdr->dlength, ISCSI_HDR_LEN);
356250e5c87dSChristoph Hellwig 	hdr->ffffffff		= cpu_to_be32(0xffffffff);
3563e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3564e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3565e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3566109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3567e48354ceSNicholas Bellinger 
35682ec5a8c1SNicholas Bellinger }
35692ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_reject);
3570e48354ceSNicholas Bellinger 
35712ec5a8c1SNicholas Bellinger static int iscsit_send_reject(
35722ec5a8c1SNicholas Bellinger 	struct iscsi_cmd *cmd,
35732ec5a8c1SNicholas Bellinger 	struct iscsi_conn *conn)
35742ec5a8c1SNicholas Bellinger {
3575bfbdb31dSNicholas Bellinger 	struct iscsi_reject *hdr = (struct iscsi_reject *)&cmd->pdu[0];
35762ec5a8c1SNicholas Bellinger 
3577bfbdb31dSNicholas Bellinger 	iscsit_build_reject(cmd, conn, hdr);
35782ec5a8c1SNicholas Bellinger 
3579e48354ceSNicholas Bellinger 	pr_debug("Built Reject PDU StatSN: 0x%08x, Reason: 0x%02x,"
3580e48354ceSNicholas Bellinger 		" CID: %hu\n", ntohl(hdr->statsn), hdr->reason, conn->cid);
3581e48354ceSNicholas Bellinger 
35822854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35832854bb23SVarun Prakash 						     cmd->buf_ptr,
35842854bb23SVarun Prakash 						     ISCSI_HDR_LEN);
3585e48354ceSNicholas Bellinger }
3586e48354ceSNicholas Bellinger 
3587e48354ceSNicholas Bellinger void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
3588e48354ceSNicholas Bellinger {
3589e48354ceSNicholas Bellinger 	int ord, cpu;
3590e48354ceSNicholas Bellinger 	/*
359188dcd2daSNicholas Bellinger 	 * bitmap_id is assigned from iscsit_global->ts_bitmap from
359288dcd2daSNicholas Bellinger 	 * within iscsit_start_kthreads()
3593e48354ceSNicholas Bellinger 	 *
359488dcd2daSNicholas Bellinger 	 * Here we use bitmap_id to determine which CPU that this
359588dcd2daSNicholas Bellinger 	 * iSCSI connection's RX/TX threads will be scheduled to
3596e48354ceSNicholas Bellinger 	 * execute upon.
3597e48354ceSNicholas Bellinger 	 */
359888dcd2daSNicholas Bellinger 	ord = conn->bitmap_id % cpumask_weight(cpu_online_mask);
3599e48354ceSNicholas Bellinger 	for_each_online_cpu(cpu) {
3600e48354ceSNicholas Bellinger 		if (ord-- == 0) {
3601e48354ceSNicholas Bellinger 			cpumask_set_cpu(cpu, conn->conn_cpumask);
3602e48354ceSNicholas Bellinger 			return;
3603e48354ceSNicholas Bellinger 		}
3604e48354ceSNicholas Bellinger 	}
3605e48354ceSNicholas Bellinger 	/*
3606e48354ceSNicholas Bellinger 	 * This should never be reached..
3607e48354ceSNicholas Bellinger 	 */
3608e48354ceSNicholas Bellinger 	dump_stack();
3609e48354ceSNicholas Bellinger 	cpumask_setall(conn->conn_cpumask);
3610e48354ceSNicholas Bellinger }
3611e48354ceSNicholas Bellinger 
3612d2faaefbSVarun Prakash int
36132ec5a8c1SNicholas Bellinger iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
3614e48354ceSNicholas Bellinger {
36152ec5a8c1SNicholas Bellinger 	int ret;
36162ec5a8c1SNicholas Bellinger 
36172ec5a8c1SNicholas Bellinger 	switch (state) {
36182ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_R2T:
36192ec5a8c1SNicholas Bellinger 		ret = iscsit_send_r2t(cmd, conn);
36202ec5a8c1SNicholas Bellinger 		if (ret < 0)
36212ec5a8c1SNicholas Bellinger 			goto err;
36222ec5a8c1SNicholas Bellinger 		break;
36232ec5a8c1SNicholas Bellinger 	case ISTATE_REMOVE:
36242ec5a8c1SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
36255159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
36262ec5a8c1SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
36272ec5a8c1SNicholas Bellinger 
3628aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
36292ec5a8c1SNicholas Bellinger 		break;
36302ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_WANT_RESPONSE:
36312ec5a8c1SNicholas Bellinger 		iscsit_mod_nopin_response_timer(conn);
36322ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 1);
36332ec5a8c1SNicholas Bellinger 		if (ret < 0)
36342ec5a8c1SNicholas Bellinger 			goto err;
36352ec5a8c1SNicholas Bellinger 		break;
36362ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_NO_RESPONSE:
36372ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 0);
36382ec5a8c1SNicholas Bellinger 		if (ret < 0)
36392ec5a8c1SNicholas Bellinger 			goto err;
36402ec5a8c1SNicholas Bellinger 		break;
36412ec5a8c1SNicholas Bellinger 	default:
36422ec5a8c1SNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
36432ec5a8c1SNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
36442ec5a8c1SNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag, state,
36452ec5a8c1SNicholas Bellinger 		       conn->cid);
36462ec5a8c1SNicholas Bellinger 		goto err;
36472ec5a8c1SNicholas Bellinger 	}
36482ec5a8c1SNicholas Bellinger 
36492ec5a8c1SNicholas Bellinger 	return 0;
36502ec5a8c1SNicholas Bellinger 
36512ec5a8c1SNicholas Bellinger err:
36522ec5a8c1SNicholas Bellinger 	return -1;
36532ec5a8c1SNicholas Bellinger }
3654d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_immediate_queue);
36552ec5a8c1SNicholas Bellinger 
36562ec5a8c1SNicholas Bellinger static int
36572ec5a8c1SNicholas Bellinger iscsit_handle_immediate_queue(struct iscsi_conn *conn)
36582ec5a8c1SNicholas Bellinger {
36592ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
36606f3c0e69SAndy Grover 	struct iscsi_queue_req *qr;
36616f3c0e69SAndy Grover 	struct iscsi_cmd *cmd;
3662e48354ceSNicholas Bellinger 	u8 state;
36636f3c0e69SAndy Grover 	int ret;
3664e48354ceSNicholas Bellinger 
3665c6037cc5SAndy Grover 	while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) {
3666e48354ceSNicholas Bellinger 		atomic_set(&conn->check_immediate_queue, 0);
3667e48354ceSNicholas Bellinger 		cmd = qr->cmd;
3668e48354ceSNicholas Bellinger 		state = qr->state;
3669e48354ceSNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
3670e48354ceSNicholas Bellinger 
36712ec5a8c1SNicholas Bellinger 		ret = t->iscsit_immediate_queue(conn, cmd, state);
36726f3c0e69SAndy Grover 		if (ret < 0)
36732ec5a8c1SNicholas Bellinger 			return ret;
3674e48354ceSNicholas Bellinger 	}
3675e48354ceSNicholas Bellinger 
36766f3c0e69SAndy Grover 	return 0;
3677e48354ceSNicholas Bellinger }
36786f3c0e69SAndy Grover 
3679d2faaefbSVarun Prakash int
36802ec5a8c1SNicholas Bellinger iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
36816f3c0e69SAndy Grover {
36826f3c0e69SAndy Grover 	int ret;
3683e48354ceSNicholas Bellinger 
3684e48354ceSNicholas Bellinger check_rsp_state:
3685e48354ceSNicholas Bellinger 	switch (state) {
3686e48354ceSNicholas Bellinger 	case ISTATE_SEND_DATAIN:
36872ec5a8c1SNicholas Bellinger 		ret = iscsit_send_datain(cmd, conn);
36886f3c0e69SAndy Grover 		if (ret < 0)
36896f3c0e69SAndy Grover 			goto err;
36906f3c0e69SAndy Grover 		else if (!ret)
36916f3c0e69SAndy Grover 			/* more drs */
36926f3c0e69SAndy Grover 			goto check_rsp_state;
36936f3c0e69SAndy Grover 		else if (ret == 1) {
36946f3c0e69SAndy Grover 			/* all done */
36956f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
36966f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SENT_STATUS;
3697e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->istate_lock);
3698fd3a9025SNicholas Bellinger 
3699fd3a9025SNicholas Bellinger 			if (atomic_read(&conn->check_immediate_queue))
3700fd3a9025SNicholas Bellinger 				return 1;
3701fd3a9025SNicholas Bellinger 
37022ec5a8c1SNicholas Bellinger 			return 0;
37036f3c0e69SAndy Grover 		} else if (ret == 2) {
37046f3c0e69SAndy Grover 			/* Still must send status,
37056f3c0e69SAndy Grover 			   SCF_TRANSPORT_TASK_SENSE was set */
37066f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
37076f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SEND_STATUS;
37086f3c0e69SAndy Grover 			spin_unlock_bh(&cmd->istate_lock);
37096f3c0e69SAndy Grover 			state = ISTATE_SEND_STATUS;
37106f3c0e69SAndy Grover 			goto check_rsp_state;
37116f3c0e69SAndy Grover 		}
37126f3c0e69SAndy Grover 
3713e48354ceSNicholas Bellinger 		break;
3714e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3715e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
37162ec5a8c1SNicholas Bellinger 		ret = iscsit_send_response(cmd, conn);
3717e48354ceSNicholas Bellinger 		break;
3718e48354ceSNicholas Bellinger 	case ISTATE_SEND_LOGOUTRSP:
37192ec5a8c1SNicholas Bellinger 		ret = iscsit_send_logout(cmd, conn);
3720e48354ceSNicholas Bellinger 		break;
3721e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3722e48354ceSNicholas Bellinger 		ret = iscsit_send_conn_drop_async_message(
3723e48354ceSNicholas Bellinger 			cmd, conn);
3724e48354ceSNicholas Bellinger 		break;
3725e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
37262ec5a8c1SNicholas Bellinger 		ret = iscsit_send_nopin(cmd, conn);
3727e48354ceSNicholas Bellinger 		break;
3728e48354ceSNicholas Bellinger 	case ISTATE_SEND_REJECT:
3729e48354ceSNicholas Bellinger 		ret = iscsit_send_reject(cmd, conn);
3730e48354ceSNicholas Bellinger 		break;
3731e48354ceSNicholas Bellinger 	case ISTATE_SEND_TASKMGTRSP:
3732e48354ceSNicholas Bellinger 		ret = iscsit_send_task_mgt_rsp(cmd, conn);
3733e48354ceSNicholas Bellinger 		if (ret != 0)
3734e48354ceSNicholas Bellinger 			break;
3735e48354ceSNicholas Bellinger 		ret = iscsit_tmr_post_handler(cmd, conn);
3736e48354ceSNicholas Bellinger 		if (ret != 0)
3737e48354ceSNicholas Bellinger 			iscsit_fall_back_to_erl0(conn->sess);
3738e48354ceSNicholas Bellinger 		break;
3739e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
3740e48354ceSNicholas Bellinger 		ret = iscsit_send_text_rsp(cmd, conn);
3741e48354ceSNicholas Bellinger 		break;
3742e48354ceSNicholas Bellinger 	default:
3743e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3744e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3745e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3746e48354ceSNicholas Bellinger 		       state, conn->cid);
37476f3c0e69SAndy Grover 		goto err;
3748e48354ceSNicholas Bellinger 	}
3749c6037cc5SAndy Grover 	if (ret < 0)
37506f3c0e69SAndy Grover 		goto err;
3751e48354ceSNicholas Bellinger 
3752e48354ceSNicholas Bellinger 	switch (state) {
37536f3c0e69SAndy Grover 	case ISTATE_SEND_LOGOUTRSP:
37546f3c0e69SAndy Grover 		if (!iscsit_logout_post_handler(cmd, conn))
375588dcd2daSNicholas Bellinger 			return -ECONNRESET;
37566f3c0e69SAndy Grover 		/* fall through */
3757e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3758e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3759e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
3760e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
3761e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
37626f3c0e69SAndy Grover 	case ISTATE_SEND_TASKMGTRSP:
3763ba159914SNicholas Bellinger 	case ISTATE_SEND_REJECT:
37646f3c0e69SAndy Grover 		spin_lock_bh(&cmd->istate_lock);
37656f3c0e69SAndy Grover 		cmd->i_state = ISTATE_SENT_STATUS;
37666f3c0e69SAndy Grover 		spin_unlock_bh(&cmd->istate_lock);
3767e48354ceSNicholas Bellinger 		break;
3768e48354ceSNicholas Bellinger 	default:
3769e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3770e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3771e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3772e48354ceSNicholas Bellinger 		       cmd->i_state, conn->cid);
37736f3c0e69SAndy Grover 		goto err;
3774e48354ceSNicholas Bellinger 	}
3775e48354ceSNicholas Bellinger 
3776e48354ceSNicholas Bellinger 	if (atomic_read(&conn->check_immediate_queue))
3777fd3a9025SNicholas Bellinger 		return 1;
37786f3c0e69SAndy Grover 
37796f3c0e69SAndy Grover 	return 0;
37806f3c0e69SAndy Grover 
37816f3c0e69SAndy Grover err:
37826f3c0e69SAndy Grover 	return -1;
37836f3c0e69SAndy Grover }
3784d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_response_queue);
37856f3c0e69SAndy Grover 
37862ec5a8c1SNicholas Bellinger static int iscsit_handle_response_queue(struct iscsi_conn *conn)
37872ec5a8c1SNicholas Bellinger {
37882ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
37892ec5a8c1SNicholas Bellinger 	struct iscsi_queue_req *qr;
37902ec5a8c1SNicholas Bellinger 	struct iscsi_cmd *cmd;
37912ec5a8c1SNicholas Bellinger 	u8 state;
37922ec5a8c1SNicholas Bellinger 	int ret;
37932ec5a8c1SNicholas Bellinger 
37942ec5a8c1SNicholas Bellinger 	while ((qr = iscsit_get_cmd_from_response_queue(conn))) {
37952ec5a8c1SNicholas Bellinger 		cmd = qr->cmd;
37962ec5a8c1SNicholas Bellinger 		state = qr->state;
37972ec5a8c1SNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
37982ec5a8c1SNicholas Bellinger 
37992ec5a8c1SNicholas Bellinger 		ret = t->iscsit_response_queue(conn, cmd, state);
38002ec5a8c1SNicholas Bellinger 		if (ret == 1 || ret < 0)
38012ec5a8c1SNicholas Bellinger 			return ret;
38022ec5a8c1SNicholas Bellinger 	}
38032ec5a8c1SNicholas Bellinger 
38042ec5a8c1SNicholas Bellinger 	return 0;
38052ec5a8c1SNicholas Bellinger }
38062ec5a8c1SNicholas Bellinger 
38076f3c0e69SAndy Grover int iscsi_target_tx_thread(void *arg)
38086f3c0e69SAndy Grover {
38096f3c0e69SAndy Grover 	int ret = 0;
381088dcd2daSNicholas Bellinger 	struct iscsi_conn *conn = arg;
38115e0cf5e6SJiang Yi 	bool conn_freed = false;
38125e0cf5e6SJiang Yi 
38136f3c0e69SAndy Grover 	/*
38146f3c0e69SAndy Grover 	 * Allow ourselves to be interrupted by SIGINT so that a
38156f3c0e69SAndy Grover 	 * connection recovery / failure event can be triggered externally.
38166f3c0e69SAndy Grover 	 */
38176f3c0e69SAndy Grover 	allow_signal(SIGINT);
38186f3c0e69SAndy Grover 
38196f3c0e69SAndy Grover 	while (!kthread_should_stop()) {
38206f3c0e69SAndy Grover 		/*
38216f3c0e69SAndy Grover 		 * Ensure that both TX and RX per connection kthreads
38226f3c0e69SAndy Grover 		 * are scheduled to run on the same CPU.
38236f3c0e69SAndy Grover 		 */
38246f3c0e69SAndy Grover 		iscsit_thread_check_cpumask(conn, current, 1);
38256f3c0e69SAndy Grover 
3826d5627acbSRoland Dreier 		wait_event_interruptible(conn->queues_wq,
382788dcd2daSNicholas Bellinger 					 !iscsit_conn_all_queues_empty(conn));
38286f3c0e69SAndy Grover 
382988dcd2daSNicholas Bellinger 		if (signal_pending(current))
38306f3c0e69SAndy Grover 			goto transport_err;
38316f3c0e69SAndy Grover 
3832fd3a9025SNicholas Bellinger get_immediate:
38332ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_immediate_queue(conn);
38346f3c0e69SAndy Grover 		if (ret < 0)
38356f3c0e69SAndy Grover 			goto transport_err;
38366f3c0e69SAndy Grover 
38372ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_response_queue(conn);
38385e0cf5e6SJiang Yi 		if (ret == 1) {
3839fd3a9025SNicholas Bellinger 			goto get_immediate;
38405e0cf5e6SJiang Yi 		} else if (ret == -ECONNRESET) {
38415e0cf5e6SJiang Yi 			conn_freed = true;
384288dcd2daSNicholas Bellinger 			goto out;
38435e0cf5e6SJiang Yi 		} else if (ret < 0) {
38446f3c0e69SAndy Grover 			goto transport_err;
3845e48354ceSNicholas Bellinger 		}
38465e0cf5e6SJiang Yi 	}
3847e48354ceSNicholas Bellinger 
3848e48354ceSNicholas Bellinger transport_err:
3849e5419865SNicholas Bellinger 	/*
3850e5419865SNicholas Bellinger 	 * Avoid the normal connection failure code-path if this connection
3851e5419865SNicholas Bellinger 	 * is still within LOGIN mode, and iscsi_np process context is
3852e5419865SNicholas Bellinger 	 * responsible for cleaning up the early connection failure.
3853e5419865SNicholas Bellinger 	 */
3854e5419865SNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
38555e0cf5e6SJiang Yi 		iscsit_take_action_for_connection_exit(conn, &conn_freed);
3856e48354ceSNicholas Bellinger out:
38575e0cf5e6SJiang Yi 	if (!conn_freed) {
38585e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
38595e0cf5e6SJiang Yi 			msleep(100);
38605e0cf5e6SJiang Yi 		}
38615e0cf5e6SJiang Yi 	}
3862e48354ceSNicholas Bellinger 	return 0;
3863e48354ceSNicholas Bellinger }
3864e48354ceSNicholas Bellinger 
38653e1c81a9SNicholas Bellinger static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
38663e1c81a9SNicholas Bellinger {
38673e1c81a9SNicholas Bellinger 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)buf;
38683e1c81a9SNicholas Bellinger 	struct iscsi_cmd *cmd;
38693e1c81a9SNicholas Bellinger 	int ret = 0;
38703e1c81a9SNicholas Bellinger 
38713e1c81a9SNicholas Bellinger 	switch (hdr->opcode & ISCSI_OPCODE_MASK) {
38723e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_CMD:
3873676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38743e1c81a9SNicholas Bellinger 		if (!cmd)
3875ba159914SNicholas Bellinger 			goto reject;
38763e1c81a9SNicholas Bellinger 
38773e1c81a9SNicholas Bellinger 		ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
38783e1c81a9SNicholas Bellinger 		break;
38793e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_DATA_OUT:
38803e1c81a9SNicholas Bellinger 		ret = iscsit_handle_data_out(conn, buf);
38813e1c81a9SNicholas Bellinger 		break;
38823e1c81a9SNicholas Bellinger 	case ISCSI_OP_NOOP_OUT:
38833e1c81a9SNicholas Bellinger 		cmd = NULL;
38843e1c81a9SNicholas Bellinger 		if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
3885676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38863e1c81a9SNicholas Bellinger 			if (!cmd)
3887ba159914SNicholas Bellinger 				goto reject;
38883e1c81a9SNicholas Bellinger 		}
38893e1c81a9SNicholas Bellinger 		ret = iscsit_handle_nop_out(conn, cmd, buf);
38903e1c81a9SNicholas Bellinger 		break;
38913e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_TMFUNC:
3892676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38933e1c81a9SNicholas Bellinger 		if (!cmd)
3894ba159914SNicholas Bellinger 			goto reject;
38953e1c81a9SNicholas Bellinger 
38963e1c81a9SNicholas Bellinger 		ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
38973e1c81a9SNicholas Bellinger 		break;
38983e1c81a9SNicholas Bellinger 	case ISCSI_OP_TEXT:
3899e4f4e801SSagi Grimberg 		if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
3900e4f4e801SSagi Grimberg 			cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
3901e4f4e801SSagi Grimberg 			if (!cmd)
3902e4f4e801SSagi Grimberg 				goto reject;
3903e4f4e801SSagi Grimberg 		} else {
3904676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
390564534aa7SNicholas Bellinger 			if (!cmd)
3906ba159914SNicholas Bellinger 				goto reject;
3907e4f4e801SSagi Grimberg 		}
390864534aa7SNicholas Bellinger 
390964534aa7SNicholas Bellinger 		ret = iscsit_handle_text_cmd(conn, cmd, buf);
39103e1c81a9SNicholas Bellinger 		break;
39113e1c81a9SNicholas Bellinger 	case ISCSI_OP_LOGOUT:
3912676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
39133e1c81a9SNicholas Bellinger 		if (!cmd)
3914ba159914SNicholas Bellinger 			goto reject;
39153e1c81a9SNicholas Bellinger 
39163e1c81a9SNicholas Bellinger 		ret = iscsit_handle_logout_cmd(conn, cmd, buf);
39173e1c81a9SNicholas Bellinger 		if (ret > 0)
39183e1c81a9SNicholas Bellinger 			wait_for_completion_timeout(&conn->conn_logout_comp,
39193e1c81a9SNicholas Bellinger 					SECONDS_FOR_LOGOUT_COMP * HZ);
39203e1c81a9SNicholas Bellinger 		break;
39213e1c81a9SNicholas Bellinger 	case ISCSI_OP_SNACK:
39223e1c81a9SNicholas Bellinger 		ret = iscsit_handle_snack(conn, buf);
39233e1c81a9SNicholas Bellinger 		break;
39243e1c81a9SNicholas Bellinger 	default:
39253e1c81a9SNicholas Bellinger 		pr_err("Got unknown iSCSI OpCode: 0x%02x\n", hdr->opcode);
39263e1c81a9SNicholas Bellinger 		if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
39273e1c81a9SNicholas Bellinger 			pr_err("Cannot recover from unknown"
39283e1c81a9SNicholas Bellinger 			" opcode while ERL=0, closing iSCSI connection.\n");
39293e1c81a9SNicholas Bellinger 			return -1;
39303e1c81a9SNicholas Bellinger 		}
3931c04a6091SChristophe Vu-Brugier 		pr_err("Unable to recover from unknown opcode while OFMarker=No,"
3932c04a6091SChristophe Vu-Brugier 		       " closing iSCSI connection.\n");
3933c04a6091SChristophe Vu-Brugier 		ret = -1;
39343e1c81a9SNicholas Bellinger 		break;
39353e1c81a9SNicholas Bellinger 	}
39363e1c81a9SNicholas Bellinger 
39373e1c81a9SNicholas Bellinger 	return ret;
3938ba159914SNicholas Bellinger reject:
3939ba159914SNicholas Bellinger 	return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
39403e1c81a9SNicholas Bellinger }
39413e1c81a9SNicholas Bellinger 
3942ca82c2bdSNicholas Bellinger static bool iscsi_target_check_conn_state(struct iscsi_conn *conn)
3943ca82c2bdSNicholas Bellinger {
3944ca82c2bdSNicholas Bellinger 	bool ret;
3945ca82c2bdSNicholas Bellinger 
3946ca82c2bdSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
3947ca82c2bdSNicholas Bellinger 	ret = (conn->conn_state != TARG_CONN_STATE_LOGGED_IN);
3948ca82c2bdSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
3949ca82c2bdSNicholas Bellinger 
3950ca82c2bdSNicholas Bellinger 	return ret;
3951ca82c2bdSNicholas Bellinger }
3952ca82c2bdSNicholas Bellinger 
3953e8205ccaSVarun Prakash static void iscsit_get_rx_pdu(struct iscsi_conn *conn)
3954e48354ceSNicholas Bellinger {
3955e8205ccaSVarun Prakash 	int ret;
3956679fcae4SLaura Abbott 	u8 *buffer, opcode;
3957e48354ceSNicholas Bellinger 	u32 checksum = 0, digest = 0;
3958e48354ceSNicholas Bellinger 	struct kvec iov;
39593e1c81a9SNicholas Bellinger 
3960679fcae4SLaura Abbott 	buffer = kcalloc(ISCSI_HDR_LEN, sizeof(*buffer), GFP_KERNEL);
3961679fcae4SLaura Abbott 	if (!buffer)
3962679fcae4SLaura Abbott 		return;
3963679fcae4SLaura Abbott 
3964e48354ceSNicholas Bellinger 	while (!kthread_should_stop()) {
3965e48354ceSNicholas Bellinger 		/*
3966e48354ceSNicholas Bellinger 		 * Ensure that both TX and RX per connection kthreads
3967e48354ceSNicholas Bellinger 		 * are scheduled to run on the same CPU.
3968e48354ceSNicholas Bellinger 		 */
3969e48354ceSNicholas Bellinger 		iscsit_thread_check_cpumask(conn, current, 0);
3970e48354ceSNicholas Bellinger 
3971e48354ceSNicholas Bellinger 		memset(&iov, 0, sizeof(struct kvec));
3972e48354ceSNicholas Bellinger 
3973e48354ceSNicholas Bellinger 		iov.iov_base	= buffer;
3974e48354ceSNicholas Bellinger 		iov.iov_len	= ISCSI_HDR_LEN;
3975e48354ceSNicholas Bellinger 
3976e48354ceSNicholas Bellinger 		ret = rx_data(conn, &iov, 1, ISCSI_HDR_LEN);
3977e48354ceSNicholas Bellinger 		if (ret != ISCSI_HDR_LEN) {
3978e48354ceSNicholas Bellinger 			iscsit_rx_thread_wait_for_tcp(conn);
3979679fcae4SLaura Abbott 			break;
3980e48354ceSNicholas Bellinger 		}
3981e48354ceSNicholas Bellinger 
3982e48354ceSNicholas Bellinger 		if (conn->conn_ops->HeaderDigest) {
3983e48354ceSNicholas Bellinger 			iov.iov_base	= &digest;
3984e48354ceSNicholas Bellinger 			iov.iov_len	= ISCSI_CRC_LEN;
3985e48354ceSNicholas Bellinger 
3986e48354ceSNicholas Bellinger 			ret = rx_data(conn, &iov, 1, ISCSI_CRC_LEN);
3987e48354ceSNicholas Bellinger 			if (ret != ISCSI_CRC_LEN) {
3988e48354ceSNicholas Bellinger 				iscsit_rx_thread_wait_for_tcp(conn);
3989679fcae4SLaura Abbott 				break;
3990e48354ceSNicholas Bellinger 			}
3991e48354ceSNicholas Bellinger 
3992e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer,
3993e1dfb21fSBart Van Assche 						  ISCSI_HDR_LEN, 0, NULL,
3994e1dfb21fSBart Van Assche 						  &checksum);
3995e48354ceSNicholas Bellinger 
3996e48354ceSNicholas Bellinger 			if (digest != checksum) {
3997e48354ceSNicholas Bellinger 				pr_err("HeaderDigest CRC32C failed,"
3998e48354ceSNicholas Bellinger 					" received 0x%08x, computed 0x%08x\n",
3999e48354ceSNicholas Bellinger 					digest, checksum);
4000e48354ceSNicholas Bellinger 				/*
4001e48354ceSNicholas Bellinger 				 * Set the PDU to 0xff so it will intentionally
4002e48354ceSNicholas Bellinger 				 * hit default in the switch below.
4003e48354ceSNicholas Bellinger 				 */
4004e48354ceSNicholas Bellinger 				memset(buffer, 0xff, ISCSI_HDR_LEN);
400504f3b31bSNicholas Bellinger 				atomic_long_inc(&conn->sess->conn_digest_errors);
4006e48354ceSNicholas Bellinger 			} else {
4007e48354ceSNicholas Bellinger 				pr_debug("Got HeaderDigest CRC32C"
4008e48354ceSNicholas Bellinger 						" 0x%08x\n", checksum);
4009e48354ceSNicholas Bellinger 			}
4010e48354ceSNicholas Bellinger 		}
4011e48354ceSNicholas Bellinger 
4012e48354ceSNicholas Bellinger 		if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT)
4013679fcae4SLaura Abbott 			break;
4014e48354ceSNicholas Bellinger 
4015e48354ceSNicholas Bellinger 		opcode = buffer[0] & ISCSI_OPCODE_MASK;
4016e48354ceSNicholas Bellinger 
4017e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->SessionType &&
4018e48354ceSNicholas Bellinger 		   ((!(opcode & ISCSI_OP_TEXT)) ||
4019e48354ceSNicholas Bellinger 		    (!(opcode & ISCSI_OP_LOGOUT)))) {
4020e48354ceSNicholas Bellinger 			pr_err("Received illegal iSCSI Opcode: 0x%02x"
4021e48354ceSNicholas Bellinger 			" while in Discovery Session, rejecting.\n", opcode);
4022ba159914SNicholas Bellinger 			iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
4023ba159914SNicholas Bellinger 					  buffer);
4024679fcae4SLaura Abbott 			break;
4025e48354ceSNicholas Bellinger 		}
4026e48354ceSNicholas Bellinger 
40273e1c81a9SNicholas Bellinger 		ret = iscsi_target_rx_opcode(conn, buffer);
40283e1c81a9SNicholas Bellinger 		if (ret < 0)
4029679fcae4SLaura Abbott 			break;
4030e8205ccaSVarun Prakash 	}
4031679fcae4SLaura Abbott 
4032679fcae4SLaura Abbott 	kfree(buffer);
4033e48354ceSNicholas Bellinger }
4034e48354ceSNicholas Bellinger 
4035e8205ccaSVarun Prakash int iscsi_target_rx_thread(void *arg)
4036e8205ccaSVarun Prakash {
4037e8205ccaSVarun Prakash 	int rc;
4038e8205ccaSVarun Prakash 	struct iscsi_conn *conn = arg;
40395e0cf5e6SJiang Yi 	bool conn_freed = false;
4040e8205ccaSVarun Prakash 
4041e8205ccaSVarun Prakash 	/*
4042e8205ccaSVarun Prakash 	 * Allow ourselves to be interrupted by SIGINT so that a
4043e8205ccaSVarun Prakash 	 * connection recovery / failure event can be triggered externally.
4044e8205ccaSVarun Prakash 	 */
4045e8205ccaSVarun Prakash 	allow_signal(SIGINT);
4046e8205ccaSVarun Prakash 	/*
4047e8205ccaSVarun Prakash 	 * Wait for iscsi_post_login_handler() to complete before allowing
4048e8205ccaSVarun Prakash 	 * incoming iscsi/tcp socket I/O, and/or failing the connection.
4049e8205ccaSVarun Prakash 	 */
4050e8205ccaSVarun Prakash 	rc = wait_for_completion_interruptible(&conn->rx_login_comp);
4051e8205ccaSVarun Prakash 	if (rc < 0 || iscsi_target_check_conn_state(conn))
40525e0cf5e6SJiang Yi 		goto out;
4053e8205ccaSVarun Prakash 
4054e8205ccaSVarun Prakash 	if (!conn->conn_transport->iscsit_get_rx_pdu)
4055e8205ccaSVarun Prakash 		return 0;
4056e8205ccaSVarun Prakash 
4057e8205ccaSVarun Prakash 	conn->conn_transport->iscsit_get_rx_pdu(conn);
4058e8205ccaSVarun Prakash 
4059e48354ceSNicholas Bellinger 	if (!signal_pending(current))
4060e48354ceSNicholas Bellinger 		atomic_set(&conn->transport_failed, 1);
40615e0cf5e6SJiang Yi 	iscsit_take_action_for_connection_exit(conn, &conn_freed);
40625e0cf5e6SJiang Yi 
40635e0cf5e6SJiang Yi out:
40645e0cf5e6SJiang Yi 	if (!conn_freed) {
40655e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
40665e0cf5e6SJiang Yi 			msleep(100);
40675e0cf5e6SJiang Yi 		}
40685e0cf5e6SJiang Yi 	}
40695e0cf5e6SJiang Yi 
4070e48354ceSNicholas Bellinger 	return 0;
4071e48354ceSNicholas Bellinger }
4072e48354ceSNicholas Bellinger 
4073e48354ceSNicholas Bellinger static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
4074e48354ceSNicholas Bellinger {
4075064cdd2dSNicholas Bellinger 	LIST_HEAD(tmp_list);
4076e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
4077e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4078e48354ceSNicholas Bellinger 	/*
4079e48354ceSNicholas Bellinger 	 * We expect this function to only ever be called from either RX or TX
4080e48354ceSNicholas Bellinger 	 * thread context via iscsit_close_connection() once the other context
4081e48354ceSNicholas Bellinger 	 * has been reset -> returned sleeping pre-handler state.
4082e48354ceSNicholas Bellinger 	 */
4083e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
4084064cdd2dSNicholas Bellinger 	list_splice_init(&conn->conn_cmd_list, &tmp_list);
4085e48354ceSNicholas Bellinger 
4086064cdd2dSNicholas Bellinger 	list_for_each_entry(cmd, &tmp_list, i_conn_node) {
4087064cdd2dSNicholas Bellinger 		struct se_cmd *se_cmd = &cmd->se_cmd;
4088e48354ceSNicholas Bellinger 
4089064cdd2dSNicholas Bellinger 		if (se_cmd->se_tfo != NULL) {
409032e36bfbSBart Van Assche 			spin_lock_irq(&se_cmd->t_state_lock);
4091064cdd2dSNicholas Bellinger 			se_cmd->transport_state |= CMD_T_FABRIC_STOP;
409232e36bfbSBart Van Assche 			spin_unlock_irq(&se_cmd->t_state_lock);
4093064cdd2dSNicholas Bellinger 		}
4094e48354ceSNicholas Bellinger 	}
4095e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4096064cdd2dSNicholas Bellinger 
4097064cdd2dSNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
4098064cdd2dSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
4099064cdd2dSNicholas Bellinger 
4100064cdd2dSNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, sess);
4101064cdd2dSNicholas Bellinger 		iscsit_free_cmd(cmd, true);
4102064cdd2dSNicholas Bellinger 
4103064cdd2dSNicholas Bellinger 	}
4104e48354ceSNicholas Bellinger }
4105e48354ceSNicholas Bellinger 
4106e48354ceSNicholas Bellinger static void iscsit_stop_timers_for_cmds(
4107e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4108e48354ceSNicholas Bellinger {
4109e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
4110e48354ceSNicholas Bellinger 
4111e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
41122fbb471eSAndy Grover 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
4113e48354ceSNicholas Bellinger 		if (cmd->data_direction == DMA_TO_DEVICE)
4114e48354ceSNicholas Bellinger 			iscsit_stop_dataout_timer(cmd);
4115e48354ceSNicholas Bellinger 	}
4116e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4117e48354ceSNicholas Bellinger }
4118e48354ceSNicholas Bellinger 
4119e48354ceSNicholas Bellinger int iscsit_close_connection(
4120e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4121e48354ceSNicholas Bellinger {
4122e48354ceSNicholas Bellinger 	int conn_logout = (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT);
4123e48354ceSNicholas Bellinger 	struct iscsi_session	*sess = conn->sess;
4124e48354ceSNicholas Bellinger 
4125e48354ceSNicholas Bellinger 	pr_debug("Closing iSCSI connection CID %hu on SID:"
4126e48354ceSNicholas Bellinger 		" %u\n", conn->cid, sess->sid);
4127e48354ceSNicholas Bellinger 	/*
4128b4869ee9SVarun Prakash 	 * Always up conn_logout_comp for the traditional TCP and HW_OFFLOAD
4129b4869ee9SVarun Prakash 	 * case just in case the RX Thread in iscsi_target_rx_opcode() is
4130b4869ee9SVarun Prakash 	 * sleeping and the logout response never got sent because the
4131b4869ee9SVarun Prakash 	 * connection failed.
4132f068fbc8SNicholas Bellinger 	 *
4133f068fbc8SNicholas Bellinger 	 * However for iser-target, isert_wait4logout() is using conn_logout_comp
4134f068fbc8SNicholas Bellinger 	 * to signal logout response TX interrupt completion.  Go ahead and skip
4135f068fbc8SNicholas Bellinger 	 * this for iser since isert_rx_opcode() does not wait on logout failure,
4136f068fbc8SNicholas Bellinger 	 * and to avoid iscsi_conn pointer dereference in iser-target code.
4137e48354ceSNicholas Bellinger 	 */
4138bd027d85SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown)
4139e48354ceSNicholas Bellinger 		complete(&conn->conn_logout_comp);
4140e48354ceSNicholas Bellinger 
414188dcd2daSNicholas Bellinger 	if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) {
414288dcd2daSNicholas Bellinger 		if (conn->tx_thread &&
414388dcd2daSNicholas Bellinger 		    cmpxchg(&conn->tx_thread_active, true, false)) {
414488dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->tx_thread, 1);
414588dcd2daSNicholas Bellinger 			kthread_stop(conn->tx_thread);
414688dcd2daSNicholas Bellinger 		}
414788dcd2daSNicholas Bellinger 	} else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) {
414888dcd2daSNicholas Bellinger 		if (conn->rx_thread &&
414988dcd2daSNicholas Bellinger 		    cmpxchg(&conn->rx_thread_active, true, false)) {
415088dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->rx_thread, 1);
415188dcd2daSNicholas Bellinger 			kthread_stop(conn->rx_thread);
415288dcd2daSNicholas Bellinger 		}
415388dcd2daSNicholas Bellinger 	}
415488dcd2daSNicholas Bellinger 
415588dcd2daSNicholas Bellinger 	spin_lock(&iscsit_global->ts_bitmap_lock);
415688dcd2daSNicholas Bellinger 	bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
415788dcd2daSNicholas Bellinger 			      get_order(1));
415888dcd2daSNicholas Bellinger 	spin_unlock(&iscsit_global->ts_bitmap_lock);
4159e48354ceSNicholas Bellinger 
4160e48354ceSNicholas Bellinger 	iscsit_stop_timers_for_cmds(conn);
4161e48354ceSNicholas Bellinger 	iscsit_stop_nopin_response_timer(conn);
4162e48354ceSNicholas Bellinger 	iscsit_stop_nopin_timer(conn);
4163defd8848SNicholas Bellinger 
416476261adaSBart Van Assche 	if (conn->conn_transport->iscsit_wait_conn)
416576261adaSBart Van Assche 		conn->conn_transport->iscsit_wait_conn(conn);
416676261adaSBart Van Assche 
4167e48354ceSNicholas Bellinger 	/*
4168e48354ceSNicholas Bellinger 	 * During Connection recovery drop unacknowledged out of order
4169e48354ceSNicholas Bellinger 	 * commands for this connection, and prepare the other commands
417053c561dcSBart Van Assche 	 * for reallegiance.
4171e48354ceSNicholas Bellinger 	 *
4172e48354ceSNicholas Bellinger 	 * During normal operation clear the out of order commands (but
4173e48354ceSNicholas Bellinger 	 * do not free the struct iscsi_ooo_cmdsn's) and release all
4174e48354ceSNicholas Bellinger 	 * struct iscsi_cmds.
4175e48354ceSNicholas Bellinger 	 */
4176e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery)) {
4177e48354ceSNicholas Bellinger 		iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(conn);
417853c561dcSBart Van Assche 		iscsit_prepare_cmds_for_reallegiance(conn);
4179e48354ceSNicholas Bellinger 	} else {
4180e48354ceSNicholas Bellinger 		iscsit_clear_ooo_cmdsns_for_conn(conn);
4181e48354ceSNicholas Bellinger 		iscsit_release_commands_from_conn(conn);
4182e48354ceSNicholas Bellinger 	}
4183bbc05048SNicholas Bellinger 	iscsit_free_queue_reqs_for_conn(conn);
4184e48354ceSNicholas Bellinger 
4185e48354ceSNicholas Bellinger 	/*
4186e48354ceSNicholas Bellinger 	 * Handle decrementing session or connection usage count if
4187e48354ceSNicholas Bellinger 	 * a logout response was not able to be sent because the
4188e48354ceSNicholas Bellinger 	 * connection failed.  Fall back to Session Recovery here.
4189e48354ceSNicholas Bellinger 	 */
4190e48354ceSNicholas Bellinger 	if (atomic_read(&conn->conn_logout_remove)) {
4191e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_SESSION) {
4192e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4193e48354ceSNicholas Bellinger 			iscsit_dec_session_usage_count(sess);
4194e48354ceSNicholas Bellinger 		}
4195e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION)
4196e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4197e48354ceSNicholas Bellinger 
4198e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 0);
4199e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 0);
4200e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4201e48354ceSNicholas Bellinger 	}
4202e48354ceSNicholas Bellinger 
4203e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4204e48354ceSNicholas Bellinger 	list_del(&conn->conn_list);
4205e48354ceSNicholas Bellinger 
4206e48354ceSNicholas Bellinger 	/*
4207e48354ceSNicholas Bellinger 	 * Attempt to let the Initiator know this connection failed by
4208e48354ceSNicholas Bellinger 	 * sending an Connection Dropped Async Message on another
4209e48354ceSNicholas Bellinger 	 * active connection.
4210e48354ceSNicholas Bellinger 	 */
4211e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery))
4212e48354ceSNicholas Bellinger 		iscsit_build_conn_drop_async_message(conn);
4213e48354ceSNicholas Bellinger 
4214e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4215e48354ceSNicholas Bellinger 
4216e48354ceSNicholas Bellinger 	/*
4217e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection,
4218e48354ceSNicholas Bellinger 	 * up the connection reinstatement semaphore that is being blocked on
4219e48354ceSNicholas Bellinger 	 * in iscsit_cause_connection_reinstatement().
4220e48354ceSNicholas Bellinger 	 */
4221e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
4222e48354ceSNicholas Bellinger 	if (atomic_read(&conn->sleep_on_conn_wait_comp)) {
4223e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4224e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_comp);
4225e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4226e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4227e48354ceSNicholas Bellinger 	}
4228e48354ceSNicholas Bellinger 
4229e48354ceSNicholas Bellinger 	/*
4230e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection
4231e48354ceSNicholas Bellinger 	 * by receiving a REMOVECONNFORRECOVERY logout request, up the
4232e48354ceSNicholas Bellinger 	 * connection wait rcfr semaphore that is being blocked on
4233e48354ceSNicholas Bellinger 	 * an iscsit_connection_reinstatement_rcfr().
4234e48354ceSNicholas Bellinger 	 */
4235e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_wait_rcfr)) {
4236e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4237e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_rcfr_comp);
4238e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4239e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4240e48354ceSNicholas Bellinger 	}
4241e48354ceSNicholas Bellinger 	atomic_set(&conn->connection_reinstatement, 1);
4242e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
4243e48354ceSNicholas Bellinger 
4244e48354ceSNicholas Bellinger 	/*
4245e48354ceSNicholas Bellinger 	 * If any other processes are accessing this connection pointer we
4246e48354ceSNicholas Bellinger 	 * must wait until they have completed.
4247e48354ceSNicholas Bellinger 	 */
4248e48354ceSNicholas Bellinger 	iscsit_check_conn_usage_count(conn);
4249e48354ceSNicholas Bellinger 
425069110e3cSHerbert Xu 	ahash_request_free(conn->conn_tx_hash);
425169110e3cSHerbert Xu 	if (conn->conn_rx_hash) {
425269110e3cSHerbert Xu 		struct crypto_ahash *tfm;
425369110e3cSHerbert Xu 
425469110e3cSHerbert Xu 		tfm = crypto_ahash_reqtfm(conn->conn_rx_hash);
425569110e3cSHerbert Xu 		ahash_request_free(conn->conn_rx_hash);
425669110e3cSHerbert Xu 		crypto_free_ahash(tfm);
425769110e3cSHerbert Xu 	}
4258e48354ceSNicholas Bellinger 
4259bf6932f4SAl Viro 	if (conn->sock)
4260e48354ceSNicholas Bellinger 		sock_release(conn->sock);
4261baa4d64bSNicholas Bellinger 
4262baa4d64bSNicholas Bellinger 	if (conn->conn_transport->iscsit_free_conn)
4263baa4d64bSNicholas Bellinger 		conn->conn_transport->iscsit_free_conn(conn);
4264baa4d64bSNicholas Bellinger 
4265e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
4266e48354ceSNicholas Bellinger 	conn->conn_state = TARG_CONN_STATE_FREE;
426705a86e78SMike Christie 	iscsit_free_conn(conn);
4268e48354ceSNicholas Bellinger 
4269e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4270e48354ceSNicholas Bellinger 	atomic_dec(&sess->nconn);
4271e48354ceSNicholas Bellinger 	pr_debug("Decremented iSCSI connection count to %hu from node:"
4272e48354ceSNicholas Bellinger 		" %s\n", atomic_read(&sess->nconn),
4273e48354ceSNicholas Bellinger 		sess->sess_ops->InitiatorName);
4274e48354ceSNicholas Bellinger 	/*
4275e48354ceSNicholas Bellinger 	 * Make sure that if one connection fails in an non ERL=2 iSCSI
4276e48354ceSNicholas Bellinger 	 * Session that they all fail.
4277e48354ceSNicholas Bellinger 	 */
4278e48354ceSNicholas Bellinger 	if ((sess->sess_ops->ErrorRecoveryLevel != 2) && !conn_logout &&
4279e48354ceSNicholas Bellinger 	     !atomic_read(&sess->session_logout))
4280e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4281e48354ceSNicholas Bellinger 
4282e48354ceSNicholas Bellinger 	/*
4283e48354ceSNicholas Bellinger 	 * If this was not the last connection in the session, and we are
4284e48354ceSNicholas Bellinger 	 * performing session reinstatement or falling back to ERL=0, call
4285e48354ceSNicholas Bellinger 	 * iscsit_stop_session() without sleeping to shutdown the other
4286e48354ceSNicholas Bellinger 	 * active connections.
4287e48354ceSNicholas Bellinger 	 */
4288e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4289e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_reinstatement) &&
4290e48354ceSNicholas Bellinger 		    !atomic_read(&sess->session_fall_back_to_erl0)) {
4291e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4292e48354ceSNicholas Bellinger 			return 0;
4293e48354ceSNicholas Bellinger 		}
4294e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_stop_active)) {
4295e48354ceSNicholas Bellinger 			atomic_set(&sess->session_stop_active, 1);
4296e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4297e48354ceSNicholas Bellinger 			iscsit_stop_session(sess, 0, 0);
4298e48354ceSNicholas Bellinger 			return 0;
4299e48354ceSNicholas Bellinger 		}
4300e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4301e48354ceSNicholas Bellinger 		return 0;
4302e48354ceSNicholas Bellinger 	}
4303e48354ceSNicholas Bellinger 
4304e48354ceSNicholas Bellinger 	/*
4305e48354ceSNicholas Bellinger 	 * If this was the last connection in the session and one of the
4306e48354ceSNicholas Bellinger 	 * following is occurring:
4307e48354ceSNicholas Bellinger 	 *
4308e48354ceSNicholas Bellinger 	 * Session Reinstatement is not being performed, and are falling back
4309e48354ceSNicholas Bellinger 	 * to ERL=0 call iscsit_close_session().
4310e48354ceSNicholas Bellinger 	 *
4311e48354ceSNicholas Bellinger 	 * Session Logout was requested.  iscsit_close_session() will be called
4312e48354ceSNicholas Bellinger 	 * elsewhere.
4313e48354ceSNicholas Bellinger 	 *
4314e48354ceSNicholas Bellinger 	 * Session Continuation is not being performed, start the Time2Retain
4315e48354ceSNicholas Bellinger 	 * handler and check if sleep_on_sess_wait_sem is active.
4316e48354ceSNicholas Bellinger 	 */
4317e48354ceSNicholas Bellinger 	if (!atomic_read(&sess->session_reinstatement) &&
4318e48354ceSNicholas Bellinger 	     atomic_read(&sess->session_fall_back_to_erl0)) {
4319e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
432057c46e9fSMaurizio Lombardi 		complete_all(&sess->session_wait_comp);
432144f33d0fSChristoph Hellwig 		iscsit_close_session(sess);
4322e48354ceSNicholas Bellinger 
4323e48354ceSNicholas Bellinger 		return 0;
4324e48354ceSNicholas Bellinger 	} else if (atomic_read(&sess->session_logout)) {
4325e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4326e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FREE;
4327e48354ceSNicholas Bellinger 
432857c46e9fSMaurizio Lombardi 		if (atomic_read(&sess->session_close)) {
432957c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
433057c46e9fSMaurizio Lombardi 			complete_all(&sess->session_wait_comp);
433157c46e9fSMaurizio Lombardi 			iscsit_close_session(sess);
433257c46e9fSMaurizio Lombardi 		} else {
433357c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
433457c46e9fSMaurizio Lombardi 		}
4335e48354ceSNicholas Bellinger 
4336e48354ceSNicholas Bellinger 		return 0;
4337e48354ceSNicholas Bellinger 	} else {
4338e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4339e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FAILED;
4340e48354ceSNicholas Bellinger 
434157c46e9fSMaurizio Lombardi 		if (!atomic_read(&sess->session_continuation))
4342e48354ceSNicholas Bellinger 			iscsit_start_time2retain_handler(sess);
4343e48354ceSNicholas Bellinger 
434457c46e9fSMaurizio Lombardi 		if (atomic_read(&sess->session_close)) {
434557c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
434657c46e9fSMaurizio Lombardi 			complete_all(&sess->session_wait_comp);
434757c46e9fSMaurizio Lombardi 			iscsit_close_session(sess);
434857c46e9fSMaurizio Lombardi 		} else {
434957c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
435057c46e9fSMaurizio Lombardi 		}
4351e48354ceSNicholas Bellinger 
4352e48354ceSNicholas Bellinger 		return 0;
4353e48354ceSNicholas Bellinger 	}
4354e48354ceSNicholas Bellinger }
4355e48354ceSNicholas Bellinger 
435644f33d0fSChristoph Hellwig /*
435744f33d0fSChristoph Hellwig  * If the iSCSI Session for the iSCSI Initiator Node exists,
435844f33d0fSChristoph Hellwig  * forcefully shutdown the iSCSI NEXUS.
435944f33d0fSChristoph Hellwig  */
4360e48354ceSNicholas Bellinger int iscsit_close_session(struct iscsi_session *sess)
4361e48354ceSNicholas Bellinger {
436260bfcf8eSAndy Grover 	struct iscsi_portal_group *tpg = sess->tpg;
4363e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4364e48354ceSNicholas Bellinger 
4365e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4366e48354ceSNicholas Bellinger 		pr_err("%d connection(s) still exist for iSCSI session"
4367e48354ceSNicholas Bellinger 			" to %s\n", atomic_read(&sess->nconn),
4368e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4369e48354ceSNicholas Bellinger 		BUG();
4370e48354ceSNicholas Bellinger 	}
4371e48354ceSNicholas Bellinger 
4372e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4373e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
4374e48354ceSNicholas Bellinger 	atomic_set(&sess->session_reinstatement, 1);
4375e48354ceSNicholas Bellinger 	iscsit_stop_time2retain_timer(sess);
4376e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4377e48354ceSNicholas Bellinger 
4378e48354ceSNicholas Bellinger 	/*
4379e48354ceSNicholas Bellinger 	 * transport_deregister_session_configfs() will clear the
4380e48354ceSNicholas Bellinger 	 * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context
4381e48354ceSNicholas Bellinger 	 * can be setting it again with __transport_register_session() in
4382e48354ceSNicholas Bellinger 	 * iscsi_post_login_handler() again after the iscsit_stop_session()
4383e48354ceSNicholas Bellinger 	 * completes in iscsi_np context.
4384e48354ceSNicholas Bellinger 	 */
4385e48354ceSNicholas Bellinger 	transport_deregister_session_configfs(sess->se_sess);
4386e48354ceSNicholas Bellinger 
4387e48354ceSNicholas Bellinger 	/*
4388e48354ceSNicholas Bellinger 	 * If any other processes are accessing this session pointer we must
4389e48354ceSNicholas Bellinger 	 * wait until they have completed.  If we are in an interrupt (the
4390e48354ceSNicholas Bellinger 	 * time2retain handler) and contain and active session usage count we
4391e48354ceSNicholas Bellinger 	 * restart the timer and exit.
4392e48354ceSNicholas Bellinger 	 */
4393e48354ceSNicholas Bellinger 	if (!in_interrupt()) {
4394626bac73SMaurizio Lombardi 		iscsit_check_session_usage_count(sess);
4395e48354ceSNicholas Bellinger 	} else {
4396e48354ceSNicholas Bellinger 		if (iscsit_check_session_usage_count(sess) == 2) {
4397e48354ceSNicholas Bellinger 			atomic_set(&sess->session_logout, 0);
4398e48354ceSNicholas Bellinger 			iscsit_start_time2retain_handler(sess);
4399e48354ceSNicholas Bellinger 			return 0;
4400e48354ceSNicholas Bellinger 		}
4401e48354ceSNicholas Bellinger 	}
4402e48354ceSNicholas Bellinger 
4403e48354ceSNicholas Bellinger 	transport_deregister_session(sess->se_sess);
4404e48354ceSNicholas Bellinger 
4405e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel == 2)
4406902ff860SColin Ian King 		iscsit_free_connection_recovery_entries(sess);
4407e48354ceSNicholas Bellinger 
4408e48354ceSNicholas Bellinger 	iscsit_free_all_ooo_cmdsns(sess);
4409e48354ceSNicholas Bellinger 
4410e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4411e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4412e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FREE;
4413e48354ceSNicholas Bellinger 	pr_debug("Released iSCSI session from node: %s\n",
4414e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4415e48354ceSNicholas Bellinger 	tpg->nsessions--;
4416e48354ceSNicholas Bellinger 	if (tpg->tpg_tiqn)
4417e48354ceSNicholas Bellinger 		tpg->tpg_tiqn->tiqn_nsessions--;
4418e48354ceSNicholas Bellinger 
4419e48354ceSNicholas Bellinger 	pr_debug("Decremented number of active iSCSI Sessions on"
4420e48354ceSNicholas Bellinger 		" iSCSI TPG: %hu to %u\n", tpg->tpgt, tpg->nsessions);
4421e48354ceSNicholas Bellinger 
442231ff0ceeSMatthew Wilcox 	ida_free(&sess_ida, sess->session_index);
4423e48354ceSNicholas Bellinger 	kfree(sess->sess_ops);
4424e48354ceSNicholas Bellinger 	sess->sess_ops = NULL;
4425e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4426e48354ceSNicholas Bellinger 
4427e48354ceSNicholas Bellinger 	kfree(sess);
4428e48354ceSNicholas Bellinger 	return 0;
4429e48354ceSNicholas Bellinger }
4430e48354ceSNicholas Bellinger 
4431e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_closesession(
4432e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4433e48354ceSNicholas Bellinger {
4434e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4435007d038bSNicholas Bellinger 	int sleep = 1;
4436007d038bSNicholas Bellinger 	/*
4437007d038bSNicholas Bellinger 	 * Traditional iscsi/tcp will invoke this logic from TX thread
4438007d038bSNicholas Bellinger 	 * context during session logout, so clear tx_thread_active and
4439007d038bSNicholas Bellinger 	 * sleep if iscsit_close_connection() has not already occured.
4440007d038bSNicholas Bellinger 	 *
4441007d038bSNicholas Bellinger 	 * Since iser-target invokes this logic from it's own workqueue,
4442007d038bSNicholas Bellinger 	 * always sleep waiting for RX/TX thread shutdown to complete
4443007d038bSNicholas Bellinger 	 * within iscsit_close_connection().
4444007d038bSNicholas Bellinger 	 */
4445105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4446007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4447105fa2f4SNicholas Bellinger 		if (!sleep)
4448105fa2f4SNicholas Bellinger 			return;
4449105fa2f4SNicholas Bellinger 	}
4450e48354ceSNicholas Bellinger 
4451e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4452e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4453e48354ceSNicholas Bellinger 
4454e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
445557c46e9fSMaurizio Lombardi 	atomic_set(&sess->session_close, 1);
445688dcd2daSNicholas Bellinger 	iscsit_stop_session(sess, sleep, sleep);
4457e48354ceSNicholas Bellinger 	iscsit_dec_session_usage_count(sess);
4458e48354ceSNicholas Bellinger }
4459e48354ceSNicholas Bellinger 
4460e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_samecid(
4461e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4462e48354ceSNicholas Bellinger {
4463007d038bSNicholas Bellinger 	int sleep = 1;
4464007d038bSNicholas Bellinger 
4465105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4466007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4467105fa2f4SNicholas Bellinger 		if (!sleep)
4468105fa2f4SNicholas Bellinger 			return;
4469105fa2f4SNicholas Bellinger 	}
4470e48354ceSNicholas Bellinger 
4471e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4472e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4473e48354ceSNicholas Bellinger 
447488dcd2daSNicholas Bellinger 	iscsit_cause_connection_reinstatement(conn, sleep);
4475e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
4476e48354ceSNicholas Bellinger }
4477e48354ceSNicholas Bellinger 
4478e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_diffcid(
4479e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
4480e48354ceSNicholas Bellinger 	u16 cid)
4481e48354ceSNicholas Bellinger {
4482e48354ceSNicholas Bellinger 	struct iscsi_conn *l_conn;
4483e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4484b53b0d99SNicholas Bellinger 	bool conn_found = false;
4485e48354ceSNicholas Bellinger 
4486e48354ceSNicholas Bellinger 	if (!sess)
4487e48354ceSNicholas Bellinger 		return;
4488e48354ceSNicholas Bellinger 
4489e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4490e48354ceSNicholas Bellinger 	list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) {
4491e48354ceSNicholas Bellinger 		if (l_conn->cid == cid) {
4492e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(l_conn);
4493b53b0d99SNicholas Bellinger 			conn_found = true;
4494e48354ceSNicholas Bellinger 			break;
4495e48354ceSNicholas Bellinger 		}
4496e48354ceSNicholas Bellinger 	}
4497e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4498e48354ceSNicholas Bellinger 
4499b53b0d99SNicholas Bellinger 	if (!conn_found)
4500e48354ceSNicholas Bellinger 		return;
4501e48354ceSNicholas Bellinger 
4502e48354ceSNicholas Bellinger 	if (l_conn->sock)
4503e48354ceSNicholas Bellinger 		l_conn->sock->ops->shutdown(l_conn->sock, RCV_SHUTDOWN);
4504e48354ceSNicholas Bellinger 
4505e48354ceSNicholas Bellinger 	spin_lock_bh(&l_conn->state_lock);
4506e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
4507e48354ceSNicholas Bellinger 	l_conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
4508e48354ceSNicholas Bellinger 	spin_unlock_bh(&l_conn->state_lock);
4509e48354ceSNicholas Bellinger 
4510e48354ceSNicholas Bellinger 	iscsit_cause_connection_reinstatement(l_conn, 1);
4511e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(l_conn);
4512e48354ceSNicholas Bellinger }
4513e48354ceSNicholas Bellinger 
4514e48354ceSNicholas Bellinger /*
4515e48354ceSNicholas Bellinger  *	Return of 0 causes the TX thread to restart.
4516e48354ceSNicholas Bellinger  */
45172ec5a8c1SNicholas Bellinger int iscsit_logout_post_handler(
4518e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
4519e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4520e48354ceSNicholas Bellinger {
4521e48354ceSNicholas Bellinger 	int ret = 0;
4522e48354ceSNicholas Bellinger 
4523e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
4524e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
4525e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4526e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4527e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4528e48354ceSNicholas Bellinger 		default:
4529e48354ceSNicholas Bellinger 			iscsit_logout_post_handler_closesession(conn);
4530e48354ceSNicholas Bellinger 			break;
4531e48354ceSNicholas Bellinger 		}
4532e48354ceSNicholas Bellinger 		ret = 0;
4533e48354ceSNicholas Bellinger 		break;
4534e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
4535e48354ceSNicholas Bellinger 		if (conn->cid == cmd->logout_cid) {
4536e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4537e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4538e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4539e48354ceSNicholas Bellinger 			default:
4540e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_samecid(conn);
4541e48354ceSNicholas Bellinger 				break;
4542e48354ceSNicholas Bellinger 			}
4543e48354ceSNicholas Bellinger 			ret = 0;
4544e48354ceSNicholas Bellinger 		} else {
4545e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4546e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4547e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_diffcid(conn,
4548e48354ceSNicholas Bellinger 					cmd->logout_cid);
4549e48354ceSNicholas Bellinger 				break;
4550e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CID_NOT_FOUND:
4551e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4552e48354ceSNicholas Bellinger 			default:
4553e48354ceSNicholas Bellinger 				break;
4554e48354ceSNicholas Bellinger 			}
4555e48354ceSNicholas Bellinger 			ret = 1;
4556e48354ceSNicholas Bellinger 		}
4557e48354ceSNicholas Bellinger 		break;
4558e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
4559e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4560e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4561e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CID_NOT_FOUND:
4562e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
4563e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4564e48354ceSNicholas Bellinger 		default:
4565e48354ceSNicholas Bellinger 			break;
4566e48354ceSNicholas Bellinger 		}
4567e48354ceSNicholas Bellinger 		ret = 1;
4568e48354ceSNicholas Bellinger 		break;
4569e48354ceSNicholas Bellinger 	default:
4570e48354ceSNicholas Bellinger 		break;
4571e48354ceSNicholas Bellinger 
4572e48354ceSNicholas Bellinger 	}
4573e48354ceSNicholas Bellinger 	return ret;
4574e48354ceSNicholas Bellinger }
45752ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_logout_post_handler);
4576e48354ceSNicholas Bellinger 
4577e48354ceSNicholas Bellinger void iscsit_fail_session(struct iscsi_session *sess)
4578e48354ceSNicholas Bellinger {
4579e48354ceSNicholas Bellinger 	struct iscsi_conn *conn;
4580e48354ceSNicholas Bellinger 
4581e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4582e48354ceSNicholas Bellinger 	list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
4583e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
4584e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
4585e48354ceSNicholas Bellinger 	}
4586e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4587e48354ceSNicholas Bellinger 
4588e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4589e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FAILED;
4590e48354ceSNicholas Bellinger }
4591e48354ceSNicholas Bellinger 
4592e48354ceSNicholas Bellinger void iscsit_stop_session(
4593e48354ceSNicholas Bellinger 	struct iscsi_session *sess,
4594e48354ceSNicholas Bellinger 	int session_sleep,
4595e48354ceSNicholas Bellinger 	int connection_sleep)
4596e48354ceSNicholas Bellinger {
4597e48354ceSNicholas Bellinger 	u16 conn_count = atomic_read(&sess->nconn);
4598e48354ceSNicholas Bellinger 	struct iscsi_conn *conn, *conn_tmp = NULL;
4599e48354ceSNicholas Bellinger 	int is_last;
4600e48354ceSNicholas Bellinger 
4601e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4602e48354ceSNicholas Bellinger 
4603e48354ceSNicholas Bellinger 	if (connection_sleep) {
4604e48354ceSNicholas Bellinger 		list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
4605e48354ceSNicholas Bellinger 				conn_list) {
4606e48354ceSNicholas Bellinger 			if (conn_count == 0)
4607e48354ceSNicholas Bellinger 				break;
4608e48354ceSNicholas Bellinger 
4609e48354ceSNicholas Bellinger 			if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
4610e48354ceSNicholas Bellinger 				is_last = 1;
4611e48354ceSNicholas Bellinger 			} else {
4612e48354ceSNicholas Bellinger 				iscsit_inc_conn_usage_count(conn_tmp);
4613e48354ceSNicholas Bellinger 				is_last = 0;
4614e48354ceSNicholas Bellinger 			}
4615e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn);
4616e48354ceSNicholas Bellinger 
4617e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4618e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 1);
4619e48354ceSNicholas Bellinger 			spin_lock_bh(&sess->conn_lock);
4620e48354ceSNicholas Bellinger 
4621e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4622e48354ceSNicholas Bellinger 			if (is_last == 0)
4623e48354ceSNicholas Bellinger 				iscsit_dec_conn_usage_count(conn_tmp);
4624e48354ceSNicholas Bellinger 			conn_count--;
4625e48354ceSNicholas Bellinger 		}
4626e48354ceSNicholas Bellinger 	} else {
4627e48354ceSNicholas Bellinger 		list_for_each_entry(conn, &sess->sess_conn_list, conn_list)
4628e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 0);
4629e48354ceSNicholas Bellinger 	}
4630e48354ceSNicholas Bellinger 
4631e48354ceSNicholas Bellinger 	if (session_sleep && atomic_read(&sess->nconn)) {
4632e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4633e48354ceSNicholas Bellinger 		wait_for_completion(&sess->session_wait_comp);
4634e48354ceSNicholas Bellinger 	} else
4635e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4636e48354ceSNicholas Bellinger }
4637e48354ceSNicholas Bellinger 
4638e48354ceSNicholas Bellinger int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
4639e48354ceSNicholas Bellinger {
4640e48354ceSNicholas Bellinger 	struct iscsi_session *sess;
4641e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4642e48354ceSNicholas Bellinger 	struct se_session *se_sess, *se_sess_tmp;
4643417c20a9SNicholas Bellinger 	LIST_HEAD(free_list);
4644e48354ceSNicholas Bellinger 	int session_count = 0;
4645e48354ceSNicholas Bellinger 
4646e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4647e48354ceSNicholas Bellinger 	if (tpg->nsessions && !force) {
4648e48354ceSNicholas Bellinger 		spin_unlock_bh(&se_tpg->session_lock);
4649e48354ceSNicholas Bellinger 		return -1;
4650e48354ceSNicholas Bellinger 	}
4651e48354ceSNicholas Bellinger 
4652e48354ceSNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
4653e48354ceSNicholas Bellinger 			sess_list) {
4654e48354ceSNicholas Bellinger 		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
4655e48354ceSNicholas Bellinger 
4656e48354ceSNicholas Bellinger 		spin_lock(&sess->conn_lock);
4657e48354ceSNicholas Bellinger 		if (atomic_read(&sess->session_fall_back_to_erl0) ||
4658e48354ceSNicholas Bellinger 		    atomic_read(&sess->session_logout) ||
465957c46e9fSMaurizio Lombardi 		    atomic_read(&sess->session_close) ||
4660e48354ceSNicholas Bellinger 		    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
4661e48354ceSNicholas Bellinger 			spin_unlock(&sess->conn_lock);
4662e48354ceSNicholas Bellinger 			continue;
4663e48354ceSNicholas Bellinger 		}
466457c46e9fSMaurizio Lombardi 		iscsit_inc_session_usage_count(sess);
4665e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 1);
4666197b806aSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
466757c46e9fSMaurizio Lombardi 		atomic_set(&sess->session_close, 1);
4668e48354ceSNicholas Bellinger 		spin_unlock(&sess->conn_lock);
4669e48354ceSNicholas Bellinger 
4670417c20a9SNicholas Bellinger 		list_move_tail(&se_sess->sess_list, &free_list);
4671e48354ceSNicholas Bellinger 	}
4672e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4673e48354ceSNicholas Bellinger 
4674417c20a9SNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) {
4675417c20a9SNicholas Bellinger 		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
4676417c20a9SNicholas Bellinger 
467757c46e9fSMaurizio Lombardi 		list_del_init(&se_sess->sess_list);
4678e49a7d99SMaurizio Lombardi 		iscsit_stop_session(sess, 1, 1);
467957c46e9fSMaurizio Lombardi 		iscsit_dec_session_usage_count(sess);
4680417c20a9SNicholas Bellinger 		session_count++;
4681417c20a9SNicholas Bellinger 	}
4682417c20a9SNicholas Bellinger 
4683e48354ceSNicholas Bellinger 	pr_debug("Released %d iSCSI Session(s) from Target Portal"
4684e48354ceSNicholas Bellinger 			" Group: %hu\n", session_count, tpg->tpgt);
4685e48354ceSNicholas Bellinger 	return 0;
4686e48354ceSNicholas Bellinger }
4687e48354ceSNicholas Bellinger 
4688e48354ceSNicholas Bellinger MODULE_DESCRIPTION("iSCSI-Target Driver for mainline target infrastructure");
4689e48354ceSNicholas Bellinger MODULE_VERSION("4.1.x");
4690e48354ceSNicholas Bellinger MODULE_AUTHOR("nab@Linux-iSCSI.org");
4691e48354ceSNicholas Bellinger MODULE_LICENSE("GPL");
4692e48354ceSNicholas Bellinger 
4693e48354ceSNicholas Bellinger module_init(iscsi_target_init_module);
4694e48354ceSNicholas Bellinger module_exit(iscsi_target_cleanup_module);
4695