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 
6266cd9d4eSMax Gurtovoy static int iscsit_handle_immediate_data(struct iscsit_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 
475be36d683SMax Gurtovoy static void iscsit_get_rx_pdu(struct iscsit_conn *);
4762ec5a8c1SNicholas Bellinger 
477be36d683SMax Gurtovoy int iscsit_queue_rsp(struct iscsit_conn *conn, struct iscsit_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 
483be36d683SMax Gurtovoy void iscsit_aborted_task(struct iscsit_conn *conn, struct iscsit_cmd *cmd)
484131e6abcSNicholas Bellinger {
485131e6abcSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
486f3619935SMike Christie 	if (!list_empty(&cmd->i_conn_node))
487131e6abcSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
488131e6abcSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
489131e6abcSNicholas Bellinger 
4904412a671SBart Van Assche 	__iscsit_free_cmd(cmd, true);
491131e6abcSNicholas Bellinger }
492d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_aborted_task);
493131e6abcSNicholas Bellinger 
4942854bb23SVarun Prakash static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *,
495e1dfb21fSBart Van Assche 				      u32, u32, const void *, void *);
496be36d683SMax Gurtovoy static void iscsit_tx_thread_wait_for_tcp(struct iscsit_conn *);
4972854bb23SVarun Prakash 
4982854bb23SVarun Prakash static int
499be36d683SMax Gurtovoy iscsit_xmit_nondatain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
5002854bb23SVarun Prakash 			  const void *data_buf, u32 data_buf_len)
5012854bb23SVarun Prakash {
5022854bb23SVarun Prakash 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)cmd->pdu;
5032854bb23SVarun Prakash 	struct kvec *iov;
5042854bb23SVarun Prakash 	u32 niov = 0, tx_size = ISCSI_HDR_LEN;
5052854bb23SVarun Prakash 	int ret;
5062854bb23SVarun Prakash 
5072854bb23SVarun Prakash 	iov = &cmd->iov_misc[0];
5082854bb23SVarun Prakash 	iov[niov].iov_base	= cmd->pdu;
5092854bb23SVarun Prakash 	iov[niov++].iov_len	= ISCSI_HDR_LEN;
5102854bb23SVarun Prakash 
5112854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5122854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5132854bb23SVarun Prakash 
5142854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr,
5152854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
516e1dfb21fSBart Van Assche 					  header_digest);
5172854bb23SVarun Prakash 
5182854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
5192854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
5202854bb23SVarun Prakash 		pr_debug("Attaching CRC32C HeaderDigest"
5212854bb23SVarun Prakash 			 " to opcode 0x%x 0x%08x\n",
5222854bb23SVarun Prakash 			 hdr->opcode, *header_digest);
5232854bb23SVarun Prakash 	}
5242854bb23SVarun Prakash 
5252854bb23SVarun Prakash 	if (data_buf_len) {
5262854bb23SVarun Prakash 		u32 padding = ((-data_buf_len) & 3);
5272854bb23SVarun Prakash 
5282854bb23SVarun Prakash 		iov[niov].iov_base	= (void *)data_buf;
5292854bb23SVarun Prakash 		iov[niov++].iov_len	= data_buf_len;
5302854bb23SVarun Prakash 		tx_size += data_buf_len;
5312854bb23SVarun Prakash 
5322854bb23SVarun Prakash 		if (padding != 0) {
5332854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->pad_bytes;
5342854bb23SVarun Prakash 			iov[niov++].iov_len = padding;
5352854bb23SVarun Prakash 			tx_size += padding;
5362854bb23SVarun Prakash 			pr_debug("Attaching %u additional"
5372854bb23SVarun Prakash 				 " padding bytes.\n", padding);
5382854bb23SVarun Prakash 		}
5392854bb23SVarun Prakash 
5402854bb23SVarun Prakash 		if (conn->conn_ops->DataDigest) {
5412854bb23SVarun Prakash 			iscsit_do_crypto_hash_buf(conn->conn_tx_hash,
5422854bb23SVarun Prakash 						  data_buf, data_buf_len,
543e1dfb21fSBart Van Assche 						  padding, &cmd->pad_bytes,
544e1dfb21fSBart Van Assche 						  &cmd->data_crc);
5452854bb23SVarun Prakash 
5462854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->data_crc;
5472854bb23SVarun Prakash 			iov[niov++].iov_len = ISCSI_CRC_LEN;
5482854bb23SVarun Prakash 			tx_size += ISCSI_CRC_LEN;
5492854bb23SVarun Prakash 			pr_debug("Attached DataDigest for %u"
5502854bb23SVarun Prakash 				 " bytes opcode 0x%x, CRC 0x%08x\n",
5512854bb23SVarun Prakash 				 data_buf_len, hdr->opcode, cmd->data_crc);
5522854bb23SVarun Prakash 		}
5532854bb23SVarun Prakash 	}
5542854bb23SVarun Prakash 
5552854bb23SVarun Prakash 	cmd->iov_misc_count = niov;
5562854bb23SVarun Prakash 	cmd->tx_size = tx_size;
5572854bb23SVarun Prakash 
5582854bb23SVarun Prakash 	ret = iscsit_send_tx_data(cmd, conn, 1);
5592854bb23SVarun Prakash 	if (ret < 0) {
5602854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
5612854bb23SVarun Prakash 		return ret;
5622854bb23SVarun Prakash 	}
5632854bb23SVarun Prakash 
5642854bb23SVarun Prakash 	return 0;
5652854bb23SVarun Prakash }
5662854bb23SVarun Prakash 
56766cd9d4eSMax Gurtovoy static int iscsit_map_iovec(struct iscsit_cmd *cmd, struct kvec *iov, int nvec,
5682e39f1c9SBart Van Assche 			    u32 data_offset, u32 data_length);
56966cd9d4eSMax Gurtovoy static void iscsit_unmap_iovec(struct iscsit_cmd *);
57066cd9d4eSMax Gurtovoy static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsit_cmd *,
5712854bb23SVarun Prakash 				    u32, u32, u32, u8 *);
5722854bb23SVarun Prakash static int
573be36d683SMax Gurtovoy iscsit_xmit_datain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
5742854bb23SVarun Prakash 		       const struct iscsi_datain *datain)
5752854bb23SVarun Prakash {
5762854bb23SVarun Prakash 	struct kvec *iov;
5772854bb23SVarun Prakash 	u32 iov_count = 0, tx_size = 0;
5782854bb23SVarun Prakash 	int ret, iov_ret;
5792854bb23SVarun Prakash 
5802854bb23SVarun Prakash 	iov = &cmd->iov_data[0];
5812854bb23SVarun Prakash 	iov[iov_count].iov_base	= cmd->pdu;
5822854bb23SVarun Prakash 	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
5832854bb23SVarun Prakash 	tx_size += ISCSI_HDR_LEN;
5842854bb23SVarun Prakash 
5852854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5862854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5872854bb23SVarun Prakash 
5882854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu,
5892854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
590e1dfb21fSBart Van Assche 					  header_digest);
5912854bb23SVarun Prakash 
5922854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
5932854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
5942854bb23SVarun Prakash 
5952854bb23SVarun Prakash 		pr_debug("Attaching CRC32 HeaderDigest for DataIN PDU 0x%08x\n",
5962854bb23SVarun Prakash 			 *header_digest);
5972854bb23SVarun Prakash 	}
5982854bb23SVarun Prakash 
5992e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[iov_count],
6002e39f1c9SBart Van Assche 				   cmd->orig_iov_data_count - (iov_count + 2),
6012854bb23SVarun Prakash 				   datain->offset, datain->length);
6022854bb23SVarun Prakash 	if (iov_ret < 0)
6032854bb23SVarun Prakash 		return -1;
6042854bb23SVarun Prakash 
6052854bb23SVarun Prakash 	iov_count += iov_ret;
6062854bb23SVarun Prakash 	tx_size += datain->length;
6072854bb23SVarun Prakash 
6082854bb23SVarun Prakash 	cmd->padding = ((-datain->length) & 3);
6092854bb23SVarun Prakash 	if (cmd->padding) {
6102854bb23SVarun Prakash 		iov[iov_count].iov_base		= cmd->pad_bytes;
6112854bb23SVarun Prakash 		iov[iov_count++].iov_len	= cmd->padding;
6122854bb23SVarun Prakash 		tx_size += cmd->padding;
6132854bb23SVarun Prakash 
6142854bb23SVarun Prakash 		pr_debug("Attaching %u padding bytes\n", cmd->padding);
6152854bb23SVarun Prakash 	}
6162854bb23SVarun Prakash 
6172854bb23SVarun Prakash 	if (conn->conn_ops->DataDigest) {
6182854bb23SVarun Prakash 		cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash,
6192854bb23SVarun Prakash 							 cmd, datain->offset,
6202854bb23SVarun Prakash 							 datain->length,
6212854bb23SVarun Prakash 							 cmd->padding,
6222854bb23SVarun Prakash 							 cmd->pad_bytes);
6232854bb23SVarun Prakash 
6242854bb23SVarun Prakash 		iov[iov_count].iov_base	= &cmd->data_crc;
6252854bb23SVarun Prakash 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
6262854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
6272854bb23SVarun Prakash 
6282854bb23SVarun Prakash 		pr_debug("Attached CRC32C DataDigest %d bytes, crc 0x%08x\n",
6292854bb23SVarun Prakash 			 datain->length + cmd->padding, cmd->data_crc);
6302854bb23SVarun Prakash 	}
6312854bb23SVarun Prakash 
6322854bb23SVarun Prakash 	cmd->iov_data_count = iov_count;
6332854bb23SVarun Prakash 	cmd->tx_size = tx_size;
6342854bb23SVarun Prakash 
6352854bb23SVarun Prakash 	ret = iscsit_fe_sendpage_sg(cmd, conn);
6362854bb23SVarun Prakash 
6372854bb23SVarun Prakash 	iscsit_unmap_iovec(cmd);
6382854bb23SVarun Prakash 
6392854bb23SVarun Prakash 	if (ret < 0) {
6402854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
6412854bb23SVarun Prakash 		return ret;
6422854bb23SVarun Prakash 	}
6432854bb23SVarun Prakash 
6442854bb23SVarun Prakash 	return 0;
6452854bb23SVarun Prakash }
6462854bb23SVarun Prakash 
647be36d683SMax Gurtovoy static int iscsit_xmit_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
6482854bb23SVarun Prakash 			   struct iscsi_datain_req *dr, const void *buf,
6492854bb23SVarun Prakash 			   u32 buf_len)
6502854bb23SVarun Prakash {
6512854bb23SVarun Prakash 	if (dr)
6522854bb23SVarun Prakash 		return iscsit_xmit_datain_pdu(conn, cmd, buf);
6532854bb23SVarun Prakash 	else
6542854bb23SVarun Prakash 		return iscsit_xmit_nondatain_pdu(conn, cmd, buf, buf_len);
6552854bb23SVarun Prakash }
6562854bb23SVarun Prakash 
657be36d683SMax Gurtovoy static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsit_conn *conn)
658e70beee7SNicholas Bellinger {
659e70beee7SNicholas Bellinger 	return TARGET_PROT_NORMAL;
660e70beee7SNicholas Bellinger }
661e70beee7SNicholas Bellinger 
662baa4d64bSNicholas Bellinger static struct iscsit_transport iscsi_target_transport = {
663baa4d64bSNicholas Bellinger 	.name			= "iSCSI/TCP",
664baa4d64bSNicholas Bellinger 	.transport_type		= ISCSI_TCP,
665bd027d85SNicholas Bellinger 	.rdma_shutdown		= false,
666baa4d64bSNicholas Bellinger 	.owner			= NULL,
667baa4d64bSNicholas Bellinger 	.iscsit_setup_np	= iscsit_setup_np,
668baa4d64bSNicholas Bellinger 	.iscsit_accept_np	= iscsit_accept_np,
669baa4d64bSNicholas Bellinger 	.iscsit_free_np		= iscsit_free_np,
670baa4d64bSNicholas Bellinger 	.iscsit_get_login_rx	= iscsit_get_login_rx,
671baa4d64bSNicholas Bellinger 	.iscsit_put_login_tx	= iscsit_put_login_tx,
6723e1c81a9SNicholas Bellinger 	.iscsit_get_dataout	= iscsit_build_r2ts_for_cmd,
6732ec5a8c1SNicholas Bellinger 	.iscsit_immediate_queue	= iscsit_immediate_queue,
6742ec5a8c1SNicholas Bellinger 	.iscsit_response_queue	= iscsit_response_queue,
6752ec5a8c1SNicholas Bellinger 	.iscsit_queue_data_in	= iscsit_queue_rsp,
6762ec5a8c1SNicholas Bellinger 	.iscsit_queue_status	= iscsit_queue_rsp,
677131e6abcSNicholas Bellinger 	.iscsit_aborted_task	= iscsit_aborted_task,
6782854bb23SVarun Prakash 	.iscsit_xmit_pdu	= iscsit_xmit_pdu,
679e8205ccaSVarun Prakash 	.iscsit_get_rx_pdu	= iscsit_get_rx_pdu,
680e70beee7SNicholas Bellinger 	.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
681baa4d64bSNicholas Bellinger };
682baa4d64bSNicholas Bellinger 
683e48354ceSNicholas Bellinger static int __init iscsi_target_init_module(void)
684e48354ceSNicholas Bellinger {
68588dcd2daSNicholas Bellinger 	int ret = 0, size;
686e48354ceSNicholas Bellinger 
687e48354ceSNicholas Bellinger 	pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
6883829f381SMarkus Elfring 	iscsit_global = kzalloc(sizeof(*iscsit_global), GFP_KERNEL);
689c46e22f1SMarkus Elfring 	if (!iscsit_global)
690e48354ceSNicholas Bellinger 		return -1;
691c46e22f1SMarkus Elfring 
69288dcd2daSNicholas Bellinger 	spin_lock_init(&iscsit_global->ts_bitmap_lock);
693e48354ceSNicholas Bellinger 	mutex_init(&auth_id_lock);
694e48354ceSNicholas Bellinger 	idr_init(&tiqn_idr);
695e48354ceSNicholas Bellinger 
6969ac8928eSChristoph Hellwig 	ret = target_register_template(&iscsi_ops);
6979ac8928eSChristoph Hellwig 	if (ret)
698e48354ceSNicholas Bellinger 		goto out;
699e48354ceSNicholas Bellinger 
70088dcd2daSNicholas Bellinger 	size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
70188dcd2daSNicholas Bellinger 	iscsit_global->ts_bitmap = vzalloc(size);
702c46e22f1SMarkus Elfring 	if (!iscsit_global->ts_bitmap)
703e48354ceSNicholas Bellinger 		goto configfs_out;
704e48354ceSNicholas Bellinger 
705d72d827fSMingzhe Zou 	if (!zalloc_cpumask_var(&iscsit_global->allowed_cpumask, GFP_KERNEL)) {
706d72d827fSMingzhe Zou 		pr_err("Unable to allocate iscsit_global->allowed_cpumask\n");
707d72d827fSMingzhe Zou 		goto bitmap_out;
708d72d827fSMingzhe Zou 	}
709d72d827fSMingzhe Zou 	cpumask_setall(iscsit_global->allowed_cpumask);
710d72d827fSMingzhe Zou 
711e48354ceSNicholas Bellinger 	lio_qr_cache = kmem_cache_create("lio_qr_cache",
712e48354ceSNicholas Bellinger 			sizeof(struct iscsi_queue_req),
713e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_queue_req), 0, NULL);
714e48354ceSNicholas Bellinger 	if (!lio_qr_cache) {
715621a4367SLeo Zhang 		pr_err("Unable to kmem_cache_create() for"
716e48354ceSNicholas Bellinger 				" lio_qr_cache\n");
717d72d827fSMingzhe Zou 		goto cpumask_out;
718e48354ceSNicholas Bellinger 	}
719e48354ceSNicholas Bellinger 
720e48354ceSNicholas Bellinger 	lio_dr_cache = kmem_cache_create("lio_dr_cache",
721e48354ceSNicholas Bellinger 			sizeof(struct iscsi_datain_req),
722e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_datain_req), 0, NULL);
723e48354ceSNicholas Bellinger 	if (!lio_dr_cache) {
724e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
725e48354ceSNicholas Bellinger 				" lio_dr_cache\n");
726e48354ceSNicholas Bellinger 		goto qr_out;
727e48354ceSNicholas Bellinger 	}
728e48354ceSNicholas Bellinger 
729e48354ceSNicholas Bellinger 	lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
730e48354ceSNicholas Bellinger 			sizeof(struct iscsi_ooo_cmdsn),
731e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_ooo_cmdsn), 0, NULL);
732e48354ceSNicholas Bellinger 	if (!lio_ooo_cache) {
733e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
734e48354ceSNicholas Bellinger 				" lio_ooo_cache\n");
735e48354ceSNicholas Bellinger 		goto dr_out;
736e48354ceSNicholas Bellinger 	}
737e48354ceSNicholas Bellinger 
738e48354ceSNicholas Bellinger 	lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
739e48354ceSNicholas Bellinger 			sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
740e48354ceSNicholas Bellinger 			0, NULL);
741e48354ceSNicholas Bellinger 	if (!lio_r2t_cache) {
742e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
743e48354ceSNicholas Bellinger 				" lio_r2t_cache\n");
744e48354ceSNicholas Bellinger 		goto ooo_out;
745e48354ceSNicholas Bellinger 	}
746e48354ceSNicholas Bellinger 
747baa4d64bSNicholas Bellinger 	iscsit_register_transport(&iscsi_target_transport);
748baa4d64bSNicholas Bellinger 
749e48354ceSNicholas Bellinger 	if (iscsit_load_discovery_tpg() < 0)
750e48354ceSNicholas Bellinger 		goto r2t_out;
751e48354ceSNicholas Bellinger 
752e48354ceSNicholas Bellinger 	return ret;
753e48354ceSNicholas Bellinger r2t_out:
7547f2c53bbSLino Sanfilippo 	iscsit_unregister_transport(&iscsi_target_transport);
755e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
756e48354ceSNicholas Bellinger ooo_out:
757e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
758e48354ceSNicholas Bellinger dr_out:
759e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
760e48354ceSNicholas Bellinger qr_out:
761e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
762d72d827fSMingzhe Zou cpumask_out:
763d72d827fSMingzhe Zou 	free_cpumask_var(iscsit_global->allowed_cpumask);
76488dcd2daSNicholas Bellinger bitmap_out:
76588dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
766e48354ceSNicholas Bellinger configfs_out:
7679ac8928eSChristoph Hellwig 	/* XXX: this probably wants it to be it's own unwind step.. */
7689ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7699ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
7709ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
771e48354ceSNicholas Bellinger out:
772e48354ceSNicholas Bellinger 	kfree(iscsit_global);
773e48354ceSNicholas Bellinger 	return -ENOMEM;
774e48354ceSNicholas Bellinger }
775e48354ceSNicholas Bellinger 
776e48354ceSNicholas Bellinger static void __exit iscsi_target_cleanup_module(void)
777e48354ceSNicholas Bellinger {
778e48354ceSNicholas Bellinger 	iscsit_release_discovery_tpg();
779baa4d64bSNicholas Bellinger 	iscsit_unregister_transport(&iscsi_target_transport);
780e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
781e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
782e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
783e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
784e48354ceSNicholas Bellinger 
7859ac8928eSChristoph Hellwig 	/*
7869ac8928eSChristoph Hellwig 	 * Shutdown discovery sessions and disable discovery TPG
7879ac8928eSChristoph Hellwig 	 */
7889ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7899ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
790e48354ceSNicholas Bellinger 
7919ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
792e48354ceSNicholas Bellinger 
793d72d827fSMingzhe Zou 	free_cpumask_var(iscsit_global->allowed_cpumask);
79488dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
795e48354ceSNicholas Bellinger 	kfree(iscsit_global);
796e48354ceSNicholas Bellinger }
797e48354ceSNicholas Bellinger 
798d2faaefbSVarun Prakash int iscsit_add_reject(
799be36d683SMax Gurtovoy 	struct iscsit_conn *conn,
800e48354ceSNicholas Bellinger 	u8 reason,
801ba159914SNicholas Bellinger 	unsigned char *buf)
802e48354ceSNicholas Bellinger {
80366cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd;
804e48354ceSNicholas Bellinger 
805676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
806e48354ceSNicholas Bellinger 	if (!cmd)
807e48354ceSNicholas Bellinger 		return -1;
808e48354ceSNicholas Bellinger 
809e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
810ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
811e48354ceSNicholas Bellinger 
8121c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
813e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
814e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
815aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
816e48354ceSNicholas Bellinger 		return -1;
817e48354ceSNicholas Bellinger 	}
818e48354ceSNicholas Bellinger 
819e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
8202fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
821e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
822e48354ceSNicholas Bellinger 
823e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
824e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
825e48354ceSNicholas Bellinger 
826e48354ceSNicholas Bellinger 	return -1;
827e48354ceSNicholas Bellinger }
828d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_add_reject);
829e48354ceSNicholas Bellinger 
830ba159914SNicholas Bellinger static int iscsit_add_reject_from_cmd(
83166cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
832e48354ceSNicholas Bellinger 	u8 reason,
833ba159914SNicholas Bellinger 	bool add_to_conn,
834ba159914SNicholas Bellinger 	unsigned char *buf)
835e48354ceSNicholas Bellinger {
836be36d683SMax Gurtovoy 	struct iscsit_conn *conn;
837cfe2b621SBart Van Assche 	const bool do_put = cmd->se_cmd.se_tfo != NULL;
838e48354ceSNicholas Bellinger 
839e48354ceSNicholas Bellinger 	if (!cmd->conn) {
840e48354ceSNicholas Bellinger 		pr_err("cmd->conn is NULL for ITT: 0x%08x\n",
841e48354ceSNicholas Bellinger 				cmd->init_task_tag);
842e48354ceSNicholas Bellinger 		return -1;
843e48354ceSNicholas Bellinger 	}
844e48354ceSNicholas Bellinger 	conn = cmd->conn;
845e48354ceSNicholas Bellinger 
846e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
847ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
848e48354ceSNicholas Bellinger 
8491c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
850e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
851e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
852aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
853e48354ceSNicholas Bellinger 		return -1;
854e48354ceSNicholas Bellinger 	}
855e48354ceSNicholas Bellinger 
856e48354ceSNicholas Bellinger 	if (add_to_conn) {
857e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
8582fbb471eSAndy Grover 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
859e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
860e48354ceSNicholas Bellinger 	}
861e48354ceSNicholas Bellinger 
862e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
863e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
8643e1c81a9SNicholas Bellinger 	/*
8653e1c81a9SNicholas Bellinger 	 * Perform the kref_put now if se_cmd has already been setup by
8663e1c81a9SNicholas Bellinger 	 * scsit_setup_scsi_cmd()
8673e1c81a9SNicholas Bellinger 	 */
868cfe2b621SBart Van Assche 	if (do_put) {
8693e1c81a9SNicholas Bellinger 		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
870afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
8713e1c81a9SNicholas Bellinger 	}
872e48354ceSNicholas Bellinger 	return -1;
873e48354ceSNicholas Bellinger }
874ba159914SNicholas Bellinger 
87566cd9d4eSMax Gurtovoy static int iscsit_add_reject_cmd(struct iscsit_cmd *cmd, u8 reason,
876ba159914SNicholas Bellinger 				 unsigned char *buf)
877ba159914SNicholas Bellinger {
878ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, true, buf);
879ba159914SNicholas Bellinger }
880ba159914SNicholas Bellinger 
88166cd9d4eSMax Gurtovoy int iscsit_reject_cmd(struct iscsit_cmd *cmd, u8 reason, unsigned char *buf)
882ba159914SNicholas Bellinger {
883ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, false, buf);
884ba159914SNicholas Bellinger }
885d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_reject_cmd);
886e48354ceSNicholas Bellinger 
887e48354ceSNicholas Bellinger /*
888e48354ceSNicholas Bellinger  * Map some portion of the allocated scatterlist to an iovec, suitable for
889bfb79eacSAndy Grover  * kernel sockets to copy data in/out.
890e48354ceSNicholas Bellinger  */
89166cd9d4eSMax Gurtovoy static int iscsit_map_iovec(struct iscsit_cmd *cmd, struct kvec *iov, int nvec,
8922e39f1c9SBart Van Assche 			    u32 data_offset, u32 data_length)
893e48354ceSNicholas Bellinger {
8942e39f1c9SBart Van Assche 	u32 i = 0, orig_data_length = data_length;
895e48354ceSNicholas Bellinger 	struct scatterlist *sg;
896e48354ceSNicholas Bellinger 	unsigned int page_off;
897e48354ceSNicholas Bellinger 
898e48354ceSNicholas Bellinger 	/*
899bfb79eacSAndy Grover 	 * We know each entry in t_data_sg contains a page.
900e48354ceSNicholas Bellinger 	 */
9012b16509cSImran Haider 	u32 ent = data_offset / PAGE_SIZE;
9022b16509cSImran Haider 
9032e39f1c9SBart Van Assche 	if (!data_length)
9042e39f1c9SBart Van Assche 		return 0;
9052e39f1c9SBart Van Assche 
9062b16509cSImran Haider 	if (ent >= cmd->se_cmd.t_data_nents) {
9072b16509cSImran Haider 		pr_err("Initial page entry out-of-bounds\n");
9082e39f1c9SBart Van Assche 		goto overflow;
9092b16509cSImran Haider 	}
9102b16509cSImran Haider 
9112b16509cSImran Haider 	sg = &cmd->se_cmd.t_data_sg[ent];
912e48354ceSNicholas Bellinger 	page_off = (data_offset % PAGE_SIZE);
913e48354ceSNicholas Bellinger 
914e48354ceSNicholas Bellinger 	cmd->first_data_sg = sg;
915e48354ceSNicholas Bellinger 	cmd->first_data_sg_off = page_off;
916e48354ceSNicholas Bellinger 
917e48354ceSNicholas Bellinger 	while (data_length) {
9182e39f1c9SBart Van Assche 		u32 cur_len;
9192e39f1c9SBart Van Assche 
9202e39f1c9SBart Van Assche 		if (WARN_ON_ONCE(!sg || i >= nvec))
9212e39f1c9SBart Van Assche 			goto overflow;
9222e39f1c9SBart Van Assche 
9232e39f1c9SBart Van Assche 		cur_len = min_t(u32, data_length, sg->length - page_off);
924e48354ceSNicholas Bellinger 
925e48354ceSNicholas Bellinger 		iov[i].iov_base = kmap(sg_page(sg)) + sg->offset + page_off;
926e48354ceSNicholas Bellinger 		iov[i].iov_len = cur_len;
927e48354ceSNicholas Bellinger 
928e48354ceSNicholas Bellinger 		data_length -= cur_len;
929e48354ceSNicholas Bellinger 		page_off = 0;
930e48354ceSNicholas Bellinger 		sg = sg_next(sg);
931e48354ceSNicholas Bellinger 		i++;
932e48354ceSNicholas Bellinger 	}
933e48354ceSNicholas Bellinger 
934e48354ceSNicholas Bellinger 	cmd->kmapped_nents = i;
935e48354ceSNicholas Bellinger 
936e48354ceSNicholas Bellinger 	return i;
9372e39f1c9SBart Van Assche 
9382e39f1c9SBart Van Assche overflow:
9392e39f1c9SBart Van Assche 	pr_err("offset %d + length %d overflow; %d/%d; sg-list:\n",
9402e39f1c9SBart Van Assche 	       data_offset, orig_data_length, i, nvec);
9412e39f1c9SBart Van Assche 	for_each_sg(cmd->se_cmd.t_data_sg, sg,
9422e39f1c9SBart Van Assche 		    cmd->se_cmd.t_data_nents, i) {
9432e39f1c9SBart Van Assche 		pr_err("[%d] off %d len %d\n",
9442e39f1c9SBart Van Assche 		       i, sg->offset, sg->length);
9452e39f1c9SBart Van Assche 	}
9462e39f1c9SBart Van Assche 	return -1;
947e48354ceSNicholas Bellinger }
948e48354ceSNicholas Bellinger 
94966cd9d4eSMax Gurtovoy static void iscsit_unmap_iovec(struct iscsit_cmd *cmd)
950e48354ceSNicholas Bellinger {
951e48354ceSNicholas Bellinger 	u32 i;
952e48354ceSNicholas Bellinger 	struct scatterlist *sg;
953e48354ceSNicholas Bellinger 
954e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
955e48354ceSNicholas Bellinger 
956e48354ceSNicholas Bellinger 	for (i = 0; i < cmd->kmapped_nents; i++)
957e48354ceSNicholas Bellinger 		kunmap(sg_page(&sg[i]));
958e48354ceSNicholas Bellinger }
959e48354ceSNicholas Bellinger 
960be36d683SMax Gurtovoy static void iscsit_ack_from_expstatsn(struct iscsit_conn *conn, u32 exp_statsn)
961e48354ceSNicholas Bellinger {
962f56cbbb4SNicholas Bellinger 	LIST_HEAD(ack_list);
96366cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd, *cmd_p;
964e48354ceSNicholas Bellinger 
965e48354ceSNicholas Bellinger 	conn->exp_statsn = exp_statsn;
966e48354ceSNicholas Bellinger 
9673e1c81a9SNicholas Bellinger 	if (conn->sess->sess_ops->RDMAExtensions)
9683e1c81a9SNicholas Bellinger 		return;
9693e1c81a9SNicholas Bellinger 
970e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
971f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
972e48354ceSNicholas Bellinger 		spin_lock(&cmd->istate_lock);
973e48354ceSNicholas Bellinger 		if ((cmd->i_state == ISTATE_SENT_STATUS) &&
97464c13330SSteve Hodgson 		    iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
975e48354ceSNicholas Bellinger 			cmd->i_state = ISTATE_REMOVE;
976e48354ceSNicholas Bellinger 			spin_unlock(&cmd->istate_lock);
977f56cbbb4SNicholas Bellinger 			list_move_tail(&cmd->i_conn_node, &ack_list);
978e48354ceSNicholas Bellinger 			continue;
979e48354ceSNicholas Bellinger 		}
980e48354ceSNicholas Bellinger 		spin_unlock(&cmd->istate_lock);
981e48354ceSNicholas Bellinger 	}
982e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
983f56cbbb4SNicholas Bellinger 
984f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
9855159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
986f56cbbb4SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
987f56cbbb4SNicholas Bellinger 	}
988e48354ceSNicholas Bellinger }
989e48354ceSNicholas Bellinger 
99066cd9d4eSMax Gurtovoy static int iscsit_allocate_iovecs(struct iscsit_cmd *cmd)
991e48354ceSNicholas Bellinger {
992f80e8ed3SNicholas Bellinger 	u32 iov_count = max(1UL, DIV_ROUND_UP(cmd->se_cmd.data_length, PAGE_SIZE));
993e48354ceSNicholas Bellinger 
994c0427f15SChristoph Hellwig 	iov_count += ISCSI_IOV_DATA_BUFFER;
995f1725110SMarkus Elfring 	cmd->iov_data = kcalloc(iov_count, sizeof(*cmd->iov_data), GFP_KERNEL);
996c46e22f1SMarkus Elfring 	if (!cmd->iov_data)
997e48354ceSNicholas Bellinger 		return -ENOMEM;
998e48354ceSNicholas Bellinger 
999e48354ceSNicholas Bellinger 	cmd->orig_iov_data_count = iov_count;
1000e48354ceSNicholas Bellinger 	return 0;
1001e48354ceSNicholas Bellinger }
1002e48354ceSNicholas Bellinger 
1003be36d683SMax Gurtovoy int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
1004e48354ceSNicholas Bellinger 			  unsigned char *buf)
1005e48354ceSNicholas Bellinger {
10063e1c81a9SNicholas Bellinger 	int data_direction, payload_length;
1007e48354ceSNicholas Bellinger 	struct iscsi_scsi_req *hdr;
1008d28b1169SAndy Grover 	int iscsi_task_attr;
1009d28b1169SAndy Grover 	int sam_task_attr;
1010e48354ceSNicholas Bellinger 
101104f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->cmd_pdus);
1012e48354ceSNicholas Bellinger 
1013e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_scsi_req *) buf;
1014e48354ceSNicholas Bellinger 	payload_length		= ntoh24(hdr->dlength);
1015e48354ceSNicholas Bellinger 
1016e48354ceSNicholas Bellinger 	/* FIXME; Add checks for AdditionalHeaderSegment */
1017e48354ceSNicholas Bellinger 
1018e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_WRITE) &&
1019e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1020e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
1021e48354ceSNicholas Bellinger 				" not set. Bad iSCSI Initiator.\n");
1022ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1023ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1024e48354ceSNicholas Bellinger 	}
1025e48354ceSNicholas Bellinger 
1026e48354ceSNicholas Bellinger 	if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
1027e48354ceSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
1028e48354ceSNicholas Bellinger 		/*
10294454b66cSNicholas Bellinger 		 * From RFC-3720 Section 10.3.1:
10304454b66cSNicholas Bellinger 		 *
10314454b66cSNicholas Bellinger 		 * "Either or both of R and W MAY be 1 when either the
10324454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length and/or Bidirectional Read
10334454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length are 0"
10344454b66cSNicholas Bellinger 		 *
10354454b66cSNicholas Bellinger 		 * For this case, go ahead and clear the unnecssary bits
10364454b66cSNicholas Bellinger 		 * to avoid any confusion with ->data_direction.
1037e48354ceSNicholas Bellinger 		 */
1038e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_READ;
1039e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
1040e48354ceSNicholas Bellinger 
10414454b66cSNicholas Bellinger 		pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
1042e48354ceSNicholas Bellinger 			" set when Expected Data Transfer Length is 0 for"
10434454b66cSNicholas Bellinger 			" CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
1044e48354ceSNicholas Bellinger 	}
1045e48354ceSNicholas Bellinger 
1046e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
1047e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
1048e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
1049e48354ceSNicholas Bellinger 			" MUST be set if Expected Data Transfer Length is not 0."
1050e48354ceSNicholas Bellinger 			" Bad iSCSI Initiator\n");
1051ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1052ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1053e48354ceSNicholas Bellinger 	}
1054e48354ceSNicholas Bellinger 
1055e48354ceSNicholas Bellinger 	if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
1056e48354ceSNicholas Bellinger 	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
1057e48354ceSNicholas Bellinger 		pr_err("Bidirectional operations not supported!\n");
1058ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1059ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1060e48354ceSNicholas Bellinger 	}
1061e48354ceSNicholas Bellinger 
1062e48354ceSNicholas Bellinger 	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1063e48354ceSNicholas Bellinger 		pr_err("Illegally set Immediate Bit in iSCSI Initiator"
1064e48354ceSNicholas Bellinger 				" Scsi Command PDU.\n");
1065ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1066ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1067e48354ceSNicholas Bellinger 	}
1068e48354ceSNicholas Bellinger 
1069e48354ceSNicholas Bellinger 	if (payload_length && !conn->sess->sess_ops->ImmediateData) {
1070e48354ceSNicholas Bellinger 		pr_err("ImmediateData=No but DataSegmentLength=%u,"
1071e48354ceSNicholas Bellinger 			" protocol error.\n", payload_length);
1072ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1073ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1074e48354ceSNicholas Bellinger 	}
1075e48354ceSNicholas Bellinger 
107650e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->data_length) == payload_length) &&
1077e48354ceSNicholas Bellinger 	    (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
1078e48354ceSNicholas Bellinger 		pr_err("Expected Data Transfer Length and Length of"
1079e48354ceSNicholas Bellinger 			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
1080e48354ceSNicholas Bellinger 			" bit is not set protocol error\n");
1081ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1082ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1083e48354ceSNicholas Bellinger 	}
1084e48354ceSNicholas Bellinger 
108550e5c87dSChristoph Hellwig 	if (payload_length > be32_to_cpu(hdr->data_length)) {
1086e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1087e48354ceSNicholas Bellinger 			" EDTL: %u, protocol error.\n", payload_length,
1088e48354ceSNicholas Bellinger 				hdr->data_length);
1089ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1090ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1091e48354ceSNicholas Bellinger 	}
1092e48354ceSNicholas Bellinger 
109321f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1094e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
109521f5aa7eSNicholas Bellinger 			" MaxXmitDataSegmentLength: %u, protocol error.\n",
109621f5aa7eSNicholas Bellinger 			payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
1097ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1098ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1099e48354ceSNicholas Bellinger 	}
1100e48354ceSNicholas Bellinger 
1101e48354ceSNicholas Bellinger 	if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
1102e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1103e48354ceSNicholas Bellinger 			" FirstBurstLength: %u, protocol error.\n",
1104e48354ceSNicholas Bellinger 			payload_length, conn->sess->sess_ops->FirstBurstLength);
1105ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1106ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1107e48354ceSNicholas Bellinger 	}
1108e48354ceSNicholas Bellinger 
1109e48354ceSNicholas Bellinger 	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
1110e48354ceSNicholas Bellinger 			 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE :
1111e48354ceSNicholas Bellinger 			  DMA_NONE;
1112e48354ceSNicholas Bellinger 
1113d28b1169SAndy Grover 	cmd->data_direction = data_direction;
1114d28b1169SAndy Grover 	iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK;
1115d28b1169SAndy Grover 	/*
1116d28b1169SAndy Grover 	 * Figure out the SAM Task Attribute for the incoming SCSI CDB
1117d28b1169SAndy Grover 	 */
1118d28b1169SAndy Grover 	if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
1119d28b1169SAndy Grover 	    (iscsi_task_attr == ISCSI_ATTR_SIMPLE))
112068d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1121d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
112268d81f40SChristoph Hellwig 		sam_task_attr = TCM_ORDERED_TAG;
1123d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
112468d81f40SChristoph Hellwig 		sam_task_attr = TCM_HEAD_TAG;
1125d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ACA)
112668d81f40SChristoph Hellwig 		sam_task_attr = TCM_ACA_TAG;
1127d28b1169SAndy Grover 	else {
1128d28b1169SAndy Grover 		pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
112968d81f40SChristoph Hellwig 			" TCM_SIMPLE_TAG\n", iscsi_task_attr);
113068d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1131d28b1169SAndy Grover 	}
1132d28b1169SAndy Grover 
1133e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_CMD;
1134e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_NEW_CMD;
1135e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
1136e48354ceSNicholas Bellinger 	cmd->immediate_data	= (payload_length) ? 1 : 0;
1137e48354ceSNicholas Bellinger 	cmd->unsolicited_data	= ((!(hdr->flags & ISCSI_FLAG_CMD_FINAL) &&
1138e48354ceSNicholas Bellinger 				     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) ? 1 : 0);
1139e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data)
1140e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;
1141e48354ceSNicholas Bellinger 
1142e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
11439547308bSAlexei Potashnik 	if (hdr->flags & ISCSI_FLAG_CMD_READ)
1144c1e34b64SSagi Grimberg 		cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
11459547308bSAlexei Potashnik 	else
1146e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag = 0xFFFFFFFF;
114750e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
114850e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1149e48354ceSNicholas Bellinger 	cmd->first_burst_len	= payload_length;
1150e48354ceSNicholas Bellinger 
11513e1c81a9SNicholas Bellinger 	if (!conn->sess->sess_ops->RDMAExtensions &&
11523e1c81a9SNicholas Bellinger 	     cmd->data_direction == DMA_FROM_DEVICE) {
1153e48354ceSNicholas Bellinger 		struct iscsi_datain_req *dr;
1154e48354ceSNicholas Bellinger 
1155e48354ceSNicholas Bellinger 		dr = iscsit_allocate_datain_req();
1156e48354ceSNicholas Bellinger 		if (!dr)
1157ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1158ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1159e48354ceSNicholas Bellinger 
1160e48354ceSNicholas Bellinger 		iscsit_attach_datain_req(cmd, dr);
1161e48354ceSNicholas Bellinger 	}
1162e48354ceSNicholas Bellinger 
1163e48354ceSNicholas Bellinger 	/*
1164065ca1e4SAndy Grover 	 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
1165065ca1e4SAndy Grover 	 */
1166a78b7136SMike Christie 	__target_init_cmd(&cmd->se_cmd, &iscsi_ops,
116750e5c87dSChristoph Hellwig 			 conn->sess->se_sess, be32_to_cpu(hdr->data_length),
116850e5c87dSChristoph Hellwig 			 cmd->data_direction, sam_task_attr,
1169a36840d8SSudhakar Panneerselvam 			 cmd->sense_buffer + 2, scsilun_to_int(&hdr->lun));
1170065ca1e4SAndy Grover 
1171065ca1e4SAndy Grover 	pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
1172065ca1e4SAndy Grover 		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
11733e1c81a9SNicholas Bellinger 		hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
11743e1c81a9SNicholas Bellinger 		conn->cid);
11753e1c81a9SNicholas Bellinger 
1176807b9515SBart Van Assche 	target_get_sess_cmd(&cmd->se_cmd, true);
1177065ca1e4SAndy Grover 
11780352c3d3SRoman Bolshakov 	cmd->se_cmd.tag = (__force u32)cmd->init_task_tag;
117908694199SMike Christie 	cmd->sense_reason = target_cmd_init_cdb(&cmd->se_cmd, hdr->cdb,
118008694199SMike Christie 						GFP_KERNEL);
118184b20b80SMartin K. Petersen 
1182de103c93SChristoph Hellwig 	if (cmd->sense_reason) {
1183de103c93SChristoph Hellwig 		if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
1184ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1185ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1186de103c93SChristoph Hellwig 		}
1187de103c93SChristoph Hellwig 
1188de103c93SChristoph Hellwig 		goto attach_cmd;
1189de103c93SChristoph Hellwig 	}
1190de103c93SChristoph Hellwig 
11919e95fb80SSudhakar Panneerselvam 	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd);
11929e95fb80SSudhakar Panneerselvam 	if (cmd->sense_reason)
11939e95fb80SSudhakar Panneerselvam 		goto attach_cmd;
11949e95fb80SSudhakar Panneerselvam 
1195987db587SSudhakar Panneerselvam 	cmd->sense_reason = target_cmd_parse_cdb(&cmd->se_cmd);
11969e95fb80SSudhakar Panneerselvam 	if (cmd->sense_reason)
11979e95fb80SSudhakar Panneerselvam 		goto attach_cmd;
11989e95fb80SSudhakar Panneerselvam 
1199de103c93SChristoph Hellwig 	if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
1200ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1201ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1202e48354ceSNicholas Bellinger 	}
1203e48354ceSNicholas Bellinger 
1204e48354ceSNicholas Bellinger attach_cmd:
1205e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
12062fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1207e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
1208e48354ceSNicholas Bellinger 	/*
1209e48354ceSNicholas Bellinger 	 * Check if we need to delay processing because of ALUA
1210e48354ceSNicholas Bellinger 	 * Active/NonOptimized primary access state..
1211e48354ceSNicholas Bellinger 	 */
1212e48354ceSNicholas Bellinger 	core_alua_check_nonop_delay(&cmd->se_cmd);
1213bfb79eacSAndy Grover 
12143e1c81a9SNicholas Bellinger 	return 0;
1215de103c93SChristoph Hellwig }
12163e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_scsi_cmd);
1217de103c93SChristoph Hellwig 
121866cd9d4eSMax Gurtovoy void iscsit_set_unsolicited_dataout(struct iscsit_cmd *cmd)
12193e1c81a9SNicholas Bellinger {
12203e1c81a9SNicholas Bellinger 	iscsit_set_dataout_sequence_values(cmd);
12213e1c81a9SNicholas Bellinger 
12223e1c81a9SNicholas Bellinger 	spin_lock_bh(&cmd->dataout_timeout_lock);
12233e1c81a9SNicholas Bellinger 	iscsit_start_dataout_timer(cmd, cmd->conn);
12243e1c81a9SNicholas Bellinger 	spin_unlock_bh(&cmd->dataout_timeout_lock);
12253e1c81a9SNicholas Bellinger }
12260300b114SBart Van Assche EXPORT_SYMBOL(iscsit_set_unsolicited_dataout);
12273e1c81a9SNicholas Bellinger 
1228be36d683SMax Gurtovoy int iscsit_process_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
12293e1c81a9SNicholas Bellinger 			    struct iscsi_scsi_req *hdr)
12303e1c81a9SNicholas Bellinger {
12313e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0;
1232e48354ceSNicholas Bellinger 	/*
1233e48354ceSNicholas Bellinger 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
1234e48354ceSNicholas Bellinger 	 * the Immediate Bit is not set, and no Immediate
1235e48354ceSNicholas Bellinger 	 * Data is attached.
1236e48354ceSNicholas Bellinger 	 *
1237e48354ceSNicholas Bellinger 	 * A PDU/CmdSN carrying Immediate Data can only
1238e48354ceSNicholas Bellinger 	 * be processed after the DataCRC has passed.
1239e48354ceSNicholas Bellinger 	 * If the DataCRC fails, the CmdSN MUST NOT
1240e48354ceSNicholas Bellinger 	 * be acknowledged. (See below)
1241e48354ceSNicholas Bellinger 	 */
1242e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
1243561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1244561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
1245561bf158SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1246561bf158SNicholas Bellinger 			return -1;
1247561bf158SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1248afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
12493e1c81a9SNicholas Bellinger 			return 0;
12503e1c81a9SNicholas Bellinger 		}
1251e48354ceSNicholas Bellinger 	}
1252e48354ceSNicholas Bellinger 
125350e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1254e48354ceSNicholas Bellinger 
1255e48354ceSNicholas Bellinger 	/*
1256e48354ceSNicholas Bellinger 	 * If no Immediate Data is attached, it's OK to return now.
1257e48354ceSNicholas Bellinger 	 */
1258e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
12593e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason && cmd->unsolicited_data)
12600300b114SBart Van Assche 			iscsit_set_unsolicited_dataout(cmd);
12613e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason)
12623e1c81a9SNicholas Bellinger 			return 0;
1263e48354ceSNicholas Bellinger 
1264afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
1265e48354ceSNicholas Bellinger 		return 0;
1266e48354ceSNicholas Bellinger 	}
1267e48354ceSNicholas Bellinger 
1268e48354ceSNicholas Bellinger 	/*
12693e1c81a9SNicholas Bellinger 	 * Early CHECK_CONDITIONs with ImmediateData never make it to command
12703e1c81a9SNicholas Bellinger 	 * execution.  These exceptions are processed in CmdSN order using
12713e1c81a9SNicholas Bellinger 	 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
1272e48354ceSNicholas Bellinger 	 */
12738fa4011eSBart Van Assche 	if (cmd->sense_reason)
12743e1c81a9SNicholas Bellinger 		return 1;
1275e48354ceSNicholas Bellinger 	/*
1276e48354ceSNicholas Bellinger 	 * Call directly into transport_generic_new_cmd() to perform
1277e48354ceSNicholas Bellinger 	 * the backend memory allocation.
1278e48354ceSNicholas Bellinger 	 */
1279de103c93SChristoph Hellwig 	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
1280561bf158SNicholas Bellinger 	if (cmd->sense_reason)
12813e1c81a9SNicholas Bellinger 		return 1;
1282e48354ceSNicholas Bellinger 
12833e1c81a9SNicholas Bellinger 	return 0;
12843e1c81a9SNicholas Bellinger }
12853e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_scsi_cmd);
12863e1c81a9SNicholas Bellinger 
12873e1c81a9SNicholas Bellinger static int
128866cd9d4eSMax Gurtovoy iscsit_get_immediate_data(struct iscsit_cmd *cmd, struct iscsi_scsi_req *hdr,
12893e1c81a9SNicholas Bellinger 			  bool dump_payload)
12903e1c81a9SNicholas Bellinger {
12913e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
12924b3766ecSBart Van Assche 	int rc;
12934b3766ecSBart Van Assche 
12943e1c81a9SNicholas Bellinger 	/*
12953e1c81a9SNicholas Bellinger 	 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
12963e1c81a9SNicholas Bellinger 	 */
12974b3766ecSBart Van Assche 	if (dump_payload) {
12984b3766ecSBart Van Assche 		u32 length = min(cmd->se_cmd.data_length - cmd->write_data_done,
12994b3766ecSBart Van Assche 				 cmd->first_burst_len);
13003e1c81a9SNicholas Bellinger 
13014b3766ecSBart Van Assche 		pr_debug("Dumping min(%d - %d, %d) = %d bytes of immediate data\n",
13024b3766ecSBart Van Assche 			 cmd->se_cmd.data_length, cmd->write_data_done,
13034b3766ecSBart Van Assche 			 cmd->first_burst_len, length);
13044b3766ecSBart Van Assche 		rc = iscsit_dump_data_payload(cmd->conn, length, 1);
13054b3766ecSBart Van Assche 		pr_debug("Finished dumping immediate data\n");
13064b3766ecSBart Van Assche 		if (rc < 0)
13074b3766ecSBart Van Assche 			immed_ret = IMMEDIATE_DATA_CANNOT_RECOVER;
13084b3766ecSBart Van Assche 	} else {
13093e1c81a9SNicholas Bellinger 		immed_ret = iscsit_handle_immediate_data(cmd, hdr,
13103e1c81a9SNicholas Bellinger 							 cmd->first_burst_len);
13114b3766ecSBart Van Assche 	}
13124b3766ecSBart Van Assche 
1313e48354ceSNicholas Bellinger 	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) {
1314e48354ceSNicholas Bellinger 		/*
1315e48354ceSNicholas Bellinger 		 * A PDU/CmdSN carrying Immediate Data passed
1316e48354ceSNicholas Bellinger 		 * DataCRC, check against ExpCmdSN/MaxCmdSN if
1317e48354ceSNicholas Bellinger 		 * Immediate Bit is not set.
1318e48354ceSNicholas Bellinger 		 */
1319561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd,
1320561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
13219d86a2beSNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1322561bf158SNicholas Bellinger 			return -1;
1323e48354ceSNicholas Bellinger 
13249d86a2beSNicholas Bellinger 		if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1325afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
13264b3766ecSBart Van Assche 
13274b3766ecSBart Van Assche 			return 0;
13283e1c81a9SNicholas Bellinger 		} else if (cmd->unsolicited_data)
13290300b114SBart Van Assche 			iscsit_set_unsolicited_dataout(cmd);
1330e48354ceSNicholas Bellinger 
1331e48354ceSNicholas Bellinger 	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
1332e48354ceSNicholas Bellinger 		/*
1333e48354ceSNicholas Bellinger 		 * Immediate Data failed DataCRC and ERL>=1,
1334e48354ceSNicholas Bellinger 		 * silently drop this PDU and let the initiator
1335e48354ceSNicholas Bellinger 		 * plug the CmdSN gap.
1336e48354ceSNicholas Bellinger 		 *
1337e48354ceSNicholas Bellinger 		 * FIXME: Send Unsolicited NOPIN with reserved
1338e48354ceSNicholas Bellinger 		 * TTT here to help the initiator figure out
1339e48354ceSNicholas Bellinger 		 * the missing CmdSN, although they should be
1340e48354ceSNicholas Bellinger 		 * intelligent enough to determine the missing
1341e48354ceSNicholas Bellinger 		 * CmdSN and issue a retry to plug the sequence.
1342e48354ceSNicholas Bellinger 		 */
1343e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_REMOVE;
13443e1c81a9SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, cmd->i_state);
1345e48354ceSNicholas Bellinger 	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */
1346e48354ceSNicholas Bellinger 		return -1;
1347e48354ceSNicholas Bellinger 
1348e48354ceSNicholas Bellinger 	return 0;
1349e48354ceSNicholas Bellinger }
1350e48354ceSNicholas Bellinger 
13513e1c81a9SNicholas Bellinger static int
1352be36d683SMax Gurtovoy iscsit_handle_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
13533e1c81a9SNicholas Bellinger 			   unsigned char *buf)
13543e1c81a9SNicholas Bellinger {
13553e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
13563e1c81a9SNicholas Bellinger 	int rc, immed_data;
13573e1c81a9SNicholas Bellinger 	bool dump_payload = false;
13583e1c81a9SNicholas Bellinger 
13593e1c81a9SNicholas Bellinger 	rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
13603e1c81a9SNicholas Bellinger 	if (rc < 0)
1361561bf158SNicholas Bellinger 		return 0;
13623e1c81a9SNicholas Bellinger 	/*
13633e1c81a9SNicholas Bellinger 	 * Allocation iovecs needed for struct socket operations for
13643e1c81a9SNicholas Bellinger 	 * traditional iSCSI block I/O.
13653e1c81a9SNicholas Bellinger 	 */
13663e1c81a9SNicholas Bellinger 	if (iscsit_allocate_iovecs(cmd) < 0) {
1367b815fc12SMike Christie 		return iscsit_reject_cmd(cmd,
1368ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
13693e1c81a9SNicholas Bellinger 	}
13703e1c81a9SNicholas Bellinger 	immed_data = cmd->immediate_data;
13713e1c81a9SNicholas Bellinger 
13723e1c81a9SNicholas Bellinger 	rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
13733e1c81a9SNicholas Bellinger 	if (rc < 0)
13743e1c81a9SNicholas Bellinger 		return rc;
13753e1c81a9SNicholas Bellinger 	else if (rc > 0)
13763e1c81a9SNicholas Bellinger 		dump_payload = true;
13773e1c81a9SNicholas Bellinger 
13783e1c81a9SNicholas Bellinger 	if (!immed_data)
13793e1c81a9SNicholas Bellinger 		return 0;
13803e1c81a9SNicholas Bellinger 
13813e1c81a9SNicholas Bellinger 	return iscsit_get_immediate_data(cmd, hdr, dump_payload);
13823e1c81a9SNicholas Bellinger }
13833e1c81a9SNicholas Bellinger 
1384e48354ceSNicholas Bellinger static u32 iscsit_do_crypto_hash_sg(
138569110e3cSHerbert Xu 	struct ahash_request *hash,
138666cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
1387e48354ceSNicholas Bellinger 	u32 data_offset,
1388e48354ceSNicholas Bellinger 	u32 data_length,
1389e48354ceSNicholas Bellinger 	u32 padding,
1390e48354ceSNicholas Bellinger 	u8 *pad_bytes)
1391e48354ceSNicholas Bellinger {
1392e48354ceSNicholas Bellinger 	u32 data_crc;
1393e48354ceSNicholas Bellinger 	struct scatterlist *sg;
1394e48354ceSNicholas Bellinger 	unsigned int page_off;
1395e48354ceSNicholas Bellinger 
139669110e3cSHerbert Xu 	crypto_ahash_init(hash);
1397e48354ceSNicholas Bellinger 
1398e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
1399e48354ceSNicholas Bellinger 	page_off = cmd->first_data_sg_off;
1400e48354ceSNicholas Bellinger 
14015528d031SVarun Prakash 	if (data_length && page_off) {
14025528d031SVarun Prakash 		struct scatterlist first_sg;
14035528d031SVarun Prakash 		u32 len = min_t(u32, data_length, sg->length - page_off);
14045528d031SVarun Prakash 
14055528d031SVarun Prakash 		sg_init_table(&first_sg, 1);
14065528d031SVarun Prakash 		sg_set_page(&first_sg, sg_page(sg), len, sg->offset + page_off);
14075528d031SVarun Prakash 
14085528d031SVarun Prakash 		ahash_request_set_crypt(hash, &first_sg, NULL, len);
14095528d031SVarun Prakash 		crypto_ahash_update(hash);
14105528d031SVarun Prakash 
14115528d031SVarun Prakash 		data_length -= len;
14125528d031SVarun Prakash 		sg = sg_next(sg);
14135528d031SVarun Prakash 	}
14145528d031SVarun Prakash 
1415e48354ceSNicholas Bellinger 	while (data_length) {
14165528d031SVarun Prakash 		u32 cur_len = min_t(u32, data_length, sg->length);
1417e48354ceSNicholas Bellinger 
141869110e3cSHerbert Xu 		ahash_request_set_crypt(hash, sg, NULL, cur_len);
141969110e3cSHerbert Xu 		crypto_ahash_update(hash);
1420e48354ceSNicholas Bellinger 
1421e48354ceSNicholas Bellinger 		data_length -= cur_len;
1422aa75679cSAlexei Potashnik 		/* iscsit_map_iovec has already checked for invalid sg pointers */
1423aa75679cSAlexei Potashnik 		sg = sg_next(sg);
1424e48354ceSNicholas Bellinger 	}
1425e48354ceSNicholas Bellinger 
1426e48354ceSNicholas Bellinger 	if (padding) {
1427e48354ceSNicholas Bellinger 		struct scatterlist pad_sg;
1428e48354ceSNicholas Bellinger 
1429e48354ceSNicholas Bellinger 		sg_init_one(&pad_sg, pad_bytes, padding);
143069110e3cSHerbert Xu 		ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc,
143169110e3cSHerbert Xu 					padding);
143269110e3cSHerbert Xu 		crypto_ahash_finup(hash);
143369110e3cSHerbert Xu 	} else {
143469110e3cSHerbert Xu 		ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0);
143569110e3cSHerbert Xu 		crypto_ahash_final(hash);
1436e48354ceSNicholas Bellinger 	}
1437e48354ceSNicholas Bellinger 
1438e48354ceSNicholas Bellinger 	return data_crc;
1439e48354ceSNicholas Bellinger }
1440e48354ceSNicholas Bellinger 
1441e1dfb21fSBart Van Assche static void iscsit_do_crypto_hash_buf(struct ahash_request *hash,
1442e1dfb21fSBart Van Assche 	const void *buf, u32 payload_length, u32 padding,
1443e1dfb21fSBart Van Assche 	const void *pad_bytes, void *data_crc)
1444e48354ceSNicholas Bellinger {
144569110e3cSHerbert Xu 	struct scatterlist sg[2];
1446e48354ceSNicholas Bellinger 
144769110e3cSHerbert Xu 	sg_init_table(sg, ARRAY_SIZE(sg));
144869110e3cSHerbert Xu 	sg_set_buf(sg, buf, payload_length);
1449679fcae4SLaura Abbott 	if (padding)
145069110e3cSHerbert Xu 		sg_set_buf(sg + 1, pad_bytes, padding);
1451e48354ceSNicholas Bellinger 
145269110e3cSHerbert Xu 	ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding);
1453e48354ceSNicholas Bellinger 
145469110e3cSHerbert Xu 	crypto_ahash_digest(hash);
1455e48354ceSNicholas Bellinger }
1456e48354ceSNicholas Bellinger 
14573e1c81a9SNicholas Bellinger int
1458be36d683SMax Gurtovoy __iscsit_check_dataout_hdr(struct iscsit_conn *conn, void *buf,
145966cd9d4eSMax Gurtovoy 			   struct iscsit_cmd *cmd, u32 payload_length,
14609a584bf9SVarun Prakash 			   bool *success)
1461e48354ceSNicholas Bellinger {
14629a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
1463e48354ceSNicholas Bellinger 	struct se_cmd *se_cmd;
14643e1c81a9SNicholas Bellinger 	int rc;
1465e48354ceSNicholas Bellinger 
1466e48354ceSNicholas Bellinger 	/* iSCSI write */
146704f3b31bSNicholas Bellinger 	atomic_long_add(payload_length, &conn->sess->rx_data_octets);
1468e48354ceSNicholas Bellinger 
1469e48354ceSNicholas Bellinger 	pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
1470e48354ceSNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
14713e1c81a9SNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
1472e48354ceSNicholas Bellinger 		payload_length, conn->cid);
1473e48354ceSNicholas Bellinger 
1474e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
1475e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT after"
1476e48354ceSNicholas Bellinger 			" last DataOUT received, dumping payload\n",
1477e48354ceSNicholas Bellinger 			cmd->init_task_tag);
1478e48354ceSNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1479e48354ceSNicholas Bellinger 	}
1480e48354ceSNicholas Bellinger 
1481e48354ceSNicholas Bellinger 	if (cmd->data_direction != DMA_TO_DEVICE) {
1482e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT for a"
1483e48354ceSNicholas Bellinger 			" NON-WRITE command.\n", cmd->init_task_tag);
148497c99b47SNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1485e48354ceSNicholas Bellinger 	}
1486e48354ceSNicholas Bellinger 	se_cmd = &cmd->se_cmd;
1487e48354ceSNicholas Bellinger 	iscsit_mod_dataout_timer(cmd);
1488e48354ceSNicholas Bellinger 
148950e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->offset) + payload_length) > cmd->se_cmd.data_length) {
1490de3493aeSBart Van Assche 		pr_err("DataOut Offset: %u, Length %u greater than iSCSI Command EDTL %u, protocol error.\n",
1491de3493aeSBart Van Assche 		       be32_to_cpu(hdr->offset), payload_length,
1492de3493aeSBart Van Assche 		       cmd->se_cmd.data_length);
1493ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf);
1494e48354ceSNicholas Bellinger 	}
1495e48354ceSNicholas Bellinger 
1496e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data) {
1497e48354ceSNicholas Bellinger 		int dump_unsolicited_data = 0;
1498e48354ceSNicholas Bellinger 
1499e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->InitialR2T) {
1500e48354ceSNicholas Bellinger 			pr_err("Received unexpected unsolicited data"
1501e48354ceSNicholas Bellinger 				" while InitialR2T=Yes, protocol error.\n");
1502e48354ceSNicholas Bellinger 			transport_send_check_condition_and_sense(&cmd->se_cmd,
1503e48354ceSNicholas Bellinger 					TCM_UNEXPECTED_UNSOLICITED_DATA, 0);
1504e48354ceSNicholas Bellinger 			return -1;
1505e48354ceSNicholas Bellinger 		}
1506e48354ceSNicholas Bellinger 		/*
1507e48354ceSNicholas Bellinger 		 * Special case for dealing with Unsolicited DataOUT
1508e48354ceSNicholas Bellinger 		 * and Unsupported SAM WRITE Opcodes and SE resource allocation
1509e48354ceSNicholas Bellinger 		 * failures;
1510e48354ceSNicholas Bellinger 		 */
1511e48354ceSNicholas Bellinger 
1512e48354ceSNicholas Bellinger 		/* Something's amiss if we're not in WRITE_PENDING state... */
1513e48354ceSNicholas Bellinger 		WARN_ON(se_cmd->t_state != TRANSPORT_WRITE_PENDING);
1514de103c93SChristoph Hellwig 		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE))
1515e48354ceSNicholas Bellinger 			dump_unsolicited_data = 1;
1516e48354ceSNicholas Bellinger 
1517e48354ceSNicholas Bellinger 		if (dump_unsolicited_data) {
1518e48354ceSNicholas Bellinger 			/*
1519e48354ceSNicholas Bellinger 			 * Check if a delayed TASK_ABORTED status needs to
1520e48354ceSNicholas Bellinger 			 * be sent now if the ISCSI_FLAG_CMD_FINAL has been
15215a342521SBart Van Assche 			 * received with the unsolicited data out.
1522e48354ceSNicholas Bellinger 			 */
1523e48354ceSNicholas Bellinger 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
1524e48354ceSNicholas Bellinger 				iscsit_stop_dataout_timer(cmd);
1525e48354ceSNicholas Bellinger 
1526e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1527e48354ceSNicholas Bellinger 		}
1528e48354ceSNicholas Bellinger 	} else {
1529e48354ceSNicholas Bellinger 		/*
1530e48354ceSNicholas Bellinger 		 * For the normal solicited data path:
1531e48354ceSNicholas Bellinger 		 *
1532e48354ceSNicholas Bellinger 		 * Check for a delayed TASK_ABORTED status and dump any
1533e48354ceSNicholas Bellinger 		 * incoming data out payload if one exists.  Also, when the
1534e48354ceSNicholas Bellinger 		 * ISCSI_FLAG_CMD_FINAL is set to denote the end of the current
1535e48354ceSNicholas Bellinger 		 * data out sequence, we decrement outstanding_r2ts.  Once
1536e48354ceSNicholas Bellinger 		 * outstanding_r2ts reaches zero, go ahead and send the delayed
1537e48354ceSNicholas Bellinger 		 * TASK_ABORTED status.
1538e48354ceSNicholas Bellinger 		 */
15397d680f3bSChristoph Hellwig 		if (se_cmd->transport_state & CMD_T_ABORTED) {
1540aaa00cc9SBart Van Assche 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL &&
1541aaa00cc9SBart Van Assche 			    --cmd->outstanding_r2ts < 1)
1542e48354ceSNicholas Bellinger 				iscsit_stop_dataout_timer(cmd);
1543e48354ceSNicholas Bellinger 
1544e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1545e48354ceSNicholas Bellinger 		}
1546e48354ceSNicholas Bellinger 	}
1547e48354ceSNicholas Bellinger 	/*
15480d5efb8aSBart Van Assche 	 * Perform DataSN, DataSequenceInOrder, DataPDUInOrder, and
1549e48354ceSNicholas Bellinger 	 * within-command recovery checks before receiving the payload.
1550e48354ceSNicholas Bellinger 	 */
15513e1c81a9SNicholas Bellinger 	rc = iscsit_check_pre_dataout(cmd, buf);
15523e1c81a9SNicholas Bellinger 	if (rc == DATAOUT_WITHIN_COMMAND_RECOVERY)
1553e48354ceSNicholas Bellinger 		return 0;
15543e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_CANNOT_RECOVER)
1555e48354ceSNicholas Bellinger 		return -1;
15569a584bf9SVarun Prakash 	*success = true;
15573e1c81a9SNicholas Bellinger 	return 0;
15583e1c81a9SNicholas Bellinger }
15599a584bf9SVarun Prakash EXPORT_SYMBOL(__iscsit_check_dataout_hdr);
15609a584bf9SVarun Prakash 
15619a584bf9SVarun Prakash int
1562be36d683SMax Gurtovoy iscsit_check_dataout_hdr(struct iscsit_conn *conn, void *buf,
156366cd9d4eSMax Gurtovoy 			 struct iscsit_cmd **out_cmd)
15649a584bf9SVarun Prakash {
15659a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
156666cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd;
15679a584bf9SVarun Prakash 	u32 payload_length = ntoh24(hdr->dlength);
15689a584bf9SVarun Prakash 	int rc;
15699a584bf9SVarun Prakash 	bool success = false;
15709a584bf9SVarun Prakash 
15719a584bf9SVarun Prakash 	if (!payload_length) {
15729a584bf9SVarun Prakash 		pr_warn_ratelimited("DataOUT payload is ZERO, ignoring.\n");
15739a584bf9SVarun Prakash 		return 0;
15749a584bf9SVarun Prakash 	}
15759a584bf9SVarun Prakash 
15769a584bf9SVarun Prakash 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
15779a584bf9SVarun Prakash 		pr_err_ratelimited("DataSegmentLength: %u is greater than"
15789a584bf9SVarun Prakash 			" MaxXmitDataSegmentLength: %u\n", payload_length,
15799a584bf9SVarun Prakash 			conn->conn_ops->MaxXmitDataSegmentLength);
15809a584bf9SVarun Prakash 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf);
15819a584bf9SVarun Prakash 	}
15829a584bf9SVarun Prakash 
15839a584bf9SVarun Prakash 	cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, payload_length);
15849a584bf9SVarun Prakash 	if (!cmd)
15859a584bf9SVarun Prakash 		return 0;
15869a584bf9SVarun Prakash 
15879a584bf9SVarun Prakash 	rc = __iscsit_check_dataout_hdr(conn, buf, cmd, payload_length, &success);
15889a584bf9SVarun Prakash 
15899a584bf9SVarun Prakash 	if (success)
15909a584bf9SVarun Prakash 		*out_cmd = cmd;
15919a584bf9SVarun Prakash 
15929a584bf9SVarun Prakash 	return rc;
15939a584bf9SVarun Prakash }
15943e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_hdr);
15953e1c81a9SNicholas Bellinger 
15963e1c81a9SNicholas Bellinger static int
1597be36d683SMax Gurtovoy iscsit_get_dataout(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
15983e1c81a9SNicholas Bellinger 		   struct iscsi_data *hdr)
15993e1c81a9SNicholas Bellinger {
16003e1c81a9SNicholas Bellinger 	struct kvec *iov;
16013e1c81a9SNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0;
16020ca650c1SBart Van Assche 	u32 payload_length;
16033e1c81a9SNicholas Bellinger 	int iov_ret, data_crc_failed = 0;
16043e1c81a9SNicholas Bellinger 
16050ca650c1SBart Van Assche 	payload_length = min_t(u32, cmd->se_cmd.data_length,
16060ca650c1SBart Van Assche 			       ntoh24(hdr->dlength));
1607e48354ceSNicholas Bellinger 	rx_size += payload_length;
1608e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
1609e48354ceSNicholas Bellinger 
16102e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, iov, cmd->orig_iov_data_count - 2,
16112e39f1c9SBart Van Assche 				   be32_to_cpu(hdr->offset), payload_length);
1612e48354ceSNicholas Bellinger 	if (iov_ret < 0)
1613e48354ceSNicholas Bellinger 		return -1;
1614e48354ceSNicholas Bellinger 
1615e48354ceSNicholas Bellinger 	iov_count += iov_ret;
1616e48354ceSNicholas Bellinger 
1617e48354ceSNicholas Bellinger 	padding = ((-payload_length) & 3);
1618e48354ceSNicholas Bellinger 	if (padding != 0) {
1619e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
1620e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
1621e48354ceSNicholas Bellinger 		rx_size += padding;
1622e48354ceSNicholas Bellinger 		pr_debug("Receiving %u padding bytes.\n", padding);
1623e48354ceSNicholas Bellinger 	}
1624e48354ceSNicholas Bellinger 
1625e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1626e48354ceSNicholas Bellinger 		iov[iov_count].iov_base = &checksum;
1627e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
1628e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
1629e48354ceSNicholas Bellinger 	}
1630e48354ceSNicholas Bellinger 
16312e39f1c9SBart Van Assche 	WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count);
1632e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
1633e48354ceSNicholas Bellinger 
1634e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
1635e48354ceSNicholas Bellinger 
1636e48354ceSNicholas Bellinger 	if (rx_got != rx_size)
1637e48354ceSNicholas Bellinger 		return -1;
1638e48354ceSNicholas Bellinger 
1639e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1640e48354ceSNicholas Bellinger 		u32 data_crc;
1641e48354ceSNicholas Bellinger 
164269110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
164350e5c87dSChristoph Hellwig 						    be32_to_cpu(hdr->offset),
164450e5c87dSChristoph Hellwig 						    payload_length, padding,
1645e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
1646e48354ceSNicholas Bellinger 
1647e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
1648e48354ceSNicholas Bellinger 			pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
1649e48354ceSNicholas Bellinger 				" DataSN: 0x%08x, CRC32C DataDigest 0x%08x"
1650e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n",
1651e48354ceSNicholas Bellinger 				hdr->itt, hdr->offset, payload_length,
1652e48354ceSNicholas Bellinger 				hdr->datasn, checksum, data_crc);
1653e48354ceSNicholas Bellinger 			data_crc_failed = 1;
1654e48354ceSNicholas Bellinger 		} else {
1655e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
1656e48354ceSNicholas Bellinger 				" %u bytes of Data Out\n", checksum,
1657e48354ceSNicholas Bellinger 				payload_length);
1658e48354ceSNicholas Bellinger 		}
1659e48354ceSNicholas Bellinger 	}
16603e1c81a9SNicholas Bellinger 
16613e1c81a9SNicholas Bellinger 	return data_crc_failed;
16623e1c81a9SNicholas Bellinger }
16633e1c81a9SNicholas Bellinger 
16643e1c81a9SNicholas Bellinger int
166566cd9d4eSMax Gurtovoy iscsit_check_dataout_payload(struct iscsit_cmd *cmd, struct iscsi_data *hdr,
16663e1c81a9SNicholas Bellinger 			     bool data_crc_failed)
16673e1c81a9SNicholas Bellinger {
1668be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
16693e1c81a9SNicholas Bellinger 	int rc, ooo_cmdsn;
1670e48354ceSNicholas Bellinger 	/*
1671e48354ceSNicholas Bellinger 	 * Increment post receive data and CRC values or perform
1672e48354ceSNicholas Bellinger 	 * within-command recovery.
1673e48354ceSNicholas Bellinger 	 */
16743e1c81a9SNicholas Bellinger 	rc = iscsit_check_post_dataout(cmd, (unsigned char *)hdr, data_crc_failed);
16753e1c81a9SNicholas Bellinger 	if ((rc == DATAOUT_NORMAL) || (rc == DATAOUT_WITHIN_COMMAND_RECOVERY))
1676e48354ceSNicholas Bellinger 		return 0;
16773e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_SEND_R2T) {
1678e48354ceSNicholas Bellinger 		iscsit_set_dataout_sequence_values(cmd);
16793e1c81a9SNicholas Bellinger 		conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
16803e1c81a9SNicholas Bellinger 	} else if (rc == DATAOUT_SEND_TO_TRANSPORT) {
1681e48354ceSNicholas Bellinger 		/*
1682e48354ceSNicholas Bellinger 		 * Handle extra special case for out of order
1683e48354ceSNicholas Bellinger 		 * Unsolicited Data Out.
1684e48354ceSNicholas Bellinger 		 */
1685e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
1686e48354ceSNicholas Bellinger 		ooo_cmdsn = (cmd->cmd_flags & ICF_OOO_CMDSN);
1687e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
1688e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
1689e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
1690e48354ceSNicholas Bellinger 
1691e48354ceSNicholas Bellinger 		iscsit_stop_dataout_timer(cmd);
169267441b68SChristoph Hellwig 		if (ooo_cmdsn)
169367441b68SChristoph Hellwig 			return 0;
169467441b68SChristoph Hellwig 		target_execute_cmd(&cmd->se_cmd);
169567441b68SChristoph Hellwig 		return 0;
1696e48354ceSNicholas Bellinger 	} else /* DATAOUT_CANNOT_RECOVER */
1697e48354ceSNicholas Bellinger 		return -1;
1698e48354ceSNicholas Bellinger 
1699e48354ceSNicholas Bellinger 	return 0;
1700e48354ceSNicholas Bellinger }
17013e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_payload);
1702e48354ceSNicholas Bellinger 
1703be36d683SMax Gurtovoy static int iscsit_handle_data_out(struct iscsit_conn *conn, unsigned char *buf)
17043e1c81a9SNicholas Bellinger {
170566cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd = NULL;
17063e1c81a9SNicholas Bellinger 	struct iscsi_data *hdr = (struct iscsi_data *)buf;
17073e1c81a9SNicholas Bellinger 	int rc;
17083e1c81a9SNicholas Bellinger 	bool data_crc_failed = false;
17093e1c81a9SNicholas Bellinger 
17103e1c81a9SNicholas Bellinger 	rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
17113e1c81a9SNicholas Bellinger 	if (rc < 0)
1712561bf158SNicholas Bellinger 		return 0;
17133e1c81a9SNicholas Bellinger 	else if (!cmd)
17143e1c81a9SNicholas Bellinger 		return 0;
17153e1c81a9SNicholas Bellinger 
17163e1c81a9SNicholas Bellinger 	rc = iscsit_get_dataout(conn, cmd, hdr);
17173e1c81a9SNicholas Bellinger 	if (rc < 0)
17183e1c81a9SNicholas Bellinger 		return rc;
17193e1c81a9SNicholas Bellinger 	else if (rc > 0)
17203e1c81a9SNicholas Bellinger 		data_crc_failed = true;
17213e1c81a9SNicholas Bellinger 
17223e1c81a9SNicholas Bellinger 	return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
17233e1c81a9SNicholas Bellinger }
17243e1c81a9SNicholas Bellinger 
1725be36d683SMax Gurtovoy int iscsit_setup_nop_out(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
1726778de368SNicholas Bellinger 			 struct iscsi_nopout *hdr)
1727e48354ceSNicholas Bellinger {
1728778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1729e48354ceSNicholas Bellinger 
1730a3662605SArshad Hussain 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1731a3662605SArshad Hussain 		pr_err("NopOUT Flag's, Left Most Bit not set, protocol error.\n");
1732a3662605SArshad Hussain 		if (!cmd)
1733a3662605SArshad Hussain 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
1734a3662605SArshad Hussain 						 (unsigned char *)hdr);
1735a3662605SArshad Hussain 
1736a3662605SArshad Hussain 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1737a3662605SArshad Hussain 					 (unsigned char *)hdr);
1738a3662605SArshad Hussain 	}
1739a3662605SArshad Hussain 
174066c7db68SChristoph Hellwig 	if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1741e48354ceSNicholas Bellinger 		pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
1742e48354ceSNicholas Bellinger 			" not set, protocol error.\n");
174328aaa950SNicholas Bellinger 		if (!cmd)
174428aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
174528aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
174628aaa950SNicholas Bellinger 
1747ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1748ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1749e48354ceSNicholas Bellinger 	}
1750e48354ceSNicholas Bellinger 
175121f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1752e48354ceSNicholas Bellinger 		pr_err("NOPOUT Ping Data DataSegmentLength: %u is"
175321f5aa7eSNicholas Bellinger 			" greater than MaxXmitDataSegmentLength: %u, protocol"
1754e48354ceSNicholas Bellinger 			" error.\n", payload_length,
175521f5aa7eSNicholas Bellinger 			conn->conn_ops->MaxXmitDataSegmentLength);
175628aaa950SNicholas Bellinger 		if (!cmd)
175728aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
175828aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
175928aaa950SNicholas Bellinger 
1760ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1761ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1762e48354ceSNicholas Bellinger 	}
1763e48354ceSNicholas Bellinger 
17643e1c81a9SNicholas Bellinger 	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
1765e48354ceSNicholas Bellinger 		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
176666c7db68SChristoph Hellwig 		hdr->itt == RESERVED_ITT ? "Response" : "Request",
1767e48354ceSNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
1768e48354ceSNicholas Bellinger 		payload_length);
1769e48354ceSNicholas Bellinger 	/*
1770e48354ceSNicholas Bellinger 	 * This is not a response to a Unsolicited NopIN, which means
1771e48354ceSNicholas Bellinger 	 * it can either be a NOPOUT ping request (with a valid ITT),
1772e48354ceSNicholas Bellinger 	 * or a NOPOUT not requesting a NOPIN (with a reserved ITT).
177366cd9d4eSMax Gurtovoy 	 * Either way, make sure we allocate an struct iscsit_cmd, as both
1774e48354ceSNicholas Bellinger 	 * can contain ping data.
1775e48354ceSNicholas Bellinger 	 */
177650e5c87dSChristoph Hellwig 	if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1777e48354ceSNicholas Bellinger 		cmd->iscsi_opcode	= ISCSI_OP_NOOP_OUT;
1778e48354ceSNicholas Bellinger 		cmd->i_state		= ISTATE_SEND_NOPIN;
1779e48354ceSNicholas Bellinger 		cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ?
1780e48354ceSNicholas Bellinger 						1 : 0);
1781e48354ceSNicholas Bellinger 		conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
1782e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag	= 0xFFFFFFFF;
178350e5c87dSChristoph Hellwig 		cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
178450e5c87dSChristoph Hellwig 		cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1785e48354ceSNicholas Bellinger 		cmd->data_direction	= DMA_NONE;
1786e48354ceSNicholas Bellinger 	}
1787e48354ceSNicholas Bellinger 
1788778de368SNicholas Bellinger 	return 0;
1789778de368SNicholas Bellinger }
1790778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_nop_out);
1791778de368SNicholas Bellinger 
1792be36d683SMax Gurtovoy int iscsit_process_nop_out(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
1793778de368SNicholas Bellinger 			   struct iscsi_nopout *hdr)
1794778de368SNicholas Bellinger {
179566cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd_p = NULL;
1796778de368SNicholas Bellinger 	int cmdsn_ret = 0;
1797778de368SNicholas Bellinger 	/*
1798778de368SNicholas Bellinger 	 * Initiator is expecting a NopIN ping reply..
1799778de368SNicholas Bellinger 	 */
1800778de368SNicholas Bellinger 	if (hdr->itt != RESERVED_ITT) {
18017cbfcc95SNicholas Bellinger 		if (!cmd)
18027cbfcc95SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
18037cbfcc95SNicholas Bellinger 						(unsigned char *)hdr);
1804778de368SNicholas Bellinger 
1805778de368SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
1806778de368SNicholas Bellinger 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1807778de368SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
1808778de368SNicholas Bellinger 
1809778de368SNicholas Bellinger 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1810778de368SNicholas Bellinger 
1811778de368SNicholas Bellinger 		if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1812778de368SNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
1813778de368SNicholas Bellinger 							 cmd->i_state);
1814778de368SNicholas Bellinger 			return 0;
1815778de368SNicholas Bellinger 		}
1816778de368SNicholas Bellinger 
1817561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1818561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
1819778de368SNicholas Bellinger                 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
1820778de368SNicholas Bellinger 			return 0;
1821778de368SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1822ba159914SNicholas Bellinger 			return -1;
1823778de368SNicholas Bellinger 
1824778de368SNicholas Bellinger 		return 0;
1825778de368SNicholas Bellinger 	}
1826778de368SNicholas Bellinger 	/*
1827778de368SNicholas Bellinger 	 * This was a response to a unsolicited NOPIN ping.
1828778de368SNicholas Bellinger 	 */
1829778de368SNicholas Bellinger 	if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
1830778de368SNicholas Bellinger 		cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
1831778de368SNicholas Bellinger 		if (!cmd_p)
1832778de368SNicholas Bellinger 			return -EINVAL;
1833778de368SNicholas Bellinger 
1834778de368SNicholas Bellinger 		iscsit_stop_nopin_response_timer(conn);
1835778de368SNicholas Bellinger 
1836778de368SNicholas Bellinger 		cmd_p->i_state = ISTATE_REMOVE;
1837778de368SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
1838778de368SNicholas Bellinger 
1839778de368SNicholas Bellinger 		iscsit_start_nopin_timer(conn);
1840778de368SNicholas Bellinger 		return 0;
1841778de368SNicholas Bellinger 	}
1842778de368SNicholas Bellinger 	/*
1843778de368SNicholas Bellinger 	 * Otherwise, initiator is not expecting a NOPIN is response.
1844778de368SNicholas Bellinger 	 * Just ignore for now.
1845778de368SNicholas Bellinger 	 */
18461a40f0a3SVarun Prakash 
18471a40f0a3SVarun Prakash 	if (cmd)
18481a40f0a3SVarun Prakash 		iscsit_free_cmd(cmd, false);
18491a40f0a3SVarun Prakash 
1850778de368SNicholas Bellinger         return 0;
1851778de368SNicholas Bellinger }
1852778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_nop_out);
1853778de368SNicholas Bellinger 
1854be36d683SMax Gurtovoy static int iscsit_handle_nop_out(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
1855778de368SNicholas Bellinger 				 unsigned char *buf)
1856778de368SNicholas Bellinger {
1857778de368SNicholas Bellinger 	unsigned char *ping_data = NULL;
1858778de368SNicholas Bellinger 	struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
1859778de368SNicholas Bellinger 	struct kvec *iov = NULL;
1860778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1861778de368SNicholas Bellinger 	int ret;
1862778de368SNicholas Bellinger 
1863778de368SNicholas Bellinger 	ret = iscsit_setup_nop_out(conn, cmd, hdr);
1864778de368SNicholas Bellinger 	if (ret < 0)
1865561bf158SNicholas Bellinger 		return 0;
1866778de368SNicholas Bellinger 	/*
1867778de368SNicholas Bellinger 	 * Handle NOP-OUT payload for traditional iSCSI sockets
1868778de368SNicholas Bellinger 	 */
186950e5c87dSChristoph Hellwig 	if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1870778de368SNicholas Bellinger 		u32 checksum, data_crc, padding = 0;
1871778de368SNicholas Bellinger 		int niov = 0, rx_got, rx_size = payload_length;
1872778de368SNicholas Bellinger 
1873e48354ceSNicholas Bellinger 		ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
1874e48354ceSNicholas Bellinger 		if (!ping_data) {
1875e48354ceSNicholas Bellinger 			ret = -1;
1876e48354ceSNicholas Bellinger 			goto out;
1877e48354ceSNicholas Bellinger 		}
1878e48354ceSNicholas Bellinger 
1879e48354ceSNicholas Bellinger 		iov = &cmd->iov_misc[0];
1880e48354ceSNicholas Bellinger 		iov[niov].iov_base	= ping_data;
1881e48354ceSNicholas Bellinger 		iov[niov++].iov_len	= payload_length;
1882e48354ceSNicholas Bellinger 
1883e48354ceSNicholas Bellinger 		padding = ((-payload_length) & 3);
1884e48354ceSNicholas Bellinger 		if (padding != 0) {
1885e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
1886e48354ceSNicholas Bellinger 				" for padding.\n", padding);
1887e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &cmd->pad_bytes;
1888e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= padding;
1889e48354ceSNicholas Bellinger 			rx_size += padding;
1890e48354ceSNicholas Bellinger 		}
1891e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1892e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
1893e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
1894e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
1895e48354ceSNicholas Bellinger 		}
1896e48354ceSNicholas Bellinger 
18972e39f1c9SBart Van Assche 		WARN_ON_ONCE(niov > ARRAY_SIZE(cmd->iov_misc));
1898e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &cmd->iov_misc[0], niov, rx_size);
1899e48354ceSNicholas Bellinger 		if (rx_got != rx_size) {
1900e48354ceSNicholas Bellinger 			ret = -1;
1901e48354ceSNicholas Bellinger 			goto out;
1902e48354ceSNicholas Bellinger 		}
1903e48354ceSNicholas Bellinger 
1904e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1905e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data,
1906e1dfb21fSBart Van Assche 						  payload_length, padding,
1907e1dfb21fSBart Van Assche 						  cmd->pad_bytes, &data_crc);
1908e48354ceSNicholas Bellinger 
1909e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
1910e48354ceSNicholas Bellinger 				pr_err("Ping data CRC32C DataDigest"
1911e48354ceSNicholas Bellinger 				" 0x%08x does not match computed 0x%08x\n",
1912e48354ceSNicholas Bellinger 					checksum, data_crc);
1913e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
1914e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
1915e48354ceSNicholas Bellinger 					" NOPOUT Ping DataCRC failure while in"
1916e48354ceSNicholas Bellinger 						" ERL=0.\n");
1917e48354ceSNicholas Bellinger 					ret = -1;
1918e48354ceSNicholas Bellinger 					goto out;
1919e48354ceSNicholas Bellinger 				} else {
1920e48354ceSNicholas Bellinger 					/*
1921e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
1922e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
1923e48354ceSNicholas Bellinger 					 */
1924e48354ceSNicholas Bellinger 					pr_debug("Dropping NOPOUT"
1925e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
1926e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
1927e48354ceSNicholas Bellinger 					ret = 0;
1928e48354ceSNicholas Bellinger 					goto out;
1929e48354ceSNicholas Bellinger 				}
1930e48354ceSNicholas Bellinger 			} else {
1931e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
1932e48354ceSNicholas Bellinger 				" 0x%08x for %u bytes of ping data.\n",
1933e48354ceSNicholas Bellinger 					checksum, payload_length);
1934e48354ceSNicholas Bellinger 			}
1935e48354ceSNicholas Bellinger 		}
1936e48354ceSNicholas Bellinger 
1937e48354ceSNicholas Bellinger 		ping_data[payload_length] = '\0';
1938e48354ceSNicholas Bellinger 		/*
193966cd9d4eSMax Gurtovoy 		 * Attach ping data to struct iscsit_cmd->buf_ptr.
1940e48354ceSNicholas Bellinger 		 */
19418359cf43SJörn Engel 		cmd->buf_ptr = ping_data;
1942e48354ceSNicholas Bellinger 		cmd->buf_ptr_size = payload_length;
1943e48354ceSNicholas Bellinger 
1944e48354ceSNicholas Bellinger 		pr_debug("Got %u bytes of NOPOUT ping"
1945e48354ceSNicholas Bellinger 			" data.\n", payload_length);
1946e48354ceSNicholas Bellinger 		pr_debug("Ping Data: \"%s\"\n", ping_data);
1947e48354ceSNicholas Bellinger 	}
1948e48354ceSNicholas Bellinger 
1949778de368SNicholas Bellinger 	return iscsit_process_nop_out(conn, cmd, hdr);
1950e48354ceSNicholas Bellinger out:
1951e48354ceSNicholas Bellinger 	if (cmd)
1952aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
1953778de368SNicholas Bellinger 
1954e48354ceSNicholas Bellinger 	kfree(ping_data);
1955e48354ceSNicholas Bellinger 	return ret;
1956e48354ceSNicholas Bellinger }
1957e48354ceSNicholas Bellinger 
1958e381fe9eSBart Van Assche static enum tcm_tmreq_table iscsit_convert_tmf(u8 iscsi_tmf)
1959e381fe9eSBart Van Assche {
1960e381fe9eSBart Van Assche 	switch (iscsi_tmf) {
1961e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK:
1962e381fe9eSBart Van Assche 		return TMR_ABORT_TASK;
1963e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
1964e381fe9eSBart Van Assche 		return TMR_ABORT_TASK_SET;
1965e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_ACA:
1966e381fe9eSBart Van Assche 		return TMR_CLEAR_ACA;
1967e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
1968e381fe9eSBart Van Assche 		return TMR_CLEAR_TASK_SET;
1969e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
1970e381fe9eSBart Van Assche 		return TMR_LUN_RESET;
1971e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
1972e381fe9eSBart Van Assche 		return TMR_TARGET_WARM_RESET;
1973e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
1974e381fe9eSBart Van Assche 		return TMR_TARGET_COLD_RESET;
1975e381fe9eSBart Van Assche 	default:
1976e381fe9eSBart Van Assche 		return TMR_UNKNOWN;
1977e381fe9eSBart Van Assche 	}
1978e381fe9eSBart Van Assche }
1979e381fe9eSBart Van Assche 
19803e1c81a9SNicholas Bellinger int
1981be36d683SMax Gurtovoy iscsit_handle_task_mgt_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
1982e48354ceSNicholas Bellinger 			   unsigned char *buf)
1983e48354ceSNicholas Bellinger {
1984e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr;
1985e48354ceSNicholas Bellinger 	struct iscsi_tmr_req *tmr_req;
1986e48354ceSNicholas Bellinger 	struct iscsi_tm *hdr;
1987186a9647SNicholas Bellinger 	int out_of_order_cmdsn = 0, ret;
198859b6986dSBart Van Assche 	u8 function, tcm_function = TMR_UNKNOWN;
1989e48354ceSNicholas Bellinger 
1990e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_tm *) buf;
1991e48354ceSNicholas Bellinger 	hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
1992e48354ceSNicholas Bellinger 	function = hdr->flags;
1993e48354ceSNicholas Bellinger 
1994e48354ceSNicholas Bellinger 	pr_debug("Got Task Management Request ITT: 0x%08x, CmdSN:"
1995e48354ceSNicholas Bellinger 		" 0x%08x, Function: 0x%02x, RefTaskTag: 0x%08x, RefCmdSN:"
1996e48354ceSNicholas Bellinger 		" 0x%08x, CID: %hu\n", hdr->itt, hdr->cmdsn, function,
1997e48354ceSNicholas Bellinger 		hdr->rtt, hdr->refcmdsn, conn->cid);
1998e48354ceSNicholas Bellinger 
1999e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
2000e48354ceSNicholas Bellinger 	    ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
200166c7db68SChristoph Hellwig 	     hdr->rtt != RESERVED_ITT)) {
2002e48354ceSNicholas Bellinger 		pr_err("RefTaskTag should be set to 0xFFFFFFFF.\n");
200366c7db68SChristoph Hellwig 		hdr->rtt = RESERVED_ITT;
2004e48354ceSNicholas Bellinger 	}
2005e48354ceSNicholas Bellinger 
2006e48354ceSNicholas Bellinger 	if ((function == ISCSI_TM_FUNC_TASK_REASSIGN) &&
2007e48354ceSNicholas Bellinger 			!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2008e48354ceSNicholas Bellinger 		pr_err("Task Management Request TASK_REASSIGN not"
2009e48354ceSNicholas Bellinger 			" issued as immediate command, bad iSCSI Initiator"
2010e48354ceSNicholas Bellinger 				"implementation\n");
2011ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2012ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
2013e48354ceSNicholas Bellinger 	}
2014e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
201550e5c87dSChristoph Hellwig 	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
201650e5c87dSChristoph Hellwig 		hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
2017e48354ceSNicholas Bellinger 
2018d28b1169SAndy Grover 	cmd->data_direction = DMA_NONE;
20193829f381SMarkus Elfring 	cmd->tmr_req = kzalloc(sizeof(*cmd->tmr_req), GFP_KERNEL);
2020ae072726SNicholas Bellinger 	if (!cmd->tmr_req) {
2021ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2022d28b1169SAndy Grover 					     ISCSI_REASON_BOOKMARK_NO_RESOURCES,
2023ba159914SNicholas Bellinger 					     buf);
2024ae072726SNicholas Bellinger 	}
2025ae072726SNicholas Bellinger 
2026a78b7136SMike Christie 	__target_init_cmd(&cmd->se_cmd, &iscsi_ops,
2027ae072726SNicholas Bellinger 			  conn->sess->se_sess, 0, DMA_NONE,
2028a36840d8SSudhakar Panneerselvam 			  TCM_SIMPLE_TAG, cmd->sense_buffer + 2,
2029a36840d8SSudhakar Panneerselvam 			  scsilun_to_int(&hdr->lun));
2030ae072726SNicholas Bellinger 
2031807b9515SBart Van Assche 	target_get_sess_cmd(&cmd->se_cmd, true);
2032d28b1169SAndy Grover 
2033d28b1169SAndy Grover 	/*
2034d28b1169SAndy Grover 	 * TASK_REASSIGN for ERL=2 / connection stays inside of
2035d28b1169SAndy Grover 	 * LIO-Target $FABRIC_MOD
2036d28b1169SAndy Grover 	 */
2037d28b1169SAndy Grover 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
2038e381fe9eSBart Van Assche 		tcm_function = iscsit_convert_tmf(function);
2039e381fe9eSBart Van Assche 		if (tcm_function == TMR_UNKNOWN) {
2040d28b1169SAndy Grover 			pr_err("Unknown iSCSI TMR Function:"
2041d28b1169SAndy Grover 			       " 0x%02x\n", function);
2042ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2043ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2044d28b1169SAndy Grover 		}
204559b6986dSBart Van Assche 	}
204659b6986dSBart Van Assche 	ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function,
204759b6986dSBart Van Assche 				 GFP_KERNEL);
2048d28b1169SAndy Grover 	if (ret < 0)
2049ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2050ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2051d28b1169SAndy Grover 
2052d28b1169SAndy Grover 	cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
2053d28b1169SAndy Grover 
2054e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_TMFUNC;
2055e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TASKMGTRSP;
2056e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2057e48354ceSNicholas Bellinger 	cmd->init_task_tag	= hdr->itt;
2058e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
205950e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
206050e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
2061e48354ceSNicholas Bellinger 	se_tmr			= cmd->se_cmd.se_tmr_req;
2062e48354ceSNicholas Bellinger 	tmr_req			= cmd->tmr_req;
2063e48354ceSNicholas Bellinger 	/*
2064e48354ceSNicholas Bellinger 	 * Locate the struct se_lun for all TMRs not related to ERL=2 TASK_REASSIGN
2065e48354ceSNicholas Bellinger 	 */
2066e48354ceSNicholas Bellinger 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
2067a36840d8SSudhakar Panneerselvam 		ret = transport_lookup_tmr_lun(&cmd->se_cmd);
2068e48354ceSNicholas Bellinger 		if (ret < 0) {
2069e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_NO_LUN;
2070e48354ceSNicholas Bellinger 			goto attach;
2071e48354ceSNicholas Bellinger 		}
2072e48354ceSNicholas Bellinger 	}
2073e48354ceSNicholas Bellinger 
2074e48354ceSNicholas Bellinger 	switch (function) {
2075e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK:
2076e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_abort_task(cmd, buf);
2077de103c93SChristoph Hellwig 		if (se_tmr->response)
2078e48354ceSNicholas Bellinger 			goto attach;
2079e48354ceSNicholas Bellinger 		break;
2080e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
2081e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_ACA:
2082e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
2083e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
2084e48354ceSNicholas Bellinger 		break;
2085e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
2086e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) {
2087e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2088e48354ceSNicholas Bellinger 			goto attach;
2089e48354ceSNicholas Bellinger 		}
2090e48354ceSNicholas Bellinger 		break;
2091e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
2092e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) {
2093e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2094e48354ceSNicholas Bellinger 			goto attach;
2095e48354ceSNicholas Bellinger 		}
2096e48354ceSNicholas Bellinger 		break;
2097e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TASK_REASSIGN:
2098e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_task_reassign(cmd, buf);
2099e48354ceSNicholas Bellinger 		/*
2100e48354ceSNicholas Bellinger 		 * Perform sanity checks on the ExpDataSN only if the
2101e48354ceSNicholas Bellinger 		 * TASK_REASSIGN was successful.
2102e48354ceSNicholas Bellinger 		 */
2103de103c93SChristoph Hellwig 		if (se_tmr->response)
2104e48354ceSNicholas Bellinger 			break;
2105e48354ceSNicholas Bellinger 
2106e48354ceSNicholas Bellinger 		if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
2107ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2108ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_INVALID, buf);
2109e48354ceSNicholas Bellinger 		break;
2110e48354ceSNicholas Bellinger 	default:
2111e48354ceSNicholas Bellinger 		pr_err("Unknown TMR function: 0x%02x, protocol"
2112e48354ceSNicholas Bellinger 			" error.\n", function);
2113e48354ceSNicholas Bellinger 		se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED;
2114e48354ceSNicholas Bellinger 		goto attach;
2115e48354ceSNicholas Bellinger 	}
2116e48354ceSNicholas Bellinger 
2117e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
2118e48354ceSNicholas Bellinger 	    (se_tmr->response == ISCSI_TMF_RSP_COMPLETE))
2119e48354ceSNicholas Bellinger 		se_tmr->call_transport = 1;
2120e48354ceSNicholas Bellinger attach:
2121e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
21222fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2123e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2124e48354ceSNicholas Bellinger 
2125e48354ceSNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2126561bf158SNicholas Bellinger 		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
21273fc9fb13SNicholas Bellinger 		if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) {
2128e48354ceSNicholas Bellinger 			out_of_order_cmdsn = 1;
21293fc9fb13SNicholas Bellinger 		} else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
21303fc9fb13SNicholas Bellinger 			target_put_sess_cmd(&cmd->se_cmd);
2131e48354ceSNicholas Bellinger 			return 0;
21323fc9fb13SNicholas Bellinger 		} else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
2133ba159914SNicholas Bellinger 			return -1;
2134e48354ceSNicholas Bellinger 		}
21353fc9fb13SNicholas Bellinger 	}
213650e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2137e48354ceSNicholas Bellinger 
21385a4c8666SNicholas Bellinger 	if (out_of_order_cmdsn || !(hdr->opcode & ISCSI_OP_IMMEDIATE))
2139e48354ceSNicholas Bellinger 		return 0;
2140e48354ceSNicholas Bellinger 	/*
2141e48354ceSNicholas Bellinger 	 * Found the referenced task, send to transport for processing.
2142e48354ceSNicholas Bellinger 	 */
2143e48354ceSNicholas Bellinger 	if (se_tmr->call_transport)
2144e48354ceSNicholas Bellinger 		return transport_generic_handle_tmr(&cmd->se_cmd);
2145e48354ceSNicholas Bellinger 
2146e48354ceSNicholas Bellinger 	/*
2147e48354ceSNicholas Bellinger 	 * Could not find the referenced LUN, task, or Task Management
2148e48354ceSNicholas Bellinger 	 * command not authorized or supported.  Change state and
2149e48354ceSNicholas Bellinger 	 * let the tx_thread send the response.
2150e48354ceSNicholas Bellinger 	 *
2151e48354ceSNicholas Bellinger 	 * For connection recovery, this is also the default action for
2152e48354ceSNicholas Bellinger 	 * TMR TASK_REASSIGN.
2153e48354ceSNicholas Bellinger 	 */
2154e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2155ae072726SNicholas Bellinger 	target_put_sess_cmd(&cmd->se_cmd);
2156e48354ceSNicholas Bellinger 	return 0;
2157e48354ceSNicholas Bellinger }
21583e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd);
2159e48354ceSNicholas Bellinger 
2160e48354ceSNicholas Bellinger /* #warning FIXME: Support Text Command parameters besides SendTargets */
216164534aa7SNicholas Bellinger int
2162be36d683SMax Gurtovoy iscsit_setup_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
216364534aa7SNicholas Bellinger 		      struct iscsi_text *hdr)
2164e48354ceSNicholas Bellinger {
216564534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
2166e48354ceSNicholas Bellinger 
216721f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
2168e48354ceSNicholas Bellinger 		pr_err("Unable to accept text parameter length: %u"
216921f5aa7eSNicholas Bellinger 			"greater than MaxXmitDataSegmentLength %u.\n",
217021f5aa7eSNicholas Bellinger 		       payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
2171ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2172ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
2173e48354ceSNicholas Bellinger 	}
2174e48354ceSNicholas Bellinger 
2175122f8afcSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL) ||
2176122f8afcSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_TEXT_CONTINUE)) {
2177122f8afcSNicholas Bellinger 		pr_err("Multi sequence text commands currently not supported\n");
2178122f8afcSNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_CMD_NOT_SUPPORTED,
2179122f8afcSNicholas Bellinger 					(unsigned char *)hdr);
2180122f8afcSNicholas Bellinger 	}
2181122f8afcSNicholas Bellinger 
2182e48354ceSNicholas Bellinger 	pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
2183e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
2184e48354ceSNicholas Bellinger 		hdr->exp_statsn, payload_length);
2185e48354ceSNicholas Bellinger 
218664534aa7SNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_TEXT;
218764534aa7SNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TEXTRSP;
218864534aa7SNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
218964534aa7SNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
219064534aa7SNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
219164534aa7SNicholas Bellinger 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
219264534aa7SNicholas Bellinger 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
219364534aa7SNicholas Bellinger 	cmd->data_direction	= DMA_NONE;
2194ea8dc5b4SVarun Prakash 	kfree(cmd->text_in_ptr);
2195e4f4e801SSagi Grimberg 	cmd->text_in_ptr	= NULL;
219664534aa7SNicholas Bellinger 
219764534aa7SNicholas Bellinger 	return 0;
219864534aa7SNicholas Bellinger }
219964534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_text_cmd);
220064534aa7SNicholas Bellinger 
220164534aa7SNicholas Bellinger int
2202be36d683SMax Gurtovoy iscsit_process_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
220364534aa7SNicholas Bellinger 			struct iscsi_text *hdr)
220464534aa7SNicholas Bellinger {
22059864ca9dSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr;
220664534aa7SNicholas Bellinger 	int cmdsn_ret;
220764534aa7SNicholas Bellinger 
22089864ca9dSNicholas Bellinger 	if (!text_in) {
2209e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
2210e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
22119864ca9dSNicholas Bellinger 			pr_err("Unable to locate text_in buffer for sendtargets"
22129864ca9dSNicholas Bellinger 			       " discovery\n");
22139864ca9dSNicholas Bellinger 			goto reject;
22149864ca9dSNicholas Bellinger 		}
2215e4f4e801SSagi Grimberg 		goto empty_sendtargets;
2216e4f4e801SSagi Grimberg 	}
221795f8f6a9SDavid Disseldorp 	if (strncmp("SendTargets=", text_in, 12) != 0) {
22189864ca9dSNicholas Bellinger 		pr_err("Received Text Data that is not"
22199864ca9dSNicholas Bellinger 			" SendTargets, cannot continue.\n");
22209864ca9dSNicholas Bellinger 		goto reject;
22219864ca9dSNicholas Bellinger 	}
222295f8f6a9SDavid Disseldorp 	/* '=' confirmed in strncmp */
22239864ca9dSNicholas Bellinger 	text_ptr = strchr(text_in, '=');
222495f8f6a9SDavid Disseldorp 	BUG_ON(!text_ptr);
222595f8f6a9SDavid Disseldorp 	if (!strncmp("=All", text_ptr, 5)) {
22268060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_ALL;
22276665889cSNicholas Bellinger 	} else if (!strncmp("=iqn.", text_ptr, 5) ||
22286665889cSNicholas Bellinger 		   !strncmp("=eui.", text_ptr, 5)) {
22298060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_SINGLE;
22309864ca9dSNicholas Bellinger 	} else {
223195f8f6a9SDavid Disseldorp 		pr_err("Unable to locate valid SendTargets%s value\n",
223295f8f6a9SDavid Disseldorp 		       text_ptr);
22339864ca9dSNicholas Bellinger 		goto reject;
22349864ca9dSNicholas Bellinger 	}
22359864ca9dSNicholas Bellinger 
223664534aa7SNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
223764534aa7SNicholas Bellinger 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
223864534aa7SNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
223964534aa7SNicholas Bellinger 
2240e4f4e801SSagi Grimberg empty_sendtargets:
224164534aa7SNicholas Bellinger 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
224264534aa7SNicholas Bellinger 
224364534aa7SNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2244561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
2245561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
224664534aa7SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2247ba159914SNicholas Bellinger 			return -1;
2248ba159914SNicholas Bellinger 
224964534aa7SNicholas Bellinger 		return 0;
225064534aa7SNicholas Bellinger 	}
225164534aa7SNicholas Bellinger 
225264534aa7SNicholas Bellinger 	return iscsit_execute_cmd(cmd, 0);
22539864ca9dSNicholas Bellinger 
22549864ca9dSNicholas Bellinger reject:
2255ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2256ba159914SNicholas Bellinger 				 (unsigned char *)hdr);
225764534aa7SNicholas Bellinger }
225864534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_text_cmd);
225964534aa7SNicholas Bellinger 
226064534aa7SNicholas Bellinger static int
2261be36d683SMax Gurtovoy iscsit_handle_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
226264534aa7SNicholas Bellinger 		       unsigned char *buf)
226364534aa7SNicholas Bellinger {
226464534aa7SNicholas Bellinger 	struct iscsi_text *hdr = (struct iscsi_text *)buf;
226564534aa7SNicholas Bellinger 	char *text_in = NULL;
226664534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
226764534aa7SNicholas Bellinger 	int rx_size, rc;
226864534aa7SNicholas Bellinger 
226964534aa7SNicholas Bellinger 	rc = iscsit_setup_text_cmd(conn, cmd, hdr);
227064534aa7SNicholas Bellinger 	if (rc < 0)
2271561bf158SNicholas Bellinger 		return 0;
227264534aa7SNicholas Bellinger 
227364534aa7SNicholas Bellinger 	rx_size = payload_length;
227464534aa7SNicholas Bellinger 	if (payload_length) {
227564534aa7SNicholas Bellinger 		u32 checksum = 0, data_crc = 0;
227647eefdedSBart Van Assche 		u32 padding = 0;
227764534aa7SNicholas Bellinger 		int niov = 0, rx_got;
227847eefdedSBart Van Assche 		struct kvec iov[2];
227964534aa7SNicholas Bellinger 
228047eefdedSBart Van Assche 		rx_size = ALIGN(payload_length, 4);
228147eefdedSBart Van Assche 		text_in = kzalloc(rx_size, GFP_KERNEL);
2282c46e22f1SMarkus Elfring 		if (!text_in)
228364534aa7SNicholas Bellinger 			goto reject;
2284c46e22f1SMarkus Elfring 
22859864ca9dSNicholas Bellinger 		cmd->text_in_ptr = text_in;
2286e48354ceSNicholas Bellinger 
228747eefdedSBart Van Assche 		memset(iov, 0, sizeof(iov));
2288e48354ceSNicholas Bellinger 		iov[niov].iov_base	= text_in;
228947eefdedSBart Van Assche 		iov[niov++].iov_len	= rx_size;
2290e48354ceSNicholas Bellinger 
229147eefdedSBart Van Assche 		padding = rx_size - payload_length;
229247eefdedSBart Van Assche 		if (padding)
2293e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
2294e48354ceSNicholas Bellinger 					" for padding.\n", padding);
2295e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
2296e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
2297e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
2298e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
2299e48354ceSNicholas Bellinger 		}
2300e48354ceSNicholas Bellinger 
23012e39f1c9SBart Van Assche 		WARN_ON_ONCE(niov > ARRAY_SIZE(iov));
2302e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &iov[0], niov, rx_size);
230364534aa7SNicholas Bellinger 		if (rx_got != rx_size)
230464534aa7SNicholas Bellinger 			goto reject;
2305e48354ceSNicholas Bellinger 
2306e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
230747eefdedSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash,
230847eefdedSBart Van Assche 						  text_in, rx_size, 0, NULL,
230947eefdedSBart Van Assche 						  &data_crc);
2310e48354ceSNicholas Bellinger 
2311e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
2312e48354ceSNicholas Bellinger 				pr_err("Text data CRC32C DataDigest"
2313e48354ceSNicholas Bellinger 					" 0x%08x does not match computed"
2314e48354ceSNicholas Bellinger 					" 0x%08x\n", checksum, data_crc);
2315e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2316e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
2317e48354ceSNicholas Bellinger 					" Text Data digest failure while in"
2318e48354ceSNicholas Bellinger 						" ERL=0.\n");
231964534aa7SNicholas Bellinger 					goto reject;
2320e48354ceSNicholas Bellinger 				} else {
2321e48354ceSNicholas Bellinger 					/*
2322e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
2323e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
2324e48354ceSNicholas Bellinger 					 */
2325e48354ceSNicholas Bellinger 					pr_debug("Dropping Text"
2326e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
2327e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
2328e48354ceSNicholas Bellinger 					kfree(text_in);
2329e48354ceSNicholas Bellinger 					return 0;
2330e48354ceSNicholas Bellinger 				}
2331e48354ceSNicholas Bellinger 			} else {
2332e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
2333e48354ceSNicholas Bellinger 					" 0x%08x for %u bytes of text data.\n",
233464534aa7SNicholas Bellinger 						checksum, payload_length);
2335e48354ceSNicholas Bellinger 			}
2336e48354ceSNicholas Bellinger 		}
233764534aa7SNicholas Bellinger 		text_in[payload_length - 1] = '\0';
2338e48354ceSNicholas Bellinger 		pr_debug("Successfully read %d bytes of text"
233964534aa7SNicholas Bellinger 				" data.\n", payload_length);
2340e48354ceSNicholas Bellinger 	}
2341e48354ceSNicholas Bellinger 
234264534aa7SNicholas Bellinger 	return iscsit_process_text_cmd(conn, cmd, hdr);
2343e48354ceSNicholas Bellinger 
234464534aa7SNicholas Bellinger reject:
23459864ca9dSNicholas Bellinger 	kfree(cmd->text_in_ptr);
23469864ca9dSNicholas Bellinger 	cmd->text_in_ptr = NULL;
2347ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
2348e48354ceSNicholas Bellinger }
2349e48354ceSNicholas Bellinger 
2350be36d683SMax Gurtovoy int iscsit_logout_closesession(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
2351e48354ceSNicholas Bellinger {
2352be36d683SMax Gurtovoy 	struct iscsit_conn *conn_p;
23530873fe44SMax Gurtovoy 	struct iscsit_session *sess = conn->sess;
2354e48354ceSNicholas Bellinger 
2355e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSESESSION on CID: %hu"
2356e48354ceSNicholas Bellinger 		" for SID: %u.\n", conn->cid, conn->sess->sid);
2357e48354ceSNicholas Bellinger 
2358e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
2359e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 1);
2360e48354ceSNicholas Bellinger 	conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2361e48354ceSNicholas Bellinger 
2362e48354ceSNicholas Bellinger 	iscsit_inc_conn_usage_count(conn);
2363e48354ceSNicholas Bellinger 	iscsit_inc_session_usage_count(sess);
2364e48354ceSNicholas Bellinger 
2365e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
2366e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &sess->sess_conn_list, conn_list) {
2367e48354ceSNicholas Bellinger 		if (conn_p->conn_state != TARG_CONN_STATE_LOGGED_IN)
2368e48354ceSNicholas Bellinger 			continue;
2369e48354ceSNicholas Bellinger 
2370e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2371e48354ceSNicholas Bellinger 		conn_p->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2372e48354ceSNicholas Bellinger 	}
2373e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
2374e48354ceSNicholas Bellinger 
2375e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2376e48354ceSNicholas Bellinger 
2377e48354ceSNicholas Bellinger 	return 0;
2378e48354ceSNicholas Bellinger }
2379e48354ceSNicholas Bellinger 
2380be36d683SMax Gurtovoy int iscsit_logout_closeconnection(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
2381e48354ceSNicholas Bellinger {
2382be36d683SMax Gurtovoy 	struct iscsit_conn *l_conn;
23830873fe44SMax Gurtovoy 	struct iscsit_session *sess = conn->sess;
2384e48354ceSNicholas Bellinger 
2385e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSECONNECTION for CID:"
2386e48354ceSNicholas Bellinger 		" %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2387e48354ceSNicholas Bellinger 
2388e48354ceSNicholas Bellinger 	/*
2389e48354ceSNicholas Bellinger 	 * A Logout Request with a CLOSECONNECTION reason code for a CID
2390e48354ceSNicholas Bellinger 	 * can arrive on a connection with a differing CID.
2391e48354ceSNicholas Bellinger 	 */
2392e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2393e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
2394e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2395e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2396e48354ceSNicholas Bellinger 
2397e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 1);
2398e48354ceSNicholas Bellinger 		conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_CONNECTION;
2399e48354ceSNicholas Bellinger 		iscsit_inc_conn_usage_count(conn);
2400e48354ceSNicholas Bellinger 
2401e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
2402e48354ceSNicholas Bellinger 	} else {
2403e48354ceSNicholas Bellinger 		/*
2404e48354ceSNicholas Bellinger 		 * Handle all different cid CLOSECONNECTION requests in
2405e48354ceSNicholas Bellinger 		 * iscsit_logout_post_handler_diffcid() as to give enough
2406e48354ceSNicholas Bellinger 		 * time for any non immediate command's CmdSN to be
2407e48354ceSNicholas Bellinger 		 * acknowledged on the connection in question.
2408e48354ceSNicholas Bellinger 		 *
2409e48354ceSNicholas Bellinger 		 * Here we simply make sure the CID is still around.
2410e48354ceSNicholas Bellinger 		 */
2411e48354ceSNicholas Bellinger 		l_conn = iscsit_get_conn_from_cid(sess,
2412e48354ceSNicholas Bellinger 				cmd->logout_cid);
2413e48354ceSNicholas Bellinger 		if (!l_conn) {
2414e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2415e48354ceSNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
2416e48354ceSNicholas Bellinger 					cmd->i_state);
2417e48354ceSNicholas Bellinger 			return 0;
2418e48354ceSNicholas Bellinger 		}
2419e48354ceSNicholas Bellinger 
2420e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(l_conn);
2421e48354ceSNicholas Bellinger 	}
2422e48354ceSNicholas Bellinger 
2423e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2424e48354ceSNicholas Bellinger 
2425e48354ceSNicholas Bellinger 	return 0;
2426e48354ceSNicholas Bellinger }
2427e48354ceSNicholas Bellinger 
2428be36d683SMax Gurtovoy int iscsit_logout_removeconnforrecovery(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
2429e48354ceSNicholas Bellinger {
24300873fe44SMax Gurtovoy 	struct iscsit_session *sess = conn->sess;
2431e48354ceSNicholas Bellinger 
2432e48354ceSNicholas Bellinger 	pr_debug("Received explicit REMOVECONNFORRECOVERY logout for"
2433e48354ceSNicholas Bellinger 		" CID: %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2434e48354ceSNicholas Bellinger 
2435e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel != 2) {
2436e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2437e48354ceSNicholas Bellinger 			" while ERL!=2.\n");
2438e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED;
2439e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2440e48354ceSNicholas Bellinger 		return 0;
2441e48354ceSNicholas Bellinger 	}
2442e48354ceSNicholas Bellinger 
2443e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2444e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2445e48354ceSNicholas Bellinger 			" with CID: %hu on CID: %hu, implementation error.\n",
2446e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2447e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_CLEANUP_FAILED;
2448e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2449e48354ceSNicholas Bellinger 		return 0;
2450e48354ceSNicholas Bellinger 	}
2451e48354ceSNicholas Bellinger 
2452e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2453e48354ceSNicholas Bellinger 
2454e48354ceSNicholas Bellinger 	return 0;
2455e48354ceSNicholas Bellinger }
2456e48354ceSNicholas Bellinger 
24573e1c81a9SNicholas Bellinger int
2458be36d683SMax Gurtovoy iscsit_handle_logout_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
2459e48354ceSNicholas Bellinger 			unsigned char *buf)
2460e48354ceSNicholas Bellinger {
2461e48354ceSNicholas Bellinger 	int cmdsn_ret, logout_remove = 0;
2462e48354ceSNicholas Bellinger 	u8 reason_code = 0;
2463e48354ceSNicholas Bellinger 	struct iscsi_logout *hdr;
2464e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn);
2465e48354ceSNicholas Bellinger 
2466e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_logout *) buf;
2467e48354ceSNicholas Bellinger 	reason_code		= (hdr->flags & 0x7f);
2468e48354ceSNicholas Bellinger 
2469e48354ceSNicholas Bellinger 	if (tiqn) {
2470e48354ceSNicholas Bellinger 		spin_lock(&tiqn->logout_stats.lock);
2471e48354ceSNicholas Bellinger 		if (reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION)
2472e48354ceSNicholas Bellinger 			tiqn->logout_stats.normal_logouts++;
2473e48354ceSNicholas Bellinger 		else
2474e48354ceSNicholas Bellinger 			tiqn->logout_stats.abnormal_logouts++;
2475e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->logout_stats.lock);
2476e48354ceSNicholas Bellinger 	}
2477e48354ceSNicholas Bellinger 
2478e48354ceSNicholas Bellinger 	pr_debug("Got Logout Request ITT: 0x%08x CmdSN: 0x%08x"
2479e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x Reason: 0x%02x CID: %hu on CID: %hu\n",
2480e48354ceSNicholas Bellinger 		hdr->itt, hdr->cmdsn, hdr->exp_statsn, reason_code,
2481e48354ceSNicholas Bellinger 		hdr->cid, conn->cid);
2482e48354ceSNicholas Bellinger 
2483e48354ceSNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
2484e48354ceSNicholas Bellinger 		pr_err("Received logout request on connection that"
2485e48354ceSNicholas Bellinger 			" is not in logged in state, ignoring request.\n");
2486aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
2487e48354ceSNicholas Bellinger 		return 0;
2488e48354ceSNicholas Bellinger 	}
2489e48354ceSNicholas Bellinger 
2490e48354ceSNicholas Bellinger 	cmd->iscsi_opcode       = ISCSI_OP_LOGOUT;
2491e48354ceSNicholas Bellinger 	cmd->i_state            = ISTATE_SEND_LOGOUTRSP;
2492e48354ceSNicholas Bellinger 	cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2493e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
2494e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag      = 0xFFFFFFFF;
249550e5c87dSChristoph Hellwig 	cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
249650e5c87dSChristoph Hellwig 	cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
249750e5c87dSChristoph Hellwig 	cmd->logout_cid         = be16_to_cpu(hdr->cid);
2498e48354ceSNicholas Bellinger 	cmd->logout_reason      = reason_code;
2499e48354ceSNicholas Bellinger 	cmd->data_direction     = DMA_NONE;
2500e48354ceSNicholas Bellinger 
2501e48354ceSNicholas Bellinger 	/*
2502e48354ceSNicholas Bellinger 	 * We need to sleep in these cases (by returning 1) until the Logout
2503e48354ceSNicholas Bellinger 	 * Response gets sent in the tx thread.
2504e48354ceSNicholas Bellinger 	 */
2505e48354ceSNicholas Bellinger 	if ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION) ||
2506e48354ceSNicholas Bellinger 	   ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) &&
250750e5c87dSChristoph Hellwig 	    be16_to_cpu(hdr->cid) == conn->cid))
2508e48354ceSNicholas Bellinger 		logout_remove = 1;
2509e48354ceSNicholas Bellinger 
2510e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
25112fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2512e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2513e48354ceSNicholas Bellinger 
2514e48354ceSNicholas Bellinger 	if (reason_code != ISCSI_LOGOUT_REASON_RECOVERY)
251550e5c87dSChristoph Hellwig 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2516e48354ceSNicholas Bellinger 
2517e48354ceSNicholas Bellinger 	/*
2518e48354ceSNicholas Bellinger 	 * Immediate commands are executed, well, immediately.
2519e48354ceSNicholas Bellinger 	 * Non-Immediate Logout Commands are executed in CmdSN order.
2520e48354ceSNicholas Bellinger 	 */
2521c6037cc5SAndy Grover 	if (cmd->immediate_cmd) {
2522e48354ceSNicholas Bellinger 		int ret = iscsit_execute_cmd(cmd, 0);
2523e48354ceSNicholas Bellinger 
2524e48354ceSNicholas Bellinger 		if (ret < 0)
2525e48354ceSNicholas Bellinger 			return ret;
2526e48354ceSNicholas Bellinger 	} else {
2527561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
2528ba159914SNicholas Bellinger 		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
2529e48354ceSNicholas Bellinger 			logout_remove = 0;
2530ba159914SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2531ba159914SNicholas Bellinger 			return -1;
2532e48354ceSNicholas Bellinger 	}
2533e48354ceSNicholas Bellinger 
2534e48354ceSNicholas Bellinger 	return logout_remove;
2535e48354ceSNicholas Bellinger }
25363e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_logout_cmd);
2537e48354ceSNicholas Bellinger 
2538d2faaefbSVarun Prakash int iscsit_handle_snack(
2539be36d683SMax Gurtovoy 	struct iscsit_conn *conn,
2540e48354ceSNicholas Bellinger 	unsigned char *buf)
2541e48354ceSNicholas Bellinger {
2542e48354ceSNicholas Bellinger 	struct iscsi_snack *hdr;
2543e48354ceSNicholas Bellinger 
2544e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_snack *) buf;
2545e48354ceSNicholas Bellinger 	hdr->flags		&= ~ISCSI_FLAG_CMD_FINAL;
2546e48354ceSNicholas Bellinger 
2547e48354ceSNicholas Bellinger 	pr_debug("Got ISCSI_INIT_SNACK, ITT: 0x%08x, ExpStatSN:"
2548e48354ceSNicholas Bellinger 		" 0x%08x, Type: 0x%02x, BegRun: 0x%08x, RunLength: 0x%08x,"
2549e48354ceSNicholas Bellinger 		" CID: %hu\n", hdr->itt, hdr->exp_statsn, hdr->flags,
2550e48354ceSNicholas Bellinger 			hdr->begrun, hdr->runlength, conn->cid);
2551e48354ceSNicholas Bellinger 
2552e48354ceSNicholas Bellinger 	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2553e48354ceSNicholas Bellinger 		pr_err("Initiator sent SNACK request while in"
2554e48354ceSNicholas Bellinger 			" ErrorRecoveryLevel=0.\n");
2555ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2556ba159914SNicholas Bellinger 					 buf);
2557e48354ceSNicholas Bellinger 	}
2558e48354ceSNicholas Bellinger 	/*
2559e48354ceSNicholas Bellinger 	 * SNACK_DATA and SNACK_R2T are both 0,  so check which function to
2560e48354ceSNicholas Bellinger 	 * call from inside iscsi_send_recovery_datain_or_r2t().
2561e48354ceSNicholas Bellinger 	 */
2562e48354ceSNicholas Bellinger 	switch (hdr->flags & ISCSI_FLAG_SNACK_TYPE_MASK) {
2563e48354ceSNicholas Bellinger 	case 0:
2564e48354ceSNicholas Bellinger 		return iscsit_handle_recovery_datain_or_r2t(conn, buf,
256550e5c87dSChristoph Hellwig 			hdr->itt,
256650e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
256750e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
256850e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2569e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_STATUS:
257050e5c87dSChristoph Hellwig 		return iscsit_handle_status_snack(conn, hdr->itt,
257150e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
257250e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun), be32_to_cpu(hdr->runlength));
2573e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_DATA_ACK:
257450e5c87dSChristoph Hellwig 		return iscsit_handle_data_ack(conn, be32_to_cpu(hdr->ttt),
257550e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
257650e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2577e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_RDATA:
2578e48354ceSNicholas Bellinger 		/* FIXME: Support R-Data SNACK */
2579e48354ceSNicholas Bellinger 		pr_err("R-Data SNACK Not Supported.\n");
2580ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2581ba159914SNicholas Bellinger 					 buf);
2582e48354ceSNicholas Bellinger 	default:
2583e48354ceSNicholas Bellinger 		pr_err("Unknown SNACK type 0x%02x, protocol"
2584e48354ceSNicholas Bellinger 			" error.\n", hdr->flags & 0x0f);
2585ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2586ba159914SNicholas Bellinger 					 buf);
2587e48354ceSNicholas Bellinger 	}
2588e48354ceSNicholas Bellinger 
2589e48354ceSNicholas Bellinger 	return 0;
2590e48354ceSNicholas Bellinger }
2591d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_handle_snack);
2592e48354ceSNicholas Bellinger 
2593be36d683SMax Gurtovoy static void iscsit_rx_thread_wait_for_tcp(struct iscsit_conn *conn)
2594e48354ceSNicholas Bellinger {
2595e48354ceSNicholas Bellinger 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
2596e48354ceSNicholas Bellinger 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
2597e48354ceSNicholas Bellinger 		wait_for_completion_interruptible_timeout(
2598e48354ceSNicholas Bellinger 					&conn->rx_half_close_comp,
2599e48354ceSNicholas Bellinger 					ISCSI_RX_THREAD_TCP_TIMEOUT * HZ);
2600e48354ceSNicholas Bellinger 	}
2601e48354ceSNicholas Bellinger }
2602e48354ceSNicholas Bellinger 
2603e48354ceSNicholas Bellinger static int iscsit_handle_immediate_data(
260466cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
26053e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr,
2606e48354ceSNicholas Bellinger 	u32 length)
2607e48354ceSNicholas Bellinger {
2608e48354ceSNicholas Bellinger 	int iov_ret, rx_got = 0, rx_size = 0;
2609e48354ceSNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0;
2610be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
2611e48354ceSNicholas Bellinger 	struct kvec *iov;
26120ca650c1SBart Van Assche 	void *overflow_buf = NULL;
2613e48354ceSNicholas Bellinger 
26140ca650c1SBart Van Assche 	BUG_ON(cmd->write_data_done > cmd->se_cmd.data_length);
26150ca650c1SBart Van Assche 	rx_size = min(cmd->se_cmd.data_length - cmd->write_data_done, length);
26162e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, cmd->iov_data,
26172e39f1c9SBart Van Assche 				   cmd->orig_iov_data_count - 2,
26182e39f1c9SBart Van Assche 				   cmd->write_data_done, rx_size);
2619e48354ceSNicholas Bellinger 	if (iov_ret < 0)
2620e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2621e48354ceSNicholas Bellinger 
2622e48354ceSNicholas Bellinger 	iov_count = iov_ret;
2623e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
26240ca650c1SBart Van Assche 	if (rx_size < length) {
26250ca650c1SBart Van Assche 		/*
26260ca650c1SBart Van Assche 		 * Special case: length of immediate data exceeds the data
26270ca650c1SBart Van Assche 		 * buffer size derived from the CDB.
26280ca650c1SBart Van Assche 		 */
26290ca650c1SBart Van Assche 		overflow_buf = kmalloc(length - rx_size, GFP_KERNEL);
26300ca650c1SBart Van Assche 		if (!overflow_buf) {
26310ca650c1SBart Van Assche 			iscsit_unmap_iovec(cmd);
26320ca650c1SBart Van Assche 			return IMMEDIATE_DATA_CANNOT_RECOVER;
26330ca650c1SBart Van Assche 		}
26340ca650c1SBart Van Assche 		cmd->overflow_buf = overflow_buf;
26350ca650c1SBart Van Assche 		iov[iov_count].iov_base = overflow_buf;
26360ca650c1SBart Van Assche 		iov[iov_count].iov_len = length - rx_size;
26370ca650c1SBart Van Assche 		iov_count++;
26380ca650c1SBart Van Assche 		rx_size = length;
26390ca650c1SBart Van Assche 	}
2640e48354ceSNicholas Bellinger 
2641e48354ceSNicholas Bellinger 	padding = ((-length) & 3);
2642e48354ceSNicholas Bellinger 	if (padding != 0) {
2643e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
2644e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
2645e48354ceSNicholas Bellinger 		rx_size += padding;
2646e48354ceSNicholas Bellinger 	}
2647e48354ceSNicholas Bellinger 
2648e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2649e48354ceSNicholas Bellinger 		iov[iov_count].iov_base		= &checksum;
2650e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len	= ISCSI_CRC_LEN;
2651e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
2652e48354ceSNicholas Bellinger 	}
2653e48354ceSNicholas Bellinger 
26542e39f1c9SBart Van Assche 	WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count);
2655e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
2656e48354ceSNicholas Bellinger 
2657e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
2658e48354ceSNicholas Bellinger 
2659e48354ceSNicholas Bellinger 	if (rx_got != rx_size) {
2660e48354ceSNicholas Bellinger 		iscsit_rx_thread_wait_for_tcp(conn);
2661e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2662e48354ceSNicholas Bellinger 	}
2663e48354ceSNicholas Bellinger 
2664e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2665e48354ceSNicholas Bellinger 		u32 data_crc;
2666e48354ceSNicholas Bellinger 
266769110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
2668e48354ceSNicholas Bellinger 						    cmd->write_data_done, length, padding,
2669e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
2670e48354ceSNicholas Bellinger 
2671e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
2672e48354ceSNicholas Bellinger 			pr_err("ImmediateData CRC32C DataDigest 0x%08x"
2673e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n", checksum,
2674e48354ceSNicholas Bellinger 				data_crc);
2675e48354ceSNicholas Bellinger 
2676e48354ceSNicholas Bellinger 			if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2677e48354ceSNicholas Bellinger 				pr_err("Unable to recover from"
2678e48354ceSNicholas Bellinger 					" Immediate Data digest failure while"
2679e48354ceSNicholas Bellinger 					" in ERL=0.\n");
2680ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2681e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2682ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2683e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_CANNOT_RECOVER;
2684e48354ceSNicholas Bellinger 			} else {
2685ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2686e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2687ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2688e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
2689e48354ceSNicholas Bellinger 			}
2690e48354ceSNicholas Bellinger 		} else {
2691e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
2692e48354ceSNicholas Bellinger 				" %u bytes of Immediate Data\n", checksum,
2693e48354ceSNicholas Bellinger 				length);
2694e48354ceSNicholas Bellinger 		}
2695e48354ceSNicholas Bellinger 	}
2696e48354ceSNicholas Bellinger 
2697e48354ceSNicholas Bellinger 	cmd->write_data_done += length;
2698e48354ceSNicholas Bellinger 
2699ebf1d95cSAndy Grover 	if (cmd->write_data_done == cmd->se_cmd.data_length) {
2700e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
2701e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
2702e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
2703e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
2704e48354ceSNicholas Bellinger 	}
2705e48354ceSNicholas Bellinger 
2706e48354ceSNicholas Bellinger 	return IMMEDIATE_DATA_NORMAL_OPERATION;
2707e48354ceSNicholas Bellinger }
2708e48354ceSNicholas Bellinger 
2709e48354ceSNicholas Bellinger /* #warning iscsi_build_conn_drop_async_message() only sends out on connections
2710e48354ceSNicholas Bellinger 	with active network interface */
2711be36d683SMax Gurtovoy static void iscsit_build_conn_drop_async_message(struct iscsit_conn *conn)
2712e48354ceSNicholas Bellinger {
271366cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd;
2714be36d683SMax Gurtovoy 	struct iscsit_conn *conn_p;
2715d444edc6SNicholas Bellinger 	bool found = false;
2716e48354ceSNicholas Bellinger 
2717618baaf7SBart Van Assche 	lockdep_assert_held(&conn->sess->conn_lock);
2718618baaf7SBart Van Assche 
2719e48354ceSNicholas Bellinger 	/*
2720e48354ceSNicholas Bellinger 	 * Only send a Asynchronous Message on connections whos network
2721e48354ceSNicholas Bellinger 	 * interface is still functional.
2722e48354ceSNicholas Bellinger 	 */
2723e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &conn->sess->sess_conn_list, conn_list) {
2724e48354ceSNicholas Bellinger 		if (conn_p->conn_state == TARG_CONN_STATE_LOGGED_IN) {
2725e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn_p);
2726d444edc6SNicholas Bellinger 			found = true;
2727e48354ceSNicholas Bellinger 			break;
2728e48354ceSNicholas Bellinger 		}
2729e48354ceSNicholas Bellinger 	}
2730e48354ceSNicholas Bellinger 
2731d444edc6SNicholas Bellinger 	if (!found)
2732e48354ceSNicholas Bellinger 		return;
2733e48354ceSNicholas Bellinger 
2734676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn_p, TASK_RUNNING);
2735e48354ceSNicholas Bellinger 	if (!cmd) {
2736e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(conn_p);
2737e48354ceSNicholas Bellinger 		return;
2738e48354ceSNicholas Bellinger 	}
2739e48354ceSNicholas Bellinger 
2740e48354ceSNicholas Bellinger 	cmd->logout_cid = conn->cid;
2741e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2742e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_ASYNCMSG;
2743e48354ceSNicholas Bellinger 
2744e48354ceSNicholas Bellinger 	spin_lock_bh(&conn_p->cmd_lock);
27452fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn_p->conn_cmd_list);
2746e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn_p->cmd_lock);
2747e48354ceSNicholas Bellinger 
2748e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn_p, cmd->i_state);
2749e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn_p);
2750e48354ceSNicholas Bellinger }
2751e48354ceSNicholas Bellinger 
2752e48354ceSNicholas Bellinger static int iscsit_send_conn_drop_async_message(
275366cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
2754be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
2755e48354ceSNicholas Bellinger {
2756e48354ceSNicholas Bellinger 	struct iscsi_async *hdr;
2757e48354ceSNicholas Bellinger 
2758e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2759e48354ceSNicholas Bellinger 
2760e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_async *) cmd->pdu;
2761e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_ASYNC_EVENT;
2762e48354ceSNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
276366c7db68SChristoph Hellwig 	cmd->init_task_tag	= RESERVED_ITT;
2764e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
2765e48354ceSNicholas Bellinger 	put_unaligned_be64(0xFFFFFFFFFFFFFFFFULL, &hdr->rsvd4[0]);
2766e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2767e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2768e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2769109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2770e48354ceSNicholas Bellinger 	hdr->async_event	= ISCSI_ASYNC_MSG_DROPPING_CONNECTION;
2771e48354ceSNicholas Bellinger 	hdr->param1		= cpu_to_be16(cmd->logout_cid);
2772e48354ceSNicholas Bellinger 	hdr->param2		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait);
2773e48354ceSNicholas Bellinger 	hdr->param3		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Retain);
2774e48354ceSNicholas Bellinger 
2775e48354ceSNicholas Bellinger 	pr_debug("Sending Connection Dropped Async Message StatSN:"
2776e48354ceSNicholas Bellinger 		" 0x%08x, for CID: %hu on CID: %hu\n", cmd->stat_sn,
2777e48354ceSNicholas Bellinger 			cmd->logout_cid, conn->cid);
27782854bb23SVarun Prakash 
27792854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
2780e48354ceSNicholas Bellinger }
2781e48354ceSNicholas Bellinger 
2782be36d683SMax Gurtovoy static void iscsit_tx_thread_wait_for_tcp(struct iscsit_conn *conn)
27836f3c0e69SAndy Grover {
27846f3c0e69SAndy Grover 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
27856f3c0e69SAndy Grover 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
27866f3c0e69SAndy Grover 		wait_for_completion_interruptible_timeout(
27876f3c0e69SAndy Grover 					&conn->tx_half_close_comp,
27886f3c0e69SAndy Grover 					ISCSI_TX_THREAD_TCP_TIMEOUT * HZ);
27896f3c0e69SAndy Grover 	}
27906f3c0e69SAndy Grover }
27916f3c0e69SAndy Grover 
2792d2faaefbSVarun Prakash void
2793be36d683SMax Gurtovoy iscsit_build_datain_pdu(struct iscsit_cmd *cmd, struct iscsit_conn *conn,
27942ec5a8c1SNicholas Bellinger 			struct iscsi_datain *datain, struct iscsi_data_rsp *hdr,
27952ec5a8c1SNicholas Bellinger 			bool set_statsn)
2796e48354ceSNicholas Bellinger {
27972ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_DATA_IN;
27982ec5a8c1SNicholas Bellinger 	hdr->flags		= datain->flags;
27992ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
28002ec5a8c1SNicholas Bellinger 		if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
28012ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
28022ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
28032ec5a8c1SNicholas Bellinger 		} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
28042ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
28052ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
28062ec5a8c1SNicholas Bellinger 		}
28072ec5a8c1SNicholas Bellinger 	}
28082ec5a8c1SNicholas Bellinger 	hton24(hdr->dlength, datain->length);
28092ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
28102ec5a8c1SNicholas Bellinger 		int_to_scsilun(cmd->se_cmd.orig_fe_lun,
28112ec5a8c1SNicholas Bellinger 				(struct scsi_lun *)&hdr->lun);
28122ec5a8c1SNicholas Bellinger 	else
28132ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
28142ec5a8c1SNicholas Bellinger 
28152ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
28162ec5a8c1SNicholas Bellinger 
28172ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
28182ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
28192ec5a8c1SNicholas Bellinger 	else
28202ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(0xFFFFFFFF);
28212ec5a8c1SNicholas Bellinger 	if (set_statsn)
28222ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(cmd->stat_sn);
28232ec5a8c1SNicholas Bellinger 	else
28242ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(0xFFFFFFFF);
28252ec5a8c1SNicholas Bellinger 
28262ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2827109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
28282ec5a8c1SNicholas Bellinger 	hdr->datasn		= cpu_to_be32(datain->data_sn);
28292ec5a8c1SNicholas Bellinger 	hdr->offset		= cpu_to_be32(datain->offset);
28302ec5a8c1SNicholas Bellinger 
28312ec5a8c1SNicholas Bellinger 	pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x,"
28322ec5a8c1SNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
28332ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
28342ec5a8c1SNicholas Bellinger 		ntohl(hdr->offset), datain->length, conn->cid);
28352ec5a8c1SNicholas Bellinger }
2836d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_datain_pdu);
28372ec5a8c1SNicholas Bellinger 
2838be36d683SMax Gurtovoy static int iscsit_send_datain(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
28392ec5a8c1SNicholas Bellinger {
28402ec5a8c1SNicholas Bellinger 	struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0];
2841e48354ceSNicholas Bellinger 	struct iscsi_datain datain;
2842e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
28432854bb23SVarun Prakash 	int eodr = 0, ret;
28442ec5a8c1SNicholas Bellinger 	bool set_statsn = false;
2845e48354ceSNicholas Bellinger 
2846e48354ceSNicholas Bellinger 	memset(&datain, 0, sizeof(struct iscsi_datain));
2847e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_values(cmd, &datain);
2848e48354ceSNicholas Bellinger 	if (!dr) {
2849e48354ceSNicholas Bellinger 		pr_err("iscsit_get_datain_values failed for ITT: 0x%08x\n",
2850e48354ceSNicholas Bellinger 				cmd->init_task_tag);
2851e48354ceSNicholas Bellinger 		return -1;
2852e48354ceSNicholas Bellinger 	}
2853e48354ceSNicholas Bellinger 	/*
2854e48354ceSNicholas Bellinger 	 * Be paranoid and double check the logic for now.
2855e48354ceSNicholas Bellinger 	 */
2856ebf1d95cSAndy Grover 	if ((datain.offset + datain.length) > cmd->se_cmd.data_length) {
2857e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x, datain.offset: %u and"
2858e48354ceSNicholas Bellinger 			" datain.length: %u exceeds cmd->data_length: %u\n",
2859e48354ceSNicholas Bellinger 			cmd->init_task_tag, datain.offset, datain.length,
2860ebf1d95cSAndy Grover 			cmd->se_cmd.data_length);
2861e48354ceSNicholas Bellinger 		return -1;
2862e48354ceSNicholas Bellinger 	}
2863e48354ceSNicholas Bellinger 
286404f3b31bSNicholas Bellinger 	atomic_long_add(datain.length, &conn->sess->tx_data_octets);
2865e48354ceSNicholas Bellinger 	/*
2866e48354ceSNicholas Bellinger 	 * Special case for successfully execution w/ both DATAIN
2867e48354ceSNicholas Bellinger 	 * and Sense Data.
2868e48354ceSNicholas Bellinger 	 */
2869e48354ceSNicholas Bellinger 	if ((datain.flags & ISCSI_FLAG_DATA_STATUS) &&
2870e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
2871e48354ceSNicholas Bellinger 		datain.flags &= ~ISCSI_FLAG_DATA_STATUS;
2872e48354ceSNicholas Bellinger 	else {
2873e48354ceSNicholas Bellinger 		if ((dr->dr_complete == DATAIN_COMPLETE_NORMAL) ||
2874e48354ceSNicholas Bellinger 		    (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
2875e48354ceSNicholas Bellinger 			iscsit_increment_maxcmdsn(cmd, conn->sess);
2876e48354ceSNicholas Bellinger 			cmd->stat_sn = conn->stat_sn++;
28772ec5a8c1SNicholas Bellinger 			set_statsn = true;
2878e48354ceSNicholas Bellinger 		} else if (dr->dr_complete ==
2879e48354ceSNicholas Bellinger 			   DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
28802ec5a8c1SNicholas Bellinger 			set_statsn = true;
2881e48354ceSNicholas Bellinger 	}
2882e48354ceSNicholas Bellinger 
28832ec5a8c1SNicholas Bellinger 	iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
2884e48354ceSNicholas Bellinger 
28852854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, dr, &datain, 0);
28862854bb23SVarun Prakash 	if (ret < 0)
28876f3c0e69SAndy Grover 		return ret;
28886f3c0e69SAndy Grover 
2889e48354ceSNicholas Bellinger 	if (dr->dr_complete) {
28906f3c0e69SAndy Grover 		eodr = (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ?
2891e48354ceSNicholas Bellinger 				2 : 1;
2892e48354ceSNicholas Bellinger 		iscsit_free_datain_req(cmd, dr);
2893e48354ceSNicholas Bellinger 	}
2894e48354ceSNicholas Bellinger 
28956f3c0e69SAndy Grover 	return eodr;
2896e48354ceSNicholas Bellinger }
2897e48354ceSNicholas Bellinger 
28982ec5a8c1SNicholas Bellinger int
2899be36d683SMax Gurtovoy iscsit_build_logout_rsp(struct iscsit_cmd *cmd, struct iscsit_conn *conn,
29002ec5a8c1SNicholas Bellinger 			struct iscsi_logout_rsp *hdr)
2901e48354ceSNicholas Bellinger {
2902be36d683SMax Gurtovoy 	struct iscsit_conn *logout_conn = NULL;
2903e48354ceSNicholas Bellinger 	struct iscsi_conn_recovery *cr = NULL;
29040873fe44SMax Gurtovoy 	struct iscsit_session *sess = conn->sess;
2905e48354ceSNicholas Bellinger 	/*
2906e48354ceSNicholas Bellinger 	 * The actual shutting down of Sessions and/or Connections
2907e48354ceSNicholas Bellinger 	 * for CLOSESESSION and CLOSECONNECTION Logout Requests
2908e48354ceSNicholas Bellinger 	 * is done in scsi_logout_post_handler().
2909e48354ceSNicholas Bellinger 	 */
2910e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
2911e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
2912e48354ceSNicholas Bellinger 		pr_debug("iSCSI session logout successful, setting"
2913e48354ceSNicholas Bellinger 			" logout response to ISCSI_LOGOUT_SUCCESS.\n");
2914e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2915e48354ceSNicholas Bellinger 		break;
2916e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
2917e48354ceSNicholas Bellinger 		if (cmd->logout_response == ISCSI_LOGOUT_CID_NOT_FOUND)
2918e48354ceSNicholas Bellinger 			break;
2919e48354ceSNicholas Bellinger 		/*
2920e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2921e48354ceSNicholas Bellinger 		 * a matching logout CID -> local CID, the reference
2922e48354ceSNicholas Bellinger 		 * for the local CID will have been incremented in
2923e48354ceSNicholas Bellinger 		 * iscsi_logout_closeconnection().
2924e48354ceSNicholas Bellinger 		 *
2925e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2926e48354ceSNicholas Bellinger 		 * a different CID than the connection it arrived
2927e48354ceSNicholas Bellinger 		 * on, the connection responding to cmd->logout_cid
2928e48354ceSNicholas Bellinger 		 * is stopped in iscsit_logout_post_handler_diffcid().
2929e48354ceSNicholas Bellinger 		 */
2930e48354ceSNicholas Bellinger 
2931e48354ceSNicholas Bellinger 		pr_debug("iSCSI CID: %hu logout on CID: %hu"
2932e48354ceSNicholas Bellinger 			" successful.\n", cmd->logout_cid, conn->cid);
2933e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2934e48354ceSNicholas Bellinger 		break;
2935e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
2936e48354ceSNicholas Bellinger 		if ((cmd->logout_response == ISCSI_LOGOUT_RECOVERY_UNSUPPORTED) ||
2937e48354ceSNicholas Bellinger 		    (cmd->logout_response == ISCSI_LOGOUT_CLEANUP_FAILED))
2938e48354ceSNicholas Bellinger 			break;
2939e48354ceSNicholas Bellinger 		/*
2940e48354ceSNicholas Bellinger 		 * If the connection is still active from our point of view
2941e48354ceSNicholas Bellinger 		 * force connection recovery to occur.
2942e48354ceSNicholas Bellinger 		 */
2943e48354ceSNicholas Bellinger 		logout_conn = iscsit_get_conn_from_cid_rcfr(sess,
2944e48354ceSNicholas Bellinger 				cmd->logout_cid);
2945ee1b1b9cSAndy Grover 		if (logout_conn) {
2946e48354ceSNicholas Bellinger 			iscsit_connection_reinstatement_rcfr(logout_conn);
2947e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(logout_conn);
2948e48354ceSNicholas Bellinger 		}
2949e48354ceSNicholas Bellinger 
2950e48354ceSNicholas Bellinger 		cr = iscsit_get_inactive_connection_recovery_entry(
2951e48354ceSNicholas Bellinger 				conn->sess, cmd->logout_cid);
2952e48354ceSNicholas Bellinger 		if (!cr) {
2953e48354ceSNicholas Bellinger 			pr_err("Unable to locate CID: %hu for"
2954e48354ceSNicholas Bellinger 			" REMOVECONNFORRECOVERY Logout Request.\n",
2955e48354ceSNicholas Bellinger 				cmd->logout_cid);
2956e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2957e48354ceSNicholas Bellinger 			break;
2958e48354ceSNicholas Bellinger 		}
2959e48354ceSNicholas Bellinger 
2960e48354ceSNicholas Bellinger 		iscsit_discard_cr_cmds_by_expstatsn(cr, cmd->exp_stat_sn);
2961e48354ceSNicholas Bellinger 
2962e48354ceSNicholas Bellinger 		pr_debug("iSCSI REMOVECONNFORRECOVERY logout"
2963e48354ceSNicholas Bellinger 			" for recovery for CID: %hu on CID: %hu successful.\n",
2964e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2965e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2966e48354ceSNicholas Bellinger 		break;
2967e48354ceSNicholas Bellinger 	default:
2968e48354ceSNicholas Bellinger 		pr_err("Unknown cmd->logout_reason: 0x%02x\n",
2969e48354ceSNicholas Bellinger 				cmd->logout_reason);
2970e48354ceSNicholas Bellinger 		return -1;
2971e48354ceSNicholas Bellinger 	}
2972e48354ceSNicholas Bellinger 
2973e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_LOGOUT_RSP;
2974e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
2975e48354ceSNicholas Bellinger 	hdr->response		= cmd->logout_response;
297666c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
2977e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2978e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2979e48354ceSNicholas Bellinger 
2980e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
2981e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2982109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2983e48354ceSNicholas Bellinger 
29842ec5a8c1SNicholas Bellinger 	pr_debug("Built Logout Response ITT: 0x%08x StatSN:"
29852ec5a8c1SNicholas Bellinger 		" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
29862ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response,
29872ec5a8c1SNicholas Bellinger 		cmd->logout_cid, conn->cid);
29882ec5a8c1SNicholas Bellinger 
29892ec5a8c1SNicholas Bellinger 	return 0;
29902ec5a8c1SNicholas Bellinger }
29912ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_logout_rsp);
29922ec5a8c1SNicholas Bellinger 
29932ec5a8c1SNicholas Bellinger static int
2994be36d683SMax Gurtovoy iscsit_send_logout(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
29952ec5a8c1SNicholas Bellinger {
29962854bb23SVarun Prakash 	int rc;
29972ec5a8c1SNicholas Bellinger 
29982ec5a8c1SNicholas Bellinger 	rc = iscsit_build_logout_rsp(cmd, conn,
29992ec5a8c1SNicholas Bellinger 			(struct iscsi_logout_rsp *)&cmd->pdu[0]);
30002ec5a8c1SNicholas Bellinger 	if (rc < 0)
30012ec5a8c1SNicholas Bellinger 		return rc;
30022ec5a8c1SNicholas Bellinger 
30032854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
3004e48354ceSNicholas Bellinger }
3005e48354ceSNicholas Bellinger 
30062ec5a8c1SNicholas Bellinger void
3007be36d683SMax Gurtovoy iscsit_build_nopin_rsp(struct iscsit_cmd *cmd, struct iscsit_conn *conn,
30082ec5a8c1SNicholas Bellinger 		       struct iscsi_nopin *hdr, bool nopout_response)
30092ec5a8c1SNicholas Bellinger {
30102ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_NOOP_IN;
30112ec5a8c1SNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
30122ec5a8c1SNicholas Bellinger         hton24(hdr->dlength, cmd->buf_ptr_size);
30132ec5a8c1SNicholas Bellinger 	if (nopout_response)
30142ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
30152ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
30162ec5a8c1SNicholas Bellinger 	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
30172ec5a8c1SNicholas Bellinger 	cmd->stat_sn		= (nopout_response) ? conn->stat_sn++ :
30182ec5a8c1SNicholas Bellinger 				  conn->stat_sn;
30192ec5a8c1SNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
30202ec5a8c1SNicholas Bellinger 
30212ec5a8c1SNicholas Bellinger 	if (nopout_response)
30222ec5a8c1SNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, conn->sess);
30232ec5a8c1SNicholas Bellinger 
30242ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3025109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
30262ec5a8c1SNicholas Bellinger 
30272ec5a8c1SNicholas Bellinger 	pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
30282ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Length %u\n", (nopout_response) ?
30293fc6a642SColin Ian King 		"Solicited" : "Unsolicited", cmd->init_task_tag,
30302ec5a8c1SNicholas Bellinger 		cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
30312ec5a8c1SNicholas Bellinger }
30322ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_nopin_rsp);
30332ec5a8c1SNicholas Bellinger 
3034e48354ceSNicholas Bellinger /*
3035e48354ceSNicholas Bellinger  *	Unsolicited NOPIN, either requesting a response or not.
3036e48354ceSNicholas Bellinger  */
3037e48354ceSNicholas Bellinger static int iscsit_send_unsolicited_nopin(
303866cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
3039be36d683SMax Gurtovoy 	struct iscsit_conn *conn,
3040e48354ceSNicholas Bellinger 	int want_response)
3041e48354ceSNicholas Bellinger {
30422ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
30432854bb23SVarun Prakash 	int ret;
3044e48354ceSNicholas Bellinger 
30452ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, false);
3046e48354ceSNicholas Bellinger 
3047e48354ceSNicholas Bellinger 	pr_debug("Sending Unsolicited NOPIN TTT: 0x%08x StatSN:"
3048e48354ceSNicholas Bellinger 		" 0x%08x CID: %hu\n", hdr->ttt, cmd->stat_sn, conn->cid);
3049e48354ceSNicholas Bellinger 
30502854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
30512854bb23SVarun Prakash 	if (ret < 0)
30526f3c0e69SAndy Grover 		return ret;
30536f3c0e69SAndy Grover 
30546f3c0e69SAndy Grover 	spin_lock_bh(&cmd->istate_lock);
30556f3c0e69SAndy Grover 	cmd->i_state = want_response ?
30566f3c0e69SAndy Grover 		ISTATE_SENT_NOPIN_WANT_RESPONSE : ISTATE_SENT_STATUS;
30576f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->istate_lock);
30586f3c0e69SAndy Grover 
3059e48354ceSNicholas Bellinger 	return 0;
3060e48354ceSNicholas Bellinger }
3061e48354ceSNicholas Bellinger 
30622ec5a8c1SNicholas Bellinger static int
3063be36d683SMax Gurtovoy iscsit_send_nopin(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
3064e48354ceSNicholas Bellinger {
30652ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
30662ec5a8c1SNicholas Bellinger 
30672ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, true);
3068e48354ceSNicholas Bellinger 
3069e48354ceSNicholas Bellinger 	/*
307066cd9d4eSMax Gurtovoy 	 * NOPOUT Ping Data is attached to struct iscsit_cmd->buf_ptr.
307166cd9d4eSMax Gurtovoy 	 * NOPOUT DataSegmentLength is at struct iscsit_cmd->buf_ptr_size.
3072e48354ceSNicholas Bellinger 	 */
30732854bb23SVarun Prakash 	pr_debug("Echoing back %u bytes of ping data.\n", cmd->buf_ptr_size);
3074e48354ceSNicholas Bellinger 
30752854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
30762854bb23SVarun Prakash 						     cmd->buf_ptr,
30772854bb23SVarun Prakash 						     cmd->buf_ptr_size);
3078e48354ceSNicholas Bellinger }
3079e48354ceSNicholas Bellinger 
30806f3c0e69SAndy Grover static int iscsit_send_r2t(
308166cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
3082be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
3083e48354ceSNicholas Bellinger {
3084e48354ceSNicholas Bellinger 	struct iscsi_r2t *r2t;
3085e48354ceSNicholas Bellinger 	struct iscsi_r2t_rsp *hdr;
30866f3c0e69SAndy Grover 	int ret;
3087e48354ceSNicholas Bellinger 
3088e48354ceSNicholas Bellinger 	r2t = iscsit_get_r2t_from_list(cmd);
3089e48354ceSNicholas Bellinger 	if (!r2t)
3090e48354ceSNicholas Bellinger 		return -1;
3091e48354ceSNicholas Bellinger 
3092e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_r2t_rsp *) cmd->pdu;
3093e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3094e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_R2T;
3095e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3096e48354ceSNicholas Bellinger 	int_to_scsilun(cmd->se_cmd.orig_fe_lun,
3097e48354ceSNicholas Bellinger 			(struct scsi_lun *)&hdr->lun);
309866c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
30998567270dSVarun Prakash 	if (conn->conn_transport->iscsit_get_r2t_ttt)
31008567270dSVarun Prakash 		conn->conn_transport->iscsit_get_r2t_ttt(conn, cmd, r2t);
31018567270dSVarun Prakash 	else
3102c1e34b64SSagi Grimberg 		r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
3103e48354ceSNicholas Bellinger 	hdr->ttt		= cpu_to_be32(r2t->targ_xfer_tag);
3104e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(conn->stat_sn);
3105e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3106109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3107e48354ceSNicholas Bellinger 	hdr->r2tsn		= cpu_to_be32(r2t->r2t_sn);
3108e48354ceSNicholas Bellinger 	hdr->data_offset	= cpu_to_be32(r2t->offset);
3109e48354ceSNicholas Bellinger 	hdr->data_length	= cpu_to_be32(r2t->xfer_len);
3110e48354ceSNicholas Bellinger 
3111e48354ceSNicholas Bellinger 	pr_debug("Built %sR2T, ITT: 0x%08x, TTT: 0x%08x, StatSN:"
3112e48354ceSNicholas Bellinger 		" 0x%08x, R2TSN: 0x%08x, Offset: %u, DDTL: %u, CID: %hu\n",
3113e48354ceSNicholas Bellinger 		(!r2t->recovery_r2t) ? "" : "Recovery ", cmd->init_task_tag,
3114e48354ceSNicholas Bellinger 		r2t->targ_xfer_tag, ntohl(hdr->statsn), r2t->r2t_sn,
3115e48354ceSNicholas Bellinger 			r2t->offset, r2t->xfer_len, conn->cid);
3116e48354ceSNicholas Bellinger 
3117e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3118e48354ceSNicholas Bellinger 	r2t->sent_r2t = 1;
3119e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3120e48354ceSNicholas Bellinger 
31212854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
31226f3c0e69SAndy Grover 	if (ret < 0) {
31236f3c0e69SAndy Grover 		return ret;
31246f3c0e69SAndy Grover 	}
31256f3c0e69SAndy Grover 
31266f3c0e69SAndy Grover 	spin_lock_bh(&cmd->dataout_timeout_lock);
31276f3c0e69SAndy Grover 	iscsit_start_dataout_timer(cmd, conn);
31286f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->dataout_timeout_lock);
31296f3c0e69SAndy Grover 
3130e48354ceSNicholas Bellinger 	return 0;
3131e48354ceSNicholas Bellinger }
3132e48354ceSNicholas Bellinger 
3133e48354ceSNicholas Bellinger /*
31348b1e1244SAndy Grover  *	@recovery: If called from iscsi_task_reassign_complete_write() for
3135e48354ceSNicholas Bellinger  *		connection recovery.
3136e48354ceSNicholas Bellinger  */
3137e48354ceSNicholas Bellinger int iscsit_build_r2ts_for_cmd(
3138be36d683SMax Gurtovoy 	struct iscsit_conn *conn,
313966cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
31408b1e1244SAndy Grover 	bool recovery)
3141e48354ceSNicholas Bellinger {
3142e48354ceSNicholas Bellinger 	int first_r2t = 1;
3143e48354ceSNicholas Bellinger 	u32 offset = 0, xfer_len = 0;
3144e48354ceSNicholas Bellinger 
3145e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3146e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_SENT_LAST_R2T) {
3147e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->r2t_lock);
3148e48354ceSNicholas Bellinger 		return 0;
3149e48354ceSNicholas Bellinger 	}
3150e48354ceSNicholas Bellinger 
31518b1e1244SAndy Grover 	if (conn->sess->sess_ops->DataSequenceInOrder &&
31528b1e1244SAndy Grover 	    !recovery)
3153c6037cc5SAndy Grover 		cmd->r2t_offset = max(cmd->r2t_offset, cmd->write_data_done);
3154e48354ceSNicholas Bellinger 
3155e48354ceSNicholas Bellinger 	while (cmd->outstanding_r2ts < conn->sess->sess_ops->MaxOutstandingR2T) {
3156e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->DataSequenceInOrder) {
3157e48354ceSNicholas Bellinger 			offset = cmd->r2t_offset;
3158e48354ceSNicholas Bellinger 
31598b1e1244SAndy Grover 			if (first_r2t && recovery) {
31608b1e1244SAndy Grover 				int new_data_end = offset +
31618b1e1244SAndy Grover 					conn->sess->sess_ops->MaxBurstLength -
31628b1e1244SAndy Grover 					cmd->next_burst_len;
31638b1e1244SAndy Grover 
3164ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3165ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31668b1e1244SAndy Grover 				else
31678b1e1244SAndy Grover 					xfer_len =
31688b1e1244SAndy Grover 						conn->sess->sess_ops->MaxBurstLength -
31698b1e1244SAndy Grover 						cmd->next_burst_len;
3170e48354ceSNicholas Bellinger 			} else {
31718b1e1244SAndy Grover 				int new_data_end = offset +
3172e48354ceSNicholas Bellinger 					conn->sess->sess_ops->MaxBurstLength;
31738b1e1244SAndy Grover 
3174ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3175ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31768b1e1244SAndy Grover 				else
31778b1e1244SAndy Grover 					xfer_len = conn->sess->sess_ops->MaxBurstLength;
3178e48354ceSNicholas Bellinger 			}
317996e8e26dSBart Van Assche 
318096e8e26dSBart Van Assche 			if ((s32)xfer_len < 0) {
318196e8e26dSBart Van Assche 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
318296e8e26dSBart Van Assche 				break;
318396e8e26dSBart Van Assche 			}
318496e8e26dSBart Van Assche 
3185e48354ceSNicholas Bellinger 			cmd->r2t_offset += xfer_len;
3186e48354ceSNicholas Bellinger 
3187ebf1d95cSAndy Grover 			if (cmd->r2t_offset == cmd->se_cmd.data_length)
3188e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3189e48354ceSNicholas Bellinger 		} else {
3190e48354ceSNicholas Bellinger 			struct iscsi_seq *seq;
3191e48354ceSNicholas Bellinger 
3192e48354ceSNicholas Bellinger 			seq = iscsit_get_seq_holder_for_r2t(cmd);
3193e48354ceSNicholas Bellinger 			if (!seq) {
3194e48354ceSNicholas Bellinger 				spin_unlock_bh(&cmd->r2t_lock);
3195e48354ceSNicholas Bellinger 				return -1;
3196e48354ceSNicholas Bellinger 			}
3197e48354ceSNicholas Bellinger 
3198e48354ceSNicholas Bellinger 			offset = seq->offset;
3199e48354ceSNicholas Bellinger 			xfer_len = seq->xfer_len;
3200e48354ceSNicholas Bellinger 
3201e48354ceSNicholas Bellinger 			if (cmd->seq_send_order == cmd->seq_count)
3202e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3203e48354ceSNicholas Bellinger 		}
3204e48354ceSNicholas Bellinger 		cmd->outstanding_r2ts++;
3205e48354ceSNicholas Bellinger 		first_r2t = 0;
3206e48354ceSNicholas Bellinger 
3207e48354ceSNicholas Bellinger 		if (iscsit_add_r2t_to_list(cmd, offset, xfer_len, 0, 0) < 0) {
3208e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->r2t_lock);
3209e48354ceSNicholas Bellinger 			return -1;
3210e48354ceSNicholas Bellinger 		}
3211e48354ceSNicholas Bellinger 
3212e48354ceSNicholas Bellinger 		if (cmd->cmd_flags & ICF_SENT_LAST_R2T)
3213e48354ceSNicholas Bellinger 			break;
3214e48354ceSNicholas Bellinger 	}
3215e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3216e48354ceSNicholas Bellinger 
3217e48354ceSNicholas Bellinger 	return 0;
3218e48354ceSNicholas Bellinger }
3219d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_r2ts_for_cmd);
3220e48354ceSNicholas Bellinger 
3221be36d683SMax Gurtovoy void iscsit_build_rsp_pdu(struct iscsit_cmd *cmd, struct iscsit_conn *conn,
32222ec5a8c1SNicholas Bellinger 			bool inc_stat_sn, struct iscsi_scsi_rsp *hdr)
3223e48354ceSNicholas Bellinger {
32242ec5a8c1SNicholas Bellinger 	if (inc_stat_sn)
3225e48354ceSNicholas Bellinger 		cmd->stat_sn = conn->stat_sn++;
3226e48354ceSNicholas Bellinger 
322704f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->rsp_pdus);
3228e48354ceSNicholas Bellinger 
3229e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3230e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_CMD_RSP;
3231e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3232e48354ceSNicholas Bellinger 	if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
3233e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW;
32347e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3235e48354ceSNicholas Bellinger 	} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
3236e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
32377e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3238e48354ceSNicholas Bellinger 	}
3239e48354ceSNicholas Bellinger 	hdr->response		= cmd->iscsi_response;
3240e48354ceSNicholas Bellinger 	hdr->cmd_status		= cmd->se_cmd.scsi_status;
324166c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3242e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3243e48354ceSNicholas Bellinger 
3244e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3245e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3246109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3247e48354ceSNicholas Bellinger 
32482ec5a8c1SNicholas Bellinger 	pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
32492ec5a8c1SNicholas Bellinger 		" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
32502ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, cmd->se_cmd.scsi_status,
32512ec5a8c1SNicholas Bellinger 		cmd->se_cmd.scsi_status, conn->cid);
32522ec5a8c1SNicholas Bellinger }
32532ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_rsp_pdu);
32542ec5a8c1SNicholas Bellinger 
3255be36d683SMax Gurtovoy static int iscsit_send_response(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
32562ec5a8c1SNicholas Bellinger {
32572ec5a8c1SNicholas Bellinger 	struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)&cmd->pdu[0];
32582ec5a8c1SNicholas Bellinger 	bool inc_stat_sn = (cmd->i_state == ISTATE_SEND_STATUS);
32592854bb23SVarun Prakash 	void *data_buf = NULL;
32602854bb23SVarun Prakash 	u32 padding = 0, data_buf_len = 0;
32612ec5a8c1SNicholas Bellinger 
32622ec5a8c1SNicholas Bellinger 	iscsit_build_rsp_pdu(cmd, conn, inc_stat_sn, hdr);
32632ec5a8c1SNicholas Bellinger 
3264e48354ceSNicholas Bellinger 	/*
3265e48354ceSNicholas Bellinger 	 * Attach SENSE DATA payload to iSCSI Response PDU
3266e48354ceSNicholas Bellinger 	 */
3267e48354ceSNicholas Bellinger 	if (cmd->se_cmd.sense_buffer &&
3268e48354ceSNicholas Bellinger 	   ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
3269e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
32709c58b7ddSRoland Dreier 		put_unaligned_be16(cmd->se_cmd.scsi_sense_length, cmd->sense_buffer);
32719c58b7ddSRoland Dreier 		cmd->se_cmd.scsi_sense_length += sizeof (__be16);
32729c58b7ddSRoland Dreier 
3273e48354ceSNicholas Bellinger 		padding		= -(cmd->se_cmd.scsi_sense_length) & 3;
327450e5c87dSChristoph Hellwig 		hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length);
32752854bb23SVarun Prakash 		data_buf = cmd->sense_buffer;
32762854bb23SVarun Prakash 		data_buf_len = cmd->se_cmd.scsi_sense_length + padding;
3277e48354ceSNicholas Bellinger 
3278e48354ceSNicholas Bellinger 		if (padding) {
32799c58b7ddSRoland Dreier 			memset(cmd->sense_buffer +
3280e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length, 0, padding);
3281e48354ceSNicholas Bellinger 			pr_debug("Adding %u bytes of padding to"
3282e48354ceSNicholas Bellinger 				" SENSE.\n", padding);
3283e48354ceSNicholas Bellinger 		}
3284e48354ceSNicholas Bellinger 
3285e48354ceSNicholas Bellinger 		pr_debug("Attaching SENSE DATA: %u bytes to iSCSI"
3286e48354ceSNicholas Bellinger 				" Response PDU\n",
3287e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length);
3288e48354ceSNicholas Bellinger 	}
3289e48354ceSNicholas Bellinger 
32902854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, data_buf,
32912854bb23SVarun Prakash 						     data_buf_len);
3292e48354ceSNicholas Bellinger }
3293e48354ceSNicholas Bellinger 
3294e48354ceSNicholas Bellinger static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr)
3295e48354ceSNicholas Bellinger {
3296e48354ceSNicholas Bellinger 	switch (se_tmr->response) {
3297e48354ceSNicholas Bellinger 	case TMR_FUNCTION_COMPLETE:
3298e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_COMPLETE;
3299e48354ceSNicholas Bellinger 	case TMR_TASK_DOES_NOT_EXIST:
3300e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_TASK;
3301e48354ceSNicholas Bellinger 	case TMR_LUN_DOES_NOT_EXIST:
3302e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_LUN;
3303e48354ceSNicholas Bellinger 	case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
3304e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NOT_SUPPORTED;
3305e48354ceSNicholas Bellinger 	case TMR_FUNCTION_REJECTED:
3306e48354ceSNicholas Bellinger 	default:
3307e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_REJECTED;
3308e48354ceSNicholas Bellinger 	}
3309e48354ceSNicholas Bellinger }
3310e48354ceSNicholas Bellinger 
33112ec5a8c1SNicholas Bellinger void
3312be36d683SMax Gurtovoy iscsit_build_task_mgt_rsp(struct iscsit_cmd *cmd, struct iscsit_conn *conn,
33132ec5a8c1SNicholas Bellinger 			  struct iscsi_tm_rsp *hdr)
3314e48354ceSNicholas Bellinger {
3315e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
3316e48354ceSNicholas Bellinger 
3317e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_TMFUNC_RSP;
33187ae0b103SNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
3319e48354ceSNicholas Bellinger 	hdr->response		= iscsit_convert_tcm_tmr_rsp(se_tmr);
332066c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3321e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3322e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3323e48354ceSNicholas Bellinger 
3324e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3325e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3326109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3327e48354ceSNicholas Bellinger 
33282ec5a8c1SNicholas Bellinger 	pr_debug("Built Task Management Response ITT: 0x%08x,"
33292ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
33302ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid);
33312ec5a8c1SNicholas Bellinger }
33322ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_task_mgt_rsp);
33332ec5a8c1SNicholas Bellinger 
33342ec5a8c1SNicholas Bellinger static int
3335be36d683SMax Gurtovoy iscsit_send_task_mgt_rsp(struct iscsit_cmd *cmd, struct iscsit_conn *conn)
33362ec5a8c1SNicholas Bellinger {
33372ec5a8c1SNicholas Bellinger 	struct iscsi_tm_rsp *hdr = (struct iscsi_tm_rsp *)&cmd->pdu[0];
33382ec5a8c1SNicholas Bellinger 
33392ec5a8c1SNicholas Bellinger 	iscsit_build_task_mgt_rsp(cmd, conn, hdr);
33402ec5a8c1SNicholas Bellinger 
33412854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
3342e48354ceSNicholas Bellinger }
3343e48354ceSNicholas Bellinger 
33448b1e1244SAndy Grover #define SENDTARGETS_BUF_LIMIT 32768U
33458b1e1244SAndy Grover 
334622c7aaa5SSagi Grimberg static int
334766cd9d4eSMax Gurtovoy iscsit_build_sendtargets_response(struct iscsit_cmd *cmd,
3348e4f4e801SSagi Grimberg 				  enum iscsit_transport_type network_transport,
3349e4f4e801SSagi Grimberg 				  int skip_bytes, bool *completed)
3350e48354ceSNicholas Bellinger {
3351e48354ceSNicholas Bellinger 	char *payload = NULL;
3352be36d683SMax Gurtovoy 	struct iscsit_conn *conn = cmd->conn;
3353e48354ceSNicholas Bellinger 	struct iscsi_portal_group *tpg;
3354e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn;
3355e48354ceSNicholas Bellinger 	struct iscsi_tpg_np *tpg_np;
3356e48354ceSNicholas Bellinger 	int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
33572dd1d53fSThomas Glanzmann 	int target_name_printed;
33588b1e1244SAndy Grover 	unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
33596665889cSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
3360a6415cddSDavid Disseldorp 	bool active;
3361e48354ceSNicholas Bellinger 
3362be7dcfb6SSagi Grimberg 	buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength,
33638b1e1244SAndy Grover 			 SENDTARGETS_BUF_LIMIT);
3364e48354ceSNicholas Bellinger 
3365e48354ceSNicholas Bellinger 	payload = kzalloc(buffer_len, GFP_KERNEL);
3366c46e22f1SMarkus Elfring 	if (!payload)
3367e48354ceSNicholas Bellinger 		return -ENOMEM;
3368c46e22f1SMarkus Elfring 
33696665889cSNicholas Bellinger 	/*
33708060b8ddSAndy Grover 	 * Locate pointer to iqn./eui. string for ICF_SENDTARGETS_SINGLE
33716665889cSNicholas Bellinger 	 * explicit case..
33726665889cSNicholas Bellinger 	 */
33738060b8ddSAndy Grover 	if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) {
33746665889cSNicholas Bellinger 		text_ptr = strchr(text_in, '=');
33756665889cSNicholas Bellinger 		if (!text_ptr) {
33766665889cSNicholas Bellinger 			pr_err("Unable to locate '=' string in text_in:"
33776665889cSNicholas Bellinger 			       " %s\n", text_in);
33784f45d320SDan Carpenter 			kfree(payload);
33796665889cSNicholas Bellinger 			return -EINVAL;
33806665889cSNicholas Bellinger 		}
33816665889cSNicholas Bellinger 		/*
33826665889cSNicholas Bellinger 		 * Skip over '=' character..
33836665889cSNicholas Bellinger 		 */
33846665889cSNicholas Bellinger 		text_ptr += 1;
33856665889cSNicholas Bellinger 	}
3386e48354ceSNicholas Bellinger 
3387e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
3388e48354ceSNicholas Bellinger 	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
33898060b8ddSAndy Grover 		if ((cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) &&
33906665889cSNicholas Bellinger 		     strcmp(tiqn->tiqn, text_ptr)) {
33916665889cSNicholas Bellinger 			continue;
33926665889cSNicholas Bellinger 		}
33936665889cSNicholas Bellinger 
33942dd1d53fSThomas Glanzmann 		target_name_printed = 0;
3395e48354ceSNicholas Bellinger 
3396e48354ceSNicholas Bellinger 		spin_lock(&tiqn->tiqn_tpg_lock);
3397e48354ceSNicholas Bellinger 		list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
3398e48354ceSNicholas Bellinger 
33992dd1d53fSThomas Glanzmann 			/* If demo_mode_discovery=0 and generate_node_acls=0
34002dd1d53fSThomas Glanzmann 			 * (demo mode dislabed) do not return
34012dd1d53fSThomas Glanzmann 			 * TargetName+TargetAddress unless a NodeACL exists.
34022dd1d53fSThomas Glanzmann 			 */
34032dd1d53fSThomas Glanzmann 
34042dd1d53fSThomas Glanzmann 			if ((tpg->tpg_attrib.generate_node_acls == 0) &&
34052dd1d53fSThomas Glanzmann 			    (tpg->tpg_attrib.demo_mode_discovery == 0) &&
340621aaa23bSNicholas Bellinger 			    (!target_tpg_has_node_acl(&tpg->tpg_se_tpg,
34072dd1d53fSThomas Glanzmann 				cmd->conn->sess->sess_ops->InitiatorName))) {
34082dd1d53fSThomas Glanzmann 				continue;
34092dd1d53fSThomas Glanzmann 			}
34102dd1d53fSThomas Glanzmann 
3411e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_state_lock);
3412a6415cddSDavid Disseldorp 			active = (tpg->tpg_state == TPG_STATE_ACTIVE);
3413e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_state_lock);
3414a6415cddSDavid Disseldorp 
3415a6415cddSDavid Disseldorp 			if (!active && tpg->tpg_attrib.tpg_enabled_sendtargets)
3416e48354ceSNicholas Bellinger 				continue;
3417e48354ceSNicholas Bellinger 
3418e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_np_lock);
3419e48354ceSNicholas Bellinger 			list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
3420e48354ceSNicholas Bellinger 						tpg_np_list) {
34212f9bc894SNicholas Bellinger 				struct iscsi_np *np = tpg_np->tpg_np;
342213a3cf08SAndy Grover 				struct sockaddr_storage *sockaddr;
34232f9bc894SNicholas Bellinger 
342422c7aaa5SSagi Grimberg 				if (np->np_network_transport != network_transport)
342522c7aaa5SSagi Grimberg 					continue;
342622c7aaa5SSagi Grimberg 
34272dd1d53fSThomas Glanzmann 				if (!target_name_printed) {
34282dd1d53fSThomas Glanzmann 					len = sprintf(buf, "TargetName=%s",
34292dd1d53fSThomas Glanzmann 						      tiqn->tiqn);
34302dd1d53fSThomas Glanzmann 					len += 1;
34312dd1d53fSThomas Glanzmann 
34322dd1d53fSThomas Glanzmann 					if ((len + payload_len) > buffer_len) {
34332dd1d53fSThomas Glanzmann 						spin_unlock(&tpg->tpg_np_lock);
34342dd1d53fSThomas Glanzmann 						spin_unlock(&tiqn->tiqn_tpg_lock);
34352dd1d53fSThomas Glanzmann 						end_of_buf = 1;
34362dd1d53fSThomas Glanzmann 						goto eob;
34372dd1d53fSThomas Glanzmann 					}
3438e4f4e801SSagi Grimberg 
3439e4f4e801SSagi Grimberg 					if (skip_bytes && len <= skip_bytes) {
3440e4f4e801SSagi Grimberg 						skip_bytes -= len;
3441e4f4e801SSagi Grimberg 					} else {
34422dd1d53fSThomas Glanzmann 						memcpy(payload + payload_len, buf, len);
34432dd1d53fSThomas Glanzmann 						payload_len += len;
34442dd1d53fSThomas Glanzmann 						target_name_printed = 1;
3445e4f4e801SSagi Grimberg 						if (len > skip_bytes)
3446e4f4e801SSagi Grimberg 							skip_bytes = 0;
3447e4f4e801SSagi Grimberg 					}
34482dd1d53fSThomas Glanzmann 				}
34492dd1d53fSThomas Glanzmann 
34507bfca0cfSSagi Grimberg 				if (inet_addr_is_any((struct sockaddr *)&np->np_sockaddr))
345169d75574SAndy Grover 					sockaddr = &conn->local_sockaddr;
34521997e625SAndy Grover 				else
345369d75574SAndy Grover 					sockaddr = &np->np_sockaddr;
34541997e625SAndy Grover 
345576c28f1fSAndy Grover 				len = sprintf(buf, "TargetAddress="
345676c28f1fSAndy Grover 					      "%pISpc,%hu",
345769d75574SAndy Grover 					      sockaddr,
3458e48354ceSNicholas Bellinger 					      tpg->tpgt);
3459e48354ceSNicholas Bellinger 				len += 1;
3460e48354ceSNicholas Bellinger 
3461e48354ceSNicholas Bellinger 				if ((len + payload_len) > buffer_len) {
3462e48354ceSNicholas Bellinger 					spin_unlock(&tpg->tpg_np_lock);
3463e48354ceSNicholas Bellinger 					spin_unlock(&tiqn->tiqn_tpg_lock);
3464e48354ceSNicholas Bellinger 					end_of_buf = 1;
3465e48354ceSNicholas Bellinger 					goto eob;
3466e48354ceSNicholas Bellinger 				}
3467e4f4e801SSagi Grimberg 
3468e4f4e801SSagi Grimberg 				if (skip_bytes && len <= skip_bytes) {
3469e4f4e801SSagi Grimberg 					skip_bytes -= len;
3470e4f4e801SSagi Grimberg 				} else {
34718359cf43SJörn Engel 					memcpy(payload + payload_len, buf, len);
3472e48354ceSNicholas Bellinger 					payload_len += len;
3473e4f4e801SSagi Grimberg 					if (len > skip_bytes)
3474e4f4e801SSagi Grimberg 						skip_bytes = 0;
3475e4f4e801SSagi Grimberg 				}
3476e48354ceSNicholas Bellinger 			}
3477e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_np_lock);
3478e48354ceSNicholas Bellinger 		}
3479e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_tpg_lock);
3480e48354ceSNicholas Bellinger eob:
3481e4f4e801SSagi Grimberg 		if (end_of_buf) {
3482e4f4e801SSagi Grimberg 			*completed = false;
3483e48354ceSNicholas Bellinger 			break;
3484e4f4e801SSagi Grimberg 		}
34856665889cSNicholas Bellinger 
34868060b8ddSAndy Grover 		if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE)
34876665889cSNicholas Bellinger 			break;
3488e48354ceSNicholas Bellinger 	}
3489e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
3490e48354ceSNicholas Bellinger 
3491e48354ceSNicholas Bellinger 	cmd->buf_ptr = payload;
3492e48354ceSNicholas Bellinger 
3493e48354ceSNicholas Bellinger 	return payload_len;
3494e48354ceSNicholas Bellinger }
3495e48354ceSNicholas Bellinger 
3496889c8a68SNicholas Bellinger int
3497be36d683SMax Gurtovoy iscsit_build_text_rsp(struct iscsit_cmd *cmd, struct iscsit_conn *conn,
349822c7aaa5SSagi Grimberg 		      struct iscsi_text_rsp *hdr,
349922c7aaa5SSagi Grimberg 		      enum iscsit_transport_type network_transport)
3500e48354ceSNicholas Bellinger {
3501889c8a68SNicholas Bellinger 	int text_length, padding;
3502e4f4e801SSagi Grimberg 	bool completed = true;
3503e48354ceSNicholas Bellinger 
3504e4f4e801SSagi Grimberg 	text_length = iscsit_build_sendtargets_response(cmd, network_transport,
3505e4f4e801SSagi Grimberg 							cmd->read_data_done,
3506e4f4e801SSagi Grimberg 							&completed);
3507e48354ceSNicholas Bellinger 	if (text_length < 0)
3508e48354ceSNicholas Bellinger 		return text_length;
3509e48354ceSNicholas Bellinger 
3510e4f4e801SSagi Grimberg 	if (completed) {
3511310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
3512e4f4e801SSagi Grimberg 	} else {
3513310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_TEXT_CONTINUE;
3514e4f4e801SSagi Grimberg 		cmd->read_data_done += text_length;
3515e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF)
3516e4f4e801SSagi Grimberg 			cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
3517e4f4e801SSagi Grimberg 	}
3518e4f4e801SSagi Grimberg 	hdr->opcode = ISCSI_OP_TEXT_RSP;
3519889c8a68SNicholas Bellinger 	padding = ((-text_length) & 3);
3520e48354ceSNicholas Bellinger 	hton24(hdr->dlength, text_length);
352166c7db68SChristoph Hellwig 	hdr->itt = cmd->init_task_tag;
3522e48354ceSNicholas Bellinger 	hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
3523e48354ceSNicholas Bellinger 	cmd->stat_sn = conn->stat_sn++;
3524e48354ceSNicholas Bellinger 	hdr->statsn = cpu_to_be32(cmd->stat_sn);
3525e48354ceSNicholas Bellinger 
3526e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3527e4f4e801SSagi Grimberg 	/*
3528e4f4e801SSagi Grimberg 	 * Reset maxcmdsn_inc in multi-part text payload exchanges to
3529e4f4e801SSagi Grimberg 	 * correctly increment MaxCmdSN for each response answering a
3530e4f4e801SSagi Grimberg 	 * non immediate text request with a valid CmdSN.
3531e4f4e801SSagi Grimberg 	 */
3532e4f4e801SSagi Grimberg 	cmd->maxcmdsn_inc = 0;
3533e48354ceSNicholas Bellinger 	hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
3534109e2381SRoland Dreier 	hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3535e48354ceSNicholas Bellinger 
3536e4f4e801SSagi Grimberg 	pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
3537e4f4e801SSagi Grimberg 		" Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
3538e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag, cmd->stat_sn, text_length, conn->cid,
3539e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_CMD_FINAL),
3540e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE));
3541e48354ceSNicholas Bellinger 
3542889c8a68SNicholas Bellinger 	return text_length + padding;
3543889c8a68SNicholas Bellinger }
3544889c8a68SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_text_rsp);
3545889c8a68SNicholas Bellinger 
3546889c8a68SNicholas Bellinger static int iscsit_send_text_rsp(
354766cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
3548be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
3549889c8a68SNicholas Bellinger {
3550889c8a68SNicholas Bellinger 	struct iscsi_text_rsp *hdr = (struct iscsi_text_rsp *)cmd->pdu;
35512854bb23SVarun Prakash 	int text_length;
3552889c8a68SNicholas Bellinger 
3553864e504aSVarun Prakash 	text_length = iscsit_build_text_rsp(cmd, conn, hdr,
3554864e504aSVarun Prakash 				conn->conn_transport->transport_type);
35552854bb23SVarun Prakash 	if (text_length < 0)
35562854bb23SVarun Prakash 		return text_length;
3557889c8a68SNicholas Bellinger 
35582854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35592854bb23SVarun Prakash 						     cmd->buf_ptr,
35602854bb23SVarun Prakash 						     text_length);
3561e48354ceSNicholas Bellinger }
3562e48354ceSNicholas Bellinger 
35632ec5a8c1SNicholas Bellinger void
3564be36d683SMax Gurtovoy iscsit_build_reject(struct iscsit_cmd *cmd, struct iscsit_conn *conn,
35652ec5a8c1SNicholas Bellinger 		    struct iscsi_reject *hdr)
3566e48354ceSNicholas Bellinger {
3567e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_REJECT;
3568ba159914SNicholas Bellinger 	hdr->reason		= cmd->reject_reason;
3569e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3570e48354ceSNicholas Bellinger 	hton24(hdr->dlength, ISCSI_HDR_LEN);
357150e5c87dSChristoph Hellwig 	hdr->ffffffff		= cpu_to_be32(0xffffffff);
3572e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3573e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3574e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3575109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3576e48354ceSNicholas Bellinger 
35772ec5a8c1SNicholas Bellinger }
35782ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_reject);
3579e48354ceSNicholas Bellinger 
35802ec5a8c1SNicholas Bellinger static int iscsit_send_reject(
358166cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
3582be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
35832ec5a8c1SNicholas Bellinger {
3584bfbdb31dSNicholas Bellinger 	struct iscsi_reject *hdr = (struct iscsi_reject *)&cmd->pdu[0];
35852ec5a8c1SNicholas Bellinger 
3586bfbdb31dSNicholas Bellinger 	iscsit_build_reject(cmd, conn, hdr);
35872ec5a8c1SNicholas Bellinger 
3588e48354ceSNicholas Bellinger 	pr_debug("Built Reject PDU StatSN: 0x%08x, Reason: 0x%02x,"
3589e48354ceSNicholas Bellinger 		" CID: %hu\n", ntohl(hdr->statsn), hdr->reason, conn->cid);
3590e48354ceSNicholas Bellinger 
35912854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35922854bb23SVarun Prakash 						     cmd->buf_ptr,
35932854bb23SVarun Prakash 						     ISCSI_HDR_LEN);
3594e48354ceSNicholas Bellinger }
3595e48354ceSNicholas Bellinger 
3596be36d683SMax Gurtovoy void iscsit_thread_get_cpumask(struct iscsit_conn *conn)
3597e48354ceSNicholas Bellinger {
3598e48354ceSNicholas Bellinger 	int ord, cpu;
3599525f447fSMingzhe Zou 	cpumask_var_t conn_allowed_cpumask;
3600d72d827fSMingzhe Zou 
3601e48354ceSNicholas Bellinger 	/*
360288dcd2daSNicholas Bellinger 	 * bitmap_id is assigned from iscsit_global->ts_bitmap from
360388dcd2daSNicholas Bellinger 	 * within iscsit_start_kthreads()
3604e48354ceSNicholas Bellinger 	 *
360588dcd2daSNicholas Bellinger 	 * Here we use bitmap_id to determine which CPU that this
360688dcd2daSNicholas Bellinger 	 * iSCSI connection's RX/TX threads will be scheduled to
3607e48354ceSNicholas Bellinger 	 * execute upon.
3608e48354ceSNicholas Bellinger 	 */
3609525f447fSMingzhe Zou 	if (!zalloc_cpumask_var(&conn_allowed_cpumask, GFP_KERNEL)) {
3610525f447fSMingzhe Zou 		ord = conn->bitmap_id % cpumask_weight(cpu_online_mask);
3611525f447fSMingzhe Zou 		for_each_online_cpu(cpu) {
3612e48354ceSNicholas Bellinger 			if (ord-- == 0) {
3613e48354ceSNicholas Bellinger 				cpumask_set_cpu(cpu, conn->conn_cpumask);
3614e48354ceSNicholas Bellinger 				return;
3615e48354ceSNicholas Bellinger 			}
3616e48354ceSNicholas Bellinger 		}
3617525f447fSMingzhe Zou 	} else {
3618525f447fSMingzhe Zou 		cpumask_and(conn_allowed_cpumask, iscsit_global->allowed_cpumask,
3619525f447fSMingzhe Zou 			cpu_online_mask);
3620525f447fSMingzhe Zou 
3621525f447fSMingzhe Zou 		cpumask_clear(conn->conn_cpumask);
3622525f447fSMingzhe Zou 		ord = conn->bitmap_id % cpumask_weight(conn_allowed_cpumask);
3623525f447fSMingzhe Zou 		for_each_cpu(cpu, conn_allowed_cpumask) {
3624525f447fSMingzhe Zou 			if (ord-- == 0) {
3625525f447fSMingzhe Zou 				cpumask_set_cpu(cpu, conn->conn_cpumask);
3626525f447fSMingzhe Zou 				free_cpumask_var(conn_allowed_cpumask);
3627525f447fSMingzhe Zou 				return;
3628525f447fSMingzhe Zou 			}
3629525f447fSMingzhe Zou 		}
3630525f447fSMingzhe Zou 		free_cpumask_var(conn_allowed_cpumask);
3631525f447fSMingzhe Zou 	}
3632e48354ceSNicholas Bellinger 	/*
3633e48354ceSNicholas Bellinger 	 * This should never be reached..
3634e48354ceSNicholas Bellinger 	 */
3635e48354ceSNicholas Bellinger 	dump_stack();
3636e48354ceSNicholas Bellinger 	cpumask_setall(conn->conn_cpumask);
3637e48354ceSNicholas Bellinger }
3638e48354ceSNicholas Bellinger 
3639be36d683SMax Gurtovoy static void iscsit_thread_reschedule(struct iscsit_conn *conn)
3640d72d827fSMingzhe Zou {
3641d72d827fSMingzhe Zou 	/*
3642d72d827fSMingzhe Zou 	 * If iscsit_global->allowed_cpumask modified, reschedule iSCSI
3643d72d827fSMingzhe Zou 	 * connection's RX/TX threads update conn->allowed_cpumask.
3644d72d827fSMingzhe Zou 	 */
3645d72d827fSMingzhe Zou 	if (!cpumask_equal(iscsit_global->allowed_cpumask,
3646d72d827fSMingzhe Zou 			   conn->allowed_cpumask)) {
3647d72d827fSMingzhe Zou 		iscsit_thread_get_cpumask(conn);
3648d72d827fSMingzhe Zou 		conn->conn_tx_reset_cpumask = 1;
3649d72d827fSMingzhe Zou 		conn->conn_rx_reset_cpumask = 1;
3650d72d827fSMingzhe Zou 		cpumask_copy(conn->allowed_cpumask,
3651d72d827fSMingzhe Zou 			     iscsit_global->allowed_cpumask);
3652d72d827fSMingzhe Zou 	}
3653d72d827fSMingzhe Zou }
3654d72d827fSMingzhe Zou 
3655d72d827fSMingzhe Zou void iscsit_thread_check_cpumask(
3656be36d683SMax Gurtovoy 	struct iscsit_conn *conn,
3657d72d827fSMingzhe Zou 	struct task_struct *p,
3658d72d827fSMingzhe Zou 	int mode)
3659d72d827fSMingzhe Zou {
3660d72d827fSMingzhe Zou 	/*
3661d72d827fSMingzhe Zou 	 * The TX and RX threads maybe call iscsit_thread_check_cpumask()
3662d72d827fSMingzhe Zou 	 * at the same time. The RX thread might be faster and return from
3663d72d827fSMingzhe Zou 	 * iscsit_thread_reschedule() with conn_rx_reset_cpumask set to 0.
3664d72d827fSMingzhe Zou 	 * Then the TX thread sets it back to 1.
3665d72d827fSMingzhe Zou 	 * The next time the RX thread loops, it sees conn_rx_reset_cpumask
3666d72d827fSMingzhe Zou 	 * set to 1 and calls set_cpus_allowed_ptr() again and set it to 0.
3667d72d827fSMingzhe Zou 	 */
3668d72d827fSMingzhe Zou 	iscsit_thread_reschedule(conn);
3669d72d827fSMingzhe Zou 
3670d72d827fSMingzhe Zou 	/*
3671d72d827fSMingzhe Zou 	 * mode == 1 signals iscsi_target_tx_thread() usage.
3672d72d827fSMingzhe Zou 	 * mode == 0 signals iscsi_target_rx_thread() usage.
3673d72d827fSMingzhe Zou 	 */
3674d72d827fSMingzhe Zou 	if (mode == 1) {
3675d72d827fSMingzhe Zou 		if (!conn->conn_tx_reset_cpumask)
3676d72d827fSMingzhe Zou 			return;
3677d72d827fSMingzhe Zou 	} else {
3678d72d827fSMingzhe Zou 		if (!conn->conn_rx_reset_cpumask)
3679d72d827fSMingzhe Zou 			return;
3680d72d827fSMingzhe Zou 	}
3681d72d827fSMingzhe Zou 
3682d72d827fSMingzhe Zou 	/*
3683d72d827fSMingzhe Zou 	 * Update the CPU mask for this single kthread so that
3684d72d827fSMingzhe Zou 	 * both TX and RX kthreads are scheduled to run on the
3685d72d827fSMingzhe Zou 	 * same CPU.
3686d72d827fSMingzhe Zou 	 */
3687d72d827fSMingzhe Zou 	set_cpus_allowed_ptr(p, conn->conn_cpumask);
3688d72d827fSMingzhe Zou 	if (mode == 1)
3689d72d827fSMingzhe Zou 		conn->conn_tx_reset_cpumask = 0;
3690d72d827fSMingzhe Zou 	else
3691d72d827fSMingzhe Zou 		conn->conn_rx_reset_cpumask = 0;
3692d72d827fSMingzhe Zou }
3693d72d827fSMingzhe Zou EXPORT_SYMBOL(iscsit_thread_check_cpumask);
3694d72d827fSMingzhe Zou 
3695d2faaefbSVarun Prakash int
3696be36d683SMax Gurtovoy iscsit_immediate_queue(struct iscsit_conn *conn, struct iscsit_cmd *cmd, int state)
3697e48354ceSNicholas Bellinger {
36982ec5a8c1SNicholas Bellinger 	int ret;
36992ec5a8c1SNicholas Bellinger 
37002ec5a8c1SNicholas Bellinger 	switch (state) {
37012ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_R2T:
37022ec5a8c1SNicholas Bellinger 		ret = iscsit_send_r2t(cmd, conn);
37032ec5a8c1SNicholas Bellinger 		if (ret < 0)
37042ec5a8c1SNicholas Bellinger 			goto err;
37052ec5a8c1SNicholas Bellinger 		break;
37062ec5a8c1SNicholas Bellinger 	case ISTATE_REMOVE:
37072ec5a8c1SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
37085159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
37092ec5a8c1SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
37102ec5a8c1SNicholas Bellinger 
3711aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
37122ec5a8c1SNicholas Bellinger 		break;
37132ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_WANT_RESPONSE:
37142ec5a8c1SNicholas Bellinger 		iscsit_mod_nopin_response_timer(conn);
37152ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 1);
37162ec5a8c1SNicholas Bellinger 		if (ret < 0)
37172ec5a8c1SNicholas Bellinger 			goto err;
37182ec5a8c1SNicholas Bellinger 		break;
37192ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_NO_RESPONSE:
37202ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 0);
37212ec5a8c1SNicholas Bellinger 		if (ret < 0)
37222ec5a8c1SNicholas Bellinger 			goto err;
37232ec5a8c1SNicholas Bellinger 		break;
37242ec5a8c1SNicholas Bellinger 	default:
37252ec5a8c1SNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
37262ec5a8c1SNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
37272ec5a8c1SNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag, state,
37282ec5a8c1SNicholas Bellinger 		       conn->cid);
37292ec5a8c1SNicholas Bellinger 		goto err;
37302ec5a8c1SNicholas Bellinger 	}
37312ec5a8c1SNicholas Bellinger 
37322ec5a8c1SNicholas Bellinger 	return 0;
37332ec5a8c1SNicholas Bellinger 
37342ec5a8c1SNicholas Bellinger err:
37352ec5a8c1SNicholas Bellinger 	return -1;
37362ec5a8c1SNicholas Bellinger }
3737d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_immediate_queue);
37382ec5a8c1SNicholas Bellinger 
37392ec5a8c1SNicholas Bellinger static int
3740be36d683SMax Gurtovoy iscsit_handle_immediate_queue(struct iscsit_conn *conn)
37412ec5a8c1SNicholas Bellinger {
37422ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
37436f3c0e69SAndy Grover 	struct iscsi_queue_req *qr;
374466cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd;
3745e48354ceSNicholas Bellinger 	u8 state;
37466f3c0e69SAndy Grover 	int ret;
3747e48354ceSNicholas Bellinger 
3748c6037cc5SAndy Grover 	while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) {
3749e48354ceSNicholas Bellinger 		atomic_set(&conn->check_immediate_queue, 0);
3750e48354ceSNicholas Bellinger 		cmd = qr->cmd;
3751e48354ceSNicholas Bellinger 		state = qr->state;
3752e48354ceSNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
3753e48354ceSNicholas Bellinger 
37542ec5a8c1SNicholas Bellinger 		ret = t->iscsit_immediate_queue(conn, cmd, state);
37556f3c0e69SAndy Grover 		if (ret < 0)
37562ec5a8c1SNicholas Bellinger 			return ret;
3757e48354ceSNicholas Bellinger 	}
3758e48354ceSNicholas Bellinger 
37596f3c0e69SAndy Grover 	return 0;
3760e48354ceSNicholas Bellinger }
37616f3c0e69SAndy Grover 
3762d2faaefbSVarun Prakash int
3763be36d683SMax Gurtovoy iscsit_response_queue(struct iscsit_conn *conn, struct iscsit_cmd *cmd, int state)
37646f3c0e69SAndy Grover {
37656f3c0e69SAndy Grover 	int ret;
3766e48354ceSNicholas Bellinger 
3767e48354ceSNicholas Bellinger check_rsp_state:
3768e48354ceSNicholas Bellinger 	switch (state) {
3769e48354ceSNicholas Bellinger 	case ISTATE_SEND_DATAIN:
37702ec5a8c1SNicholas Bellinger 		ret = iscsit_send_datain(cmd, conn);
37716f3c0e69SAndy Grover 		if (ret < 0)
37726f3c0e69SAndy Grover 			goto err;
37736f3c0e69SAndy Grover 		else if (!ret)
37746f3c0e69SAndy Grover 			/* more drs */
37756f3c0e69SAndy Grover 			goto check_rsp_state;
37766f3c0e69SAndy Grover 		else if (ret == 1) {
37776f3c0e69SAndy Grover 			/* all done */
37786f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
37796f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SENT_STATUS;
3780e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->istate_lock);
3781fd3a9025SNicholas Bellinger 
3782fd3a9025SNicholas Bellinger 			if (atomic_read(&conn->check_immediate_queue))
3783fd3a9025SNicholas Bellinger 				return 1;
3784fd3a9025SNicholas Bellinger 
37852ec5a8c1SNicholas Bellinger 			return 0;
37866f3c0e69SAndy Grover 		} else if (ret == 2) {
37876f3c0e69SAndy Grover 			/* Still must send status,
37886f3c0e69SAndy Grover 			   SCF_TRANSPORT_TASK_SENSE was set */
37896f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
37906f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SEND_STATUS;
37916f3c0e69SAndy Grover 			spin_unlock_bh(&cmd->istate_lock);
37926f3c0e69SAndy Grover 			state = ISTATE_SEND_STATUS;
37936f3c0e69SAndy Grover 			goto check_rsp_state;
37946f3c0e69SAndy Grover 		}
37956f3c0e69SAndy Grover 
3796e48354ceSNicholas Bellinger 		break;
3797e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3798e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
37992ec5a8c1SNicholas Bellinger 		ret = iscsit_send_response(cmd, conn);
3800e48354ceSNicholas Bellinger 		break;
3801e48354ceSNicholas Bellinger 	case ISTATE_SEND_LOGOUTRSP:
38022ec5a8c1SNicholas Bellinger 		ret = iscsit_send_logout(cmd, conn);
3803e48354ceSNicholas Bellinger 		break;
3804e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3805e48354ceSNicholas Bellinger 		ret = iscsit_send_conn_drop_async_message(
3806e48354ceSNicholas Bellinger 			cmd, conn);
3807e48354ceSNicholas Bellinger 		break;
3808e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
38092ec5a8c1SNicholas Bellinger 		ret = iscsit_send_nopin(cmd, conn);
3810e48354ceSNicholas Bellinger 		break;
3811e48354ceSNicholas Bellinger 	case ISTATE_SEND_REJECT:
3812e48354ceSNicholas Bellinger 		ret = iscsit_send_reject(cmd, conn);
3813e48354ceSNicholas Bellinger 		break;
3814e48354ceSNicholas Bellinger 	case ISTATE_SEND_TASKMGTRSP:
3815e48354ceSNicholas Bellinger 		ret = iscsit_send_task_mgt_rsp(cmd, conn);
3816e48354ceSNicholas Bellinger 		if (ret != 0)
3817e48354ceSNicholas Bellinger 			break;
3818e48354ceSNicholas Bellinger 		ret = iscsit_tmr_post_handler(cmd, conn);
3819e48354ceSNicholas Bellinger 		if (ret != 0)
3820e48354ceSNicholas Bellinger 			iscsit_fall_back_to_erl0(conn->sess);
3821e48354ceSNicholas Bellinger 		break;
3822e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
3823e48354ceSNicholas Bellinger 		ret = iscsit_send_text_rsp(cmd, conn);
3824e48354ceSNicholas Bellinger 		break;
3825e48354ceSNicholas Bellinger 	default:
3826e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3827e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3828e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3829e48354ceSNicholas Bellinger 		       state, conn->cid);
38306f3c0e69SAndy Grover 		goto err;
3831e48354ceSNicholas Bellinger 	}
3832c6037cc5SAndy Grover 	if (ret < 0)
38336f3c0e69SAndy Grover 		goto err;
3834e48354ceSNicholas Bellinger 
3835e48354ceSNicholas Bellinger 	switch (state) {
38366f3c0e69SAndy Grover 	case ISTATE_SEND_LOGOUTRSP:
38376f3c0e69SAndy Grover 		if (!iscsit_logout_post_handler(cmd, conn))
383888dcd2daSNicholas Bellinger 			return -ECONNRESET;
3839df561f66SGustavo A. R. Silva 		fallthrough;
3840e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3841e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3842e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
3843e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
3844e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
38456f3c0e69SAndy Grover 	case ISTATE_SEND_TASKMGTRSP:
3846ba159914SNicholas Bellinger 	case ISTATE_SEND_REJECT:
38476f3c0e69SAndy Grover 		spin_lock_bh(&cmd->istate_lock);
38486f3c0e69SAndy Grover 		cmd->i_state = ISTATE_SENT_STATUS;
38496f3c0e69SAndy Grover 		spin_unlock_bh(&cmd->istate_lock);
3850e48354ceSNicholas Bellinger 		break;
3851e48354ceSNicholas Bellinger 	default:
3852e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3853e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3854e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3855e48354ceSNicholas Bellinger 		       cmd->i_state, conn->cid);
38566f3c0e69SAndy Grover 		goto err;
3857e48354ceSNicholas Bellinger 	}
3858e48354ceSNicholas Bellinger 
3859e48354ceSNicholas Bellinger 	if (atomic_read(&conn->check_immediate_queue))
3860fd3a9025SNicholas Bellinger 		return 1;
38616f3c0e69SAndy Grover 
38626f3c0e69SAndy Grover 	return 0;
38636f3c0e69SAndy Grover 
38646f3c0e69SAndy Grover err:
38656f3c0e69SAndy Grover 	return -1;
38666f3c0e69SAndy Grover }
3867d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_response_queue);
38686f3c0e69SAndy Grover 
3869be36d683SMax Gurtovoy static int iscsit_handle_response_queue(struct iscsit_conn *conn)
38702ec5a8c1SNicholas Bellinger {
38712ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
38722ec5a8c1SNicholas Bellinger 	struct iscsi_queue_req *qr;
387366cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd;
38742ec5a8c1SNicholas Bellinger 	u8 state;
38752ec5a8c1SNicholas Bellinger 	int ret;
38762ec5a8c1SNicholas Bellinger 
38772ec5a8c1SNicholas Bellinger 	while ((qr = iscsit_get_cmd_from_response_queue(conn))) {
38782ec5a8c1SNicholas Bellinger 		cmd = qr->cmd;
38792ec5a8c1SNicholas Bellinger 		state = qr->state;
38802ec5a8c1SNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
38812ec5a8c1SNicholas Bellinger 
38822ec5a8c1SNicholas Bellinger 		ret = t->iscsit_response_queue(conn, cmd, state);
38832ec5a8c1SNicholas Bellinger 		if (ret == 1 || ret < 0)
38842ec5a8c1SNicholas Bellinger 			return ret;
38852ec5a8c1SNicholas Bellinger 	}
38862ec5a8c1SNicholas Bellinger 
38872ec5a8c1SNicholas Bellinger 	return 0;
38882ec5a8c1SNicholas Bellinger }
38892ec5a8c1SNicholas Bellinger 
38906f3c0e69SAndy Grover int iscsi_target_tx_thread(void *arg)
38916f3c0e69SAndy Grover {
38926f3c0e69SAndy Grover 	int ret = 0;
3893be36d683SMax Gurtovoy 	struct iscsit_conn *conn = arg;
38945e0cf5e6SJiang Yi 	bool conn_freed = false;
38955e0cf5e6SJiang Yi 
38966f3c0e69SAndy Grover 	/*
38976f3c0e69SAndy Grover 	 * Allow ourselves to be interrupted by SIGINT so that a
38986f3c0e69SAndy Grover 	 * connection recovery / failure event can be triggered externally.
38996f3c0e69SAndy Grover 	 */
39006f3c0e69SAndy Grover 	allow_signal(SIGINT);
39016f3c0e69SAndy Grover 
39026f3c0e69SAndy Grover 	while (!kthread_should_stop()) {
39036f3c0e69SAndy Grover 		/*
39046f3c0e69SAndy Grover 		 * Ensure that both TX and RX per connection kthreads
39056f3c0e69SAndy Grover 		 * are scheduled to run on the same CPU.
39066f3c0e69SAndy Grover 		 */
39076f3c0e69SAndy Grover 		iscsit_thread_check_cpumask(conn, current, 1);
39086f3c0e69SAndy Grover 
3909d5627acbSRoland Dreier 		wait_event_interruptible(conn->queues_wq,
391088dcd2daSNicholas Bellinger 					 !iscsit_conn_all_queues_empty(conn));
39116f3c0e69SAndy Grover 
391288dcd2daSNicholas Bellinger 		if (signal_pending(current))
39136f3c0e69SAndy Grover 			goto transport_err;
39146f3c0e69SAndy Grover 
3915fd3a9025SNicholas Bellinger get_immediate:
39162ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_immediate_queue(conn);
39176f3c0e69SAndy Grover 		if (ret < 0)
39186f3c0e69SAndy Grover 			goto transport_err;
39196f3c0e69SAndy Grover 
39202ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_response_queue(conn);
39215e0cf5e6SJiang Yi 		if (ret == 1) {
3922fd3a9025SNicholas Bellinger 			goto get_immediate;
39235e0cf5e6SJiang Yi 		} else if (ret == -ECONNRESET) {
39245e0cf5e6SJiang Yi 			conn_freed = true;
392588dcd2daSNicholas Bellinger 			goto out;
39265e0cf5e6SJiang Yi 		} else if (ret < 0) {
39276f3c0e69SAndy Grover 			goto transport_err;
3928e48354ceSNicholas Bellinger 		}
39295e0cf5e6SJiang Yi 	}
3930e48354ceSNicholas Bellinger 
3931e48354ceSNicholas Bellinger transport_err:
3932e5419865SNicholas Bellinger 	/*
3933e5419865SNicholas Bellinger 	 * Avoid the normal connection failure code-path if this connection
3934e5419865SNicholas Bellinger 	 * is still within LOGIN mode, and iscsi_np process context is
3935e5419865SNicholas Bellinger 	 * responsible for cleaning up the early connection failure.
3936e5419865SNicholas Bellinger 	 */
3937e5419865SNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
39385e0cf5e6SJiang Yi 		iscsit_take_action_for_connection_exit(conn, &conn_freed);
3939e48354ceSNicholas Bellinger out:
39405e0cf5e6SJiang Yi 	if (!conn_freed) {
39415e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
39425e0cf5e6SJiang Yi 			msleep(100);
39435e0cf5e6SJiang Yi 		}
39445e0cf5e6SJiang Yi 	}
3945e48354ceSNicholas Bellinger 	return 0;
3946e48354ceSNicholas Bellinger }
3947e48354ceSNicholas Bellinger 
3948be36d683SMax Gurtovoy static int iscsi_target_rx_opcode(struct iscsit_conn *conn, unsigned char *buf)
39493e1c81a9SNicholas Bellinger {
39503e1c81a9SNicholas Bellinger 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)buf;
395166cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd;
39523e1c81a9SNicholas Bellinger 	int ret = 0;
39533e1c81a9SNicholas Bellinger 
39543e1c81a9SNicholas Bellinger 	switch (hdr->opcode & ISCSI_OPCODE_MASK) {
39553e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_CMD:
3956676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
39573e1c81a9SNicholas Bellinger 		if (!cmd)
3958ba159914SNicholas Bellinger 			goto reject;
39593e1c81a9SNicholas Bellinger 
39603e1c81a9SNicholas Bellinger 		ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
39613e1c81a9SNicholas Bellinger 		break;
39623e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_DATA_OUT:
39633e1c81a9SNicholas Bellinger 		ret = iscsit_handle_data_out(conn, buf);
39643e1c81a9SNicholas Bellinger 		break;
39653e1c81a9SNicholas Bellinger 	case ISCSI_OP_NOOP_OUT:
39663e1c81a9SNicholas Bellinger 		cmd = NULL;
39673e1c81a9SNicholas Bellinger 		if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
3968676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
39693e1c81a9SNicholas Bellinger 			if (!cmd)
3970ba159914SNicholas Bellinger 				goto reject;
39713e1c81a9SNicholas Bellinger 		}
39723e1c81a9SNicholas Bellinger 		ret = iscsit_handle_nop_out(conn, cmd, buf);
39733e1c81a9SNicholas Bellinger 		break;
39743e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_TMFUNC:
3975676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
39763e1c81a9SNicholas Bellinger 		if (!cmd)
3977ba159914SNicholas Bellinger 			goto reject;
39783e1c81a9SNicholas Bellinger 
39793e1c81a9SNicholas Bellinger 		ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
39803e1c81a9SNicholas Bellinger 		break;
39813e1c81a9SNicholas Bellinger 	case ISCSI_OP_TEXT:
3982e4f4e801SSagi Grimberg 		if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
3983e4f4e801SSagi Grimberg 			cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
3984e4f4e801SSagi Grimberg 			if (!cmd)
3985e4f4e801SSagi Grimberg 				goto reject;
3986e4f4e801SSagi Grimberg 		} else {
3987676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
398864534aa7SNicholas Bellinger 			if (!cmd)
3989ba159914SNicholas Bellinger 				goto reject;
3990e4f4e801SSagi Grimberg 		}
399164534aa7SNicholas Bellinger 
399264534aa7SNicholas Bellinger 		ret = iscsit_handle_text_cmd(conn, cmd, buf);
39933e1c81a9SNicholas Bellinger 		break;
39943e1c81a9SNicholas Bellinger 	case ISCSI_OP_LOGOUT:
3995676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
39963e1c81a9SNicholas Bellinger 		if (!cmd)
3997ba159914SNicholas Bellinger 			goto reject;
39983e1c81a9SNicholas Bellinger 
39993e1c81a9SNicholas Bellinger 		ret = iscsit_handle_logout_cmd(conn, cmd, buf);
40003e1c81a9SNicholas Bellinger 		if (ret > 0)
40013e1c81a9SNicholas Bellinger 			wait_for_completion_timeout(&conn->conn_logout_comp,
40023e1c81a9SNicholas Bellinger 					SECONDS_FOR_LOGOUT_COMP * HZ);
40033e1c81a9SNicholas Bellinger 		break;
40043e1c81a9SNicholas Bellinger 	case ISCSI_OP_SNACK:
40053e1c81a9SNicholas Bellinger 		ret = iscsit_handle_snack(conn, buf);
40063e1c81a9SNicholas Bellinger 		break;
40073e1c81a9SNicholas Bellinger 	default:
40083e1c81a9SNicholas Bellinger 		pr_err("Got unknown iSCSI OpCode: 0x%02x\n", hdr->opcode);
40093e1c81a9SNicholas Bellinger 		if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
40103e1c81a9SNicholas Bellinger 			pr_err("Cannot recover from unknown"
40113e1c81a9SNicholas Bellinger 			" opcode while ERL=0, closing iSCSI connection.\n");
40123e1c81a9SNicholas Bellinger 			return -1;
40133e1c81a9SNicholas Bellinger 		}
4014c04a6091SChristophe Vu-Brugier 		pr_err("Unable to recover from unknown opcode while OFMarker=No,"
4015c04a6091SChristophe Vu-Brugier 		       " closing iSCSI connection.\n");
4016c04a6091SChristophe Vu-Brugier 		ret = -1;
40173e1c81a9SNicholas Bellinger 		break;
40183e1c81a9SNicholas Bellinger 	}
40193e1c81a9SNicholas Bellinger 
40203e1c81a9SNicholas Bellinger 	return ret;
4021ba159914SNicholas Bellinger reject:
4022ba159914SNicholas Bellinger 	return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
40233e1c81a9SNicholas Bellinger }
40243e1c81a9SNicholas Bellinger 
4025be36d683SMax Gurtovoy static bool iscsi_target_check_conn_state(struct iscsit_conn *conn)
4026ca82c2bdSNicholas Bellinger {
4027ca82c2bdSNicholas Bellinger 	bool ret;
4028ca82c2bdSNicholas Bellinger 
4029ca82c2bdSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
4030ca82c2bdSNicholas Bellinger 	ret = (conn->conn_state != TARG_CONN_STATE_LOGGED_IN);
4031ca82c2bdSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
4032ca82c2bdSNicholas Bellinger 
4033ca82c2bdSNicholas Bellinger 	return ret;
4034ca82c2bdSNicholas Bellinger }
4035ca82c2bdSNicholas Bellinger 
4036be36d683SMax Gurtovoy static void iscsit_get_rx_pdu(struct iscsit_conn *conn)
4037e48354ceSNicholas Bellinger {
4038e8205ccaSVarun Prakash 	int ret;
4039679fcae4SLaura Abbott 	u8 *buffer, opcode;
4040e48354ceSNicholas Bellinger 	u32 checksum = 0, digest = 0;
4041e48354ceSNicholas Bellinger 	struct kvec iov;
40423e1c81a9SNicholas Bellinger 
4043679fcae4SLaura Abbott 	buffer = kcalloc(ISCSI_HDR_LEN, sizeof(*buffer), GFP_KERNEL);
4044679fcae4SLaura Abbott 	if (!buffer)
4045679fcae4SLaura Abbott 		return;
4046679fcae4SLaura Abbott 
4047e48354ceSNicholas Bellinger 	while (!kthread_should_stop()) {
4048e48354ceSNicholas Bellinger 		/*
4049e48354ceSNicholas Bellinger 		 * Ensure that both TX and RX per connection kthreads
4050e48354ceSNicholas Bellinger 		 * are scheduled to run on the same CPU.
4051e48354ceSNicholas Bellinger 		 */
4052e48354ceSNicholas Bellinger 		iscsit_thread_check_cpumask(conn, current, 0);
4053e48354ceSNicholas Bellinger 
4054e48354ceSNicholas Bellinger 		memset(&iov, 0, sizeof(struct kvec));
4055e48354ceSNicholas Bellinger 
4056e48354ceSNicholas Bellinger 		iov.iov_base	= buffer;
4057e48354ceSNicholas Bellinger 		iov.iov_len	= ISCSI_HDR_LEN;
4058e48354ceSNicholas Bellinger 
4059e48354ceSNicholas Bellinger 		ret = rx_data(conn, &iov, 1, ISCSI_HDR_LEN);
4060e48354ceSNicholas Bellinger 		if (ret != ISCSI_HDR_LEN) {
4061e48354ceSNicholas Bellinger 			iscsit_rx_thread_wait_for_tcp(conn);
4062679fcae4SLaura Abbott 			break;
4063e48354ceSNicholas Bellinger 		}
4064e48354ceSNicholas Bellinger 
4065e48354ceSNicholas Bellinger 		if (conn->conn_ops->HeaderDigest) {
4066e48354ceSNicholas Bellinger 			iov.iov_base	= &digest;
4067e48354ceSNicholas Bellinger 			iov.iov_len	= ISCSI_CRC_LEN;
4068e48354ceSNicholas Bellinger 
4069e48354ceSNicholas Bellinger 			ret = rx_data(conn, &iov, 1, ISCSI_CRC_LEN);
4070e48354ceSNicholas Bellinger 			if (ret != ISCSI_CRC_LEN) {
4071e48354ceSNicholas Bellinger 				iscsit_rx_thread_wait_for_tcp(conn);
4072679fcae4SLaura Abbott 				break;
4073e48354ceSNicholas Bellinger 			}
4074e48354ceSNicholas Bellinger 
4075e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer,
4076e1dfb21fSBart Van Assche 						  ISCSI_HDR_LEN, 0, NULL,
4077e1dfb21fSBart Van Assche 						  &checksum);
4078e48354ceSNicholas Bellinger 
4079e48354ceSNicholas Bellinger 			if (digest != checksum) {
4080e48354ceSNicholas Bellinger 				pr_err("HeaderDigest CRC32C failed,"
4081e48354ceSNicholas Bellinger 					" received 0x%08x, computed 0x%08x\n",
4082e48354ceSNicholas Bellinger 					digest, checksum);
4083e48354ceSNicholas Bellinger 				/*
4084e48354ceSNicholas Bellinger 				 * Set the PDU to 0xff so it will intentionally
4085e48354ceSNicholas Bellinger 				 * hit default in the switch below.
4086e48354ceSNicholas Bellinger 				 */
4087e48354ceSNicholas Bellinger 				memset(buffer, 0xff, ISCSI_HDR_LEN);
408804f3b31bSNicholas Bellinger 				atomic_long_inc(&conn->sess->conn_digest_errors);
4089e48354ceSNicholas Bellinger 			} else {
4090e48354ceSNicholas Bellinger 				pr_debug("Got HeaderDigest CRC32C"
4091e48354ceSNicholas Bellinger 						" 0x%08x\n", checksum);
4092e48354ceSNicholas Bellinger 			}
4093e48354ceSNicholas Bellinger 		}
4094e48354ceSNicholas Bellinger 
4095e48354ceSNicholas Bellinger 		if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT)
4096679fcae4SLaura Abbott 			break;
4097e48354ceSNicholas Bellinger 
4098e48354ceSNicholas Bellinger 		opcode = buffer[0] & ISCSI_OPCODE_MASK;
4099e48354ceSNicholas Bellinger 
4100e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->SessionType &&
4101e48354ceSNicholas Bellinger 		   ((!(opcode & ISCSI_OP_TEXT)) ||
4102e48354ceSNicholas Bellinger 		    (!(opcode & ISCSI_OP_LOGOUT)))) {
4103e48354ceSNicholas Bellinger 			pr_err("Received illegal iSCSI Opcode: 0x%02x"
4104e48354ceSNicholas Bellinger 			" while in Discovery Session, rejecting.\n", opcode);
4105ba159914SNicholas Bellinger 			iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
4106ba159914SNicholas Bellinger 					  buffer);
4107679fcae4SLaura Abbott 			break;
4108e48354ceSNicholas Bellinger 		}
4109e48354ceSNicholas Bellinger 
41103e1c81a9SNicholas Bellinger 		ret = iscsi_target_rx_opcode(conn, buffer);
41113e1c81a9SNicholas Bellinger 		if (ret < 0)
4112679fcae4SLaura Abbott 			break;
4113e8205ccaSVarun Prakash 	}
4114679fcae4SLaura Abbott 
4115679fcae4SLaura Abbott 	kfree(buffer);
4116e48354ceSNicholas Bellinger }
4117e48354ceSNicholas Bellinger 
4118e8205ccaSVarun Prakash int iscsi_target_rx_thread(void *arg)
4119e8205ccaSVarun Prakash {
4120e8205ccaSVarun Prakash 	int rc;
4121be36d683SMax Gurtovoy 	struct iscsit_conn *conn = arg;
41225e0cf5e6SJiang Yi 	bool conn_freed = false;
4123e8205ccaSVarun Prakash 
4124e8205ccaSVarun Prakash 	/*
4125e8205ccaSVarun Prakash 	 * Allow ourselves to be interrupted by SIGINT so that a
4126e8205ccaSVarun Prakash 	 * connection recovery / failure event can be triggered externally.
4127e8205ccaSVarun Prakash 	 */
4128e8205ccaSVarun Prakash 	allow_signal(SIGINT);
4129e8205ccaSVarun Prakash 	/*
4130e8205ccaSVarun Prakash 	 * Wait for iscsi_post_login_handler() to complete before allowing
4131e8205ccaSVarun Prakash 	 * incoming iscsi/tcp socket I/O, and/or failing the connection.
4132e8205ccaSVarun Prakash 	 */
4133e8205ccaSVarun Prakash 	rc = wait_for_completion_interruptible(&conn->rx_login_comp);
4134e8205ccaSVarun Prakash 	if (rc < 0 || iscsi_target_check_conn_state(conn))
41355e0cf5e6SJiang Yi 		goto out;
4136e8205ccaSVarun Prakash 
4137e8205ccaSVarun Prakash 	if (!conn->conn_transport->iscsit_get_rx_pdu)
4138e8205ccaSVarun Prakash 		return 0;
4139e8205ccaSVarun Prakash 
4140e8205ccaSVarun Prakash 	conn->conn_transport->iscsit_get_rx_pdu(conn);
4141e8205ccaSVarun Prakash 
4142e48354ceSNicholas Bellinger 	if (!signal_pending(current))
4143e48354ceSNicholas Bellinger 		atomic_set(&conn->transport_failed, 1);
41445e0cf5e6SJiang Yi 	iscsit_take_action_for_connection_exit(conn, &conn_freed);
41455e0cf5e6SJiang Yi 
41465e0cf5e6SJiang Yi out:
41475e0cf5e6SJiang Yi 	if (!conn_freed) {
41485e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
41495e0cf5e6SJiang Yi 			msleep(100);
41505e0cf5e6SJiang Yi 		}
41515e0cf5e6SJiang Yi 	}
41525e0cf5e6SJiang Yi 
4153e48354ceSNicholas Bellinger 	return 0;
4154e48354ceSNicholas Bellinger }
4155e48354ceSNicholas Bellinger 
4156be36d683SMax Gurtovoy static void iscsit_release_commands_from_conn(struct iscsit_conn *conn)
4157e48354ceSNicholas Bellinger {
4158064cdd2dSNicholas Bellinger 	LIST_HEAD(tmp_list);
415966cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd = NULL, *cmd_tmp = NULL;
41600873fe44SMax Gurtovoy 	struct iscsit_session *sess = conn->sess;
4161e48354ceSNicholas Bellinger 	/*
4162e48354ceSNicholas Bellinger 	 * We expect this function to only ever be called from either RX or TX
4163e48354ceSNicholas Bellinger 	 * thread context via iscsit_close_connection() once the other context
4164e48354ceSNicholas Bellinger 	 * has been reset -> returned sleeping pre-handler state.
4165e48354ceSNicholas Bellinger 	 */
4166e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
4167064cdd2dSNicholas Bellinger 	list_splice_init(&conn->conn_cmd_list, &tmp_list);
4168e48354ceSNicholas Bellinger 
4169f3619935SMike Christie 	list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
4170064cdd2dSNicholas Bellinger 		struct se_cmd *se_cmd = &cmd->se_cmd;
4171e48354ceSNicholas Bellinger 
4172064cdd2dSNicholas Bellinger 		if (se_cmd->se_tfo != NULL) {
417332e36bfbSBart Van Assche 			spin_lock_irq(&se_cmd->t_state_lock);
4174f3619935SMike Christie 			if (se_cmd->transport_state & CMD_T_ABORTED) {
4175f3619935SMike Christie 				/*
4176f3619935SMike Christie 				 * LIO's abort path owns the cleanup for this,
4177f3619935SMike Christie 				 * so put it back on the list and let
4178f3619935SMike Christie 				 * aborted_task handle it.
4179f3619935SMike Christie 				 */
4180f3619935SMike Christie 				list_move_tail(&cmd->i_conn_node,
4181f3619935SMike Christie 					       &conn->conn_cmd_list);
4182f3619935SMike Christie 			} else {
4183064cdd2dSNicholas Bellinger 				se_cmd->transport_state |= CMD_T_FABRIC_STOP;
4184f3619935SMike Christie 			}
418532e36bfbSBart Van Assche 			spin_unlock_irq(&se_cmd->t_state_lock);
4186064cdd2dSNicholas Bellinger 		}
4187e48354ceSNicholas Bellinger 	}
4188e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4189064cdd2dSNicholas Bellinger 
4190064cdd2dSNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
4191064cdd2dSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
4192064cdd2dSNicholas Bellinger 
4193064cdd2dSNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, sess);
4194064cdd2dSNicholas Bellinger 		iscsit_free_cmd(cmd, true);
4195064cdd2dSNicholas Bellinger 
4196064cdd2dSNicholas Bellinger 	}
4197e48354ceSNicholas Bellinger }
4198e48354ceSNicholas Bellinger 
4199e48354ceSNicholas Bellinger static void iscsit_stop_timers_for_cmds(
4200be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
4201e48354ceSNicholas Bellinger {
420266cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd;
4203e48354ceSNicholas Bellinger 
4204e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
42052fbb471eSAndy Grover 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
4206e48354ceSNicholas Bellinger 		if (cmd->data_direction == DMA_TO_DEVICE)
4207e48354ceSNicholas Bellinger 			iscsit_stop_dataout_timer(cmd);
4208e48354ceSNicholas Bellinger 	}
4209e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4210e48354ceSNicholas Bellinger }
4211e48354ceSNicholas Bellinger 
4212e48354ceSNicholas Bellinger int iscsit_close_connection(
4213be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
4214e48354ceSNicholas Bellinger {
4215e48354ceSNicholas Bellinger 	int conn_logout = (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT);
42160873fe44SMax Gurtovoy 	struct iscsit_session	*sess = conn->sess;
4217e48354ceSNicholas Bellinger 
4218e48354ceSNicholas Bellinger 	pr_debug("Closing iSCSI connection CID %hu on SID:"
4219e48354ceSNicholas Bellinger 		" %u\n", conn->cid, sess->sid);
4220e48354ceSNicholas Bellinger 	/*
4221b4869ee9SVarun Prakash 	 * Always up conn_logout_comp for the traditional TCP and HW_OFFLOAD
4222b4869ee9SVarun Prakash 	 * case just in case the RX Thread in iscsi_target_rx_opcode() is
4223b4869ee9SVarun Prakash 	 * sleeping and the logout response never got sent because the
4224b4869ee9SVarun Prakash 	 * connection failed.
4225f068fbc8SNicholas Bellinger 	 *
4226f068fbc8SNicholas Bellinger 	 * However for iser-target, isert_wait4logout() is using conn_logout_comp
4227f068fbc8SNicholas Bellinger 	 * to signal logout response TX interrupt completion.  Go ahead and skip
4228f068fbc8SNicholas Bellinger 	 * this for iser since isert_rx_opcode() does not wait on logout failure,
4229be36d683SMax Gurtovoy 	 * and to avoid iscsit_conn pointer dereference in iser-target code.
4230e48354ceSNicholas Bellinger 	 */
4231bd027d85SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown)
4232e48354ceSNicholas Bellinger 		complete(&conn->conn_logout_comp);
4233e48354ceSNicholas Bellinger 
423488dcd2daSNicholas Bellinger 	if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) {
423588dcd2daSNicholas Bellinger 		if (conn->tx_thread &&
423688dcd2daSNicholas Bellinger 		    cmpxchg(&conn->tx_thread_active, true, false)) {
423788dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->tx_thread, 1);
423888dcd2daSNicholas Bellinger 			kthread_stop(conn->tx_thread);
423988dcd2daSNicholas Bellinger 		}
424088dcd2daSNicholas Bellinger 	} else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) {
424188dcd2daSNicholas Bellinger 		if (conn->rx_thread &&
424288dcd2daSNicholas Bellinger 		    cmpxchg(&conn->rx_thread_active, true, false)) {
424388dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->rx_thread, 1);
424488dcd2daSNicholas Bellinger 			kthread_stop(conn->rx_thread);
424588dcd2daSNicholas Bellinger 		}
424688dcd2daSNicholas Bellinger 	}
424788dcd2daSNicholas Bellinger 
424888dcd2daSNicholas Bellinger 	spin_lock(&iscsit_global->ts_bitmap_lock);
424988dcd2daSNicholas Bellinger 	bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
425088dcd2daSNicholas Bellinger 			      get_order(1));
425188dcd2daSNicholas Bellinger 	spin_unlock(&iscsit_global->ts_bitmap_lock);
4252e48354ceSNicholas Bellinger 
4253e48354ceSNicholas Bellinger 	iscsit_stop_timers_for_cmds(conn);
4254e48354ceSNicholas Bellinger 	iscsit_stop_nopin_response_timer(conn);
4255e48354ceSNicholas Bellinger 	iscsit_stop_nopin_timer(conn);
4256defd8848SNicholas Bellinger 
425776261adaSBart Van Assche 	if (conn->conn_transport->iscsit_wait_conn)
425876261adaSBart Van Assche 		conn->conn_transport->iscsit_wait_conn(conn);
425976261adaSBart Van Assche 
4260e48354ceSNicholas Bellinger 	/*
4261e48354ceSNicholas Bellinger 	 * During Connection recovery drop unacknowledged out of order
4262e48354ceSNicholas Bellinger 	 * commands for this connection, and prepare the other commands
426353c561dcSBart Van Assche 	 * for reallegiance.
4264e48354ceSNicholas Bellinger 	 *
4265e48354ceSNicholas Bellinger 	 * During normal operation clear the out of order commands (but
4266e48354ceSNicholas Bellinger 	 * do not free the struct iscsi_ooo_cmdsn's) and release all
426766cd9d4eSMax Gurtovoy 	 * struct iscsit_cmds.
4268e48354ceSNicholas Bellinger 	 */
4269e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery)) {
4270e48354ceSNicholas Bellinger 		iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(conn);
427153c561dcSBart Van Assche 		iscsit_prepare_cmds_for_reallegiance(conn);
4272e48354ceSNicholas Bellinger 	} else {
4273e48354ceSNicholas Bellinger 		iscsit_clear_ooo_cmdsns_for_conn(conn);
4274e48354ceSNicholas Bellinger 		iscsit_release_commands_from_conn(conn);
4275e48354ceSNicholas Bellinger 	}
4276bbc05048SNicholas Bellinger 	iscsit_free_queue_reqs_for_conn(conn);
4277e48354ceSNicholas Bellinger 
4278e48354ceSNicholas Bellinger 	/*
4279e48354ceSNicholas Bellinger 	 * Handle decrementing session or connection usage count if
4280e48354ceSNicholas Bellinger 	 * a logout response was not able to be sent because the
4281e48354ceSNicholas Bellinger 	 * connection failed.  Fall back to Session Recovery here.
4282e48354ceSNicholas Bellinger 	 */
4283e48354ceSNicholas Bellinger 	if (atomic_read(&conn->conn_logout_remove)) {
4284e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_SESSION) {
4285e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4286e48354ceSNicholas Bellinger 			iscsit_dec_session_usage_count(sess);
4287e48354ceSNicholas Bellinger 		}
4288e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION)
4289e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4290e48354ceSNicholas Bellinger 
4291e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 0);
4292e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 0);
4293e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4294e48354ceSNicholas Bellinger 	}
4295e48354ceSNicholas Bellinger 
4296e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4297e48354ceSNicholas Bellinger 	list_del(&conn->conn_list);
4298e48354ceSNicholas Bellinger 
4299e48354ceSNicholas Bellinger 	/*
4300e48354ceSNicholas Bellinger 	 * Attempt to let the Initiator know this connection failed by
4301e48354ceSNicholas Bellinger 	 * sending an Connection Dropped Async Message on another
4302e48354ceSNicholas Bellinger 	 * active connection.
4303e48354ceSNicholas Bellinger 	 */
4304e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery))
4305e48354ceSNicholas Bellinger 		iscsit_build_conn_drop_async_message(conn);
4306e48354ceSNicholas Bellinger 
4307e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4308e48354ceSNicholas Bellinger 
4309e48354ceSNicholas Bellinger 	/*
4310e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection,
4311e48354ceSNicholas Bellinger 	 * up the connection reinstatement semaphore that is being blocked on
4312e48354ceSNicholas Bellinger 	 * in iscsit_cause_connection_reinstatement().
4313e48354ceSNicholas Bellinger 	 */
4314e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
4315e48354ceSNicholas Bellinger 	if (atomic_read(&conn->sleep_on_conn_wait_comp)) {
4316e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4317e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_comp);
4318e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4319e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4320e48354ceSNicholas Bellinger 	}
4321e48354ceSNicholas Bellinger 
4322e48354ceSNicholas Bellinger 	/*
4323e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection
4324e48354ceSNicholas Bellinger 	 * by receiving a REMOVECONNFORRECOVERY logout request, up the
4325e48354ceSNicholas Bellinger 	 * connection wait rcfr semaphore that is being blocked on
4326e48354ceSNicholas Bellinger 	 * an iscsit_connection_reinstatement_rcfr().
4327e48354ceSNicholas Bellinger 	 */
4328e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_wait_rcfr)) {
4329e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4330e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_rcfr_comp);
4331e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4332e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4333e48354ceSNicholas Bellinger 	}
4334e48354ceSNicholas Bellinger 	atomic_set(&conn->connection_reinstatement, 1);
4335e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
4336e48354ceSNicholas Bellinger 
4337e48354ceSNicholas Bellinger 	/*
4338e48354ceSNicholas Bellinger 	 * If any other processes are accessing this connection pointer we
4339e48354ceSNicholas Bellinger 	 * must wait until they have completed.
4340e48354ceSNicholas Bellinger 	 */
4341e48354ceSNicholas Bellinger 	iscsit_check_conn_usage_count(conn);
4342e48354ceSNicholas Bellinger 
434369110e3cSHerbert Xu 	ahash_request_free(conn->conn_tx_hash);
434469110e3cSHerbert Xu 	if (conn->conn_rx_hash) {
434569110e3cSHerbert Xu 		struct crypto_ahash *tfm;
434669110e3cSHerbert Xu 
434769110e3cSHerbert Xu 		tfm = crypto_ahash_reqtfm(conn->conn_rx_hash);
434869110e3cSHerbert Xu 		ahash_request_free(conn->conn_rx_hash);
434969110e3cSHerbert Xu 		crypto_free_ahash(tfm);
435069110e3cSHerbert Xu 	}
4351e48354ceSNicholas Bellinger 
4352bf6932f4SAl Viro 	if (conn->sock)
4353e48354ceSNicholas Bellinger 		sock_release(conn->sock);
4354baa4d64bSNicholas Bellinger 
4355baa4d64bSNicholas Bellinger 	if (conn->conn_transport->iscsit_free_conn)
4356baa4d64bSNicholas Bellinger 		conn->conn_transport->iscsit_free_conn(conn);
4357baa4d64bSNicholas Bellinger 
4358e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
4359e48354ceSNicholas Bellinger 	conn->conn_state = TARG_CONN_STATE_FREE;
436005a86e78SMike Christie 	iscsit_free_conn(conn);
4361e48354ceSNicholas Bellinger 
4362e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4363e48354ceSNicholas Bellinger 	atomic_dec(&sess->nconn);
4364*71b25693SJustin Stitt 	pr_debug("Decremented iSCSI connection count to %d from node:"
4365e48354ceSNicholas Bellinger 		" %s\n", atomic_read(&sess->nconn),
4366e48354ceSNicholas Bellinger 		sess->sess_ops->InitiatorName);
4367e48354ceSNicholas Bellinger 	/*
4368e48354ceSNicholas Bellinger 	 * Make sure that if one connection fails in an non ERL=2 iSCSI
4369e48354ceSNicholas Bellinger 	 * Session that they all fail.
4370e48354ceSNicholas Bellinger 	 */
4371e48354ceSNicholas Bellinger 	if ((sess->sess_ops->ErrorRecoveryLevel != 2) && !conn_logout &&
4372e48354ceSNicholas Bellinger 	     !atomic_read(&sess->session_logout))
4373e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4374e48354ceSNicholas Bellinger 
4375e48354ceSNicholas Bellinger 	/*
4376e48354ceSNicholas Bellinger 	 * If this was not the last connection in the session, and we are
4377e48354ceSNicholas Bellinger 	 * performing session reinstatement or falling back to ERL=0, call
4378e48354ceSNicholas Bellinger 	 * iscsit_stop_session() without sleeping to shutdown the other
4379e48354ceSNicholas Bellinger 	 * active connections.
4380e48354ceSNicholas Bellinger 	 */
4381e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4382e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_reinstatement) &&
4383e48354ceSNicholas Bellinger 		    !atomic_read(&sess->session_fall_back_to_erl0)) {
4384e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4385e48354ceSNicholas Bellinger 			return 0;
4386e48354ceSNicholas Bellinger 		}
4387e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_stop_active)) {
4388e48354ceSNicholas Bellinger 			atomic_set(&sess->session_stop_active, 1);
4389e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4390e48354ceSNicholas Bellinger 			iscsit_stop_session(sess, 0, 0);
4391e48354ceSNicholas Bellinger 			return 0;
4392e48354ceSNicholas Bellinger 		}
4393e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4394e48354ceSNicholas Bellinger 		return 0;
4395e48354ceSNicholas Bellinger 	}
4396e48354ceSNicholas Bellinger 
4397e48354ceSNicholas Bellinger 	/*
4398e48354ceSNicholas Bellinger 	 * If this was the last connection in the session and one of the
4399e48354ceSNicholas Bellinger 	 * following is occurring:
4400e48354ceSNicholas Bellinger 	 *
4401e48354ceSNicholas Bellinger 	 * Session Reinstatement is not being performed, and are falling back
4402e48354ceSNicholas Bellinger 	 * to ERL=0 call iscsit_close_session().
4403e48354ceSNicholas Bellinger 	 *
4404e48354ceSNicholas Bellinger 	 * Session Logout was requested.  iscsit_close_session() will be called
4405e48354ceSNicholas Bellinger 	 * elsewhere.
4406e48354ceSNicholas Bellinger 	 *
4407e48354ceSNicholas Bellinger 	 * Session Continuation is not being performed, start the Time2Retain
4408e48354ceSNicholas Bellinger 	 * handler and check if sleep_on_sess_wait_sem is active.
4409e48354ceSNicholas Bellinger 	 */
4410e48354ceSNicholas Bellinger 	if (!atomic_read(&sess->session_reinstatement) &&
4411e48354ceSNicholas Bellinger 	     atomic_read(&sess->session_fall_back_to_erl0)) {
4412e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
441357c46e9fSMaurizio Lombardi 		complete_all(&sess->session_wait_comp);
441443367548SSebastian Andrzej Siewior 		iscsit_close_session(sess, true);
4415e48354ceSNicholas Bellinger 
4416e48354ceSNicholas Bellinger 		return 0;
4417e48354ceSNicholas Bellinger 	} else if (atomic_read(&sess->session_logout)) {
4418e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4419e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FREE;
4420e48354ceSNicholas Bellinger 
442157c46e9fSMaurizio Lombardi 		if (atomic_read(&sess->session_close)) {
442257c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
442357c46e9fSMaurizio Lombardi 			complete_all(&sess->session_wait_comp);
442443367548SSebastian Andrzej Siewior 			iscsit_close_session(sess, true);
442557c46e9fSMaurizio Lombardi 		} else {
442657c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
442757c46e9fSMaurizio Lombardi 		}
4428e48354ceSNicholas Bellinger 
4429e48354ceSNicholas Bellinger 		return 0;
4430e48354ceSNicholas Bellinger 	} else {
4431e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4432e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FAILED;
4433e48354ceSNicholas Bellinger 
443457c46e9fSMaurizio Lombardi 		if (!atomic_read(&sess->session_continuation))
4435e48354ceSNicholas Bellinger 			iscsit_start_time2retain_handler(sess);
4436e48354ceSNicholas Bellinger 
443757c46e9fSMaurizio Lombardi 		if (atomic_read(&sess->session_close)) {
443857c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
443957c46e9fSMaurizio Lombardi 			complete_all(&sess->session_wait_comp);
444043367548SSebastian Andrzej Siewior 			iscsit_close_session(sess, true);
444157c46e9fSMaurizio Lombardi 		} else {
444257c46e9fSMaurizio Lombardi 			spin_unlock_bh(&sess->conn_lock);
444357c46e9fSMaurizio Lombardi 		}
4444e48354ceSNicholas Bellinger 
4445e48354ceSNicholas Bellinger 		return 0;
4446e48354ceSNicholas Bellinger 	}
4447e48354ceSNicholas Bellinger }
4448e48354ceSNicholas Bellinger 
444944f33d0fSChristoph Hellwig /*
445044f33d0fSChristoph Hellwig  * If the iSCSI Session for the iSCSI Initiator Node exists,
445144f33d0fSChristoph Hellwig  * forcefully shutdown the iSCSI NEXUS.
445244f33d0fSChristoph Hellwig  */
44530873fe44SMax Gurtovoy int iscsit_close_session(struct iscsit_session *sess, bool can_sleep)
4454e48354ceSNicholas Bellinger {
445560bfcf8eSAndy Grover 	struct iscsi_portal_group *tpg = sess->tpg;
4456e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4457e48354ceSNicholas Bellinger 
4458e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4459e48354ceSNicholas Bellinger 		pr_err("%d connection(s) still exist for iSCSI session"
4460e48354ceSNicholas Bellinger 			" to %s\n", atomic_read(&sess->nconn),
4461e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4462e48354ceSNicholas Bellinger 		BUG();
4463e48354ceSNicholas Bellinger 	}
4464e48354ceSNicholas Bellinger 
4465e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4466e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
4467e48354ceSNicholas Bellinger 	atomic_set(&sess->session_reinstatement, 1);
4468e48354ceSNicholas Bellinger 	iscsit_stop_time2retain_timer(sess);
4469e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4470e48354ceSNicholas Bellinger 
4471e48354ceSNicholas Bellinger 	/*
4472e48354ceSNicholas Bellinger 	 * transport_deregister_session_configfs() will clear the
4473e48354ceSNicholas Bellinger 	 * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context
4474e48354ceSNicholas Bellinger 	 * can be setting it again with __transport_register_session() in
4475e48354ceSNicholas Bellinger 	 * iscsi_post_login_handler() again after the iscsit_stop_session()
4476e48354ceSNicholas Bellinger 	 * completes in iscsi_np context.
4477e48354ceSNicholas Bellinger 	 */
4478e48354ceSNicholas Bellinger 	transport_deregister_session_configfs(sess->se_sess);
4479e48354ceSNicholas Bellinger 
4480e48354ceSNicholas Bellinger 	/*
4481e48354ceSNicholas Bellinger 	 * If any other processes are accessing this session pointer we must
4482e48354ceSNicholas Bellinger 	 * wait until they have completed.  If we are in an interrupt (the
4483e48354ceSNicholas Bellinger 	 * time2retain handler) and contain and active session usage count we
4484e48354ceSNicholas Bellinger 	 * restart the timer and exit.
4485e48354ceSNicholas Bellinger 	 */
4486f88a10f8SSebastian Andrzej Siewior 	if (iscsit_check_session_usage_count(sess, can_sleep)) {
4487e48354ceSNicholas Bellinger 		atomic_set(&sess->session_logout, 0);
4488e48354ceSNicholas Bellinger 		iscsit_start_time2retain_handler(sess);
4489e48354ceSNicholas Bellinger 		return 0;
4490e48354ceSNicholas Bellinger 	}
4491e48354ceSNicholas Bellinger 
4492e48354ceSNicholas Bellinger 	transport_deregister_session(sess->se_sess);
4493e48354ceSNicholas Bellinger 
4494e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel == 2)
4495902ff860SColin Ian King 		iscsit_free_connection_recovery_entries(sess);
4496e48354ceSNicholas Bellinger 
4497e48354ceSNicholas Bellinger 	iscsit_free_all_ooo_cmdsns(sess);
4498e48354ceSNicholas Bellinger 
4499e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4500e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4501e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FREE;
4502e48354ceSNicholas Bellinger 	pr_debug("Released iSCSI session from node: %s\n",
4503e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4504e48354ceSNicholas Bellinger 	tpg->nsessions--;
4505e48354ceSNicholas Bellinger 	if (tpg->tpg_tiqn)
4506e48354ceSNicholas Bellinger 		tpg->tpg_tiqn->tiqn_nsessions--;
4507e48354ceSNicholas Bellinger 
4508e48354ceSNicholas Bellinger 	pr_debug("Decremented number of active iSCSI Sessions on"
4509e48354ceSNicholas Bellinger 		" iSCSI TPG: %hu to %u\n", tpg->tpgt, tpg->nsessions);
4510e48354ceSNicholas Bellinger 
451131ff0ceeSMatthew Wilcox 	ida_free(&sess_ida, sess->session_index);
4512e48354ceSNicholas Bellinger 	kfree(sess->sess_ops);
4513e48354ceSNicholas Bellinger 	sess->sess_ops = NULL;
4514e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4515e48354ceSNicholas Bellinger 
4516e48354ceSNicholas Bellinger 	kfree(sess);
4517e48354ceSNicholas Bellinger 	return 0;
4518e48354ceSNicholas Bellinger }
4519e48354ceSNicholas Bellinger 
4520e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_closesession(
4521be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
4522e48354ceSNicholas Bellinger {
45230873fe44SMax Gurtovoy 	struct iscsit_session *sess = conn->sess;
4524007d038bSNicholas Bellinger 	int sleep = 1;
4525007d038bSNicholas Bellinger 	/*
4526007d038bSNicholas Bellinger 	 * Traditional iscsi/tcp will invoke this logic from TX thread
4527007d038bSNicholas Bellinger 	 * context during session logout, so clear tx_thread_active and
4528007d038bSNicholas Bellinger 	 * sleep if iscsit_close_connection() has not already occured.
4529007d038bSNicholas Bellinger 	 *
4530007d038bSNicholas Bellinger 	 * Since iser-target invokes this logic from it's own workqueue,
4531007d038bSNicholas Bellinger 	 * always sleep waiting for RX/TX thread shutdown to complete
4532007d038bSNicholas Bellinger 	 * within iscsit_close_connection().
4533007d038bSNicholas Bellinger 	 */
4534105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4535007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4536105fa2f4SNicholas Bellinger 		if (!sleep)
4537105fa2f4SNicholas Bellinger 			return;
4538105fa2f4SNicholas Bellinger 	}
4539e48354ceSNicholas Bellinger 
4540e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4541e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4542e48354ceSNicholas Bellinger 
4543e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
454457c46e9fSMaurizio Lombardi 	atomic_set(&sess->session_close, 1);
454588dcd2daSNicholas Bellinger 	iscsit_stop_session(sess, sleep, sleep);
4546e48354ceSNicholas Bellinger 	iscsit_dec_session_usage_count(sess);
4547e48354ceSNicholas Bellinger }
4548e48354ceSNicholas Bellinger 
4549e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_samecid(
4550be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
4551e48354ceSNicholas Bellinger {
4552007d038bSNicholas Bellinger 	int sleep = 1;
4553007d038bSNicholas Bellinger 
4554105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4555007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4556105fa2f4SNicholas Bellinger 		if (!sleep)
4557105fa2f4SNicholas Bellinger 			return;
4558105fa2f4SNicholas Bellinger 	}
4559e48354ceSNicholas Bellinger 
4560e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4561e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4562e48354ceSNicholas Bellinger 
456388dcd2daSNicholas Bellinger 	iscsit_cause_connection_reinstatement(conn, sleep);
4564e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
4565e48354ceSNicholas Bellinger }
4566e48354ceSNicholas Bellinger 
4567e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_diffcid(
4568be36d683SMax Gurtovoy 	struct iscsit_conn *conn,
4569e48354ceSNicholas Bellinger 	u16 cid)
4570e48354ceSNicholas Bellinger {
4571be36d683SMax Gurtovoy 	struct iscsit_conn *l_conn;
45720873fe44SMax Gurtovoy 	struct iscsit_session *sess = conn->sess;
4573b53b0d99SNicholas Bellinger 	bool conn_found = false;
4574e48354ceSNicholas Bellinger 
4575e48354ceSNicholas Bellinger 	if (!sess)
4576e48354ceSNicholas Bellinger 		return;
4577e48354ceSNicholas Bellinger 
4578e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4579e48354ceSNicholas Bellinger 	list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) {
4580e48354ceSNicholas Bellinger 		if (l_conn->cid == cid) {
4581e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(l_conn);
4582b53b0d99SNicholas Bellinger 			conn_found = true;
4583e48354ceSNicholas Bellinger 			break;
4584e48354ceSNicholas Bellinger 		}
4585e48354ceSNicholas Bellinger 	}
4586e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4587e48354ceSNicholas Bellinger 
4588b53b0d99SNicholas Bellinger 	if (!conn_found)
4589e48354ceSNicholas Bellinger 		return;
4590e48354ceSNicholas Bellinger 
4591e48354ceSNicholas Bellinger 	if (l_conn->sock)
4592e48354ceSNicholas Bellinger 		l_conn->sock->ops->shutdown(l_conn->sock, RCV_SHUTDOWN);
4593e48354ceSNicholas Bellinger 
4594e48354ceSNicholas Bellinger 	spin_lock_bh(&l_conn->state_lock);
4595e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
4596e48354ceSNicholas Bellinger 	l_conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
4597e48354ceSNicholas Bellinger 	spin_unlock_bh(&l_conn->state_lock);
4598e48354ceSNicholas Bellinger 
4599e48354ceSNicholas Bellinger 	iscsit_cause_connection_reinstatement(l_conn, 1);
4600e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(l_conn);
4601e48354ceSNicholas Bellinger }
4602e48354ceSNicholas Bellinger 
4603e48354ceSNicholas Bellinger /*
4604e48354ceSNicholas Bellinger  *	Return of 0 causes the TX thread to restart.
4605e48354ceSNicholas Bellinger  */
46062ec5a8c1SNicholas Bellinger int iscsit_logout_post_handler(
460766cd9d4eSMax Gurtovoy 	struct iscsit_cmd *cmd,
4608be36d683SMax Gurtovoy 	struct iscsit_conn *conn)
4609e48354ceSNicholas Bellinger {
4610e48354ceSNicholas Bellinger 	int ret = 0;
4611e48354ceSNicholas Bellinger 
4612e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
4613e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
4614e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4615e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4616e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4617e48354ceSNicholas Bellinger 		default:
4618e48354ceSNicholas Bellinger 			iscsit_logout_post_handler_closesession(conn);
4619e48354ceSNicholas Bellinger 			break;
4620e48354ceSNicholas Bellinger 		}
4621e48354ceSNicholas Bellinger 		break;
4622e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
4623e48354ceSNicholas Bellinger 		if (conn->cid == cmd->logout_cid) {
4624e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4625e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4626e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4627e48354ceSNicholas Bellinger 			default:
4628e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_samecid(conn);
4629e48354ceSNicholas Bellinger 				break;
4630e48354ceSNicholas Bellinger 			}
4631e48354ceSNicholas Bellinger 		} else {
4632e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4633e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4634e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_diffcid(conn,
4635e48354ceSNicholas Bellinger 					cmd->logout_cid);
4636e48354ceSNicholas Bellinger 				break;
4637e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CID_NOT_FOUND:
4638e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4639e48354ceSNicholas Bellinger 			default:
4640e48354ceSNicholas Bellinger 				break;
4641e48354ceSNicholas Bellinger 			}
4642e48354ceSNicholas Bellinger 			ret = 1;
4643e48354ceSNicholas Bellinger 		}
4644e48354ceSNicholas Bellinger 		break;
4645e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
4646e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4647e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4648e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CID_NOT_FOUND:
4649e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
4650e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4651e48354ceSNicholas Bellinger 		default:
4652e48354ceSNicholas Bellinger 			break;
4653e48354ceSNicholas Bellinger 		}
4654e48354ceSNicholas Bellinger 		ret = 1;
4655e48354ceSNicholas Bellinger 		break;
4656e48354ceSNicholas Bellinger 	default:
4657e48354ceSNicholas Bellinger 		break;
4658e48354ceSNicholas Bellinger 
4659e48354ceSNicholas Bellinger 	}
4660e48354ceSNicholas Bellinger 	return ret;
4661e48354ceSNicholas Bellinger }
46622ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_logout_post_handler);
4663e48354ceSNicholas Bellinger 
46640873fe44SMax Gurtovoy void iscsit_fail_session(struct iscsit_session *sess)
4665e48354ceSNicholas Bellinger {
4666be36d683SMax Gurtovoy 	struct iscsit_conn *conn;
4667e48354ceSNicholas Bellinger 
4668e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4669e48354ceSNicholas Bellinger 	list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
4670e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
4671e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
4672e48354ceSNicholas Bellinger 	}
4673e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4674e48354ceSNicholas Bellinger 
4675e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4676e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FAILED;
4677e48354ceSNicholas Bellinger }
4678e48354ceSNicholas Bellinger 
4679e48354ceSNicholas Bellinger void iscsit_stop_session(
46800873fe44SMax Gurtovoy 	struct iscsit_session *sess,
4681e48354ceSNicholas Bellinger 	int session_sleep,
4682e48354ceSNicholas Bellinger 	int connection_sleep)
4683e48354ceSNicholas Bellinger {
4684e48354ceSNicholas Bellinger 	u16 conn_count = atomic_read(&sess->nconn);
4685be36d683SMax Gurtovoy 	struct iscsit_conn *conn, *conn_tmp = NULL;
4686e48354ceSNicholas Bellinger 	int is_last;
4687e48354ceSNicholas Bellinger 
4688e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4689e48354ceSNicholas Bellinger 
4690e48354ceSNicholas Bellinger 	if (connection_sleep) {
4691e48354ceSNicholas Bellinger 		list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
4692e48354ceSNicholas Bellinger 				conn_list) {
4693e48354ceSNicholas Bellinger 			if (conn_count == 0)
4694e48354ceSNicholas Bellinger 				break;
4695e48354ceSNicholas Bellinger 
4696e48354ceSNicholas Bellinger 			if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
4697e48354ceSNicholas Bellinger 				is_last = 1;
4698e48354ceSNicholas Bellinger 			} else {
4699e48354ceSNicholas Bellinger 				iscsit_inc_conn_usage_count(conn_tmp);
4700e48354ceSNicholas Bellinger 				is_last = 0;
4701e48354ceSNicholas Bellinger 			}
4702e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn);
4703e48354ceSNicholas Bellinger 
4704e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4705e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 1);
4706e48354ceSNicholas Bellinger 			spin_lock_bh(&sess->conn_lock);
4707e48354ceSNicholas Bellinger 
4708e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4709e48354ceSNicholas Bellinger 			if (is_last == 0)
4710e48354ceSNicholas Bellinger 				iscsit_dec_conn_usage_count(conn_tmp);
4711e48354ceSNicholas Bellinger 			conn_count--;
4712e48354ceSNicholas Bellinger 		}
4713e48354ceSNicholas Bellinger 	} else {
4714e48354ceSNicholas Bellinger 		list_for_each_entry(conn, &sess->sess_conn_list, conn_list)
4715e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 0);
4716e48354ceSNicholas Bellinger 	}
4717e48354ceSNicholas Bellinger 
4718e48354ceSNicholas Bellinger 	if (session_sleep && atomic_read(&sess->nconn)) {
4719e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4720e48354ceSNicholas Bellinger 		wait_for_completion(&sess->session_wait_comp);
4721e48354ceSNicholas Bellinger 	} else
4722e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4723e48354ceSNicholas Bellinger }
4724e48354ceSNicholas Bellinger 
4725e48354ceSNicholas Bellinger int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
4726e48354ceSNicholas Bellinger {
47270873fe44SMax Gurtovoy 	struct iscsit_session *sess;
4728e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4729e48354ceSNicholas Bellinger 	struct se_session *se_sess, *se_sess_tmp;
4730417c20a9SNicholas Bellinger 	LIST_HEAD(free_list);
4731e48354ceSNicholas Bellinger 	int session_count = 0;
4732e48354ceSNicholas Bellinger 
4733e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4734e48354ceSNicholas Bellinger 	if (tpg->nsessions && !force) {
4735e48354ceSNicholas Bellinger 		spin_unlock_bh(&se_tpg->session_lock);
4736e48354ceSNicholas Bellinger 		return -1;
4737e48354ceSNicholas Bellinger 	}
4738e48354ceSNicholas Bellinger 
4739e48354ceSNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
4740e48354ceSNicholas Bellinger 			sess_list) {
47410873fe44SMax Gurtovoy 		sess = (struct iscsit_session *)se_sess->fabric_sess_ptr;
4742e48354ceSNicholas Bellinger 
4743e48354ceSNicholas Bellinger 		spin_lock(&sess->conn_lock);
4744e48354ceSNicholas Bellinger 		if (atomic_read(&sess->session_fall_back_to_erl0) ||
4745e48354ceSNicholas Bellinger 		    atomic_read(&sess->session_logout) ||
474657c46e9fSMaurizio Lombardi 		    atomic_read(&sess->session_close) ||
4747e48354ceSNicholas Bellinger 		    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
4748e48354ceSNicholas Bellinger 			spin_unlock(&sess->conn_lock);
4749e48354ceSNicholas Bellinger 			continue;
4750e48354ceSNicholas Bellinger 		}
475157c46e9fSMaurizio Lombardi 		iscsit_inc_session_usage_count(sess);
4752e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 1);
4753197b806aSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
475457c46e9fSMaurizio Lombardi 		atomic_set(&sess->session_close, 1);
4755e48354ceSNicholas Bellinger 		spin_unlock(&sess->conn_lock);
4756e48354ceSNicholas Bellinger 
4757417c20a9SNicholas Bellinger 		list_move_tail(&se_sess->sess_list, &free_list);
4758e48354ceSNicholas Bellinger 	}
4759e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4760e48354ceSNicholas Bellinger 
4761417c20a9SNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) {
47620873fe44SMax Gurtovoy 		sess = (struct iscsit_session *)se_sess->fabric_sess_ptr;
4763417c20a9SNicholas Bellinger 
476457c46e9fSMaurizio Lombardi 		list_del_init(&se_sess->sess_list);
4765e49a7d99SMaurizio Lombardi 		iscsit_stop_session(sess, 1, 1);
476657c46e9fSMaurizio Lombardi 		iscsit_dec_session_usage_count(sess);
4767417c20a9SNicholas Bellinger 		session_count++;
4768417c20a9SNicholas Bellinger 	}
4769417c20a9SNicholas Bellinger 
4770e48354ceSNicholas Bellinger 	pr_debug("Released %d iSCSI Session(s) from Target Portal"
4771e48354ceSNicholas Bellinger 			" Group: %hu\n", session_count, tpg->tpgt);
4772e48354ceSNicholas Bellinger 	return 0;
4773e48354ceSNicholas Bellinger }
4774e48354ceSNicholas Bellinger 
4775e48354ceSNicholas Bellinger MODULE_DESCRIPTION("iSCSI-Target Driver for mainline target infrastructure");
4776e48354ceSNicholas Bellinger MODULE_VERSION("4.1.x");
4777e48354ceSNicholas Bellinger MODULE_AUTHOR("nab@Linux-iSCSI.org");
4778e48354ceSNicholas Bellinger MODULE_LICENSE("GPL");
4779e48354ceSNicholas Bellinger 
4780e48354ceSNicholas Bellinger module_init(iscsi_target_init_module);
4781e48354ceSNicholas Bellinger module_exit(iscsi_target_cleanup_module);
4782