1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e48354ceSNicholas Bellinger /*******************************************************************************
3e48354ceSNicholas Bellinger  * This file contains main functions related to the iSCSI Target Core Driver.
4e48354ceSNicholas Bellinger  *
54c76251eSNicholas Bellinger  * (c) Copyright 2007-2013 Datera, Inc.
6e48354ceSNicholas Bellinger  *
7e48354ceSNicholas Bellinger  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
8e48354ceSNicholas Bellinger  *
9e48354ceSNicholas Bellinger  ******************************************************************************/
10e48354ceSNicholas Bellinger 
1169110e3cSHerbert Xu #include <crypto/hash.h>
12e48354ceSNicholas Bellinger #include <linux/string.h>
13e48354ceSNicholas Bellinger #include <linux/kthread.h>
14e48354ceSNicholas Bellinger #include <linux/completion.h>
15827509e3SPaul Gortmaker #include <linux/module.h>
165538d294SDavid S. Miller #include <linux/vmalloc.h>
1740401530SAl Viro #include <linux/idr.h>
188dcf07beSBart Van Assche #include <linux/delay.h>
193f07c014SIngo Molnar #include <linux/sched/signal.h>
20e48354ceSNicholas Bellinger #include <asm/unaligned.h>
217bfca0cfSSagi Grimberg #include <linux/inet.h>
228dcf07beSBart Van Assche #include <net/ipv6.h>
23ba929992SBart Van Assche #include <scsi/scsi_proto.h>
24e48354ceSNicholas Bellinger #include <scsi/iscsi_proto.h>
25d28b1169SAndy Grover #include <scsi/scsi_tcq.h>
26e48354ceSNicholas Bellinger #include <target/target_core_base.h>
27c4795fb2SChristoph Hellwig #include <target/target_core_fabric.h>
28e48354ceSNicholas Bellinger 
2967f091f2SSagi Grimberg #include <target/iscsi/iscsi_target_core.h>
30e48354ceSNicholas Bellinger #include "iscsi_target_parameters.h"
31e48354ceSNicholas Bellinger #include "iscsi_target_seq_pdu_list.h"
32e48354ceSNicholas Bellinger #include "iscsi_target_datain_values.h"
33e48354ceSNicholas Bellinger #include "iscsi_target_erl0.h"
34e48354ceSNicholas Bellinger #include "iscsi_target_erl1.h"
35e48354ceSNicholas Bellinger #include "iscsi_target_erl2.h"
36e48354ceSNicholas Bellinger #include "iscsi_target_login.h"
37e48354ceSNicholas Bellinger #include "iscsi_target_tmr.h"
38e48354ceSNicholas Bellinger #include "iscsi_target_tpg.h"
39e48354ceSNicholas Bellinger #include "iscsi_target_util.h"
40e48354ceSNicholas Bellinger #include "iscsi_target.h"
41e48354ceSNicholas Bellinger #include "iscsi_target_device.h"
4267f091f2SSagi Grimberg #include <target/iscsi/iscsi_target_stat.h>
43e48354ceSNicholas Bellinger 
44baa4d64bSNicholas Bellinger #include <target/iscsi/iscsi_transport.h>
45baa4d64bSNicholas Bellinger 
46e48354ceSNicholas Bellinger static LIST_HEAD(g_tiqn_list);
47e48354ceSNicholas Bellinger static LIST_HEAD(g_np_list);
48e48354ceSNicholas Bellinger static DEFINE_SPINLOCK(tiqn_lock);
49ee291e63SAndy Grover static DEFINE_MUTEX(np_lock);
50e48354ceSNicholas Bellinger 
51e48354ceSNicholas Bellinger static struct idr tiqn_idr;
5231ff0ceeSMatthew Wilcox DEFINE_IDA(sess_ida);
53e48354ceSNicholas Bellinger struct mutex auth_id_lock;
54e48354ceSNicholas Bellinger 
55e48354ceSNicholas Bellinger struct iscsit_global *iscsit_global;
56e48354ceSNicholas Bellinger 
57e48354ceSNicholas Bellinger struct kmem_cache *lio_qr_cache;
58e48354ceSNicholas Bellinger struct kmem_cache *lio_dr_cache;
59e48354ceSNicholas Bellinger struct kmem_cache *lio_ooo_cache;
60e48354ceSNicholas Bellinger struct kmem_cache *lio_r2t_cache;
61e48354ceSNicholas Bellinger 
62e48354ceSNicholas Bellinger static int iscsit_handle_immediate_data(struct iscsi_cmd *,
632ec5a8c1SNicholas Bellinger 			struct iscsi_scsi_req *, u32);
64e48354ceSNicholas Bellinger 
65e48354ceSNicholas Bellinger struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf)
66e48354ceSNicholas Bellinger {
67e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = NULL;
68e48354ceSNicholas Bellinger 
69e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
70e48354ceSNicholas Bellinger 	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
71e48354ceSNicholas Bellinger 		if (!strcmp(tiqn->tiqn, buf)) {
72e48354ceSNicholas Bellinger 
73e48354ceSNicholas Bellinger 			spin_lock(&tiqn->tiqn_state_lock);
74e48354ceSNicholas Bellinger 			if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
75e48354ceSNicholas Bellinger 				tiqn->tiqn_access_count++;
76e48354ceSNicholas Bellinger 				spin_unlock(&tiqn->tiqn_state_lock);
77e48354ceSNicholas Bellinger 				spin_unlock(&tiqn_lock);
78e48354ceSNicholas Bellinger 				return tiqn;
79e48354ceSNicholas Bellinger 			}
80e48354ceSNicholas Bellinger 			spin_unlock(&tiqn->tiqn_state_lock);
81e48354ceSNicholas Bellinger 		}
82e48354ceSNicholas Bellinger 	}
83e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
84e48354ceSNicholas Bellinger 
85e48354ceSNicholas Bellinger 	return NULL;
86e48354ceSNicholas Bellinger }
87e48354ceSNicholas Bellinger 
88e48354ceSNicholas Bellinger static int iscsit_set_tiqn_shutdown(struct iscsi_tiqn *tiqn)
89e48354ceSNicholas Bellinger {
90e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
91e48354ceSNicholas Bellinger 	if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
92e48354ceSNicholas Bellinger 		tiqn->tiqn_state = TIQN_STATE_SHUTDOWN;
93e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_state_lock);
94e48354ceSNicholas Bellinger 		return 0;
95e48354ceSNicholas Bellinger 	}
96e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
97e48354ceSNicholas Bellinger 
98e48354ceSNicholas Bellinger 	return -1;
99e48354ceSNicholas Bellinger }
100e48354ceSNicholas Bellinger 
101e48354ceSNicholas Bellinger void iscsit_put_tiqn_for_login(struct iscsi_tiqn *tiqn)
102e48354ceSNicholas Bellinger {
103e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
104e48354ceSNicholas Bellinger 	tiqn->tiqn_access_count--;
105e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
106e48354ceSNicholas Bellinger }
107e48354ceSNicholas Bellinger 
108e48354ceSNicholas Bellinger /*
109e48354ceSNicholas Bellinger  * Note that IQN formatting is expected to be done in userspace, and
110e48354ceSNicholas Bellinger  * no explict IQN format checks are done here.
111e48354ceSNicholas Bellinger  */
112e48354ceSNicholas Bellinger struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf)
113e48354ceSNicholas Bellinger {
114e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = NULL;
115e48354ceSNicholas Bellinger 	int ret;
116e48354ceSNicholas Bellinger 
1178f50c7f5SDan Carpenter 	if (strlen(buf) >= ISCSI_IQN_LEN) {
118e48354ceSNicholas Bellinger 		pr_err("Target IQN exceeds %d bytes\n",
119e48354ceSNicholas Bellinger 				ISCSI_IQN_LEN);
120e48354ceSNicholas Bellinger 		return ERR_PTR(-EINVAL);
121e48354ceSNicholas Bellinger 	}
122e48354ceSNicholas Bellinger 
1233829f381SMarkus Elfring 	tiqn = kzalloc(sizeof(*tiqn), GFP_KERNEL);
124c46e22f1SMarkus Elfring 	if (!tiqn)
125e48354ceSNicholas Bellinger 		return ERR_PTR(-ENOMEM);
126e48354ceSNicholas Bellinger 
127e48354ceSNicholas Bellinger 	sprintf(tiqn->tiqn, "%s", buf);
128e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&tiqn->tiqn_list);
129e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&tiqn->tiqn_tpg_list);
130e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->tiqn_state_lock);
131e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->tiqn_tpg_lock);
132e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->sess_err_stats.lock);
133e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->login_stats.lock);
134e48354ceSNicholas Bellinger 	spin_lock_init(&tiqn->logout_stats.lock);
135e48354ceSNicholas Bellinger 
136e48354ceSNicholas Bellinger 	tiqn->tiqn_state = TIQN_STATE_ACTIVE;
137e48354ceSNicholas Bellinger 
138c9365bd0STejun Heo 	idr_preload(GFP_KERNEL);
139e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
140c9365bd0STejun Heo 
141c9365bd0STejun Heo 	ret = idr_alloc(&tiqn_idr, NULL, 0, 0, GFP_NOWAIT);
142e48354ceSNicholas Bellinger 	if (ret < 0) {
143c9365bd0STejun Heo 		pr_err("idr_alloc() failed for tiqn->tiqn_index\n");
144e48354ceSNicholas Bellinger 		spin_unlock(&tiqn_lock);
145c9365bd0STejun Heo 		idr_preload_end();
146e48354ceSNicholas Bellinger 		kfree(tiqn);
147e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
148e48354ceSNicholas Bellinger 	}
149c9365bd0STejun Heo 	tiqn->tiqn_index = ret;
150e48354ceSNicholas Bellinger 	list_add_tail(&tiqn->tiqn_list, &g_tiqn_list);
151c9365bd0STejun Heo 
152e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
153c9365bd0STejun Heo 	idr_preload_end();
154e48354ceSNicholas Bellinger 
155e48354ceSNicholas Bellinger 	pr_debug("CORE[0] - Added iSCSI Target IQN: %s\n", tiqn->tiqn);
156e48354ceSNicholas Bellinger 
157e48354ceSNicholas Bellinger 	return tiqn;
158e48354ceSNicholas Bellinger 
159e48354ceSNicholas Bellinger }
160e48354ceSNicholas Bellinger 
161e48354ceSNicholas Bellinger static void iscsit_wait_for_tiqn(struct iscsi_tiqn *tiqn)
162e48354ceSNicholas Bellinger {
163e48354ceSNicholas Bellinger 	/*
164e48354ceSNicholas Bellinger 	 * Wait for accesses to said struct iscsi_tiqn to end.
165e48354ceSNicholas Bellinger 	 */
166e48354ceSNicholas Bellinger 	spin_lock(&tiqn->tiqn_state_lock);
167e48354ceSNicholas Bellinger 	while (tiqn->tiqn_access_count != 0) {
168e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_state_lock);
169e48354ceSNicholas Bellinger 		msleep(10);
170e48354ceSNicholas Bellinger 		spin_lock(&tiqn->tiqn_state_lock);
171e48354ceSNicholas Bellinger 	}
172e48354ceSNicholas Bellinger 	spin_unlock(&tiqn->tiqn_state_lock);
173e48354ceSNicholas Bellinger }
174e48354ceSNicholas Bellinger 
175e48354ceSNicholas Bellinger void iscsit_del_tiqn(struct iscsi_tiqn *tiqn)
176e48354ceSNicholas Bellinger {
177e48354ceSNicholas Bellinger 	/*
178e48354ceSNicholas Bellinger 	 * iscsit_set_tiqn_shutdown sets tiqn->tiqn_state = TIQN_STATE_SHUTDOWN
179e48354ceSNicholas Bellinger 	 * while holding tiqn->tiqn_state_lock.  This means that all subsequent
180e48354ceSNicholas Bellinger 	 * attempts to access this struct iscsi_tiqn will fail from both transport
181e48354ceSNicholas Bellinger 	 * fabric and control code paths.
182e48354ceSNicholas Bellinger 	 */
183e48354ceSNicholas Bellinger 	if (iscsit_set_tiqn_shutdown(tiqn) < 0) {
184e48354ceSNicholas Bellinger 		pr_err("iscsit_set_tiqn_shutdown() failed\n");
185e48354ceSNicholas Bellinger 		return;
186e48354ceSNicholas Bellinger 	}
187e48354ceSNicholas Bellinger 
188e48354ceSNicholas Bellinger 	iscsit_wait_for_tiqn(tiqn);
189e48354ceSNicholas Bellinger 
190e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
191e48354ceSNicholas Bellinger 	list_del(&tiqn->tiqn_list);
192e48354ceSNicholas Bellinger 	idr_remove(&tiqn_idr, tiqn->tiqn_index);
193e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
194e48354ceSNicholas Bellinger 
195e48354ceSNicholas Bellinger 	pr_debug("CORE[0] - Deleted iSCSI Target IQN: %s\n",
196e48354ceSNicholas Bellinger 			tiqn->tiqn);
197e48354ceSNicholas Bellinger 	kfree(tiqn);
198e48354ceSNicholas Bellinger }
199e48354ceSNicholas Bellinger 
200e48354ceSNicholas Bellinger int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
201e48354ceSNicholas Bellinger {
202e48354ceSNicholas Bellinger 	int ret;
203e48354ceSNicholas Bellinger 	/*
204e48354ceSNicholas Bellinger 	 * Determine if the network portal is accepting storage traffic.
205e48354ceSNicholas Bellinger 	 */
206e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
207e48354ceSNicholas Bellinger 	if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
208e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
209e48354ceSNicholas Bellinger 		return -1;
210e48354ceSNicholas Bellinger 	}
211e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
212e48354ceSNicholas Bellinger 	/*
213e48354ceSNicholas Bellinger 	 * Determine if the portal group is accepting storage traffic.
214e48354ceSNicholas Bellinger 	 */
215e48354ceSNicholas Bellinger 	spin_lock_bh(&tpg->tpg_state_lock);
216e48354ceSNicholas Bellinger 	if (tpg->tpg_state != TPG_STATE_ACTIVE) {
217e48354ceSNicholas Bellinger 		spin_unlock_bh(&tpg->tpg_state_lock);
218e48354ceSNicholas Bellinger 		return -1;
219e48354ceSNicholas Bellinger 	}
220e48354ceSNicholas Bellinger 	spin_unlock_bh(&tpg->tpg_state_lock);
221e48354ceSNicholas Bellinger 
222e48354ceSNicholas Bellinger 	/*
223e48354ceSNicholas Bellinger 	 * Here we serialize access across the TIQN+TPG Tuple.
224e48354ceSNicholas Bellinger 	 */
225a91eb7d9SNicholas Bellinger 	ret = down_interruptible(&tpg->np_login_sem);
226ee7619f2SNicholas Bellinger 	if (ret != 0)
227e48354ceSNicholas Bellinger 		return -1;
228e48354ceSNicholas Bellinger 
229a91eb7d9SNicholas Bellinger 	spin_lock_bh(&tpg->tpg_state_lock);
230a91eb7d9SNicholas Bellinger 	if (tpg->tpg_state != TPG_STATE_ACTIVE) {
231a91eb7d9SNicholas Bellinger 		spin_unlock_bh(&tpg->tpg_state_lock);
232a91eb7d9SNicholas Bellinger 		up(&tpg->np_login_sem);
233a91eb7d9SNicholas Bellinger 		return -1;
234a91eb7d9SNicholas Bellinger 	}
235a91eb7d9SNicholas Bellinger 	spin_unlock_bh(&tpg->tpg_state_lock);
236e48354ceSNicholas Bellinger 
237e48354ceSNicholas Bellinger 	return 0;
238e48354ceSNicholas Bellinger }
239e48354ceSNicholas Bellinger 
240a91eb7d9SNicholas Bellinger void iscsit_login_kref_put(struct kref *kref)
241a91eb7d9SNicholas Bellinger {
242a91eb7d9SNicholas Bellinger 	struct iscsi_tpg_np *tpg_np = container_of(kref,
243a91eb7d9SNicholas Bellinger 				struct iscsi_tpg_np, tpg_np_kref);
244a91eb7d9SNicholas Bellinger 
245a91eb7d9SNicholas Bellinger 	complete(&tpg_np->tpg_np_comp);
246a91eb7d9SNicholas Bellinger }
247a91eb7d9SNicholas Bellinger 
248a91eb7d9SNicholas Bellinger int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg,
249a91eb7d9SNicholas Bellinger 		       struct iscsi_tpg_np *tpg_np)
250e48354ceSNicholas Bellinger {
251e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
252e48354ceSNicholas Bellinger 
253a91eb7d9SNicholas Bellinger 	up(&tpg->np_login_sem);
254e48354ceSNicholas Bellinger 
255a91eb7d9SNicholas Bellinger 	if (tpg_np)
256a91eb7d9SNicholas Bellinger 		kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
257e48354ceSNicholas Bellinger 
258e48354ceSNicholas Bellinger 	if (tiqn)
259e48354ceSNicholas Bellinger 		iscsit_put_tiqn_for_login(tiqn);
260e48354ceSNicholas Bellinger 
261e48354ceSNicholas Bellinger 	return 0;
262e48354ceSNicholas Bellinger }
263e48354ceSNicholas Bellinger 
26405b96892SNicholas Bellinger bool iscsit_check_np_match(
26513a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
26605b96892SNicholas Bellinger 	struct iscsi_np *np,
267e48354ceSNicholas Bellinger 	int network_transport)
268e48354ceSNicholas Bellinger {
269e48354ceSNicholas Bellinger 	struct sockaddr_in *sock_in, *sock_in_e;
270e48354ceSNicholas Bellinger 	struct sockaddr_in6 *sock_in6, *sock_in6_e;
27105b96892SNicholas Bellinger 	bool ip_match = false;
27269d75574SAndy Grover 	u16 port, port_e;
273e48354ceSNicholas Bellinger 
27405b96892SNicholas Bellinger 	if (sockaddr->ss_family == AF_INET6) {
27505b96892SNicholas Bellinger 		sock_in6 = (struct sockaddr_in6 *)sockaddr;
27605b96892SNicholas Bellinger 		sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;
27705b96892SNicholas Bellinger 
27805b96892SNicholas Bellinger 		if (!memcmp(&sock_in6->sin6_addr.in6_u,
27905b96892SNicholas Bellinger 			    &sock_in6_e->sin6_addr.in6_u,
28005b96892SNicholas Bellinger 			    sizeof(struct in6_addr)))
28105b96892SNicholas Bellinger 			ip_match = true;
28205b96892SNicholas Bellinger 
28305b96892SNicholas Bellinger 		port = ntohs(sock_in6->sin6_port);
28469d75574SAndy Grover 		port_e = ntohs(sock_in6_e->sin6_port);
28505b96892SNicholas Bellinger 	} else {
28605b96892SNicholas Bellinger 		sock_in = (struct sockaddr_in *)sockaddr;
28705b96892SNicholas Bellinger 		sock_in_e = (struct sockaddr_in *)&np->np_sockaddr;
28805b96892SNicholas Bellinger 
28905b96892SNicholas Bellinger 		if (sock_in->sin_addr.s_addr == sock_in_e->sin_addr.s_addr)
29005b96892SNicholas Bellinger 			ip_match = true;
29105b96892SNicholas Bellinger 
29205b96892SNicholas Bellinger 		port = ntohs(sock_in->sin_port);
29369d75574SAndy Grover 		port_e = ntohs(sock_in_e->sin_port);
29405b96892SNicholas Bellinger 	}
29505b96892SNicholas Bellinger 
29669d75574SAndy Grover 	if (ip_match && (port_e == port) &&
29705b96892SNicholas Bellinger 	    (np->np_network_transport == network_transport))
29805b96892SNicholas Bellinger 		return true;
29905b96892SNicholas Bellinger 
30005b96892SNicholas Bellinger 	return false;
30105b96892SNicholas Bellinger }
30205b96892SNicholas Bellinger 
30305b96892SNicholas Bellinger static struct iscsi_np *iscsit_get_np(
30413a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
30505b96892SNicholas Bellinger 	int network_transport)
30605b96892SNicholas Bellinger {
30705b96892SNicholas Bellinger 	struct iscsi_np *np;
30805b96892SNicholas Bellinger 	bool match;
30905b96892SNicholas Bellinger 
310618baaf7SBart Van Assche 	lockdep_assert_held(&np_lock);
311618baaf7SBart Van Assche 
312e48354ceSNicholas Bellinger 	list_for_each_entry(np, &g_np_list, np_list) {
313ee291e63SAndy Grover 		spin_lock_bh(&np->np_thread_lock);
314e48354ceSNicholas Bellinger 		if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
315ee291e63SAndy Grover 			spin_unlock_bh(&np->np_thread_lock);
316e48354ceSNicholas Bellinger 			continue;
317e48354ceSNicholas Bellinger 		}
318e48354ceSNicholas Bellinger 
31905b96892SNicholas Bellinger 		match = iscsit_check_np_match(sockaddr, np, network_transport);
3200bcc297eSChristophe Vu-Brugier 		if (match) {
321e48354ceSNicholas Bellinger 			/*
322e48354ceSNicholas Bellinger 			 * Increment the np_exports reference count now to
323e48354ceSNicholas Bellinger 			 * prevent iscsit_del_np() below from being called
324e48354ceSNicholas Bellinger 			 * while iscsi_tpg_add_network_portal() is called.
325e48354ceSNicholas Bellinger 			 */
326e48354ceSNicholas Bellinger 			np->np_exports++;
327ee291e63SAndy Grover 			spin_unlock_bh(&np->np_thread_lock);
328e48354ceSNicholas Bellinger 			return np;
329e48354ceSNicholas Bellinger 		}
330ee291e63SAndy Grover 		spin_unlock_bh(&np->np_thread_lock);
331e48354ceSNicholas Bellinger 	}
332e48354ceSNicholas Bellinger 
333e48354ceSNicholas Bellinger 	return NULL;
334e48354ceSNicholas Bellinger }
335e48354ceSNicholas Bellinger 
336e48354ceSNicholas Bellinger struct iscsi_np *iscsit_add_np(
33713a3cf08SAndy Grover 	struct sockaddr_storage *sockaddr,
338e48354ceSNicholas Bellinger 	int network_transport)
339e48354ceSNicholas Bellinger {
340e48354ceSNicholas Bellinger 	struct iscsi_np *np;
341e48354ceSNicholas Bellinger 	int ret;
342ee291e63SAndy Grover 
343ee291e63SAndy Grover 	mutex_lock(&np_lock);
344ee291e63SAndy Grover 
345e48354ceSNicholas Bellinger 	/*
346e48354ceSNicholas Bellinger 	 * Locate the existing struct iscsi_np if already active..
347e48354ceSNicholas Bellinger 	 */
348e48354ceSNicholas Bellinger 	np = iscsit_get_np(sockaddr, network_transport);
349ee291e63SAndy Grover 	if (np) {
350ee291e63SAndy Grover 		mutex_unlock(&np_lock);
351e48354ceSNicholas Bellinger 		return np;
352ee291e63SAndy Grover 	}
353e48354ceSNicholas Bellinger 
3543829f381SMarkus Elfring 	np = kzalloc(sizeof(*np), GFP_KERNEL);
355e48354ceSNicholas Bellinger 	if (!np) {
356ee291e63SAndy Grover 		mutex_unlock(&np_lock);
357e48354ceSNicholas Bellinger 		return ERR_PTR(-ENOMEM);
358e48354ceSNicholas Bellinger 	}
359e48354ceSNicholas Bellinger 
360e48354ceSNicholas Bellinger 	np->np_flags |= NPF_IP_NETWORK;
361e48354ceSNicholas Bellinger 	np->np_network_transport = network_transport;
362e48354ceSNicholas Bellinger 	spin_lock_init(&np->np_thread_lock);
363e48354ceSNicholas Bellinger 	init_completion(&np->np_restart_comp);
364e48354ceSNicholas Bellinger 	INIT_LIST_HEAD(&np->np_list);
365e48354ceSNicholas Bellinger 
366f7c9564aSKees Cook 	timer_setup(&np->np_login_timer, iscsi_handle_login_thread_timeout, 0);
3678a47aa9dSBart Van Assche 
368e48354ceSNicholas Bellinger 	ret = iscsi_target_setup_login_socket(np, sockaddr);
369e48354ceSNicholas Bellinger 	if (ret != 0) {
370e48354ceSNicholas Bellinger 		kfree(np);
371ee291e63SAndy Grover 		mutex_unlock(&np_lock);
372e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
373e48354ceSNicholas Bellinger 	}
374e48354ceSNicholas Bellinger 
375e48354ceSNicholas Bellinger 	np->np_thread = kthread_run(iscsi_target_login_thread, np, "iscsi_np");
376e48354ceSNicholas Bellinger 	if (IS_ERR(np->np_thread)) {
377e48354ceSNicholas Bellinger 		pr_err("Unable to create kthread: iscsi_np\n");
378e48354ceSNicholas Bellinger 		ret = PTR_ERR(np->np_thread);
379e48354ceSNicholas Bellinger 		kfree(np);
380ee291e63SAndy Grover 		mutex_unlock(&np_lock);
381e48354ceSNicholas Bellinger 		return ERR_PTR(ret);
382e48354ceSNicholas Bellinger 	}
383e48354ceSNicholas Bellinger 	/*
384e48354ceSNicholas Bellinger 	 * Increment the np_exports reference count now to prevent
385e48354ceSNicholas Bellinger 	 * iscsit_del_np() below from being run while a new call to
386e48354ceSNicholas Bellinger 	 * iscsi_tpg_add_network_portal() for a matching iscsi_np is
387e48354ceSNicholas Bellinger 	 * active.  We don't need to hold np->np_thread_lock at this
388e48354ceSNicholas Bellinger 	 * point because iscsi_np has not been added to g_np_list yet.
389e48354ceSNicholas Bellinger 	 */
390e48354ceSNicholas Bellinger 	np->np_exports = 1;
391ee291e63SAndy Grover 	np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
392e48354ceSNicholas Bellinger 
393e48354ceSNicholas Bellinger 	list_add_tail(&np->np_list, &g_np_list);
394ee291e63SAndy Grover 	mutex_unlock(&np_lock);
395e48354ceSNicholas Bellinger 
39669d75574SAndy Grover 	pr_debug("CORE[0] - Added Network Portal: %pISpc on %s\n",
39769d75574SAndy Grover 		&np->np_sockaddr, np->np_transport->name);
398e48354ceSNicholas Bellinger 
399e48354ceSNicholas Bellinger 	return np;
400e48354ceSNicholas Bellinger }
401e48354ceSNicholas Bellinger 
402e48354ceSNicholas Bellinger int iscsit_reset_np_thread(
403e48354ceSNicholas Bellinger 	struct iscsi_np *np,
404e48354ceSNicholas Bellinger 	struct iscsi_tpg_np *tpg_np,
405a91eb7d9SNicholas Bellinger 	struct iscsi_portal_group *tpg,
406a91eb7d9SNicholas Bellinger 	bool shutdown)
407e48354ceSNicholas Bellinger {
408e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
409e48354ceSNicholas Bellinger 	if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) {
410e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
411e48354ceSNicholas Bellinger 		return 0;
412e48354ceSNicholas Bellinger 	}
413e48354ceSNicholas Bellinger 	np->np_thread_state = ISCSI_NP_THREAD_RESET;
414978d13d6SNicholas Bellinger 	atomic_inc(&np->np_reset_count);
415e48354ceSNicholas Bellinger 
416e48354ceSNicholas Bellinger 	if (np->np_thread) {
417e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
418e48354ceSNicholas Bellinger 		send_sig(SIGINT, np->np_thread, 1);
419e48354ceSNicholas Bellinger 		wait_for_completion(&np->np_restart_comp);
420e48354ceSNicholas Bellinger 		spin_lock_bh(&np->np_thread_lock);
421e48354ceSNicholas Bellinger 	}
422e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
423e48354ceSNicholas Bellinger 
424a91eb7d9SNicholas Bellinger 	if (tpg_np && shutdown) {
425a91eb7d9SNicholas Bellinger 		kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
426a91eb7d9SNicholas Bellinger 
427a91eb7d9SNicholas Bellinger 		wait_for_completion(&tpg_np->tpg_np_comp);
428a91eb7d9SNicholas Bellinger 	}
429a91eb7d9SNicholas Bellinger 
430e48354ceSNicholas Bellinger 	return 0;
431e48354ceSNicholas Bellinger }
432e48354ceSNicholas Bellinger 
433baa4d64bSNicholas Bellinger static void iscsit_free_np(struct iscsi_np *np)
434e48354ceSNicholas Bellinger {
435bf6932f4SAl Viro 	if (np->np_socket)
436e48354ceSNicholas Bellinger 		sock_release(np->np_socket);
437e48354ceSNicholas Bellinger }
438e48354ceSNicholas Bellinger 
439e48354ceSNicholas Bellinger int iscsit_del_np(struct iscsi_np *np)
440e48354ceSNicholas Bellinger {
441e48354ceSNicholas Bellinger 	spin_lock_bh(&np->np_thread_lock);
442e48354ceSNicholas Bellinger 	np->np_exports--;
443e48354ceSNicholas Bellinger 	if (np->np_exports) {
4442363d196SNicholas Bellinger 		np->enabled = true;
445e48354ceSNicholas Bellinger 		spin_unlock_bh(&np->np_thread_lock);
446e48354ceSNicholas Bellinger 		return 0;
447e48354ceSNicholas Bellinger 	}
448e48354ceSNicholas Bellinger 	np->np_thread_state = ISCSI_NP_THREAD_SHUTDOWN;
449e48354ceSNicholas Bellinger 	spin_unlock_bh(&np->np_thread_lock);
450e48354ceSNicholas Bellinger 
451e48354ceSNicholas Bellinger 	if (np->np_thread) {
452e48354ceSNicholas Bellinger 		/*
453e48354ceSNicholas Bellinger 		 * We need to send the signal to wakeup Linux/Net
454e48354ceSNicholas Bellinger 		 * which may be sleeping in sock_accept()..
455e48354ceSNicholas Bellinger 		 */
456e48354ceSNicholas Bellinger 		send_sig(SIGINT, np->np_thread, 1);
457e48354ceSNicholas Bellinger 		kthread_stop(np->np_thread);
458db6077fdSNicholas Bellinger 		np->np_thread = NULL;
459e48354ceSNicholas Bellinger 	}
460baa4d64bSNicholas Bellinger 
461baa4d64bSNicholas Bellinger 	np->np_transport->iscsit_free_np(np);
462e48354ceSNicholas Bellinger 
463ee291e63SAndy Grover 	mutex_lock(&np_lock);
464e48354ceSNicholas Bellinger 	list_del(&np->np_list);
465ee291e63SAndy Grover 	mutex_unlock(&np_lock);
466e48354ceSNicholas Bellinger 
46769d75574SAndy Grover 	pr_debug("CORE[0] - Removed Network Portal: %pISpc on %s\n",
46869d75574SAndy Grover 		&np->np_sockaddr, np->np_transport->name);
469e48354ceSNicholas Bellinger 
470baa4d64bSNicholas Bellinger 	iscsit_put_transport(np->np_transport);
471e48354ceSNicholas Bellinger 	kfree(np);
472e48354ceSNicholas Bellinger 	return 0;
473e48354ceSNicholas Bellinger }
474e48354ceSNicholas Bellinger 
475e8205ccaSVarun Prakash static void iscsit_get_rx_pdu(struct iscsi_conn *);
4762ec5a8c1SNicholas Bellinger 
477d2faaefbSVarun Prakash int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
4782ec5a8c1SNicholas Bellinger {
479a4467018SNicholas Bellinger 	return iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
4802ec5a8c1SNicholas Bellinger }
481d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_queue_rsp);
4822ec5a8c1SNicholas Bellinger 
483d2faaefbSVarun Prakash void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
484131e6abcSNicholas Bellinger {
485131e6abcSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
486064cdd2dSNicholas Bellinger 	if (!list_empty(&cmd->i_conn_node) &&
487064cdd2dSNicholas Bellinger 	    !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
488131e6abcSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
489131e6abcSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
490131e6abcSNicholas Bellinger 
4914412a671SBart Van Assche 	__iscsit_free_cmd(cmd, true);
492131e6abcSNicholas Bellinger }
493d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_aborted_task);
494131e6abcSNicholas Bellinger 
4952854bb23SVarun Prakash static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *,
496e1dfb21fSBart Van Assche 				      u32, u32, const void *, void *);
4972854bb23SVarun Prakash static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *);
4982854bb23SVarun Prakash 
4992854bb23SVarun Prakash static int
5002854bb23SVarun Prakash iscsit_xmit_nondatain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
5012854bb23SVarun Prakash 			  const void *data_buf, u32 data_buf_len)
5022854bb23SVarun Prakash {
5032854bb23SVarun Prakash 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)cmd->pdu;
5042854bb23SVarun Prakash 	struct kvec *iov;
5052854bb23SVarun Prakash 	u32 niov = 0, tx_size = ISCSI_HDR_LEN;
5062854bb23SVarun Prakash 	int ret;
5072854bb23SVarun Prakash 
5082854bb23SVarun Prakash 	iov = &cmd->iov_misc[0];
5092854bb23SVarun Prakash 	iov[niov].iov_base	= cmd->pdu;
5102854bb23SVarun Prakash 	iov[niov++].iov_len	= ISCSI_HDR_LEN;
5112854bb23SVarun Prakash 
5122854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5132854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5142854bb23SVarun Prakash 
5152854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr,
5162854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
517e1dfb21fSBart Van Assche 					  header_digest);
5182854bb23SVarun Prakash 
5192854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
5202854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
5212854bb23SVarun Prakash 		pr_debug("Attaching CRC32C HeaderDigest"
5222854bb23SVarun Prakash 			 " to opcode 0x%x 0x%08x\n",
5232854bb23SVarun Prakash 			 hdr->opcode, *header_digest);
5242854bb23SVarun Prakash 	}
5252854bb23SVarun Prakash 
5262854bb23SVarun Prakash 	if (data_buf_len) {
5272854bb23SVarun Prakash 		u32 padding = ((-data_buf_len) & 3);
5282854bb23SVarun Prakash 
5292854bb23SVarun Prakash 		iov[niov].iov_base	= (void *)data_buf;
5302854bb23SVarun Prakash 		iov[niov++].iov_len	= data_buf_len;
5312854bb23SVarun Prakash 		tx_size += data_buf_len;
5322854bb23SVarun Prakash 
5332854bb23SVarun Prakash 		if (padding != 0) {
5342854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->pad_bytes;
5352854bb23SVarun Prakash 			iov[niov++].iov_len = padding;
5362854bb23SVarun Prakash 			tx_size += padding;
5372854bb23SVarun Prakash 			pr_debug("Attaching %u additional"
5382854bb23SVarun Prakash 				 " padding bytes.\n", padding);
5392854bb23SVarun Prakash 		}
5402854bb23SVarun Prakash 
5412854bb23SVarun Prakash 		if (conn->conn_ops->DataDigest) {
5422854bb23SVarun Prakash 			iscsit_do_crypto_hash_buf(conn->conn_tx_hash,
5432854bb23SVarun Prakash 						  data_buf, data_buf_len,
544e1dfb21fSBart Van Assche 						  padding, &cmd->pad_bytes,
545e1dfb21fSBart Van Assche 						  &cmd->data_crc);
5462854bb23SVarun Prakash 
5472854bb23SVarun Prakash 			iov[niov].iov_base = &cmd->data_crc;
5482854bb23SVarun Prakash 			iov[niov++].iov_len = ISCSI_CRC_LEN;
5492854bb23SVarun Prakash 			tx_size += ISCSI_CRC_LEN;
5502854bb23SVarun Prakash 			pr_debug("Attached DataDigest for %u"
5512854bb23SVarun Prakash 				 " bytes opcode 0x%x, CRC 0x%08x\n",
5522854bb23SVarun Prakash 				 data_buf_len, hdr->opcode, cmd->data_crc);
5532854bb23SVarun Prakash 		}
5542854bb23SVarun Prakash 	}
5552854bb23SVarun Prakash 
5562854bb23SVarun Prakash 	cmd->iov_misc_count = niov;
5572854bb23SVarun Prakash 	cmd->tx_size = tx_size;
5582854bb23SVarun Prakash 
5592854bb23SVarun Prakash 	ret = iscsit_send_tx_data(cmd, conn, 1);
5602854bb23SVarun Prakash 	if (ret < 0) {
5612854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
5622854bb23SVarun Prakash 		return ret;
5632854bb23SVarun Prakash 	}
5642854bb23SVarun Prakash 
5652854bb23SVarun Prakash 	return 0;
5662854bb23SVarun Prakash }
5672854bb23SVarun Prakash 
5682e39f1c9SBart Van Assche static int iscsit_map_iovec(struct iscsi_cmd *cmd, struct kvec *iov, int nvec,
5692e39f1c9SBart Van Assche 			    u32 data_offset, u32 data_length);
5702854bb23SVarun Prakash static void iscsit_unmap_iovec(struct iscsi_cmd *);
5712854bb23SVarun Prakash static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsi_cmd *,
5722854bb23SVarun Prakash 				    u32, u32, u32, u8 *);
5732854bb23SVarun Prakash static int
5742854bb23SVarun Prakash iscsit_xmit_datain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
5752854bb23SVarun Prakash 		       const struct iscsi_datain *datain)
5762854bb23SVarun Prakash {
5772854bb23SVarun Prakash 	struct kvec *iov;
5782854bb23SVarun Prakash 	u32 iov_count = 0, tx_size = 0;
5792854bb23SVarun Prakash 	int ret, iov_ret;
5802854bb23SVarun Prakash 
5812854bb23SVarun Prakash 	iov = &cmd->iov_data[0];
5822854bb23SVarun Prakash 	iov[iov_count].iov_base	= cmd->pdu;
5832854bb23SVarun Prakash 	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
5842854bb23SVarun Prakash 	tx_size += ISCSI_HDR_LEN;
5852854bb23SVarun Prakash 
5862854bb23SVarun Prakash 	if (conn->conn_ops->HeaderDigest) {
5872854bb23SVarun Prakash 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
5882854bb23SVarun Prakash 
5892854bb23SVarun Prakash 		iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu,
5902854bb23SVarun Prakash 					  ISCSI_HDR_LEN, 0, NULL,
591e1dfb21fSBart Van Assche 					  header_digest);
5922854bb23SVarun Prakash 
5932854bb23SVarun Prakash 		iov[0].iov_len += ISCSI_CRC_LEN;
5942854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
5952854bb23SVarun Prakash 
5962854bb23SVarun Prakash 		pr_debug("Attaching CRC32 HeaderDigest for DataIN PDU 0x%08x\n",
5972854bb23SVarun Prakash 			 *header_digest);
5982854bb23SVarun Prakash 	}
5992854bb23SVarun Prakash 
6002e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[iov_count],
6012e39f1c9SBart Van Assche 				   cmd->orig_iov_data_count - (iov_count + 2),
6022854bb23SVarun Prakash 				   datain->offset, datain->length);
6032854bb23SVarun Prakash 	if (iov_ret < 0)
6042854bb23SVarun Prakash 		return -1;
6052854bb23SVarun Prakash 
6062854bb23SVarun Prakash 	iov_count += iov_ret;
6072854bb23SVarun Prakash 	tx_size += datain->length;
6082854bb23SVarun Prakash 
6092854bb23SVarun Prakash 	cmd->padding = ((-datain->length) & 3);
6102854bb23SVarun Prakash 	if (cmd->padding) {
6112854bb23SVarun Prakash 		iov[iov_count].iov_base		= cmd->pad_bytes;
6122854bb23SVarun Prakash 		iov[iov_count++].iov_len	= cmd->padding;
6132854bb23SVarun Prakash 		tx_size += cmd->padding;
6142854bb23SVarun Prakash 
6152854bb23SVarun Prakash 		pr_debug("Attaching %u padding bytes\n", cmd->padding);
6162854bb23SVarun Prakash 	}
6172854bb23SVarun Prakash 
6182854bb23SVarun Prakash 	if (conn->conn_ops->DataDigest) {
6192854bb23SVarun Prakash 		cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash,
6202854bb23SVarun Prakash 							 cmd, datain->offset,
6212854bb23SVarun Prakash 							 datain->length,
6222854bb23SVarun Prakash 							 cmd->padding,
6232854bb23SVarun Prakash 							 cmd->pad_bytes);
6242854bb23SVarun Prakash 
6252854bb23SVarun Prakash 		iov[iov_count].iov_base	= &cmd->data_crc;
6262854bb23SVarun Prakash 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
6272854bb23SVarun Prakash 		tx_size += ISCSI_CRC_LEN;
6282854bb23SVarun Prakash 
6292854bb23SVarun Prakash 		pr_debug("Attached CRC32C DataDigest %d bytes, crc 0x%08x\n",
6302854bb23SVarun Prakash 			 datain->length + cmd->padding, cmd->data_crc);
6312854bb23SVarun Prakash 	}
6322854bb23SVarun Prakash 
6332854bb23SVarun Prakash 	cmd->iov_data_count = iov_count;
6342854bb23SVarun Prakash 	cmd->tx_size = tx_size;
6352854bb23SVarun Prakash 
6362854bb23SVarun Prakash 	ret = iscsit_fe_sendpage_sg(cmd, conn);
6372854bb23SVarun Prakash 
6382854bb23SVarun Prakash 	iscsit_unmap_iovec(cmd);
6392854bb23SVarun Prakash 
6402854bb23SVarun Prakash 	if (ret < 0) {
6412854bb23SVarun Prakash 		iscsit_tx_thread_wait_for_tcp(conn);
6422854bb23SVarun Prakash 		return ret;
6432854bb23SVarun Prakash 	}
6442854bb23SVarun Prakash 
6452854bb23SVarun Prakash 	return 0;
6462854bb23SVarun Prakash }
6472854bb23SVarun Prakash 
6482854bb23SVarun Prakash static int iscsit_xmit_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
6492854bb23SVarun Prakash 			   struct iscsi_datain_req *dr, const void *buf,
6502854bb23SVarun Prakash 			   u32 buf_len)
6512854bb23SVarun Prakash {
6522854bb23SVarun Prakash 	if (dr)
6532854bb23SVarun Prakash 		return iscsit_xmit_datain_pdu(conn, cmd, buf);
6542854bb23SVarun Prakash 	else
6552854bb23SVarun Prakash 		return iscsit_xmit_nondatain_pdu(conn, cmd, buf, buf_len);
6562854bb23SVarun Prakash }
6572854bb23SVarun Prakash 
658e70beee7SNicholas Bellinger static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
659e70beee7SNicholas Bellinger {
660e70beee7SNicholas Bellinger 	return TARGET_PROT_NORMAL;
661e70beee7SNicholas Bellinger }
662e70beee7SNicholas Bellinger 
663baa4d64bSNicholas Bellinger static struct iscsit_transport iscsi_target_transport = {
664baa4d64bSNicholas Bellinger 	.name			= "iSCSI/TCP",
665baa4d64bSNicholas Bellinger 	.transport_type		= ISCSI_TCP,
666bd027d85SNicholas Bellinger 	.rdma_shutdown		= false,
667baa4d64bSNicholas Bellinger 	.owner			= NULL,
668baa4d64bSNicholas Bellinger 	.iscsit_setup_np	= iscsit_setup_np,
669baa4d64bSNicholas Bellinger 	.iscsit_accept_np	= iscsit_accept_np,
670baa4d64bSNicholas Bellinger 	.iscsit_free_np		= iscsit_free_np,
671baa4d64bSNicholas Bellinger 	.iscsit_get_login_rx	= iscsit_get_login_rx,
672baa4d64bSNicholas Bellinger 	.iscsit_put_login_tx	= iscsit_put_login_tx,
6733e1c81a9SNicholas Bellinger 	.iscsit_get_dataout	= iscsit_build_r2ts_for_cmd,
6742ec5a8c1SNicholas Bellinger 	.iscsit_immediate_queue	= iscsit_immediate_queue,
6752ec5a8c1SNicholas Bellinger 	.iscsit_response_queue	= iscsit_response_queue,
6762ec5a8c1SNicholas Bellinger 	.iscsit_queue_data_in	= iscsit_queue_rsp,
6772ec5a8c1SNicholas Bellinger 	.iscsit_queue_status	= iscsit_queue_rsp,
678131e6abcSNicholas Bellinger 	.iscsit_aborted_task	= iscsit_aborted_task,
6792854bb23SVarun Prakash 	.iscsit_xmit_pdu	= iscsit_xmit_pdu,
680e8205ccaSVarun Prakash 	.iscsit_get_rx_pdu	= iscsit_get_rx_pdu,
681e70beee7SNicholas Bellinger 	.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
682baa4d64bSNicholas Bellinger };
683baa4d64bSNicholas Bellinger 
684e48354ceSNicholas Bellinger static int __init iscsi_target_init_module(void)
685e48354ceSNicholas Bellinger {
68688dcd2daSNicholas Bellinger 	int ret = 0, size;
687e48354ceSNicholas Bellinger 
688e48354ceSNicholas Bellinger 	pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
6893829f381SMarkus Elfring 	iscsit_global = kzalloc(sizeof(*iscsit_global), GFP_KERNEL);
690c46e22f1SMarkus Elfring 	if (!iscsit_global)
691e48354ceSNicholas Bellinger 		return -1;
692c46e22f1SMarkus Elfring 
69388dcd2daSNicholas Bellinger 	spin_lock_init(&iscsit_global->ts_bitmap_lock);
694e48354ceSNicholas Bellinger 	mutex_init(&auth_id_lock);
695e48354ceSNicholas Bellinger 	idr_init(&tiqn_idr);
696e48354ceSNicholas Bellinger 
6979ac8928eSChristoph Hellwig 	ret = target_register_template(&iscsi_ops);
6989ac8928eSChristoph Hellwig 	if (ret)
699e48354ceSNicholas Bellinger 		goto out;
700e48354ceSNicholas Bellinger 
70188dcd2daSNicholas Bellinger 	size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
70288dcd2daSNicholas Bellinger 	iscsit_global->ts_bitmap = vzalloc(size);
703c46e22f1SMarkus Elfring 	if (!iscsit_global->ts_bitmap)
704e48354ceSNicholas Bellinger 		goto configfs_out;
705e48354ceSNicholas Bellinger 
706e48354ceSNicholas Bellinger 	lio_qr_cache = kmem_cache_create("lio_qr_cache",
707e48354ceSNicholas Bellinger 			sizeof(struct iscsi_queue_req),
708e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_queue_req), 0, NULL);
709e48354ceSNicholas Bellinger 	if (!lio_qr_cache) {
710621a4367SLeo Zhang 		pr_err("Unable to kmem_cache_create() for"
711e48354ceSNicholas Bellinger 				" lio_qr_cache\n");
71288dcd2daSNicholas Bellinger 		goto bitmap_out;
713e48354ceSNicholas Bellinger 	}
714e48354ceSNicholas Bellinger 
715e48354ceSNicholas Bellinger 	lio_dr_cache = kmem_cache_create("lio_dr_cache",
716e48354ceSNicholas Bellinger 			sizeof(struct iscsi_datain_req),
717e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_datain_req), 0, NULL);
718e48354ceSNicholas Bellinger 	if (!lio_dr_cache) {
719e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
720e48354ceSNicholas Bellinger 				" lio_dr_cache\n");
721e48354ceSNicholas Bellinger 		goto qr_out;
722e48354ceSNicholas Bellinger 	}
723e48354ceSNicholas Bellinger 
724e48354ceSNicholas Bellinger 	lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
725e48354ceSNicholas Bellinger 			sizeof(struct iscsi_ooo_cmdsn),
726e48354ceSNicholas Bellinger 			__alignof__(struct iscsi_ooo_cmdsn), 0, NULL);
727e48354ceSNicholas Bellinger 	if (!lio_ooo_cache) {
728e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
729e48354ceSNicholas Bellinger 				" lio_ooo_cache\n");
730e48354ceSNicholas Bellinger 		goto dr_out;
731e48354ceSNicholas Bellinger 	}
732e48354ceSNicholas Bellinger 
733e48354ceSNicholas Bellinger 	lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
734e48354ceSNicholas Bellinger 			sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
735e48354ceSNicholas Bellinger 			0, NULL);
736e48354ceSNicholas Bellinger 	if (!lio_r2t_cache) {
737e48354ceSNicholas Bellinger 		pr_err("Unable to kmem_cache_create() for"
738e48354ceSNicholas Bellinger 				" lio_r2t_cache\n");
739e48354ceSNicholas Bellinger 		goto ooo_out;
740e48354ceSNicholas Bellinger 	}
741e48354ceSNicholas Bellinger 
742baa4d64bSNicholas Bellinger 	iscsit_register_transport(&iscsi_target_transport);
743baa4d64bSNicholas Bellinger 
744e48354ceSNicholas Bellinger 	if (iscsit_load_discovery_tpg() < 0)
745e48354ceSNicholas Bellinger 		goto r2t_out;
746e48354ceSNicholas Bellinger 
747e48354ceSNicholas Bellinger 	return ret;
748e48354ceSNicholas Bellinger r2t_out:
7497f2c53bbSLino Sanfilippo 	iscsit_unregister_transport(&iscsi_target_transport);
750e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
751e48354ceSNicholas Bellinger ooo_out:
752e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
753e48354ceSNicholas Bellinger dr_out:
754e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
755e48354ceSNicholas Bellinger qr_out:
756e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
75788dcd2daSNicholas Bellinger bitmap_out:
75888dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
759e48354ceSNicholas Bellinger configfs_out:
7609ac8928eSChristoph Hellwig 	/* XXX: this probably wants it to be it's own unwind step.. */
7619ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7629ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
7639ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
764e48354ceSNicholas Bellinger out:
765e48354ceSNicholas Bellinger 	kfree(iscsit_global);
766e48354ceSNicholas Bellinger 	return -ENOMEM;
767e48354ceSNicholas Bellinger }
768e48354ceSNicholas Bellinger 
769e48354ceSNicholas Bellinger static void __exit iscsi_target_cleanup_module(void)
770e48354ceSNicholas Bellinger {
771e48354ceSNicholas Bellinger 	iscsit_release_discovery_tpg();
772baa4d64bSNicholas Bellinger 	iscsit_unregister_transport(&iscsi_target_transport);
773e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_qr_cache);
774e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_dr_cache);
775e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_ooo_cache);
776e48354ceSNicholas Bellinger 	kmem_cache_destroy(lio_r2t_cache);
777e48354ceSNicholas Bellinger 
7789ac8928eSChristoph Hellwig 	/*
7799ac8928eSChristoph Hellwig 	 * Shutdown discovery sessions and disable discovery TPG
7809ac8928eSChristoph Hellwig 	 */
7819ac8928eSChristoph Hellwig 	if (iscsit_global->discovery_tpg)
7829ac8928eSChristoph Hellwig 		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
783e48354ceSNicholas Bellinger 
7849ac8928eSChristoph Hellwig 	target_unregister_template(&iscsi_ops);
785e48354ceSNicholas Bellinger 
78688dcd2daSNicholas Bellinger 	vfree(iscsit_global->ts_bitmap);
787e48354ceSNicholas Bellinger 	kfree(iscsit_global);
788e48354ceSNicholas Bellinger }
789e48354ceSNicholas Bellinger 
790d2faaefbSVarun Prakash int iscsit_add_reject(
791ba159914SNicholas Bellinger 	struct iscsi_conn *conn,
792e48354ceSNicholas Bellinger 	u8 reason,
793ba159914SNicholas Bellinger 	unsigned char *buf)
794e48354ceSNicholas Bellinger {
795e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
796e48354ceSNicholas Bellinger 
797676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
798e48354ceSNicholas Bellinger 	if (!cmd)
799e48354ceSNicholas Bellinger 		return -1;
800e48354ceSNicholas Bellinger 
801e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
802ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
803e48354ceSNicholas Bellinger 
8041c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
805e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
806e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
807aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
808e48354ceSNicholas Bellinger 		return -1;
809e48354ceSNicholas Bellinger 	}
810e48354ceSNicholas Bellinger 
811e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
8122fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
813e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
814e48354ceSNicholas Bellinger 
815e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
816e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
817e48354ceSNicholas Bellinger 
818e48354ceSNicholas Bellinger 	return -1;
819e48354ceSNicholas Bellinger }
820d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_add_reject);
821e48354ceSNicholas Bellinger 
822ba159914SNicholas Bellinger static int iscsit_add_reject_from_cmd(
823ba159914SNicholas Bellinger 	struct iscsi_cmd *cmd,
824e48354ceSNicholas Bellinger 	u8 reason,
825ba159914SNicholas Bellinger 	bool add_to_conn,
826ba159914SNicholas Bellinger 	unsigned char *buf)
827e48354ceSNicholas Bellinger {
828e48354ceSNicholas Bellinger 	struct iscsi_conn *conn;
829cfe2b621SBart Van Assche 	const bool do_put = cmd->se_cmd.se_tfo != NULL;
830e48354ceSNicholas Bellinger 
831e48354ceSNicholas Bellinger 	if (!cmd->conn) {
832e48354ceSNicholas Bellinger 		pr_err("cmd->conn is NULL for ITT: 0x%08x\n",
833e48354ceSNicholas Bellinger 				cmd->init_task_tag);
834e48354ceSNicholas Bellinger 		return -1;
835e48354ceSNicholas Bellinger 	}
836e48354ceSNicholas Bellinger 	conn = cmd->conn;
837e48354ceSNicholas Bellinger 
838e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_REJECT;
839ba159914SNicholas Bellinger 	cmd->reject_reason = reason;
840e48354ceSNicholas Bellinger 
8411c3d5794SThomas Meyer 	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
842e48354ceSNicholas Bellinger 	if (!cmd->buf_ptr) {
843e48354ceSNicholas Bellinger 		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
844aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
845e48354ceSNicholas Bellinger 		return -1;
846e48354ceSNicholas Bellinger 	}
847e48354ceSNicholas Bellinger 
848e48354ceSNicholas Bellinger 	if (add_to_conn) {
849e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
8502fbb471eSAndy Grover 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
851e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
852e48354ceSNicholas Bellinger 	}
853e48354ceSNicholas Bellinger 
854e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_REJECT;
855e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
8563e1c81a9SNicholas Bellinger 	/*
8573e1c81a9SNicholas Bellinger 	 * Perform the kref_put now if se_cmd has already been setup by
8583e1c81a9SNicholas Bellinger 	 * scsit_setup_scsi_cmd()
8593e1c81a9SNicholas Bellinger 	 */
860cfe2b621SBart Van Assche 	if (do_put) {
8613e1c81a9SNicholas Bellinger 		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
862afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
8633e1c81a9SNicholas Bellinger 	}
864e48354ceSNicholas Bellinger 	return -1;
865e48354ceSNicholas Bellinger }
866ba159914SNicholas Bellinger 
867ba159914SNicholas Bellinger static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason,
868ba159914SNicholas Bellinger 				 unsigned char *buf)
869ba159914SNicholas Bellinger {
870ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, true, buf);
871ba159914SNicholas Bellinger }
872ba159914SNicholas Bellinger 
873ba159914SNicholas Bellinger int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf)
874ba159914SNicholas Bellinger {
875ba159914SNicholas Bellinger 	return iscsit_add_reject_from_cmd(cmd, reason, false, buf);
876ba159914SNicholas Bellinger }
877d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_reject_cmd);
878e48354ceSNicholas Bellinger 
879e48354ceSNicholas Bellinger /*
880e48354ceSNicholas Bellinger  * Map some portion of the allocated scatterlist to an iovec, suitable for
881bfb79eacSAndy Grover  * kernel sockets to copy data in/out.
882e48354ceSNicholas Bellinger  */
8832e39f1c9SBart Van Assche static int iscsit_map_iovec(struct iscsi_cmd *cmd, struct kvec *iov, int nvec,
8842e39f1c9SBart Van Assche 			    u32 data_offset, u32 data_length)
885e48354ceSNicholas Bellinger {
8862e39f1c9SBart Van Assche 	u32 i = 0, orig_data_length = data_length;
887e48354ceSNicholas Bellinger 	struct scatterlist *sg;
888e48354ceSNicholas Bellinger 	unsigned int page_off;
889e48354ceSNicholas Bellinger 
890e48354ceSNicholas Bellinger 	/*
891bfb79eacSAndy Grover 	 * We know each entry in t_data_sg contains a page.
892e48354ceSNicholas Bellinger 	 */
8932b16509cSImran Haider 	u32 ent = data_offset / PAGE_SIZE;
8942b16509cSImran Haider 
8952e39f1c9SBart Van Assche 	if (!data_length)
8962e39f1c9SBart Van Assche 		return 0;
8972e39f1c9SBart Van Assche 
8982b16509cSImran Haider 	if (ent >= cmd->se_cmd.t_data_nents) {
8992b16509cSImran Haider 		pr_err("Initial page entry out-of-bounds\n");
9002e39f1c9SBart Van Assche 		goto overflow;
9012b16509cSImran Haider 	}
9022b16509cSImran Haider 
9032b16509cSImran Haider 	sg = &cmd->se_cmd.t_data_sg[ent];
904e48354ceSNicholas Bellinger 	page_off = (data_offset % PAGE_SIZE);
905e48354ceSNicholas Bellinger 
906e48354ceSNicholas Bellinger 	cmd->first_data_sg = sg;
907e48354ceSNicholas Bellinger 	cmd->first_data_sg_off = page_off;
908e48354ceSNicholas Bellinger 
909e48354ceSNicholas Bellinger 	while (data_length) {
9102e39f1c9SBart Van Assche 		u32 cur_len;
9112e39f1c9SBart Van Assche 
9122e39f1c9SBart Van Assche 		if (WARN_ON_ONCE(!sg || i >= nvec))
9132e39f1c9SBart Van Assche 			goto overflow;
9142e39f1c9SBart Van Assche 
9152e39f1c9SBart Van Assche 		cur_len = min_t(u32, data_length, sg->length - page_off);
916e48354ceSNicholas Bellinger 
917e48354ceSNicholas Bellinger 		iov[i].iov_base = kmap(sg_page(sg)) + sg->offset + page_off;
918e48354ceSNicholas Bellinger 		iov[i].iov_len = cur_len;
919e48354ceSNicholas Bellinger 
920e48354ceSNicholas Bellinger 		data_length -= cur_len;
921e48354ceSNicholas Bellinger 		page_off = 0;
922e48354ceSNicholas Bellinger 		sg = sg_next(sg);
923e48354ceSNicholas Bellinger 		i++;
924e48354ceSNicholas Bellinger 	}
925e48354ceSNicholas Bellinger 
926e48354ceSNicholas Bellinger 	cmd->kmapped_nents = i;
927e48354ceSNicholas Bellinger 
928e48354ceSNicholas Bellinger 	return i;
9292e39f1c9SBart Van Assche 
9302e39f1c9SBart Van Assche overflow:
9312e39f1c9SBart Van Assche 	pr_err("offset %d + length %d overflow; %d/%d; sg-list:\n",
9322e39f1c9SBart Van Assche 	       data_offset, orig_data_length, i, nvec);
9332e39f1c9SBart Van Assche 	for_each_sg(cmd->se_cmd.t_data_sg, sg,
9342e39f1c9SBart Van Assche 		    cmd->se_cmd.t_data_nents, i) {
9352e39f1c9SBart Van Assche 		pr_err("[%d] off %d len %d\n",
9362e39f1c9SBart Van Assche 		       i, sg->offset, sg->length);
9372e39f1c9SBart Van Assche 	}
9382e39f1c9SBart Van Assche 	return -1;
939e48354ceSNicholas Bellinger }
940e48354ceSNicholas Bellinger 
941e48354ceSNicholas Bellinger static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)
942e48354ceSNicholas Bellinger {
943e48354ceSNicholas Bellinger 	u32 i;
944e48354ceSNicholas Bellinger 	struct scatterlist *sg;
945e48354ceSNicholas Bellinger 
946e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
947e48354ceSNicholas Bellinger 
948e48354ceSNicholas Bellinger 	for (i = 0; i < cmd->kmapped_nents; i++)
949e48354ceSNicholas Bellinger 		kunmap(sg_page(&sg[i]));
950e48354ceSNicholas Bellinger }
951e48354ceSNicholas Bellinger 
952e48354ceSNicholas Bellinger static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
953e48354ceSNicholas Bellinger {
954f56cbbb4SNicholas Bellinger 	LIST_HEAD(ack_list);
955f56cbbb4SNicholas Bellinger 	struct iscsi_cmd *cmd, *cmd_p;
956e48354ceSNicholas Bellinger 
957e48354ceSNicholas Bellinger 	conn->exp_statsn = exp_statsn;
958e48354ceSNicholas Bellinger 
9593e1c81a9SNicholas Bellinger 	if (conn->sess->sess_ops->RDMAExtensions)
9603e1c81a9SNicholas Bellinger 		return;
9613e1c81a9SNicholas Bellinger 
962e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
963f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
964e48354ceSNicholas Bellinger 		spin_lock(&cmd->istate_lock);
965e48354ceSNicholas Bellinger 		if ((cmd->i_state == ISTATE_SENT_STATUS) &&
96664c13330SSteve Hodgson 		    iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
967e48354ceSNicholas Bellinger 			cmd->i_state = ISTATE_REMOVE;
968e48354ceSNicholas Bellinger 			spin_unlock(&cmd->istate_lock);
969f56cbbb4SNicholas Bellinger 			list_move_tail(&cmd->i_conn_node, &ack_list);
970e48354ceSNicholas Bellinger 			continue;
971e48354ceSNicholas Bellinger 		}
972e48354ceSNicholas Bellinger 		spin_unlock(&cmd->istate_lock);
973e48354ceSNicholas Bellinger 	}
974e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
975f56cbbb4SNicholas Bellinger 
976f56cbbb4SNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
9775159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
978f56cbbb4SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
979f56cbbb4SNicholas Bellinger 	}
980e48354ceSNicholas Bellinger }
981e48354ceSNicholas Bellinger 
982e48354ceSNicholas Bellinger static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
983e48354ceSNicholas Bellinger {
984f80e8ed3SNicholas Bellinger 	u32 iov_count = max(1UL, DIV_ROUND_UP(cmd->se_cmd.data_length, PAGE_SIZE));
985e48354ceSNicholas Bellinger 
986c0427f15SChristoph Hellwig 	iov_count += ISCSI_IOV_DATA_BUFFER;
987f1725110SMarkus Elfring 	cmd->iov_data = kcalloc(iov_count, sizeof(*cmd->iov_data), GFP_KERNEL);
988c46e22f1SMarkus Elfring 	if (!cmd->iov_data)
989e48354ceSNicholas Bellinger 		return -ENOMEM;
990e48354ceSNicholas Bellinger 
991e48354ceSNicholas Bellinger 	cmd->orig_iov_data_count = iov_count;
992e48354ceSNicholas Bellinger 	return 0;
993e48354ceSNicholas Bellinger }
994e48354ceSNicholas Bellinger 
9953e1c81a9SNicholas Bellinger int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
996e48354ceSNicholas Bellinger 			  unsigned char *buf)
997e48354ceSNicholas Bellinger {
9983e1c81a9SNicholas Bellinger 	int data_direction, payload_length;
999e48354ceSNicholas Bellinger 	struct iscsi_scsi_req *hdr;
1000d28b1169SAndy Grover 	int iscsi_task_attr;
1001d28b1169SAndy Grover 	int sam_task_attr;
1002e48354ceSNicholas Bellinger 
100304f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->cmd_pdus);
1004e48354ceSNicholas Bellinger 
1005e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_scsi_req *) buf;
1006e48354ceSNicholas Bellinger 	payload_length		= ntoh24(hdr->dlength);
1007e48354ceSNicholas Bellinger 
1008e48354ceSNicholas Bellinger 	/* FIXME; Add checks for AdditionalHeaderSegment */
1009e48354ceSNicholas Bellinger 
1010e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_WRITE) &&
1011e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1012e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
1013e48354ceSNicholas Bellinger 				" not set. Bad iSCSI Initiator.\n");
1014ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1015ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1016e48354ceSNicholas Bellinger 	}
1017e48354ceSNicholas Bellinger 
1018e48354ceSNicholas Bellinger 	if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
1019e48354ceSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
1020e48354ceSNicholas Bellinger 		/*
10214454b66cSNicholas Bellinger 		 * From RFC-3720 Section 10.3.1:
10224454b66cSNicholas Bellinger 		 *
10234454b66cSNicholas Bellinger 		 * "Either or both of R and W MAY be 1 when either the
10244454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length and/or Bidirectional Read
10254454b66cSNicholas Bellinger 		 *  Expected Data Transfer Length are 0"
10264454b66cSNicholas Bellinger 		 *
10274454b66cSNicholas Bellinger 		 * For this case, go ahead and clear the unnecssary bits
10284454b66cSNicholas Bellinger 		 * to avoid any confusion with ->data_direction.
1029e48354ceSNicholas Bellinger 		 */
1030e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_READ;
1031e48354ceSNicholas Bellinger 		hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
1032e48354ceSNicholas Bellinger 
10334454b66cSNicholas Bellinger 		pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
1034e48354ceSNicholas Bellinger 			" set when Expected Data Transfer Length is 0 for"
10354454b66cSNicholas Bellinger 			" CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
1036e48354ceSNicholas Bellinger 	}
1037e48354ceSNicholas Bellinger 
1038e48354ceSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
1039e48354ceSNicholas Bellinger 	    !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
1040e48354ceSNicholas Bellinger 		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
1041e48354ceSNicholas Bellinger 			" MUST be set if Expected Data Transfer Length is not 0."
1042e48354ceSNicholas Bellinger 			" Bad iSCSI Initiator\n");
1043ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1044ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1045e48354ceSNicholas Bellinger 	}
1046e48354ceSNicholas Bellinger 
1047e48354ceSNicholas Bellinger 	if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
1048e48354ceSNicholas Bellinger 	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
1049e48354ceSNicholas Bellinger 		pr_err("Bidirectional operations not supported!\n");
1050ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1051ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1052e48354ceSNicholas Bellinger 	}
1053e48354ceSNicholas Bellinger 
1054e48354ceSNicholas Bellinger 	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1055e48354ceSNicholas Bellinger 		pr_err("Illegally set Immediate Bit in iSCSI Initiator"
1056e48354ceSNicholas Bellinger 				" Scsi Command PDU.\n");
1057ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1058ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1059e48354ceSNicholas Bellinger 	}
1060e48354ceSNicholas Bellinger 
1061e48354ceSNicholas Bellinger 	if (payload_length && !conn->sess->sess_ops->ImmediateData) {
1062e48354ceSNicholas Bellinger 		pr_err("ImmediateData=No but DataSegmentLength=%u,"
1063e48354ceSNicholas Bellinger 			" protocol error.\n", payload_length);
1064ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1065ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1066e48354ceSNicholas Bellinger 	}
1067e48354ceSNicholas Bellinger 
106850e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->data_length) == payload_length) &&
1069e48354ceSNicholas Bellinger 	    (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
1070e48354ceSNicholas Bellinger 		pr_err("Expected Data Transfer Length and Length of"
1071e48354ceSNicholas Bellinger 			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
1072e48354ceSNicholas Bellinger 			" bit is not set protocol error\n");
1073ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1074ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1075e48354ceSNicholas Bellinger 	}
1076e48354ceSNicholas Bellinger 
107750e5c87dSChristoph Hellwig 	if (payload_length > be32_to_cpu(hdr->data_length)) {
1078e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1079e48354ceSNicholas Bellinger 			" EDTL: %u, protocol error.\n", payload_length,
1080e48354ceSNicholas Bellinger 				hdr->data_length);
1081ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1082ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1083e48354ceSNicholas Bellinger 	}
1084e48354ceSNicholas Bellinger 
108521f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1086e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
108721f5aa7eSNicholas Bellinger 			" MaxXmitDataSegmentLength: %u, protocol error.\n",
108821f5aa7eSNicholas Bellinger 			payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
1089ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1090ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1091e48354ceSNicholas Bellinger 	}
1092e48354ceSNicholas Bellinger 
1093e48354ceSNicholas Bellinger 	if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
1094e48354ceSNicholas Bellinger 		pr_err("DataSegmentLength: %u is greater than"
1095e48354ceSNicholas Bellinger 			" FirstBurstLength: %u, protocol error.\n",
1096e48354ceSNicholas Bellinger 			payload_length, conn->sess->sess_ops->FirstBurstLength);
1097ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1098ba159914SNicholas Bellinger 					     ISCSI_REASON_BOOKMARK_INVALID, buf);
1099e48354ceSNicholas Bellinger 	}
1100e48354ceSNicholas Bellinger 
1101e48354ceSNicholas Bellinger 	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
1102e48354ceSNicholas Bellinger 			 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE :
1103e48354ceSNicholas Bellinger 			  DMA_NONE;
1104e48354ceSNicholas Bellinger 
1105d28b1169SAndy Grover 	cmd->data_direction = data_direction;
1106d28b1169SAndy Grover 	iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK;
1107d28b1169SAndy Grover 	/*
1108d28b1169SAndy Grover 	 * Figure out the SAM Task Attribute for the incoming SCSI CDB
1109d28b1169SAndy Grover 	 */
1110d28b1169SAndy Grover 	if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
1111d28b1169SAndy Grover 	    (iscsi_task_attr == ISCSI_ATTR_SIMPLE))
111268d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1113d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
111468d81f40SChristoph Hellwig 		sam_task_attr = TCM_ORDERED_TAG;
1115d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
111668d81f40SChristoph Hellwig 		sam_task_attr = TCM_HEAD_TAG;
1117d28b1169SAndy Grover 	else if (iscsi_task_attr == ISCSI_ATTR_ACA)
111868d81f40SChristoph Hellwig 		sam_task_attr = TCM_ACA_TAG;
1119d28b1169SAndy Grover 	else {
1120d28b1169SAndy Grover 		pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
112168d81f40SChristoph Hellwig 			" TCM_SIMPLE_TAG\n", iscsi_task_attr);
112268d81f40SChristoph Hellwig 		sam_task_attr = TCM_SIMPLE_TAG;
1123d28b1169SAndy Grover 	}
1124d28b1169SAndy Grover 
1125e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_CMD;
1126e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_NEW_CMD;
1127e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
1128e48354ceSNicholas Bellinger 	cmd->immediate_data	= (payload_length) ? 1 : 0;
1129e48354ceSNicholas Bellinger 	cmd->unsolicited_data	= ((!(hdr->flags & ISCSI_FLAG_CMD_FINAL) &&
1130e48354ceSNicholas Bellinger 				     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) ? 1 : 0);
1131e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data)
1132e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;
1133e48354ceSNicholas Bellinger 
1134e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
11359547308bSAlexei Potashnik 	if (hdr->flags & ISCSI_FLAG_CMD_READ)
1136c1e34b64SSagi Grimberg 		cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
11379547308bSAlexei Potashnik 	else
1138e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag = 0xFFFFFFFF;
113950e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
114050e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1141e48354ceSNicholas Bellinger 	cmd->first_burst_len	= payload_length;
1142e48354ceSNicholas Bellinger 
11433e1c81a9SNicholas Bellinger 	if (!conn->sess->sess_ops->RDMAExtensions &&
11443e1c81a9SNicholas Bellinger 	     cmd->data_direction == DMA_FROM_DEVICE) {
1145e48354ceSNicholas Bellinger 		struct iscsi_datain_req *dr;
1146e48354ceSNicholas Bellinger 
1147e48354ceSNicholas Bellinger 		dr = iscsit_allocate_datain_req();
1148e48354ceSNicholas Bellinger 		if (!dr)
1149ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1150ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1151e48354ceSNicholas Bellinger 
1152e48354ceSNicholas Bellinger 		iscsit_attach_datain_req(cmd, dr);
1153e48354ceSNicholas Bellinger 	}
1154e48354ceSNicholas Bellinger 
1155e48354ceSNicholas Bellinger 	/*
1156065ca1e4SAndy Grover 	 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
1157065ca1e4SAndy Grover 	 */
11589ac8928eSChristoph Hellwig 	transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
115950e5c87dSChristoph Hellwig 			conn->sess->se_sess, be32_to_cpu(hdr->data_length),
116050e5c87dSChristoph Hellwig 			cmd->data_direction, sam_task_attr,
116150e5c87dSChristoph Hellwig 			cmd->sense_buffer + 2);
1162065ca1e4SAndy Grover 
1163065ca1e4SAndy Grover 	pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
1164065ca1e4SAndy Grover 		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
11653e1c81a9SNicholas Bellinger 		hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
11663e1c81a9SNicholas Bellinger 		conn->cid);
11673e1c81a9SNicholas Bellinger 
1168e9d3009cSBart Van Assche 	if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
1169e9d3009cSBart Van Assche 		return iscsit_add_reject_cmd(cmd,
1170e9d3009cSBart Van Assche 				ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
1171065ca1e4SAndy Grover 
1172de103c93SChristoph Hellwig 	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
11734f26998aSAndy Grover 						     scsilun_to_int(&hdr->lun));
1174de103c93SChristoph Hellwig 	if (cmd->sense_reason)
1175e48354ceSNicholas Bellinger 		goto attach_cmd;
1176a12f41f8SAndy Grover 
1177649ee054SBart Van Assche 	/* only used for printks or comparing with ->ref_task_tag */
1178649ee054SBart Van Assche 	cmd->se_cmd.tag = (__force u32)cmd->init_task_tag;
1179de103c93SChristoph Hellwig 	cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
1180de103c93SChristoph Hellwig 	if (cmd->sense_reason) {
1181de103c93SChristoph Hellwig 		if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
1182ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
1183ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1184de103c93SChristoph Hellwig 		}
1185de103c93SChristoph Hellwig 
1186de103c93SChristoph Hellwig 		goto attach_cmd;
1187de103c93SChristoph Hellwig 	}
1188de103c93SChristoph Hellwig 
1189de103c93SChristoph Hellwig 	if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
1190ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1191ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
1192e48354ceSNicholas Bellinger 	}
1193e48354ceSNicholas Bellinger 
1194e48354ceSNicholas Bellinger attach_cmd:
1195e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
11962fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1197e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
1198e48354ceSNicholas Bellinger 	/*
1199e48354ceSNicholas Bellinger 	 * Check if we need to delay processing because of ALUA
1200e48354ceSNicholas Bellinger 	 * Active/NonOptimized primary access state..
1201e48354ceSNicholas Bellinger 	 */
1202e48354ceSNicholas Bellinger 	core_alua_check_nonop_delay(&cmd->se_cmd);
1203bfb79eacSAndy Grover 
12043e1c81a9SNicholas Bellinger 	return 0;
1205de103c93SChristoph Hellwig }
12063e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_scsi_cmd);
1207de103c93SChristoph Hellwig 
12080300b114SBart Van Assche void iscsit_set_unsolicited_dataout(struct iscsi_cmd *cmd)
12093e1c81a9SNicholas Bellinger {
12103e1c81a9SNicholas Bellinger 	iscsit_set_dataout_sequence_values(cmd);
12113e1c81a9SNicholas Bellinger 
12123e1c81a9SNicholas Bellinger 	spin_lock_bh(&cmd->dataout_timeout_lock);
12133e1c81a9SNicholas Bellinger 	iscsit_start_dataout_timer(cmd, cmd->conn);
12143e1c81a9SNicholas Bellinger 	spin_unlock_bh(&cmd->dataout_timeout_lock);
12153e1c81a9SNicholas Bellinger }
12160300b114SBart Van Assche EXPORT_SYMBOL(iscsit_set_unsolicited_dataout);
12173e1c81a9SNicholas Bellinger 
12183e1c81a9SNicholas Bellinger int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
12193e1c81a9SNicholas Bellinger 			    struct iscsi_scsi_req *hdr)
12203e1c81a9SNicholas Bellinger {
12213e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0;
1222e48354ceSNicholas Bellinger 	/*
1223e48354ceSNicholas Bellinger 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
1224e48354ceSNicholas Bellinger 	 * the Immediate Bit is not set, and no Immediate
1225e48354ceSNicholas Bellinger 	 * Data is attached.
1226e48354ceSNicholas Bellinger 	 *
1227e48354ceSNicholas Bellinger 	 * A PDU/CmdSN carrying Immediate Data can only
1228e48354ceSNicholas Bellinger 	 * be processed after the DataCRC has passed.
1229e48354ceSNicholas Bellinger 	 * If the DataCRC fails, the CmdSN MUST NOT
1230e48354ceSNicholas Bellinger 	 * be acknowledged. (See below)
1231e48354ceSNicholas Bellinger 	 */
1232e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
1233561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1234561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
1235561bf158SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1236561bf158SNicholas Bellinger 			return -1;
1237561bf158SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1238afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
12393e1c81a9SNicholas Bellinger 			return 0;
12403e1c81a9SNicholas Bellinger 		}
1241e48354ceSNicholas Bellinger 	}
1242e48354ceSNicholas Bellinger 
124350e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1244e48354ceSNicholas Bellinger 
1245e48354ceSNicholas Bellinger 	/*
1246e48354ceSNicholas Bellinger 	 * If no Immediate Data is attached, it's OK to return now.
1247e48354ceSNicholas Bellinger 	 */
1248e48354ceSNicholas Bellinger 	if (!cmd->immediate_data) {
12493e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason && cmd->unsolicited_data)
12500300b114SBart Van Assche 			iscsit_set_unsolicited_dataout(cmd);
12513e1c81a9SNicholas Bellinger 		if (!cmd->sense_reason)
12523e1c81a9SNicholas Bellinger 			return 0;
1253e48354ceSNicholas Bellinger 
1254afc16604SBart Van Assche 		target_put_sess_cmd(&cmd->se_cmd);
1255e48354ceSNicholas Bellinger 		return 0;
1256e48354ceSNicholas Bellinger 	}
1257e48354ceSNicholas Bellinger 
1258e48354ceSNicholas Bellinger 	/*
12593e1c81a9SNicholas Bellinger 	 * Early CHECK_CONDITIONs with ImmediateData never make it to command
12603e1c81a9SNicholas Bellinger 	 * execution.  These exceptions are processed in CmdSN order using
12613e1c81a9SNicholas Bellinger 	 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
1262e48354ceSNicholas Bellinger 	 */
12638fa4011eSBart Van Assche 	if (cmd->sense_reason)
12643e1c81a9SNicholas Bellinger 		return 1;
1265e48354ceSNicholas Bellinger 	/*
1266e48354ceSNicholas Bellinger 	 * Call directly into transport_generic_new_cmd() to perform
1267e48354ceSNicholas Bellinger 	 * the backend memory allocation.
1268e48354ceSNicholas Bellinger 	 */
1269de103c93SChristoph Hellwig 	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
1270561bf158SNicholas Bellinger 	if (cmd->sense_reason)
12713e1c81a9SNicholas Bellinger 		return 1;
1272e48354ceSNicholas Bellinger 
12733e1c81a9SNicholas Bellinger 	return 0;
12743e1c81a9SNicholas Bellinger }
12753e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_scsi_cmd);
12763e1c81a9SNicholas Bellinger 
12773e1c81a9SNicholas Bellinger static int
12783e1c81a9SNicholas Bellinger iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
12793e1c81a9SNicholas Bellinger 			  bool dump_payload)
12803e1c81a9SNicholas Bellinger {
12813e1c81a9SNicholas Bellinger 	int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
12824b3766ecSBart Van Assche 	int rc;
12834b3766ecSBart Van Assche 
12843e1c81a9SNicholas Bellinger 	/*
12853e1c81a9SNicholas Bellinger 	 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
12863e1c81a9SNicholas Bellinger 	 */
12874b3766ecSBart Van Assche 	if (dump_payload) {
12884b3766ecSBart Van Assche 		u32 length = min(cmd->se_cmd.data_length - cmd->write_data_done,
12894b3766ecSBart Van Assche 				 cmd->first_burst_len);
12903e1c81a9SNicholas Bellinger 
12914b3766ecSBart Van Assche 		pr_debug("Dumping min(%d - %d, %d) = %d bytes of immediate data\n",
12924b3766ecSBart Van Assche 			 cmd->se_cmd.data_length, cmd->write_data_done,
12934b3766ecSBart Van Assche 			 cmd->first_burst_len, length);
12944b3766ecSBart Van Assche 		rc = iscsit_dump_data_payload(cmd->conn, length, 1);
12954b3766ecSBart Van Assche 		pr_debug("Finished dumping immediate data\n");
12964b3766ecSBart Van Assche 		if (rc < 0)
12974b3766ecSBart Van Assche 			immed_ret = IMMEDIATE_DATA_CANNOT_RECOVER;
12984b3766ecSBart Van Assche 	} else {
12993e1c81a9SNicholas Bellinger 		immed_ret = iscsit_handle_immediate_data(cmd, hdr,
13003e1c81a9SNicholas Bellinger 							 cmd->first_burst_len);
13014b3766ecSBart Van Assche 	}
13024b3766ecSBart Van Assche 
1303e48354ceSNicholas Bellinger 	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) {
1304e48354ceSNicholas Bellinger 		/*
1305e48354ceSNicholas Bellinger 		 * A PDU/CmdSN carrying Immediate Data passed
1306e48354ceSNicholas Bellinger 		 * DataCRC, check against ExpCmdSN/MaxCmdSN if
1307e48354ceSNicholas Bellinger 		 * Immediate Bit is not set.
1308e48354ceSNicholas Bellinger 		 */
1309561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd,
1310561bf158SNicholas Bellinger 					(unsigned char *)hdr, hdr->cmdsn);
13119d86a2beSNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1312561bf158SNicholas Bellinger 			return -1;
1313e48354ceSNicholas Bellinger 
13149d86a2beSNicholas Bellinger 		if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1315afc16604SBart Van Assche 			target_put_sess_cmd(&cmd->se_cmd);
13164b3766ecSBart Van Assche 
13174b3766ecSBart Van Assche 			return 0;
13183e1c81a9SNicholas Bellinger 		} else if (cmd->unsolicited_data)
13190300b114SBart Van Assche 			iscsit_set_unsolicited_dataout(cmd);
1320e48354ceSNicholas Bellinger 
1321e48354ceSNicholas Bellinger 	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
1322e48354ceSNicholas Bellinger 		/*
1323e48354ceSNicholas Bellinger 		 * Immediate Data failed DataCRC and ERL>=1,
1324e48354ceSNicholas Bellinger 		 * silently drop this PDU and let the initiator
1325e48354ceSNicholas Bellinger 		 * plug the CmdSN gap.
1326e48354ceSNicholas Bellinger 		 *
1327e48354ceSNicholas Bellinger 		 * FIXME: Send Unsolicited NOPIN with reserved
1328e48354ceSNicholas Bellinger 		 * TTT here to help the initiator figure out
1329e48354ceSNicholas Bellinger 		 * the missing CmdSN, although they should be
1330e48354ceSNicholas Bellinger 		 * intelligent enough to determine the missing
1331e48354ceSNicholas Bellinger 		 * CmdSN and issue a retry to plug the sequence.
1332e48354ceSNicholas Bellinger 		 */
1333e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_REMOVE;
13343e1c81a9SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, cmd->i_state);
1335e48354ceSNicholas Bellinger 	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */
1336e48354ceSNicholas Bellinger 		return -1;
1337e48354ceSNicholas Bellinger 
1338e48354ceSNicholas Bellinger 	return 0;
1339e48354ceSNicholas Bellinger }
1340e48354ceSNicholas Bellinger 
13413e1c81a9SNicholas Bellinger static int
13423e1c81a9SNicholas Bellinger iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
13433e1c81a9SNicholas Bellinger 			   unsigned char *buf)
13443e1c81a9SNicholas Bellinger {
13453e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
13463e1c81a9SNicholas Bellinger 	int rc, immed_data;
13473e1c81a9SNicholas Bellinger 	bool dump_payload = false;
13483e1c81a9SNicholas Bellinger 
13493e1c81a9SNicholas Bellinger 	rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
13503e1c81a9SNicholas Bellinger 	if (rc < 0)
1351561bf158SNicholas Bellinger 		return 0;
13523e1c81a9SNicholas Bellinger 	/*
13533e1c81a9SNicholas Bellinger 	 * Allocation iovecs needed for struct socket operations for
13543e1c81a9SNicholas Bellinger 	 * traditional iSCSI block I/O.
13553e1c81a9SNicholas Bellinger 	 */
13563e1c81a9SNicholas Bellinger 	if (iscsit_allocate_iovecs(cmd) < 0) {
1357b815fc12SMike Christie 		return iscsit_reject_cmd(cmd,
1358ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
13593e1c81a9SNicholas Bellinger 	}
13603e1c81a9SNicholas Bellinger 	immed_data = cmd->immediate_data;
13613e1c81a9SNicholas Bellinger 
13623e1c81a9SNicholas Bellinger 	rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
13633e1c81a9SNicholas Bellinger 	if (rc < 0)
13643e1c81a9SNicholas Bellinger 		return rc;
13653e1c81a9SNicholas Bellinger 	else if (rc > 0)
13663e1c81a9SNicholas Bellinger 		dump_payload = true;
13673e1c81a9SNicholas Bellinger 
13683e1c81a9SNicholas Bellinger 	if (!immed_data)
13693e1c81a9SNicholas Bellinger 		return 0;
13703e1c81a9SNicholas Bellinger 
13713e1c81a9SNicholas Bellinger 	return iscsit_get_immediate_data(cmd, hdr, dump_payload);
13723e1c81a9SNicholas Bellinger }
13733e1c81a9SNicholas Bellinger 
1374e48354ceSNicholas Bellinger static u32 iscsit_do_crypto_hash_sg(
137569110e3cSHerbert Xu 	struct ahash_request *hash,
1376e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
1377e48354ceSNicholas Bellinger 	u32 data_offset,
1378e48354ceSNicholas Bellinger 	u32 data_length,
1379e48354ceSNicholas Bellinger 	u32 padding,
1380e48354ceSNicholas Bellinger 	u8 *pad_bytes)
1381e48354ceSNicholas Bellinger {
1382e48354ceSNicholas Bellinger 	u32 data_crc;
1383e48354ceSNicholas Bellinger 	struct scatterlist *sg;
1384e48354ceSNicholas Bellinger 	unsigned int page_off;
1385e48354ceSNicholas Bellinger 
138669110e3cSHerbert Xu 	crypto_ahash_init(hash);
1387e48354ceSNicholas Bellinger 
1388e48354ceSNicholas Bellinger 	sg = cmd->first_data_sg;
1389e48354ceSNicholas Bellinger 	page_off = cmd->first_data_sg_off;
1390e48354ceSNicholas Bellinger 
1391e48354ceSNicholas Bellinger 	while (data_length) {
1392aa75679cSAlexei Potashnik 		u32 cur_len = min_t(u32, data_length, (sg->length - page_off));
1393e48354ceSNicholas Bellinger 
139469110e3cSHerbert Xu 		ahash_request_set_crypt(hash, sg, NULL, cur_len);
139569110e3cSHerbert Xu 		crypto_ahash_update(hash);
1396e48354ceSNicholas Bellinger 
1397e48354ceSNicholas Bellinger 		data_length -= cur_len;
1398e48354ceSNicholas Bellinger 		page_off = 0;
1399aa75679cSAlexei Potashnik 		/* iscsit_map_iovec has already checked for invalid sg pointers */
1400aa75679cSAlexei Potashnik 		sg = sg_next(sg);
1401e48354ceSNicholas Bellinger 	}
1402e48354ceSNicholas Bellinger 
1403e48354ceSNicholas Bellinger 	if (padding) {
1404e48354ceSNicholas Bellinger 		struct scatterlist pad_sg;
1405e48354ceSNicholas Bellinger 
1406e48354ceSNicholas Bellinger 		sg_init_one(&pad_sg, pad_bytes, padding);
140769110e3cSHerbert Xu 		ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc,
140869110e3cSHerbert Xu 					padding);
140969110e3cSHerbert Xu 		crypto_ahash_finup(hash);
141069110e3cSHerbert Xu 	} else {
141169110e3cSHerbert Xu 		ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0);
141269110e3cSHerbert Xu 		crypto_ahash_final(hash);
1413e48354ceSNicholas Bellinger 	}
1414e48354ceSNicholas Bellinger 
1415e48354ceSNicholas Bellinger 	return data_crc;
1416e48354ceSNicholas Bellinger }
1417e48354ceSNicholas Bellinger 
1418e1dfb21fSBart Van Assche static void iscsit_do_crypto_hash_buf(struct ahash_request *hash,
1419e1dfb21fSBart Van Assche 	const void *buf, u32 payload_length, u32 padding,
1420e1dfb21fSBart Van Assche 	const void *pad_bytes, void *data_crc)
1421e48354ceSNicholas Bellinger {
142269110e3cSHerbert Xu 	struct scatterlist sg[2];
1423e48354ceSNicholas Bellinger 
142469110e3cSHerbert Xu 	sg_init_table(sg, ARRAY_SIZE(sg));
142569110e3cSHerbert Xu 	sg_set_buf(sg, buf, payload_length);
1426679fcae4SLaura Abbott 	if (padding)
142769110e3cSHerbert Xu 		sg_set_buf(sg + 1, pad_bytes, padding);
1428e48354ceSNicholas Bellinger 
142969110e3cSHerbert Xu 	ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding);
1430e48354ceSNicholas Bellinger 
143169110e3cSHerbert Xu 	crypto_ahash_digest(hash);
1432e48354ceSNicholas Bellinger }
1433e48354ceSNicholas Bellinger 
14343e1c81a9SNicholas Bellinger int
14359a584bf9SVarun Prakash __iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
14369a584bf9SVarun Prakash 			   struct iscsi_cmd *cmd, u32 payload_length,
14379a584bf9SVarun Prakash 			   bool *success)
1438e48354ceSNicholas Bellinger {
14399a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
1440e48354ceSNicholas Bellinger 	struct se_cmd *se_cmd;
14413e1c81a9SNicholas Bellinger 	int rc;
1442e48354ceSNicholas Bellinger 
1443e48354ceSNicholas Bellinger 	/* iSCSI write */
144404f3b31bSNicholas Bellinger 	atomic_long_add(payload_length, &conn->sess->rx_data_octets);
1445e48354ceSNicholas Bellinger 
1446e48354ceSNicholas Bellinger 	pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
1447e48354ceSNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
14483e1c81a9SNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
1449e48354ceSNicholas Bellinger 		payload_length, conn->cid);
1450e48354ceSNicholas Bellinger 
1451e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
1452e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT after"
1453e48354ceSNicholas Bellinger 			" last DataOUT received, dumping payload\n",
1454e48354ceSNicholas Bellinger 			cmd->init_task_tag);
1455e48354ceSNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1456e48354ceSNicholas Bellinger 	}
1457e48354ceSNicholas Bellinger 
1458e48354ceSNicholas Bellinger 	if (cmd->data_direction != DMA_TO_DEVICE) {
1459e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x received DataOUT for a"
1460e48354ceSNicholas Bellinger 			" NON-WRITE command.\n", cmd->init_task_tag);
146197c99b47SNicholas Bellinger 		return iscsit_dump_data_payload(conn, payload_length, 1);
1462e48354ceSNicholas Bellinger 	}
1463e48354ceSNicholas Bellinger 	se_cmd = &cmd->se_cmd;
1464e48354ceSNicholas Bellinger 	iscsit_mod_dataout_timer(cmd);
1465e48354ceSNicholas Bellinger 
146650e5c87dSChristoph Hellwig 	if ((be32_to_cpu(hdr->offset) + payload_length) > cmd->se_cmd.data_length) {
1467de3493aeSBart Van Assche 		pr_err("DataOut Offset: %u, Length %u greater than iSCSI Command EDTL %u, protocol error.\n",
1468de3493aeSBart Van Assche 		       be32_to_cpu(hdr->offset), payload_length,
1469de3493aeSBart Van Assche 		       cmd->se_cmd.data_length);
1470ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf);
1471e48354ceSNicholas Bellinger 	}
1472e48354ceSNicholas Bellinger 
1473e48354ceSNicholas Bellinger 	if (cmd->unsolicited_data) {
1474e48354ceSNicholas Bellinger 		int dump_unsolicited_data = 0;
1475e48354ceSNicholas Bellinger 
1476e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->InitialR2T) {
1477e48354ceSNicholas Bellinger 			pr_err("Received unexpected unsolicited data"
1478e48354ceSNicholas Bellinger 				" while InitialR2T=Yes, protocol error.\n");
1479e48354ceSNicholas Bellinger 			transport_send_check_condition_and_sense(&cmd->se_cmd,
1480e48354ceSNicholas Bellinger 					TCM_UNEXPECTED_UNSOLICITED_DATA, 0);
1481e48354ceSNicholas Bellinger 			return -1;
1482e48354ceSNicholas Bellinger 		}
1483e48354ceSNicholas Bellinger 		/*
1484e48354ceSNicholas Bellinger 		 * Special case for dealing with Unsolicited DataOUT
1485e48354ceSNicholas Bellinger 		 * and Unsupported SAM WRITE Opcodes and SE resource allocation
1486e48354ceSNicholas Bellinger 		 * failures;
1487e48354ceSNicholas Bellinger 		 */
1488e48354ceSNicholas Bellinger 
1489e48354ceSNicholas Bellinger 		/* Something's amiss if we're not in WRITE_PENDING state... */
1490e48354ceSNicholas Bellinger 		WARN_ON(se_cmd->t_state != TRANSPORT_WRITE_PENDING);
1491de103c93SChristoph Hellwig 		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE))
1492e48354ceSNicholas Bellinger 			dump_unsolicited_data = 1;
1493e48354ceSNicholas Bellinger 
1494e48354ceSNicholas Bellinger 		if (dump_unsolicited_data) {
1495e48354ceSNicholas Bellinger 			/*
1496e48354ceSNicholas Bellinger 			 * Check if a delayed TASK_ABORTED status needs to
1497e48354ceSNicholas Bellinger 			 * be sent now if the ISCSI_FLAG_CMD_FINAL has been
14985a342521SBart Van Assche 			 * received with the unsolicited data out.
1499e48354ceSNicholas Bellinger 			 */
1500e48354ceSNicholas Bellinger 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
1501e48354ceSNicholas Bellinger 				iscsit_stop_dataout_timer(cmd);
1502e48354ceSNicholas Bellinger 
1503e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1504e48354ceSNicholas Bellinger 		}
1505e48354ceSNicholas Bellinger 	} else {
1506e48354ceSNicholas Bellinger 		/*
1507e48354ceSNicholas Bellinger 		 * For the normal solicited data path:
1508e48354ceSNicholas Bellinger 		 *
1509e48354ceSNicholas Bellinger 		 * Check for a delayed TASK_ABORTED status and dump any
1510e48354ceSNicholas Bellinger 		 * incoming data out payload if one exists.  Also, when the
1511e48354ceSNicholas Bellinger 		 * ISCSI_FLAG_CMD_FINAL is set to denote the end of the current
1512e48354ceSNicholas Bellinger 		 * data out sequence, we decrement outstanding_r2ts.  Once
1513e48354ceSNicholas Bellinger 		 * outstanding_r2ts reaches zero, go ahead and send the delayed
1514e48354ceSNicholas Bellinger 		 * TASK_ABORTED status.
1515e48354ceSNicholas Bellinger 		 */
15167d680f3bSChristoph Hellwig 		if (se_cmd->transport_state & CMD_T_ABORTED) {
1517aaa00cc9SBart Van Assche 			if (hdr->flags & ISCSI_FLAG_CMD_FINAL &&
1518aaa00cc9SBart Van Assche 			    --cmd->outstanding_r2ts < 1)
1519e48354ceSNicholas Bellinger 				iscsit_stop_dataout_timer(cmd);
1520e48354ceSNicholas Bellinger 
1521e48354ceSNicholas Bellinger 			return iscsit_dump_data_payload(conn, payload_length, 1);
1522e48354ceSNicholas Bellinger 		}
1523e48354ceSNicholas Bellinger 	}
1524e48354ceSNicholas Bellinger 	/*
15250d5efb8aSBart Van Assche 	 * Perform DataSN, DataSequenceInOrder, DataPDUInOrder, and
1526e48354ceSNicholas Bellinger 	 * within-command recovery checks before receiving the payload.
1527e48354ceSNicholas Bellinger 	 */
15283e1c81a9SNicholas Bellinger 	rc = iscsit_check_pre_dataout(cmd, buf);
15293e1c81a9SNicholas Bellinger 	if (rc == DATAOUT_WITHIN_COMMAND_RECOVERY)
1530e48354ceSNicholas Bellinger 		return 0;
15313e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_CANNOT_RECOVER)
1532e48354ceSNicholas Bellinger 		return -1;
15339a584bf9SVarun Prakash 	*success = true;
15343e1c81a9SNicholas Bellinger 	return 0;
15353e1c81a9SNicholas Bellinger }
15369a584bf9SVarun Prakash EXPORT_SYMBOL(__iscsit_check_dataout_hdr);
15379a584bf9SVarun Prakash 
15389a584bf9SVarun Prakash int
15399a584bf9SVarun Prakash iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
15409a584bf9SVarun Prakash 			 struct iscsi_cmd **out_cmd)
15419a584bf9SVarun Prakash {
15429a584bf9SVarun Prakash 	struct iscsi_data *hdr = buf;
15439a584bf9SVarun Prakash 	struct iscsi_cmd *cmd;
15449a584bf9SVarun Prakash 	u32 payload_length = ntoh24(hdr->dlength);
15459a584bf9SVarun Prakash 	int rc;
15469a584bf9SVarun Prakash 	bool success = false;
15479a584bf9SVarun Prakash 
15489a584bf9SVarun Prakash 	if (!payload_length) {
15499a584bf9SVarun Prakash 		pr_warn_ratelimited("DataOUT payload is ZERO, ignoring.\n");
15509a584bf9SVarun Prakash 		return 0;
15519a584bf9SVarun Prakash 	}
15529a584bf9SVarun Prakash 
15539a584bf9SVarun Prakash 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
15549a584bf9SVarun Prakash 		pr_err_ratelimited("DataSegmentLength: %u is greater than"
15559a584bf9SVarun Prakash 			" MaxXmitDataSegmentLength: %u\n", payload_length,
15569a584bf9SVarun Prakash 			conn->conn_ops->MaxXmitDataSegmentLength);
15579a584bf9SVarun Prakash 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf);
15589a584bf9SVarun Prakash 	}
15599a584bf9SVarun Prakash 
15609a584bf9SVarun Prakash 	cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, payload_length);
15619a584bf9SVarun Prakash 	if (!cmd)
15629a584bf9SVarun Prakash 		return 0;
15639a584bf9SVarun Prakash 
15649a584bf9SVarun Prakash 	rc = __iscsit_check_dataout_hdr(conn, buf, cmd, payload_length, &success);
15659a584bf9SVarun Prakash 
15669a584bf9SVarun Prakash 	if (success)
15679a584bf9SVarun Prakash 		*out_cmd = cmd;
15689a584bf9SVarun Prakash 
15699a584bf9SVarun Prakash 	return rc;
15709a584bf9SVarun Prakash }
15713e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_hdr);
15723e1c81a9SNicholas Bellinger 
15733e1c81a9SNicholas Bellinger static int
15743e1c81a9SNicholas Bellinger iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
15753e1c81a9SNicholas Bellinger 		   struct iscsi_data *hdr)
15763e1c81a9SNicholas Bellinger {
15773e1c81a9SNicholas Bellinger 	struct kvec *iov;
15783e1c81a9SNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0;
15790ca650c1SBart Van Assche 	u32 payload_length;
15803e1c81a9SNicholas Bellinger 	int iov_ret, data_crc_failed = 0;
15813e1c81a9SNicholas Bellinger 
15820ca650c1SBart Van Assche 	payload_length = min_t(u32, cmd->se_cmd.data_length,
15830ca650c1SBart Van Assche 			       ntoh24(hdr->dlength));
1584e48354ceSNicholas Bellinger 	rx_size += payload_length;
1585e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
1586e48354ceSNicholas Bellinger 
15872e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, iov, cmd->orig_iov_data_count - 2,
15882e39f1c9SBart Van Assche 				   be32_to_cpu(hdr->offset), payload_length);
1589e48354ceSNicholas Bellinger 	if (iov_ret < 0)
1590e48354ceSNicholas Bellinger 		return -1;
1591e48354ceSNicholas Bellinger 
1592e48354ceSNicholas Bellinger 	iov_count += iov_ret;
1593e48354ceSNicholas Bellinger 
1594e48354ceSNicholas Bellinger 	padding = ((-payload_length) & 3);
1595e48354ceSNicholas Bellinger 	if (padding != 0) {
1596e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
1597e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
1598e48354ceSNicholas Bellinger 		rx_size += padding;
1599e48354ceSNicholas Bellinger 		pr_debug("Receiving %u padding bytes.\n", padding);
1600e48354ceSNicholas Bellinger 	}
1601e48354ceSNicholas Bellinger 
1602e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1603e48354ceSNicholas Bellinger 		iov[iov_count].iov_base = &checksum;
1604e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
1605e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
1606e48354ceSNicholas Bellinger 	}
1607e48354ceSNicholas Bellinger 
16082e39f1c9SBart Van Assche 	WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count);
1609e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
1610e48354ceSNicholas Bellinger 
1611e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
1612e48354ceSNicholas Bellinger 
1613e48354ceSNicholas Bellinger 	if (rx_got != rx_size)
1614e48354ceSNicholas Bellinger 		return -1;
1615e48354ceSNicholas Bellinger 
1616e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
1617e48354ceSNicholas Bellinger 		u32 data_crc;
1618e48354ceSNicholas Bellinger 
161969110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
162050e5c87dSChristoph Hellwig 						    be32_to_cpu(hdr->offset),
162150e5c87dSChristoph Hellwig 						    payload_length, padding,
1622e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
1623e48354ceSNicholas Bellinger 
1624e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
1625e48354ceSNicholas Bellinger 			pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
1626e48354ceSNicholas Bellinger 				" DataSN: 0x%08x, CRC32C DataDigest 0x%08x"
1627e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n",
1628e48354ceSNicholas Bellinger 				hdr->itt, hdr->offset, payload_length,
1629e48354ceSNicholas Bellinger 				hdr->datasn, checksum, data_crc);
1630e48354ceSNicholas Bellinger 			data_crc_failed = 1;
1631e48354ceSNicholas Bellinger 		} else {
1632e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
1633e48354ceSNicholas Bellinger 				" %u bytes of Data Out\n", checksum,
1634e48354ceSNicholas Bellinger 				payload_length);
1635e48354ceSNicholas Bellinger 		}
1636e48354ceSNicholas Bellinger 	}
16373e1c81a9SNicholas Bellinger 
16383e1c81a9SNicholas Bellinger 	return data_crc_failed;
16393e1c81a9SNicholas Bellinger }
16403e1c81a9SNicholas Bellinger 
16413e1c81a9SNicholas Bellinger int
16423e1c81a9SNicholas Bellinger iscsit_check_dataout_payload(struct iscsi_cmd *cmd, struct iscsi_data *hdr,
16433e1c81a9SNicholas Bellinger 			     bool data_crc_failed)
16443e1c81a9SNicholas Bellinger {
16453e1c81a9SNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
16463e1c81a9SNicholas Bellinger 	int rc, ooo_cmdsn;
1647e48354ceSNicholas Bellinger 	/*
1648e48354ceSNicholas Bellinger 	 * Increment post receive data and CRC values or perform
1649e48354ceSNicholas Bellinger 	 * within-command recovery.
1650e48354ceSNicholas Bellinger 	 */
16513e1c81a9SNicholas Bellinger 	rc = iscsit_check_post_dataout(cmd, (unsigned char *)hdr, data_crc_failed);
16523e1c81a9SNicholas Bellinger 	if ((rc == DATAOUT_NORMAL) || (rc == DATAOUT_WITHIN_COMMAND_RECOVERY))
1653e48354ceSNicholas Bellinger 		return 0;
16543e1c81a9SNicholas Bellinger 	else if (rc == DATAOUT_SEND_R2T) {
1655e48354ceSNicholas Bellinger 		iscsit_set_dataout_sequence_values(cmd);
16563e1c81a9SNicholas Bellinger 		conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
16573e1c81a9SNicholas Bellinger 	} else if (rc == DATAOUT_SEND_TO_TRANSPORT) {
1658e48354ceSNicholas Bellinger 		/*
1659e48354ceSNicholas Bellinger 		 * Handle extra special case for out of order
1660e48354ceSNicholas Bellinger 		 * Unsolicited Data Out.
1661e48354ceSNicholas Bellinger 		 */
1662e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
1663e48354ceSNicholas Bellinger 		ooo_cmdsn = (cmd->cmd_flags & ICF_OOO_CMDSN);
1664e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
1665e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
1666e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
1667e48354ceSNicholas Bellinger 
1668e48354ceSNicholas Bellinger 		iscsit_stop_dataout_timer(cmd);
166967441b68SChristoph Hellwig 		if (ooo_cmdsn)
167067441b68SChristoph Hellwig 			return 0;
167167441b68SChristoph Hellwig 		target_execute_cmd(&cmd->se_cmd);
167267441b68SChristoph Hellwig 		return 0;
1673e48354ceSNicholas Bellinger 	} else /* DATAOUT_CANNOT_RECOVER */
1674e48354ceSNicholas Bellinger 		return -1;
1675e48354ceSNicholas Bellinger 
1676e48354ceSNicholas Bellinger 	return 0;
1677e48354ceSNicholas Bellinger }
16783e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_check_dataout_payload);
1679e48354ceSNicholas Bellinger 
16803e1c81a9SNicholas Bellinger static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
16813e1c81a9SNicholas Bellinger {
1682dbcbc95cSNicholas Bellinger 	struct iscsi_cmd *cmd = NULL;
16833e1c81a9SNicholas Bellinger 	struct iscsi_data *hdr = (struct iscsi_data *)buf;
16843e1c81a9SNicholas Bellinger 	int rc;
16853e1c81a9SNicholas Bellinger 	bool data_crc_failed = false;
16863e1c81a9SNicholas Bellinger 
16873e1c81a9SNicholas Bellinger 	rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
16883e1c81a9SNicholas Bellinger 	if (rc < 0)
1689561bf158SNicholas Bellinger 		return 0;
16903e1c81a9SNicholas Bellinger 	else if (!cmd)
16913e1c81a9SNicholas Bellinger 		return 0;
16923e1c81a9SNicholas Bellinger 
16933e1c81a9SNicholas Bellinger 	rc = iscsit_get_dataout(conn, cmd, hdr);
16943e1c81a9SNicholas Bellinger 	if (rc < 0)
16953e1c81a9SNicholas Bellinger 		return rc;
16963e1c81a9SNicholas Bellinger 	else if (rc > 0)
16973e1c81a9SNicholas Bellinger 		data_crc_failed = true;
16983e1c81a9SNicholas Bellinger 
16993e1c81a9SNicholas Bellinger 	return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
17003e1c81a9SNicholas Bellinger }
17013e1c81a9SNicholas Bellinger 
1702778de368SNicholas Bellinger int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1703778de368SNicholas Bellinger 			 struct iscsi_nopout *hdr)
1704e48354ceSNicholas Bellinger {
1705778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1706e48354ceSNicholas Bellinger 
1707a3662605SArshad Hussain 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
1708a3662605SArshad Hussain 		pr_err("NopOUT Flag's, Left Most Bit not set, protocol error.\n");
1709a3662605SArshad Hussain 		if (!cmd)
1710a3662605SArshad Hussain 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
1711a3662605SArshad Hussain 						 (unsigned char *)hdr);
1712a3662605SArshad Hussain 
1713a3662605SArshad Hussain 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1714a3662605SArshad Hussain 					 (unsigned char *)hdr);
1715a3662605SArshad Hussain 	}
1716a3662605SArshad Hussain 
171766c7db68SChristoph Hellwig 	if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1718e48354ceSNicholas Bellinger 		pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
1719e48354ceSNicholas Bellinger 			" not set, protocol error.\n");
172028aaa950SNicholas Bellinger 		if (!cmd)
172128aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
172228aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
172328aaa950SNicholas Bellinger 
1724ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1725ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1726e48354ceSNicholas Bellinger 	}
1727e48354ceSNicholas Bellinger 
172821f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
1729e48354ceSNicholas Bellinger 		pr_err("NOPOUT Ping Data DataSegmentLength: %u is"
173021f5aa7eSNicholas Bellinger 			" greater than MaxXmitDataSegmentLength: %u, protocol"
1731e48354ceSNicholas Bellinger 			" error.\n", payload_length,
173221f5aa7eSNicholas Bellinger 			conn->conn_ops->MaxXmitDataSegmentLength);
173328aaa950SNicholas Bellinger 		if (!cmd)
173428aaa950SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
173528aaa950SNicholas Bellinger 						 (unsigned char *)hdr);
173628aaa950SNicholas Bellinger 
1737ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
1738ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
1739e48354ceSNicholas Bellinger 	}
1740e48354ceSNicholas Bellinger 
17413e1c81a9SNicholas Bellinger 	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
1742e48354ceSNicholas Bellinger 		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
174366c7db68SChristoph Hellwig 		hdr->itt == RESERVED_ITT ? "Response" : "Request",
1744e48354ceSNicholas Bellinger 		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
1745e48354ceSNicholas Bellinger 		payload_length);
1746e48354ceSNicholas Bellinger 	/*
1747e48354ceSNicholas Bellinger 	 * This is not a response to a Unsolicited NopIN, which means
1748e48354ceSNicholas Bellinger 	 * it can either be a NOPOUT ping request (with a valid ITT),
1749e48354ceSNicholas Bellinger 	 * or a NOPOUT not requesting a NOPIN (with a reserved ITT).
1750e48354ceSNicholas Bellinger 	 * Either way, make sure we allocate an struct iscsi_cmd, as both
1751e48354ceSNicholas Bellinger 	 * can contain ping data.
1752e48354ceSNicholas Bellinger 	 */
175350e5c87dSChristoph Hellwig 	if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1754e48354ceSNicholas Bellinger 		cmd->iscsi_opcode	= ISCSI_OP_NOOP_OUT;
1755e48354ceSNicholas Bellinger 		cmd->i_state		= ISTATE_SEND_NOPIN;
1756e48354ceSNicholas Bellinger 		cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ?
1757e48354ceSNicholas Bellinger 						1 : 0);
1758e48354ceSNicholas Bellinger 		conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
1759e48354ceSNicholas Bellinger 		cmd->targ_xfer_tag	= 0xFFFFFFFF;
176050e5c87dSChristoph Hellwig 		cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
176150e5c87dSChristoph Hellwig 		cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
1762e48354ceSNicholas Bellinger 		cmd->data_direction	= DMA_NONE;
1763e48354ceSNicholas Bellinger 	}
1764e48354ceSNicholas Bellinger 
1765778de368SNicholas Bellinger 	return 0;
1766778de368SNicholas Bellinger }
1767778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_nop_out);
1768778de368SNicholas Bellinger 
1769778de368SNicholas Bellinger int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1770778de368SNicholas Bellinger 			   struct iscsi_nopout *hdr)
1771778de368SNicholas Bellinger {
1772778de368SNicholas Bellinger 	struct iscsi_cmd *cmd_p = NULL;
1773778de368SNicholas Bellinger 	int cmdsn_ret = 0;
1774778de368SNicholas Bellinger 	/*
1775778de368SNicholas Bellinger 	 * Initiator is expecting a NopIN ping reply..
1776778de368SNicholas Bellinger 	 */
1777778de368SNicholas Bellinger 	if (hdr->itt != RESERVED_ITT) {
17787cbfcc95SNicholas Bellinger 		if (!cmd)
17797cbfcc95SNicholas Bellinger 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
17807cbfcc95SNicholas Bellinger 						(unsigned char *)hdr);
1781778de368SNicholas Bellinger 
1782778de368SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
1783778de368SNicholas Bellinger 		list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1784778de368SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
1785778de368SNicholas Bellinger 
1786778de368SNicholas Bellinger 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1787778de368SNicholas Bellinger 
1788778de368SNicholas Bellinger 		if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1789778de368SNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
1790778de368SNicholas Bellinger 							 cmd->i_state);
1791778de368SNicholas Bellinger 			return 0;
1792778de368SNicholas Bellinger 		}
1793778de368SNicholas Bellinger 
1794561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1795561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
1796778de368SNicholas Bellinger                 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
1797778de368SNicholas Bellinger 			return 0;
1798778de368SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1799ba159914SNicholas Bellinger 			return -1;
1800778de368SNicholas Bellinger 
1801778de368SNicholas Bellinger 		return 0;
1802778de368SNicholas Bellinger 	}
1803778de368SNicholas Bellinger 	/*
1804778de368SNicholas Bellinger 	 * This was a response to a unsolicited NOPIN ping.
1805778de368SNicholas Bellinger 	 */
1806778de368SNicholas Bellinger 	if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
1807778de368SNicholas Bellinger 		cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
1808778de368SNicholas Bellinger 		if (!cmd_p)
1809778de368SNicholas Bellinger 			return -EINVAL;
1810778de368SNicholas Bellinger 
1811778de368SNicholas Bellinger 		iscsit_stop_nopin_response_timer(conn);
1812778de368SNicholas Bellinger 
1813778de368SNicholas Bellinger 		cmd_p->i_state = ISTATE_REMOVE;
1814778de368SNicholas Bellinger 		iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
1815778de368SNicholas Bellinger 
1816778de368SNicholas Bellinger 		iscsit_start_nopin_timer(conn);
1817778de368SNicholas Bellinger 		return 0;
1818778de368SNicholas Bellinger 	}
1819778de368SNicholas Bellinger 	/*
1820778de368SNicholas Bellinger 	 * Otherwise, initiator is not expecting a NOPIN is response.
1821778de368SNicholas Bellinger 	 * Just ignore for now.
1822778de368SNicholas Bellinger 	 */
18231a40f0a3SVarun Prakash 
18241a40f0a3SVarun Prakash 	if (cmd)
18251a40f0a3SVarun Prakash 		iscsit_free_cmd(cmd, false);
18261a40f0a3SVarun Prakash 
1827778de368SNicholas Bellinger         return 0;
1828778de368SNicholas Bellinger }
1829778de368SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_nop_out);
1830778de368SNicholas Bellinger 
1831778de368SNicholas Bellinger static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1832778de368SNicholas Bellinger 				 unsigned char *buf)
1833778de368SNicholas Bellinger {
1834778de368SNicholas Bellinger 	unsigned char *ping_data = NULL;
1835778de368SNicholas Bellinger 	struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
1836778de368SNicholas Bellinger 	struct kvec *iov = NULL;
1837778de368SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
1838778de368SNicholas Bellinger 	int ret;
1839778de368SNicholas Bellinger 
1840778de368SNicholas Bellinger 	ret = iscsit_setup_nop_out(conn, cmd, hdr);
1841778de368SNicholas Bellinger 	if (ret < 0)
1842561bf158SNicholas Bellinger 		return 0;
1843778de368SNicholas Bellinger 	/*
1844778de368SNicholas Bellinger 	 * Handle NOP-OUT payload for traditional iSCSI sockets
1845778de368SNicholas Bellinger 	 */
184650e5c87dSChristoph Hellwig 	if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1847778de368SNicholas Bellinger 		u32 checksum, data_crc, padding = 0;
1848778de368SNicholas Bellinger 		int niov = 0, rx_got, rx_size = payload_length;
1849778de368SNicholas Bellinger 
1850e48354ceSNicholas Bellinger 		ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
1851e48354ceSNicholas Bellinger 		if (!ping_data) {
1852e48354ceSNicholas Bellinger 			ret = -1;
1853e48354ceSNicholas Bellinger 			goto out;
1854e48354ceSNicholas Bellinger 		}
1855e48354ceSNicholas Bellinger 
1856e48354ceSNicholas Bellinger 		iov = &cmd->iov_misc[0];
1857e48354ceSNicholas Bellinger 		iov[niov].iov_base	= ping_data;
1858e48354ceSNicholas Bellinger 		iov[niov++].iov_len	= payload_length;
1859e48354ceSNicholas Bellinger 
1860e48354ceSNicholas Bellinger 		padding = ((-payload_length) & 3);
1861e48354ceSNicholas Bellinger 		if (padding != 0) {
1862e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
1863e48354ceSNicholas Bellinger 				" for padding.\n", padding);
1864e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &cmd->pad_bytes;
1865e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= padding;
1866e48354ceSNicholas Bellinger 			rx_size += padding;
1867e48354ceSNicholas Bellinger 		}
1868e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1869e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
1870e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
1871e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
1872e48354ceSNicholas Bellinger 		}
1873e48354ceSNicholas Bellinger 
18742e39f1c9SBart Van Assche 		WARN_ON_ONCE(niov > ARRAY_SIZE(cmd->iov_misc));
1875e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &cmd->iov_misc[0], niov, rx_size);
1876e48354ceSNicholas Bellinger 		if (rx_got != rx_size) {
1877e48354ceSNicholas Bellinger 			ret = -1;
1878e48354ceSNicholas Bellinger 			goto out;
1879e48354ceSNicholas Bellinger 		}
1880e48354ceSNicholas Bellinger 
1881e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
1882e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data,
1883e1dfb21fSBart Van Assche 						  payload_length, padding,
1884e1dfb21fSBart Van Assche 						  cmd->pad_bytes, &data_crc);
1885e48354ceSNicholas Bellinger 
1886e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
1887e48354ceSNicholas Bellinger 				pr_err("Ping data CRC32C DataDigest"
1888e48354ceSNicholas Bellinger 				" 0x%08x does not match computed 0x%08x\n",
1889e48354ceSNicholas Bellinger 					checksum, data_crc);
1890e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
1891e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
1892e48354ceSNicholas Bellinger 					" NOPOUT Ping DataCRC failure while in"
1893e48354ceSNicholas Bellinger 						" ERL=0.\n");
1894e48354ceSNicholas Bellinger 					ret = -1;
1895e48354ceSNicholas Bellinger 					goto out;
1896e48354ceSNicholas Bellinger 				} else {
1897e48354ceSNicholas Bellinger 					/*
1898e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
1899e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
1900e48354ceSNicholas Bellinger 					 */
1901e48354ceSNicholas Bellinger 					pr_debug("Dropping NOPOUT"
1902e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
1903e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
1904e48354ceSNicholas Bellinger 					ret = 0;
1905e48354ceSNicholas Bellinger 					goto out;
1906e48354ceSNicholas Bellinger 				}
1907e48354ceSNicholas Bellinger 			} else {
1908e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
1909e48354ceSNicholas Bellinger 				" 0x%08x for %u bytes of ping data.\n",
1910e48354ceSNicholas Bellinger 					checksum, payload_length);
1911e48354ceSNicholas Bellinger 			}
1912e48354ceSNicholas Bellinger 		}
1913e48354ceSNicholas Bellinger 
1914e48354ceSNicholas Bellinger 		ping_data[payload_length] = '\0';
1915e48354ceSNicholas Bellinger 		/*
1916e48354ceSNicholas Bellinger 		 * Attach ping data to struct iscsi_cmd->buf_ptr.
1917e48354ceSNicholas Bellinger 		 */
19188359cf43SJörn Engel 		cmd->buf_ptr = ping_data;
1919e48354ceSNicholas Bellinger 		cmd->buf_ptr_size = payload_length;
1920e48354ceSNicholas Bellinger 
1921e48354ceSNicholas Bellinger 		pr_debug("Got %u bytes of NOPOUT ping"
1922e48354ceSNicholas Bellinger 			" data.\n", payload_length);
1923e48354ceSNicholas Bellinger 		pr_debug("Ping Data: \"%s\"\n", ping_data);
1924e48354ceSNicholas Bellinger 	}
1925e48354ceSNicholas Bellinger 
1926778de368SNicholas Bellinger 	return iscsit_process_nop_out(conn, cmd, hdr);
1927e48354ceSNicholas Bellinger out:
1928e48354ceSNicholas Bellinger 	if (cmd)
1929aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
1930778de368SNicholas Bellinger 
1931e48354ceSNicholas Bellinger 	kfree(ping_data);
1932e48354ceSNicholas Bellinger 	return ret;
1933e48354ceSNicholas Bellinger }
1934e48354ceSNicholas Bellinger 
1935e381fe9eSBart Van Assche static enum tcm_tmreq_table iscsit_convert_tmf(u8 iscsi_tmf)
1936e381fe9eSBart Van Assche {
1937e381fe9eSBart Van Assche 	switch (iscsi_tmf) {
1938e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK:
1939e381fe9eSBart Van Assche 		return TMR_ABORT_TASK;
1940e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
1941e381fe9eSBart Van Assche 		return TMR_ABORT_TASK_SET;
1942e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_ACA:
1943e381fe9eSBart Van Assche 		return TMR_CLEAR_ACA;
1944e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
1945e381fe9eSBart Van Assche 		return TMR_CLEAR_TASK_SET;
1946e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
1947e381fe9eSBart Van Assche 		return TMR_LUN_RESET;
1948e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
1949e381fe9eSBart Van Assche 		return TMR_TARGET_WARM_RESET;
1950e381fe9eSBart Van Assche 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
1951e381fe9eSBart Van Assche 		return TMR_TARGET_COLD_RESET;
1952e381fe9eSBart Van Assche 	default:
1953e381fe9eSBart Van Assche 		return TMR_UNKNOWN;
1954e381fe9eSBart Van Assche 	}
1955e381fe9eSBart Van Assche }
1956e381fe9eSBart Van Assche 
19573e1c81a9SNicholas Bellinger int
19583e1c81a9SNicholas Bellinger iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1959e48354ceSNicholas Bellinger 			   unsigned char *buf)
1960e48354ceSNicholas Bellinger {
1961e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr;
1962e48354ceSNicholas Bellinger 	struct iscsi_tmr_req *tmr_req;
1963e48354ceSNicholas Bellinger 	struct iscsi_tm *hdr;
1964186a9647SNicholas Bellinger 	int out_of_order_cmdsn = 0, ret;
196559b6986dSBart Van Assche 	u8 function, tcm_function = TMR_UNKNOWN;
1966e48354ceSNicholas Bellinger 
1967e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_tm *) buf;
1968e48354ceSNicholas Bellinger 	hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
1969e48354ceSNicholas Bellinger 	function = hdr->flags;
1970e48354ceSNicholas Bellinger 
1971e48354ceSNicholas Bellinger 	pr_debug("Got Task Management Request ITT: 0x%08x, CmdSN:"
1972e48354ceSNicholas Bellinger 		" 0x%08x, Function: 0x%02x, RefTaskTag: 0x%08x, RefCmdSN:"
1973e48354ceSNicholas Bellinger 		" 0x%08x, CID: %hu\n", hdr->itt, hdr->cmdsn, function,
1974e48354ceSNicholas Bellinger 		hdr->rtt, hdr->refcmdsn, conn->cid);
1975e48354ceSNicholas Bellinger 
1976e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
1977e48354ceSNicholas Bellinger 	    ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
197866c7db68SChristoph Hellwig 	     hdr->rtt != RESERVED_ITT)) {
1979e48354ceSNicholas Bellinger 		pr_err("RefTaskTag should be set to 0xFFFFFFFF.\n");
198066c7db68SChristoph Hellwig 		hdr->rtt = RESERVED_ITT;
1981e48354ceSNicholas Bellinger 	}
1982e48354ceSNicholas Bellinger 
1983e48354ceSNicholas Bellinger 	if ((function == ISCSI_TM_FUNC_TASK_REASSIGN) &&
1984e48354ceSNicholas Bellinger 			!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1985e48354ceSNicholas Bellinger 		pr_err("Task Management Request TASK_REASSIGN not"
1986e48354ceSNicholas Bellinger 			" issued as immediate command, bad iSCSI Initiator"
1987e48354ceSNicholas Bellinger 				"implementation\n");
1988ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1989ba159914SNicholas Bellinger 					     ISCSI_REASON_PROTOCOL_ERROR, buf);
1990e48354ceSNicholas Bellinger 	}
1991e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
199250e5c87dSChristoph Hellwig 	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
199350e5c87dSChristoph Hellwig 		hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
1994e48354ceSNicholas Bellinger 
1995d28b1169SAndy Grover 	cmd->data_direction = DMA_NONE;
19963829f381SMarkus Elfring 	cmd->tmr_req = kzalloc(sizeof(*cmd->tmr_req), GFP_KERNEL);
1997ae072726SNicholas Bellinger 	if (!cmd->tmr_req) {
1998ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
1999d28b1169SAndy Grover 					     ISCSI_REASON_BOOKMARK_NO_RESOURCES,
2000ba159914SNicholas Bellinger 					     buf);
2001ae072726SNicholas Bellinger 	}
2002ae072726SNicholas Bellinger 
2003ae072726SNicholas Bellinger 	transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
2004ae072726SNicholas Bellinger 			      conn->sess->se_sess, 0, DMA_NONE,
2005ae072726SNicholas Bellinger 			      TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
2006ae072726SNicholas Bellinger 
2007e9d3009cSBart Van Assche 	if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
2008e9d3009cSBart Van Assche 		return iscsit_add_reject_cmd(cmd,
2009e9d3009cSBart Van Assche 				ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
2010d28b1169SAndy Grover 
2011d28b1169SAndy Grover 	/*
2012d28b1169SAndy Grover 	 * TASK_REASSIGN for ERL=2 / connection stays inside of
2013d28b1169SAndy Grover 	 * LIO-Target $FABRIC_MOD
2014d28b1169SAndy Grover 	 */
2015d28b1169SAndy Grover 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
2016e381fe9eSBart Van Assche 		tcm_function = iscsit_convert_tmf(function);
2017e381fe9eSBart Van Assche 		if (tcm_function == TMR_UNKNOWN) {
2018d28b1169SAndy Grover 			pr_err("Unknown iSCSI TMR Function:"
2019d28b1169SAndy Grover 			       " 0x%02x\n", function);
2020ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2021ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2022d28b1169SAndy Grover 		}
202359b6986dSBart Van Assche 	}
202459b6986dSBart Van Assche 	ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function,
202559b6986dSBart Van Assche 				 GFP_KERNEL);
2026d28b1169SAndy Grover 	if (ret < 0)
2027ba159914SNicholas Bellinger 		return iscsit_add_reject_cmd(cmd,
2028ba159914SNicholas Bellinger 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
2029d28b1169SAndy Grover 
2030d28b1169SAndy Grover 	cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
2031d28b1169SAndy Grover 
2032e48354ceSNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_SCSI_TMFUNC;
2033e48354ceSNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TASKMGTRSP;
2034e48354ceSNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2035e48354ceSNicholas Bellinger 	cmd->init_task_tag	= hdr->itt;
2036e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
203750e5c87dSChristoph Hellwig 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
203850e5c87dSChristoph Hellwig 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
2039e48354ceSNicholas Bellinger 	se_tmr			= cmd->se_cmd.se_tmr_req;
2040e48354ceSNicholas Bellinger 	tmr_req			= cmd->tmr_req;
2041e48354ceSNicholas Bellinger 	/*
2042e48354ceSNicholas Bellinger 	 * Locate the struct se_lun for all TMRs not related to ERL=2 TASK_REASSIGN
2043e48354ceSNicholas Bellinger 	 */
2044e48354ceSNicholas Bellinger 	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
20454f26998aSAndy Grover 		ret = transport_lookup_tmr_lun(&cmd->se_cmd,
20464f26998aSAndy Grover 					       scsilun_to_int(&hdr->lun));
2047e48354ceSNicholas Bellinger 		if (ret < 0) {
2048e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_NO_LUN;
2049e48354ceSNicholas Bellinger 			goto attach;
2050e48354ceSNicholas Bellinger 		}
2051e48354ceSNicholas Bellinger 	}
2052e48354ceSNicholas Bellinger 
2053e48354ceSNicholas Bellinger 	switch (function) {
2054e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK:
2055e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_abort_task(cmd, buf);
2056de103c93SChristoph Hellwig 		if (se_tmr->response)
2057e48354ceSNicholas Bellinger 			goto attach;
2058e48354ceSNicholas Bellinger 		break;
2059e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
2060e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_ACA:
2061e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
2062e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
2063e48354ceSNicholas Bellinger 		break;
2064e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
2065e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) {
2066e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2067e48354ceSNicholas Bellinger 			goto attach;
2068e48354ceSNicholas Bellinger 		}
2069e48354ceSNicholas Bellinger 		break;
2070e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
2071e48354ceSNicholas Bellinger 		if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) {
2072e48354ceSNicholas Bellinger 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
2073e48354ceSNicholas Bellinger 			goto attach;
2074e48354ceSNicholas Bellinger 		}
2075e48354ceSNicholas Bellinger 		break;
2076e48354ceSNicholas Bellinger 	case ISCSI_TM_FUNC_TASK_REASSIGN:
2077e48354ceSNicholas Bellinger 		se_tmr->response = iscsit_tmr_task_reassign(cmd, buf);
2078e48354ceSNicholas Bellinger 		/*
2079e48354ceSNicholas Bellinger 		 * Perform sanity checks on the ExpDataSN only if the
2080e48354ceSNicholas Bellinger 		 * TASK_REASSIGN was successful.
2081e48354ceSNicholas Bellinger 		 */
2082de103c93SChristoph Hellwig 		if (se_tmr->response)
2083e48354ceSNicholas Bellinger 			break;
2084e48354ceSNicholas Bellinger 
2085e48354ceSNicholas Bellinger 		if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
2086ba159914SNicholas Bellinger 			return iscsit_add_reject_cmd(cmd,
2087ba159914SNicholas Bellinger 					ISCSI_REASON_BOOKMARK_INVALID, buf);
2088e48354ceSNicholas Bellinger 		break;
2089e48354ceSNicholas Bellinger 	default:
2090e48354ceSNicholas Bellinger 		pr_err("Unknown TMR function: 0x%02x, protocol"
2091e48354ceSNicholas Bellinger 			" error.\n", function);
2092e48354ceSNicholas Bellinger 		se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED;
2093e48354ceSNicholas Bellinger 		goto attach;
2094e48354ceSNicholas Bellinger 	}
2095e48354ceSNicholas Bellinger 
2096e48354ceSNicholas Bellinger 	if ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
2097e48354ceSNicholas Bellinger 	    (se_tmr->response == ISCSI_TMF_RSP_COMPLETE))
2098e48354ceSNicholas Bellinger 		se_tmr->call_transport = 1;
2099e48354ceSNicholas Bellinger attach:
2100e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
21012fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2102e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2103e48354ceSNicholas Bellinger 
2104e48354ceSNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2105561bf158SNicholas Bellinger 		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
21063fc9fb13SNicholas Bellinger 		if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) {
2107e48354ceSNicholas Bellinger 			out_of_order_cmdsn = 1;
21083fc9fb13SNicholas Bellinger 		} else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
21093fc9fb13SNicholas Bellinger 			target_put_sess_cmd(&cmd->se_cmd);
2110e48354ceSNicholas Bellinger 			return 0;
21113fc9fb13SNicholas Bellinger 		} else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
2112ba159914SNicholas Bellinger 			return -1;
2113e48354ceSNicholas Bellinger 		}
21143fc9fb13SNicholas Bellinger 	}
211550e5c87dSChristoph Hellwig 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2116e48354ceSNicholas Bellinger 
21175a4c8666SNicholas Bellinger 	if (out_of_order_cmdsn || !(hdr->opcode & ISCSI_OP_IMMEDIATE))
2118e48354ceSNicholas Bellinger 		return 0;
2119e48354ceSNicholas Bellinger 	/*
2120e48354ceSNicholas Bellinger 	 * Found the referenced task, send to transport for processing.
2121e48354ceSNicholas Bellinger 	 */
2122e48354ceSNicholas Bellinger 	if (se_tmr->call_transport)
2123e48354ceSNicholas Bellinger 		return transport_generic_handle_tmr(&cmd->se_cmd);
2124e48354ceSNicholas Bellinger 
2125e48354ceSNicholas Bellinger 	/*
2126e48354ceSNicholas Bellinger 	 * Could not find the referenced LUN, task, or Task Management
2127e48354ceSNicholas Bellinger 	 * command not authorized or supported.  Change state and
2128e48354ceSNicholas Bellinger 	 * let the tx_thread send the response.
2129e48354ceSNicholas Bellinger 	 *
2130e48354ceSNicholas Bellinger 	 * For connection recovery, this is also the default action for
2131e48354ceSNicholas Bellinger 	 * TMR TASK_REASSIGN.
2132e48354ceSNicholas Bellinger 	 */
2133e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2134ae072726SNicholas Bellinger 	target_put_sess_cmd(&cmd->se_cmd);
2135e48354ceSNicholas Bellinger 	return 0;
2136e48354ceSNicholas Bellinger }
21373e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd);
2138e48354ceSNicholas Bellinger 
2139e48354ceSNicholas Bellinger /* #warning FIXME: Support Text Command parameters besides SendTargets */
214064534aa7SNicholas Bellinger int
214164534aa7SNicholas Bellinger iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
214264534aa7SNicholas Bellinger 		      struct iscsi_text *hdr)
2143e48354ceSNicholas Bellinger {
214464534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
2145e48354ceSNicholas Bellinger 
214621f5aa7eSNicholas Bellinger 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
2147e48354ceSNicholas Bellinger 		pr_err("Unable to accept text parameter length: %u"
214821f5aa7eSNicholas Bellinger 			"greater than MaxXmitDataSegmentLength %u.\n",
214921f5aa7eSNicholas Bellinger 		       payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
2150ba159914SNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2151ba159914SNicholas Bellinger 					 (unsigned char *)hdr);
2152e48354ceSNicholas Bellinger 	}
2153e48354ceSNicholas Bellinger 
2154122f8afcSNicholas Bellinger 	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL) ||
2155122f8afcSNicholas Bellinger 	     (hdr->flags & ISCSI_FLAG_TEXT_CONTINUE)) {
2156122f8afcSNicholas Bellinger 		pr_err("Multi sequence text commands currently not supported\n");
2157122f8afcSNicholas Bellinger 		return iscsit_reject_cmd(cmd, ISCSI_REASON_CMD_NOT_SUPPORTED,
2158122f8afcSNicholas Bellinger 					(unsigned char *)hdr);
2159122f8afcSNicholas Bellinger 	}
2160122f8afcSNicholas Bellinger 
2161e48354ceSNicholas Bellinger 	pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
2162e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
2163e48354ceSNicholas Bellinger 		hdr->exp_statsn, payload_length);
2164e48354ceSNicholas Bellinger 
216564534aa7SNicholas Bellinger 	cmd->iscsi_opcode	= ISCSI_OP_TEXT;
216664534aa7SNicholas Bellinger 	cmd->i_state		= ISTATE_SEND_TEXTRSP;
216764534aa7SNicholas Bellinger 	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
216864534aa7SNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
216964534aa7SNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
217064534aa7SNicholas Bellinger 	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
217164534aa7SNicholas Bellinger 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
217264534aa7SNicholas Bellinger 	cmd->data_direction	= DMA_NONE;
2173ea8dc5b4SVarun Prakash 	kfree(cmd->text_in_ptr);
2174e4f4e801SSagi Grimberg 	cmd->text_in_ptr	= NULL;
217564534aa7SNicholas Bellinger 
217664534aa7SNicholas Bellinger 	return 0;
217764534aa7SNicholas Bellinger }
217864534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_setup_text_cmd);
217964534aa7SNicholas Bellinger 
218064534aa7SNicholas Bellinger int
218164534aa7SNicholas Bellinger iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
218264534aa7SNicholas Bellinger 			struct iscsi_text *hdr)
218364534aa7SNicholas Bellinger {
21849864ca9dSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr;
218564534aa7SNicholas Bellinger 	int cmdsn_ret;
218664534aa7SNicholas Bellinger 
21879864ca9dSNicholas Bellinger 	if (!text_in) {
2188e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
2189e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
21909864ca9dSNicholas Bellinger 			pr_err("Unable to locate text_in buffer for sendtargets"
21919864ca9dSNicholas Bellinger 			       " discovery\n");
21929864ca9dSNicholas Bellinger 			goto reject;
21939864ca9dSNicholas Bellinger 		}
2194e4f4e801SSagi Grimberg 		goto empty_sendtargets;
2195e4f4e801SSagi Grimberg 	}
219695f8f6a9SDavid Disseldorp 	if (strncmp("SendTargets=", text_in, 12) != 0) {
21979864ca9dSNicholas Bellinger 		pr_err("Received Text Data that is not"
21989864ca9dSNicholas Bellinger 			" SendTargets, cannot continue.\n");
21999864ca9dSNicholas Bellinger 		goto reject;
22009864ca9dSNicholas Bellinger 	}
220195f8f6a9SDavid Disseldorp 	/* '=' confirmed in strncmp */
22029864ca9dSNicholas Bellinger 	text_ptr = strchr(text_in, '=');
220395f8f6a9SDavid Disseldorp 	BUG_ON(!text_ptr);
220495f8f6a9SDavid Disseldorp 	if (!strncmp("=All", text_ptr, 5)) {
22058060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_ALL;
22066665889cSNicholas Bellinger 	} else if (!strncmp("=iqn.", text_ptr, 5) ||
22076665889cSNicholas Bellinger 		   !strncmp("=eui.", text_ptr, 5)) {
22088060b8ddSAndy Grover 		cmd->cmd_flags |= ICF_SENDTARGETS_SINGLE;
22099864ca9dSNicholas Bellinger 	} else {
221095f8f6a9SDavid Disseldorp 		pr_err("Unable to locate valid SendTargets%s value\n",
221195f8f6a9SDavid Disseldorp 		       text_ptr);
22129864ca9dSNicholas Bellinger 		goto reject;
22139864ca9dSNicholas Bellinger 	}
22149864ca9dSNicholas Bellinger 
221564534aa7SNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
221664534aa7SNicholas Bellinger 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
221764534aa7SNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
221864534aa7SNicholas Bellinger 
2219e4f4e801SSagi Grimberg empty_sendtargets:
222064534aa7SNicholas Bellinger 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
222164534aa7SNicholas Bellinger 
222264534aa7SNicholas Bellinger 	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2223561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
2224561bf158SNicholas Bellinger 				(unsigned char *)hdr, hdr->cmdsn);
222564534aa7SNicholas Bellinger 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2226ba159914SNicholas Bellinger 			return -1;
2227ba159914SNicholas Bellinger 
222864534aa7SNicholas Bellinger 		return 0;
222964534aa7SNicholas Bellinger 	}
223064534aa7SNicholas Bellinger 
223164534aa7SNicholas Bellinger 	return iscsit_execute_cmd(cmd, 0);
22329864ca9dSNicholas Bellinger 
22339864ca9dSNicholas Bellinger reject:
2234ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
2235ba159914SNicholas Bellinger 				 (unsigned char *)hdr);
223664534aa7SNicholas Bellinger }
223764534aa7SNicholas Bellinger EXPORT_SYMBOL(iscsit_process_text_cmd);
223864534aa7SNicholas Bellinger 
223964534aa7SNicholas Bellinger static int
224064534aa7SNicholas Bellinger iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
224164534aa7SNicholas Bellinger 		       unsigned char *buf)
224264534aa7SNicholas Bellinger {
224364534aa7SNicholas Bellinger 	struct iscsi_text *hdr = (struct iscsi_text *)buf;
224464534aa7SNicholas Bellinger 	char *text_in = NULL;
224564534aa7SNicholas Bellinger 	u32 payload_length = ntoh24(hdr->dlength);
224664534aa7SNicholas Bellinger 	int rx_size, rc;
224764534aa7SNicholas Bellinger 
224864534aa7SNicholas Bellinger 	rc = iscsit_setup_text_cmd(conn, cmd, hdr);
224964534aa7SNicholas Bellinger 	if (rc < 0)
2250561bf158SNicholas Bellinger 		return 0;
225164534aa7SNicholas Bellinger 
225264534aa7SNicholas Bellinger 	rx_size = payload_length;
225364534aa7SNicholas Bellinger 	if (payload_length) {
225464534aa7SNicholas Bellinger 		u32 checksum = 0, data_crc = 0;
225547eefdedSBart Van Assche 		u32 padding = 0;
225664534aa7SNicholas Bellinger 		int niov = 0, rx_got;
225747eefdedSBart Van Assche 		struct kvec iov[2];
225864534aa7SNicholas Bellinger 
225947eefdedSBart Van Assche 		rx_size = ALIGN(payload_length, 4);
226047eefdedSBart Van Assche 		text_in = kzalloc(rx_size, GFP_KERNEL);
2261c46e22f1SMarkus Elfring 		if (!text_in)
226264534aa7SNicholas Bellinger 			goto reject;
2263c46e22f1SMarkus Elfring 
22649864ca9dSNicholas Bellinger 		cmd->text_in_ptr = text_in;
2265e48354ceSNicholas Bellinger 
226647eefdedSBart Van Assche 		memset(iov, 0, sizeof(iov));
2267e48354ceSNicholas Bellinger 		iov[niov].iov_base	= text_in;
226847eefdedSBart Van Assche 		iov[niov++].iov_len	= rx_size;
2269e48354ceSNicholas Bellinger 
227047eefdedSBart Van Assche 		padding = rx_size - payload_length;
227147eefdedSBart Van Assche 		if (padding)
2272e48354ceSNicholas Bellinger 			pr_debug("Receiving %u additional bytes"
2273e48354ceSNicholas Bellinger 					" for padding.\n", padding);
2274e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
2275e48354ceSNicholas Bellinger 			iov[niov].iov_base	= &checksum;
2276e48354ceSNicholas Bellinger 			iov[niov++].iov_len	= ISCSI_CRC_LEN;
2277e48354ceSNicholas Bellinger 			rx_size += ISCSI_CRC_LEN;
2278e48354ceSNicholas Bellinger 		}
2279e48354ceSNicholas Bellinger 
22802e39f1c9SBart Van Assche 		WARN_ON_ONCE(niov > ARRAY_SIZE(iov));
2281e48354ceSNicholas Bellinger 		rx_got = rx_data(conn, &iov[0], niov, rx_size);
228264534aa7SNicholas Bellinger 		if (rx_got != rx_size)
228364534aa7SNicholas Bellinger 			goto reject;
2284e48354ceSNicholas Bellinger 
2285e48354ceSNicholas Bellinger 		if (conn->conn_ops->DataDigest) {
228647eefdedSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash,
228747eefdedSBart Van Assche 						  text_in, rx_size, 0, NULL,
228847eefdedSBart Van Assche 						  &data_crc);
2289e48354ceSNicholas Bellinger 
2290e48354ceSNicholas Bellinger 			if (checksum != data_crc) {
2291e48354ceSNicholas Bellinger 				pr_err("Text data CRC32C DataDigest"
2292e48354ceSNicholas Bellinger 					" 0x%08x does not match computed"
2293e48354ceSNicholas Bellinger 					" 0x%08x\n", checksum, data_crc);
2294e48354ceSNicholas Bellinger 				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2295e48354ceSNicholas Bellinger 					pr_err("Unable to recover from"
2296e48354ceSNicholas Bellinger 					" Text Data digest failure while in"
2297e48354ceSNicholas Bellinger 						" ERL=0.\n");
229864534aa7SNicholas Bellinger 					goto reject;
2299e48354ceSNicholas Bellinger 				} else {
2300e48354ceSNicholas Bellinger 					/*
2301e48354ceSNicholas Bellinger 					 * Silently drop this PDU and let the
2302e48354ceSNicholas Bellinger 					 * initiator plug the CmdSN gap.
2303e48354ceSNicholas Bellinger 					 */
2304e48354ceSNicholas Bellinger 					pr_debug("Dropping Text"
2305e48354ceSNicholas Bellinger 					" Command CmdSN: 0x%08x due to"
2306e48354ceSNicholas Bellinger 					" DataCRC error.\n", hdr->cmdsn);
2307e48354ceSNicholas Bellinger 					kfree(text_in);
2308e48354ceSNicholas Bellinger 					return 0;
2309e48354ceSNicholas Bellinger 				}
2310e48354ceSNicholas Bellinger 			} else {
2311e48354ceSNicholas Bellinger 				pr_debug("Got CRC32C DataDigest"
2312e48354ceSNicholas Bellinger 					" 0x%08x for %u bytes of text data.\n",
231364534aa7SNicholas Bellinger 						checksum, payload_length);
2314e48354ceSNicholas Bellinger 			}
2315e48354ceSNicholas Bellinger 		}
231664534aa7SNicholas Bellinger 		text_in[payload_length - 1] = '\0';
2317e48354ceSNicholas Bellinger 		pr_debug("Successfully read %d bytes of text"
231864534aa7SNicholas Bellinger 				" data.\n", payload_length);
2319e48354ceSNicholas Bellinger 	}
2320e48354ceSNicholas Bellinger 
232164534aa7SNicholas Bellinger 	return iscsit_process_text_cmd(conn, cmd, hdr);
2322e48354ceSNicholas Bellinger 
232364534aa7SNicholas Bellinger reject:
23249864ca9dSNicholas Bellinger 	kfree(cmd->text_in_ptr);
23259864ca9dSNicholas Bellinger 	cmd->text_in_ptr = NULL;
2326ba159914SNicholas Bellinger 	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
2327e48354ceSNicholas Bellinger }
2328e48354ceSNicholas Bellinger 
2329e48354ceSNicholas Bellinger int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2330e48354ceSNicholas Bellinger {
2331e48354ceSNicholas Bellinger 	struct iscsi_conn *conn_p;
2332e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2333e48354ceSNicholas Bellinger 
2334e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSESESSION on CID: %hu"
2335e48354ceSNicholas Bellinger 		" for SID: %u.\n", conn->cid, conn->sess->sid);
2336e48354ceSNicholas Bellinger 
2337e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
2338e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 1);
2339e48354ceSNicholas Bellinger 	conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2340e48354ceSNicholas Bellinger 
2341e48354ceSNicholas Bellinger 	iscsit_inc_conn_usage_count(conn);
2342e48354ceSNicholas Bellinger 	iscsit_inc_session_usage_count(sess);
2343e48354ceSNicholas Bellinger 
2344e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
2345e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &sess->sess_conn_list, conn_list) {
2346e48354ceSNicholas Bellinger 		if (conn_p->conn_state != TARG_CONN_STATE_LOGGED_IN)
2347e48354ceSNicholas Bellinger 			continue;
2348e48354ceSNicholas Bellinger 
2349e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2350e48354ceSNicholas Bellinger 		conn_p->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2351e48354ceSNicholas Bellinger 	}
2352e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
2353e48354ceSNicholas Bellinger 
2354e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2355e48354ceSNicholas Bellinger 
2356e48354ceSNicholas Bellinger 	return 0;
2357e48354ceSNicholas Bellinger }
2358e48354ceSNicholas Bellinger 
2359e48354ceSNicholas Bellinger int iscsit_logout_closeconnection(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2360e48354ceSNicholas Bellinger {
2361e48354ceSNicholas Bellinger 	struct iscsi_conn *l_conn;
2362e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2363e48354ceSNicholas Bellinger 
2364e48354ceSNicholas Bellinger 	pr_debug("Received logout request CLOSECONNECTION for CID:"
2365e48354ceSNicholas Bellinger 		" %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2366e48354ceSNicholas Bellinger 
2367e48354ceSNicholas Bellinger 	/*
2368e48354ceSNicholas Bellinger 	 * A Logout Request with a CLOSECONNECTION reason code for a CID
2369e48354ceSNicholas Bellinger 	 * can arrive on a connection with a differing CID.
2370e48354ceSNicholas Bellinger 	 */
2371e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2372e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
2373e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
2374e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
2375e48354ceSNicholas Bellinger 
2376e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 1);
2377e48354ceSNicholas Bellinger 		conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_CONNECTION;
2378e48354ceSNicholas Bellinger 		iscsit_inc_conn_usage_count(conn);
2379e48354ceSNicholas Bellinger 
2380e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
2381e48354ceSNicholas Bellinger 	} else {
2382e48354ceSNicholas Bellinger 		/*
2383e48354ceSNicholas Bellinger 		 * Handle all different cid CLOSECONNECTION requests in
2384e48354ceSNicholas Bellinger 		 * iscsit_logout_post_handler_diffcid() as to give enough
2385e48354ceSNicholas Bellinger 		 * time for any non immediate command's CmdSN to be
2386e48354ceSNicholas Bellinger 		 * acknowledged on the connection in question.
2387e48354ceSNicholas Bellinger 		 *
2388e48354ceSNicholas Bellinger 		 * Here we simply make sure the CID is still around.
2389e48354ceSNicholas Bellinger 		 */
2390e48354ceSNicholas Bellinger 		l_conn = iscsit_get_conn_from_cid(sess,
2391e48354ceSNicholas Bellinger 				cmd->logout_cid);
2392e48354ceSNicholas Bellinger 		if (!l_conn) {
2393e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2394e48354ceSNicholas Bellinger 			iscsit_add_cmd_to_response_queue(cmd, conn,
2395e48354ceSNicholas Bellinger 					cmd->i_state);
2396e48354ceSNicholas Bellinger 			return 0;
2397e48354ceSNicholas Bellinger 		}
2398e48354ceSNicholas Bellinger 
2399e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(l_conn);
2400e48354ceSNicholas Bellinger 	}
2401e48354ceSNicholas Bellinger 
2402e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2403e48354ceSNicholas Bellinger 
2404e48354ceSNicholas Bellinger 	return 0;
2405e48354ceSNicholas Bellinger }
2406e48354ceSNicholas Bellinger 
2407e48354ceSNicholas Bellinger int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
2408e48354ceSNicholas Bellinger {
2409e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2410e48354ceSNicholas Bellinger 
2411e48354ceSNicholas Bellinger 	pr_debug("Received explicit REMOVECONNFORRECOVERY logout for"
2412e48354ceSNicholas Bellinger 		" CID: %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
2413e48354ceSNicholas Bellinger 
2414e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel != 2) {
2415e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2416e48354ceSNicholas Bellinger 			" while ERL!=2.\n");
2417e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED;
2418e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2419e48354ceSNicholas Bellinger 		return 0;
2420e48354ceSNicholas Bellinger 	}
2421e48354ceSNicholas Bellinger 
2422e48354ceSNicholas Bellinger 	if (conn->cid == cmd->logout_cid) {
2423e48354ceSNicholas Bellinger 		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
2424e48354ceSNicholas Bellinger 			" with CID: %hu on CID: %hu, implementation error.\n",
2425e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2426e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_CLEANUP_FAILED;
2427e48354ceSNicholas Bellinger 		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2428e48354ceSNicholas Bellinger 		return 0;
2429e48354ceSNicholas Bellinger 	}
2430e48354ceSNicholas Bellinger 
2431e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
2432e48354ceSNicholas Bellinger 
2433e48354ceSNicholas Bellinger 	return 0;
2434e48354ceSNicholas Bellinger }
2435e48354ceSNicholas Bellinger 
24363e1c81a9SNicholas Bellinger int
24373e1c81a9SNicholas Bellinger iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2438e48354ceSNicholas Bellinger 			unsigned char *buf)
2439e48354ceSNicholas Bellinger {
2440e48354ceSNicholas Bellinger 	int cmdsn_ret, logout_remove = 0;
2441e48354ceSNicholas Bellinger 	u8 reason_code = 0;
2442e48354ceSNicholas Bellinger 	struct iscsi_logout *hdr;
2443e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn);
2444e48354ceSNicholas Bellinger 
2445e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_logout *) buf;
2446e48354ceSNicholas Bellinger 	reason_code		= (hdr->flags & 0x7f);
2447e48354ceSNicholas Bellinger 
2448e48354ceSNicholas Bellinger 	if (tiqn) {
2449e48354ceSNicholas Bellinger 		spin_lock(&tiqn->logout_stats.lock);
2450e48354ceSNicholas Bellinger 		if (reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION)
2451e48354ceSNicholas Bellinger 			tiqn->logout_stats.normal_logouts++;
2452e48354ceSNicholas Bellinger 		else
2453e48354ceSNicholas Bellinger 			tiqn->logout_stats.abnormal_logouts++;
2454e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->logout_stats.lock);
2455e48354ceSNicholas Bellinger 	}
2456e48354ceSNicholas Bellinger 
2457e48354ceSNicholas Bellinger 	pr_debug("Got Logout Request ITT: 0x%08x CmdSN: 0x%08x"
2458e48354ceSNicholas Bellinger 		" ExpStatSN: 0x%08x Reason: 0x%02x CID: %hu on CID: %hu\n",
2459e48354ceSNicholas Bellinger 		hdr->itt, hdr->cmdsn, hdr->exp_statsn, reason_code,
2460e48354ceSNicholas Bellinger 		hdr->cid, conn->cid);
2461e48354ceSNicholas Bellinger 
2462e48354ceSNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
2463e48354ceSNicholas Bellinger 		pr_err("Received logout request on connection that"
2464e48354ceSNicholas Bellinger 			" is not in logged in state, ignoring request.\n");
2465aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
2466e48354ceSNicholas Bellinger 		return 0;
2467e48354ceSNicholas Bellinger 	}
2468e48354ceSNicholas Bellinger 
2469e48354ceSNicholas Bellinger 	cmd->iscsi_opcode       = ISCSI_OP_LOGOUT;
2470e48354ceSNicholas Bellinger 	cmd->i_state            = ISTATE_SEND_LOGOUTRSP;
2471e48354ceSNicholas Bellinger 	cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
2472e48354ceSNicholas Bellinger 	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
2473e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag      = 0xFFFFFFFF;
247450e5c87dSChristoph Hellwig 	cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
247550e5c87dSChristoph Hellwig 	cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
247650e5c87dSChristoph Hellwig 	cmd->logout_cid         = be16_to_cpu(hdr->cid);
2477e48354ceSNicholas Bellinger 	cmd->logout_reason      = reason_code;
2478e48354ceSNicholas Bellinger 	cmd->data_direction     = DMA_NONE;
2479e48354ceSNicholas Bellinger 
2480e48354ceSNicholas Bellinger 	/*
2481e48354ceSNicholas Bellinger 	 * We need to sleep in these cases (by returning 1) until the Logout
2482e48354ceSNicholas Bellinger 	 * Response gets sent in the tx thread.
2483e48354ceSNicholas Bellinger 	 */
2484e48354ceSNicholas Bellinger 	if ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION) ||
2485e48354ceSNicholas Bellinger 	   ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) &&
248650e5c87dSChristoph Hellwig 	    be16_to_cpu(hdr->cid) == conn->cid))
2487e48354ceSNicholas Bellinger 		logout_remove = 1;
2488e48354ceSNicholas Bellinger 
2489e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
24902fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2491e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
2492e48354ceSNicholas Bellinger 
2493e48354ceSNicholas Bellinger 	if (reason_code != ISCSI_LOGOUT_REASON_RECOVERY)
249450e5c87dSChristoph Hellwig 		iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2495e48354ceSNicholas Bellinger 
2496e48354ceSNicholas Bellinger 	/*
2497e48354ceSNicholas Bellinger 	 * Immediate commands are executed, well, immediately.
2498e48354ceSNicholas Bellinger 	 * Non-Immediate Logout Commands are executed in CmdSN order.
2499e48354ceSNicholas Bellinger 	 */
2500c6037cc5SAndy Grover 	if (cmd->immediate_cmd) {
2501e48354ceSNicholas Bellinger 		int ret = iscsit_execute_cmd(cmd, 0);
2502e48354ceSNicholas Bellinger 
2503e48354ceSNicholas Bellinger 		if (ret < 0)
2504e48354ceSNicholas Bellinger 			return ret;
2505e48354ceSNicholas Bellinger 	} else {
2506561bf158SNicholas Bellinger 		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
2507ba159914SNicholas Bellinger 		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
2508e48354ceSNicholas Bellinger 			logout_remove = 0;
2509ba159914SNicholas Bellinger 		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2510ba159914SNicholas Bellinger 			return -1;
2511e48354ceSNicholas Bellinger 	}
2512e48354ceSNicholas Bellinger 
2513e48354ceSNicholas Bellinger 	return logout_remove;
2514e48354ceSNicholas Bellinger }
25153e1c81a9SNicholas Bellinger EXPORT_SYMBOL(iscsit_handle_logout_cmd);
2516e48354ceSNicholas Bellinger 
2517d2faaefbSVarun Prakash int iscsit_handle_snack(
2518e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
2519e48354ceSNicholas Bellinger 	unsigned char *buf)
2520e48354ceSNicholas Bellinger {
2521e48354ceSNicholas Bellinger 	struct iscsi_snack *hdr;
2522e48354ceSNicholas Bellinger 
2523e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_snack *) buf;
2524e48354ceSNicholas Bellinger 	hdr->flags		&= ~ISCSI_FLAG_CMD_FINAL;
2525e48354ceSNicholas Bellinger 
2526e48354ceSNicholas Bellinger 	pr_debug("Got ISCSI_INIT_SNACK, ITT: 0x%08x, ExpStatSN:"
2527e48354ceSNicholas Bellinger 		" 0x%08x, Type: 0x%02x, BegRun: 0x%08x, RunLength: 0x%08x,"
2528e48354ceSNicholas Bellinger 		" CID: %hu\n", hdr->itt, hdr->exp_statsn, hdr->flags,
2529e48354ceSNicholas Bellinger 			hdr->begrun, hdr->runlength, conn->cid);
2530e48354ceSNicholas Bellinger 
2531e48354ceSNicholas Bellinger 	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2532e48354ceSNicholas Bellinger 		pr_err("Initiator sent SNACK request while in"
2533e48354ceSNicholas Bellinger 			" ErrorRecoveryLevel=0.\n");
2534ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2535ba159914SNicholas Bellinger 					 buf);
2536e48354ceSNicholas Bellinger 	}
2537e48354ceSNicholas Bellinger 	/*
2538e48354ceSNicholas Bellinger 	 * SNACK_DATA and SNACK_R2T are both 0,  so check which function to
2539e48354ceSNicholas Bellinger 	 * call from inside iscsi_send_recovery_datain_or_r2t().
2540e48354ceSNicholas Bellinger 	 */
2541e48354ceSNicholas Bellinger 	switch (hdr->flags & ISCSI_FLAG_SNACK_TYPE_MASK) {
2542e48354ceSNicholas Bellinger 	case 0:
2543e48354ceSNicholas Bellinger 		return iscsit_handle_recovery_datain_or_r2t(conn, buf,
254450e5c87dSChristoph Hellwig 			hdr->itt,
254550e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
254650e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
254750e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2548e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_STATUS:
254950e5c87dSChristoph Hellwig 		return iscsit_handle_status_snack(conn, hdr->itt,
255050e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->ttt),
255150e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun), be32_to_cpu(hdr->runlength));
2552e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_DATA_ACK:
255350e5c87dSChristoph Hellwig 		return iscsit_handle_data_ack(conn, be32_to_cpu(hdr->ttt),
255450e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->begrun),
255550e5c87dSChristoph Hellwig 			be32_to_cpu(hdr->runlength));
2556e48354ceSNicholas Bellinger 	case ISCSI_FLAG_SNACK_TYPE_RDATA:
2557e48354ceSNicholas Bellinger 		/* FIXME: Support R-Data SNACK */
2558e48354ceSNicholas Bellinger 		pr_err("R-Data SNACK Not Supported.\n");
2559ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2560ba159914SNicholas Bellinger 					 buf);
2561e48354ceSNicholas Bellinger 	default:
2562e48354ceSNicholas Bellinger 		pr_err("Unknown SNACK type 0x%02x, protocol"
2563e48354ceSNicholas Bellinger 			" error.\n", hdr->flags & 0x0f);
2564ba159914SNicholas Bellinger 		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
2565ba159914SNicholas Bellinger 					 buf);
2566e48354ceSNicholas Bellinger 	}
2567e48354ceSNicholas Bellinger 
2568e48354ceSNicholas Bellinger 	return 0;
2569e48354ceSNicholas Bellinger }
2570d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_handle_snack);
2571e48354ceSNicholas Bellinger 
2572e48354ceSNicholas Bellinger static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn)
2573e48354ceSNicholas Bellinger {
2574e48354ceSNicholas Bellinger 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
2575e48354ceSNicholas Bellinger 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
2576e48354ceSNicholas Bellinger 		wait_for_completion_interruptible_timeout(
2577e48354ceSNicholas Bellinger 					&conn->rx_half_close_comp,
2578e48354ceSNicholas Bellinger 					ISCSI_RX_THREAD_TCP_TIMEOUT * HZ);
2579e48354ceSNicholas Bellinger 	}
2580e48354ceSNicholas Bellinger }
2581e48354ceSNicholas Bellinger 
2582e48354ceSNicholas Bellinger static int iscsit_handle_immediate_data(
2583e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
25843e1c81a9SNicholas Bellinger 	struct iscsi_scsi_req *hdr,
2585e48354ceSNicholas Bellinger 	u32 length)
2586e48354ceSNicholas Bellinger {
2587e48354ceSNicholas Bellinger 	int iov_ret, rx_got = 0, rx_size = 0;
2588e48354ceSNicholas Bellinger 	u32 checksum, iov_count = 0, padding = 0;
2589e48354ceSNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
2590e48354ceSNicholas Bellinger 	struct kvec *iov;
25910ca650c1SBart Van Assche 	void *overflow_buf = NULL;
2592e48354ceSNicholas Bellinger 
25930ca650c1SBart Van Assche 	BUG_ON(cmd->write_data_done > cmd->se_cmd.data_length);
25940ca650c1SBart Van Assche 	rx_size = min(cmd->se_cmd.data_length - cmd->write_data_done, length);
25952e39f1c9SBart Van Assche 	iov_ret = iscsit_map_iovec(cmd, cmd->iov_data,
25962e39f1c9SBart Van Assche 				   cmd->orig_iov_data_count - 2,
25972e39f1c9SBart Van Assche 				   cmd->write_data_done, rx_size);
2598e48354ceSNicholas Bellinger 	if (iov_ret < 0)
2599e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2600e48354ceSNicholas Bellinger 
2601e48354ceSNicholas Bellinger 	iov_count = iov_ret;
2602e48354ceSNicholas Bellinger 	iov = &cmd->iov_data[0];
26030ca650c1SBart Van Assche 	if (rx_size < length) {
26040ca650c1SBart Van Assche 		/*
26050ca650c1SBart Van Assche 		 * Special case: length of immediate data exceeds the data
26060ca650c1SBart Van Assche 		 * buffer size derived from the CDB.
26070ca650c1SBart Van Assche 		 */
26080ca650c1SBart Van Assche 		overflow_buf = kmalloc(length - rx_size, GFP_KERNEL);
26090ca650c1SBart Van Assche 		if (!overflow_buf) {
26100ca650c1SBart Van Assche 			iscsit_unmap_iovec(cmd);
26110ca650c1SBart Van Assche 			return IMMEDIATE_DATA_CANNOT_RECOVER;
26120ca650c1SBart Van Assche 		}
26130ca650c1SBart Van Assche 		cmd->overflow_buf = overflow_buf;
26140ca650c1SBart Van Assche 		iov[iov_count].iov_base = overflow_buf;
26150ca650c1SBart Van Assche 		iov[iov_count].iov_len = length - rx_size;
26160ca650c1SBart Van Assche 		iov_count++;
26170ca650c1SBart Van Assche 		rx_size = length;
26180ca650c1SBart Van Assche 	}
2619e48354ceSNicholas Bellinger 
2620e48354ceSNicholas Bellinger 	padding = ((-length) & 3);
2621e48354ceSNicholas Bellinger 	if (padding != 0) {
2622e48354ceSNicholas Bellinger 		iov[iov_count].iov_base	= cmd->pad_bytes;
2623e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len = padding;
2624e48354ceSNicholas Bellinger 		rx_size += padding;
2625e48354ceSNicholas Bellinger 	}
2626e48354ceSNicholas Bellinger 
2627e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2628e48354ceSNicholas Bellinger 		iov[iov_count].iov_base		= &checksum;
2629e48354ceSNicholas Bellinger 		iov[iov_count++].iov_len	= ISCSI_CRC_LEN;
2630e48354ceSNicholas Bellinger 		rx_size += ISCSI_CRC_LEN;
2631e48354ceSNicholas Bellinger 	}
2632e48354ceSNicholas Bellinger 
26332e39f1c9SBart Van Assche 	WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count);
2634e48354ceSNicholas Bellinger 	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
2635e48354ceSNicholas Bellinger 
2636e48354ceSNicholas Bellinger 	iscsit_unmap_iovec(cmd);
2637e48354ceSNicholas Bellinger 
2638e48354ceSNicholas Bellinger 	if (rx_got != rx_size) {
2639e48354ceSNicholas Bellinger 		iscsit_rx_thread_wait_for_tcp(conn);
2640e48354ceSNicholas Bellinger 		return IMMEDIATE_DATA_CANNOT_RECOVER;
2641e48354ceSNicholas Bellinger 	}
2642e48354ceSNicholas Bellinger 
2643e48354ceSNicholas Bellinger 	if (conn->conn_ops->DataDigest) {
2644e48354ceSNicholas Bellinger 		u32 data_crc;
2645e48354ceSNicholas Bellinger 
264669110e3cSHerbert Xu 		data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd,
2647e48354ceSNicholas Bellinger 						    cmd->write_data_done, length, padding,
2648e48354ceSNicholas Bellinger 						    cmd->pad_bytes);
2649e48354ceSNicholas Bellinger 
2650e48354ceSNicholas Bellinger 		if (checksum != data_crc) {
2651e48354ceSNicholas Bellinger 			pr_err("ImmediateData CRC32C DataDigest 0x%08x"
2652e48354ceSNicholas Bellinger 				" does not match computed 0x%08x\n", checksum,
2653e48354ceSNicholas Bellinger 				data_crc);
2654e48354ceSNicholas Bellinger 
2655e48354ceSNicholas Bellinger 			if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
2656e48354ceSNicholas Bellinger 				pr_err("Unable to recover from"
2657e48354ceSNicholas Bellinger 					" Immediate Data digest failure while"
2658e48354ceSNicholas Bellinger 					" in ERL=0.\n");
2659ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2660e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2661ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2662e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_CANNOT_RECOVER;
2663e48354ceSNicholas Bellinger 			} else {
2664ba159914SNicholas Bellinger 				iscsit_reject_cmd(cmd,
2665e48354ceSNicholas Bellinger 						ISCSI_REASON_DATA_DIGEST_ERROR,
2666ba159914SNicholas Bellinger 						(unsigned char *)hdr);
2667e48354ceSNicholas Bellinger 				return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
2668e48354ceSNicholas Bellinger 			}
2669e48354ceSNicholas Bellinger 		} else {
2670e48354ceSNicholas Bellinger 			pr_debug("Got CRC32C DataDigest 0x%08x for"
2671e48354ceSNicholas Bellinger 				" %u bytes of Immediate Data\n", checksum,
2672e48354ceSNicholas Bellinger 				length);
2673e48354ceSNicholas Bellinger 		}
2674e48354ceSNicholas Bellinger 	}
2675e48354ceSNicholas Bellinger 
2676e48354ceSNicholas Bellinger 	cmd->write_data_done += length;
2677e48354ceSNicholas Bellinger 
2678ebf1d95cSAndy Grover 	if (cmd->write_data_done == cmd->se_cmd.data_length) {
2679e48354ceSNicholas Bellinger 		spin_lock_bh(&cmd->istate_lock);
2680e48354ceSNicholas Bellinger 		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
2681e48354ceSNicholas Bellinger 		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
2682e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->istate_lock);
2683e48354ceSNicholas Bellinger 	}
2684e48354ceSNicholas Bellinger 
2685e48354ceSNicholas Bellinger 	return IMMEDIATE_DATA_NORMAL_OPERATION;
2686e48354ceSNicholas Bellinger }
2687e48354ceSNicholas Bellinger 
2688e48354ceSNicholas Bellinger /* #warning iscsi_build_conn_drop_async_message() only sends out on connections
2689e48354ceSNicholas Bellinger 	with active network interface */
2690e48354ceSNicholas Bellinger static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn)
2691e48354ceSNicholas Bellinger {
2692e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
2693e48354ceSNicholas Bellinger 	struct iscsi_conn *conn_p;
2694d444edc6SNicholas Bellinger 	bool found = false;
2695e48354ceSNicholas Bellinger 
2696618baaf7SBart Van Assche 	lockdep_assert_held(&conn->sess->conn_lock);
2697618baaf7SBart Van Assche 
2698e48354ceSNicholas Bellinger 	/*
2699e48354ceSNicholas Bellinger 	 * Only send a Asynchronous Message on connections whos network
2700e48354ceSNicholas Bellinger 	 * interface is still functional.
2701e48354ceSNicholas Bellinger 	 */
2702e48354ceSNicholas Bellinger 	list_for_each_entry(conn_p, &conn->sess->sess_conn_list, conn_list) {
2703e48354ceSNicholas Bellinger 		if (conn_p->conn_state == TARG_CONN_STATE_LOGGED_IN) {
2704e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn_p);
2705d444edc6SNicholas Bellinger 			found = true;
2706e48354ceSNicholas Bellinger 			break;
2707e48354ceSNicholas Bellinger 		}
2708e48354ceSNicholas Bellinger 	}
2709e48354ceSNicholas Bellinger 
2710d444edc6SNicholas Bellinger 	if (!found)
2711e48354ceSNicholas Bellinger 		return;
2712e48354ceSNicholas Bellinger 
2713676687c6SNicholas Bellinger 	cmd = iscsit_allocate_cmd(conn_p, TASK_RUNNING);
2714e48354ceSNicholas Bellinger 	if (!cmd) {
2715e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(conn_p);
2716e48354ceSNicholas Bellinger 		return;
2717e48354ceSNicholas Bellinger 	}
2718e48354ceSNicholas Bellinger 
2719e48354ceSNicholas Bellinger 	cmd->logout_cid = conn->cid;
2720e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2721e48354ceSNicholas Bellinger 	cmd->i_state = ISTATE_SEND_ASYNCMSG;
2722e48354ceSNicholas Bellinger 
2723e48354ceSNicholas Bellinger 	spin_lock_bh(&conn_p->cmd_lock);
27242fbb471eSAndy Grover 	list_add_tail(&cmd->i_conn_node, &conn_p->conn_cmd_list);
2725e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn_p->cmd_lock);
2726e48354ceSNicholas Bellinger 
2727e48354ceSNicholas Bellinger 	iscsit_add_cmd_to_response_queue(cmd, conn_p, cmd->i_state);
2728e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn_p);
2729e48354ceSNicholas Bellinger }
2730e48354ceSNicholas Bellinger 
2731e48354ceSNicholas Bellinger static int iscsit_send_conn_drop_async_message(
2732e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
2733e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
2734e48354ceSNicholas Bellinger {
2735e48354ceSNicholas Bellinger 	struct iscsi_async *hdr;
2736e48354ceSNicholas Bellinger 
2737e48354ceSNicholas Bellinger 	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
2738e48354ceSNicholas Bellinger 
2739e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_async *) cmd->pdu;
2740e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_ASYNC_EVENT;
2741e48354ceSNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
274266c7db68SChristoph Hellwig 	cmd->init_task_tag	= RESERVED_ITT;
2743e48354ceSNicholas Bellinger 	cmd->targ_xfer_tag	= 0xFFFFFFFF;
2744e48354ceSNicholas Bellinger 	put_unaligned_be64(0xFFFFFFFFFFFFFFFFULL, &hdr->rsvd4[0]);
2745e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2746e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2747e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2748109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2749e48354ceSNicholas Bellinger 	hdr->async_event	= ISCSI_ASYNC_MSG_DROPPING_CONNECTION;
2750e48354ceSNicholas Bellinger 	hdr->param1		= cpu_to_be16(cmd->logout_cid);
2751e48354ceSNicholas Bellinger 	hdr->param2		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait);
2752e48354ceSNicholas Bellinger 	hdr->param3		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Retain);
2753e48354ceSNicholas Bellinger 
2754e48354ceSNicholas Bellinger 	pr_debug("Sending Connection Dropped Async Message StatSN:"
2755e48354ceSNicholas Bellinger 		" 0x%08x, for CID: %hu on CID: %hu\n", cmd->stat_sn,
2756e48354ceSNicholas Bellinger 			cmd->logout_cid, conn->cid);
27572854bb23SVarun Prakash 
27582854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
2759e48354ceSNicholas Bellinger }
2760e48354ceSNicholas Bellinger 
27616f3c0e69SAndy Grover static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
27626f3c0e69SAndy Grover {
27636f3c0e69SAndy Grover 	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
27646f3c0e69SAndy Grover 	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
27656f3c0e69SAndy Grover 		wait_for_completion_interruptible_timeout(
27666f3c0e69SAndy Grover 					&conn->tx_half_close_comp,
27676f3c0e69SAndy Grover 					ISCSI_TX_THREAD_TCP_TIMEOUT * HZ);
27686f3c0e69SAndy Grover 	}
27696f3c0e69SAndy Grover }
27706f3c0e69SAndy Grover 
2771d2faaefbSVarun Prakash void
27722ec5a8c1SNicholas Bellinger iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
27732ec5a8c1SNicholas Bellinger 			struct iscsi_datain *datain, struct iscsi_data_rsp *hdr,
27742ec5a8c1SNicholas Bellinger 			bool set_statsn)
2775e48354ceSNicholas Bellinger {
27762ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_DATA_IN;
27772ec5a8c1SNicholas Bellinger 	hdr->flags		= datain->flags;
27782ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
27792ec5a8c1SNicholas Bellinger 		if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
27802ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
27812ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
27822ec5a8c1SNicholas Bellinger 		} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
27832ec5a8c1SNicholas Bellinger 			hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
27842ec5a8c1SNicholas Bellinger 			hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
27852ec5a8c1SNicholas Bellinger 		}
27862ec5a8c1SNicholas Bellinger 	}
27872ec5a8c1SNicholas Bellinger 	hton24(hdr->dlength, datain->length);
27882ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
27892ec5a8c1SNicholas Bellinger 		int_to_scsilun(cmd->se_cmd.orig_fe_lun,
27902ec5a8c1SNicholas Bellinger 				(struct scsi_lun *)&hdr->lun);
27912ec5a8c1SNicholas Bellinger 	else
27922ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
27932ec5a8c1SNicholas Bellinger 
27942ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
27952ec5a8c1SNicholas Bellinger 
27962ec5a8c1SNicholas Bellinger 	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
27972ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
27982ec5a8c1SNicholas Bellinger 	else
27992ec5a8c1SNicholas Bellinger 		hdr->ttt		= cpu_to_be32(0xFFFFFFFF);
28002ec5a8c1SNicholas Bellinger 	if (set_statsn)
28012ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(cmd->stat_sn);
28022ec5a8c1SNicholas Bellinger 	else
28032ec5a8c1SNicholas Bellinger 		hdr->statsn		= cpu_to_be32(0xFFFFFFFF);
28042ec5a8c1SNicholas Bellinger 
28052ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2806109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
28072ec5a8c1SNicholas Bellinger 	hdr->datasn		= cpu_to_be32(datain->data_sn);
28082ec5a8c1SNicholas Bellinger 	hdr->offset		= cpu_to_be32(datain->offset);
28092ec5a8c1SNicholas Bellinger 
28102ec5a8c1SNicholas Bellinger 	pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x,"
28112ec5a8c1SNicholas Bellinger 		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
28122ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
28132ec5a8c1SNicholas Bellinger 		ntohl(hdr->offset), datain->length, conn->cid);
28142ec5a8c1SNicholas Bellinger }
2815d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_datain_pdu);
28162ec5a8c1SNicholas Bellinger 
28172ec5a8c1SNicholas Bellinger static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
28182ec5a8c1SNicholas Bellinger {
28192ec5a8c1SNicholas Bellinger 	struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0];
2820e48354ceSNicholas Bellinger 	struct iscsi_datain datain;
2821e48354ceSNicholas Bellinger 	struct iscsi_datain_req *dr;
28222854bb23SVarun Prakash 	int eodr = 0, ret;
28232ec5a8c1SNicholas Bellinger 	bool set_statsn = false;
2824e48354ceSNicholas Bellinger 
2825e48354ceSNicholas Bellinger 	memset(&datain, 0, sizeof(struct iscsi_datain));
2826e48354ceSNicholas Bellinger 	dr = iscsit_get_datain_values(cmd, &datain);
2827e48354ceSNicholas Bellinger 	if (!dr) {
2828e48354ceSNicholas Bellinger 		pr_err("iscsit_get_datain_values failed for ITT: 0x%08x\n",
2829e48354ceSNicholas Bellinger 				cmd->init_task_tag);
2830e48354ceSNicholas Bellinger 		return -1;
2831e48354ceSNicholas Bellinger 	}
2832e48354ceSNicholas Bellinger 	/*
2833e48354ceSNicholas Bellinger 	 * Be paranoid and double check the logic for now.
2834e48354ceSNicholas Bellinger 	 */
2835ebf1d95cSAndy Grover 	if ((datain.offset + datain.length) > cmd->se_cmd.data_length) {
2836e48354ceSNicholas Bellinger 		pr_err("Command ITT: 0x%08x, datain.offset: %u and"
2837e48354ceSNicholas Bellinger 			" datain.length: %u exceeds cmd->data_length: %u\n",
2838e48354ceSNicholas Bellinger 			cmd->init_task_tag, datain.offset, datain.length,
2839ebf1d95cSAndy Grover 			cmd->se_cmd.data_length);
2840e48354ceSNicholas Bellinger 		return -1;
2841e48354ceSNicholas Bellinger 	}
2842e48354ceSNicholas Bellinger 
284304f3b31bSNicholas Bellinger 	atomic_long_add(datain.length, &conn->sess->tx_data_octets);
2844e48354ceSNicholas Bellinger 	/*
2845e48354ceSNicholas Bellinger 	 * Special case for successfully execution w/ both DATAIN
2846e48354ceSNicholas Bellinger 	 * and Sense Data.
2847e48354ceSNicholas Bellinger 	 */
2848e48354ceSNicholas Bellinger 	if ((datain.flags & ISCSI_FLAG_DATA_STATUS) &&
2849e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
2850e48354ceSNicholas Bellinger 		datain.flags &= ~ISCSI_FLAG_DATA_STATUS;
2851e48354ceSNicholas Bellinger 	else {
2852e48354ceSNicholas Bellinger 		if ((dr->dr_complete == DATAIN_COMPLETE_NORMAL) ||
2853e48354ceSNicholas Bellinger 		    (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
2854e48354ceSNicholas Bellinger 			iscsit_increment_maxcmdsn(cmd, conn->sess);
2855e48354ceSNicholas Bellinger 			cmd->stat_sn = conn->stat_sn++;
28562ec5a8c1SNicholas Bellinger 			set_statsn = true;
2857e48354ceSNicholas Bellinger 		} else if (dr->dr_complete ==
2858e48354ceSNicholas Bellinger 			   DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
28592ec5a8c1SNicholas Bellinger 			set_statsn = true;
2860e48354ceSNicholas Bellinger 	}
2861e48354ceSNicholas Bellinger 
28622ec5a8c1SNicholas Bellinger 	iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
2863e48354ceSNicholas Bellinger 
28642854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, dr, &datain, 0);
28652854bb23SVarun Prakash 	if (ret < 0)
28666f3c0e69SAndy Grover 		return ret;
28676f3c0e69SAndy Grover 
2868e48354ceSNicholas Bellinger 	if (dr->dr_complete) {
28696f3c0e69SAndy Grover 		eodr = (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ?
2870e48354ceSNicholas Bellinger 				2 : 1;
2871e48354ceSNicholas Bellinger 		iscsit_free_datain_req(cmd, dr);
2872e48354ceSNicholas Bellinger 	}
2873e48354ceSNicholas Bellinger 
28746f3c0e69SAndy Grover 	return eodr;
2875e48354ceSNicholas Bellinger }
2876e48354ceSNicholas Bellinger 
28772ec5a8c1SNicholas Bellinger int
28782ec5a8c1SNicholas Bellinger iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
28792ec5a8c1SNicholas Bellinger 			struct iscsi_logout_rsp *hdr)
2880e48354ceSNicholas Bellinger {
2881e48354ceSNicholas Bellinger 	struct iscsi_conn *logout_conn = NULL;
2882e48354ceSNicholas Bellinger 	struct iscsi_conn_recovery *cr = NULL;
2883e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
2884e48354ceSNicholas Bellinger 	/*
2885e48354ceSNicholas Bellinger 	 * The actual shutting down of Sessions and/or Connections
2886e48354ceSNicholas Bellinger 	 * for CLOSESESSION and CLOSECONNECTION Logout Requests
2887e48354ceSNicholas Bellinger 	 * is done in scsi_logout_post_handler().
2888e48354ceSNicholas Bellinger 	 */
2889e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
2890e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
2891e48354ceSNicholas Bellinger 		pr_debug("iSCSI session logout successful, setting"
2892e48354ceSNicholas Bellinger 			" logout response to ISCSI_LOGOUT_SUCCESS.\n");
2893e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2894e48354ceSNicholas Bellinger 		break;
2895e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
2896e48354ceSNicholas Bellinger 		if (cmd->logout_response == ISCSI_LOGOUT_CID_NOT_FOUND)
2897e48354ceSNicholas Bellinger 			break;
2898e48354ceSNicholas Bellinger 		/*
2899e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2900e48354ceSNicholas Bellinger 		 * a matching logout CID -> local CID, the reference
2901e48354ceSNicholas Bellinger 		 * for the local CID will have been incremented in
2902e48354ceSNicholas Bellinger 		 * iscsi_logout_closeconnection().
2903e48354ceSNicholas Bellinger 		 *
2904e48354ceSNicholas Bellinger 		 * For CLOSECONNECTION logout requests carrying
2905e48354ceSNicholas Bellinger 		 * a different CID than the connection it arrived
2906e48354ceSNicholas Bellinger 		 * on, the connection responding to cmd->logout_cid
2907e48354ceSNicholas Bellinger 		 * is stopped in iscsit_logout_post_handler_diffcid().
2908e48354ceSNicholas Bellinger 		 */
2909e48354ceSNicholas Bellinger 
2910e48354ceSNicholas Bellinger 		pr_debug("iSCSI CID: %hu logout on CID: %hu"
2911e48354ceSNicholas Bellinger 			" successful.\n", cmd->logout_cid, conn->cid);
2912e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2913e48354ceSNicholas Bellinger 		break;
2914e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
2915e48354ceSNicholas Bellinger 		if ((cmd->logout_response == ISCSI_LOGOUT_RECOVERY_UNSUPPORTED) ||
2916e48354ceSNicholas Bellinger 		    (cmd->logout_response == ISCSI_LOGOUT_CLEANUP_FAILED))
2917e48354ceSNicholas Bellinger 			break;
2918e48354ceSNicholas Bellinger 		/*
2919e48354ceSNicholas Bellinger 		 * If the connection is still active from our point of view
2920e48354ceSNicholas Bellinger 		 * force connection recovery to occur.
2921e48354ceSNicholas Bellinger 		 */
2922e48354ceSNicholas Bellinger 		logout_conn = iscsit_get_conn_from_cid_rcfr(sess,
2923e48354ceSNicholas Bellinger 				cmd->logout_cid);
2924ee1b1b9cSAndy Grover 		if (logout_conn) {
2925e48354ceSNicholas Bellinger 			iscsit_connection_reinstatement_rcfr(logout_conn);
2926e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(logout_conn);
2927e48354ceSNicholas Bellinger 		}
2928e48354ceSNicholas Bellinger 
2929e48354ceSNicholas Bellinger 		cr = iscsit_get_inactive_connection_recovery_entry(
2930e48354ceSNicholas Bellinger 				conn->sess, cmd->logout_cid);
2931e48354ceSNicholas Bellinger 		if (!cr) {
2932e48354ceSNicholas Bellinger 			pr_err("Unable to locate CID: %hu for"
2933e48354ceSNicholas Bellinger 			" REMOVECONNFORRECOVERY Logout Request.\n",
2934e48354ceSNicholas Bellinger 				cmd->logout_cid);
2935e48354ceSNicholas Bellinger 			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
2936e48354ceSNicholas Bellinger 			break;
2937e48354ceSNicholas Bellinger 		}
2938e48354ceSNicholas Bellinger 
2939e48354ceSNicholas Bellinger 		iscsit_discard_cr_cmds_by_expstatsn(cr, cmd->exp_stat_sn);
2940e48354ceSNicholas Bellinger 
2941e48354ceSNicholas Bellinger 		pr_debug("iSCSI REMOVECONNFORRECOVERY logout"
2942e48354ceSNicholas Bellinger 			" for recovery for CID: %hu on CID: %hu successful.\n",
2943e48354ceSNicholas Bellinger 				cmd->logout_cid, conn->cid);
2944e48354ceSNicholas Bellinger 		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
2945e48354ceSNicholas Bellinger 		break;
2946e48354ceSNicholas Bellinger 	default:
2947e48354ceSNicholas Bellinger 		pr_err("Unknown cmd->logout_reason: 0x%02x\n",
2948e48354ceSNicholas Bellinger 				cmd->logout_reason);
2949e48354ceSNicholas Bellinger 		return -1;
2950e48354ceSNicholas Bellinger 	}
2951e48354ceSNicholas Bellinger 
2952e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_LOGOUT_RSP;
2953e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
2954e48354ceSNicholas Bellinger 	hdr->response		= cmd->logout_response;
295566c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
2956e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
2957e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
2958e48354ceSNicholas Bellinger 
2959e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
2960e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
2961109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
2962e48354ceSNicholas Bellinger 
29632ec5a8c1SNicholas Bellinger 	pr_debug("Built Logout Response ITT: 0x%08x StatSN:"
29642ec5a8c1SNicholas Bellinger 		" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
29652ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response,
29662ec5a8c1SNicholas Bellinger 		cmd->logout_cid, conn->cid);
29672ec5a8c1SNicholas Bellinger 
29682ec5a8c1SNicholas Bellinger 	return 0;
29692ec5a8c1SNicholas Bellinger }
29702ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_logout_rsp);
29712ec5a8c1SNicholas Bellinger 
29722ec5a8c1SNicholas Bellinger static int
29732ec5a8c1SNicholas Bellinger iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
29742ec5a8c1SNicholas Bellinger {
29752854bb23SVarun Prakash 	int rc;
29762ec5a8c1SNicholas Bellinger 
29772ec5a8c1SNicholas Bellinger 	rc = iscsit_build_logout_rsp(cmd, conn,
29782ec5a8c1SNicholas Bellinger 			(struct iscsi_logout_rsp *)&cmd->pdu[0]);
29792ec5a8c1SNicholas Bellinger 	if (rc < 0)
29802ec5a8c1SNicholas Bellinger 		return rc;
29812ec5a8c1SNicholas Bellinger 
29822854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
2983e48354ceSNicholas Bellinger }
2984e48354ceSNicholas Bellinger 
29852ec5a8c1SNicholas Bellinger void
29862ec5a8c1SNicholas Bellinger iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
29872ec5a8c1SNicholas Bellinger 		       struct iscsi_nopin *hdr, bool nopout_response)
29882ec5a8c1SNicholas Bellinger {
29892ec5a8c1SNicholas Bellinger 	hdr->opcode		= ISCSI_OP_NOOP_IN;
29902ec5a8c1SNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
29912ec5a8c1SNicholas Bellinger         hton24(hdr->dlength, cmd->buf_ptr_size);
29922ec5a8c1SNicholas Bellinger 	if (nopout_response)
29932ec5a8c1SNicholas Bellinger 		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
29942ec5a8c1SNicholas Bellinger 	hdr->itt		= cmd->init_task_tag;
29952ec5a8c1SNicholas Bellinger 	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
29962ec5a8c1SNicholas Bellinger 	cmd->stat_sn		= (nopout_response) ? conn->stat_sn++ :
29972ec5a8c1SNicholas Bellinger 				  conn->stat_sn;
29982ec5a8c1SNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
29992ec5a8c1SNicholas Bellinger 
30002ec5a8c1SNicholas Bellinger 	if (nopout_response)
30012ec5a8c1SNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, conn->sess);
30022ec5a8c1SNicholas Bellinger 
30032ec5a8c1SNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3004109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
30052ec5a8c1SNicholas Bellinger 
30062ec5a8c1SNicholas Bellinger 	pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
30072ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Length %u\n", (nopout_response) ?
30083fc6a642SColin Ian King 		"Solicited" : "Unsolicited", cmd->init_task_tag,
30092ec5a8c1SNicholas Bellinger 		cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
30102ec5a8c1SNicholas Bellinger }
30112ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_nopin_rsp);
30122ec5a8c1SNicholas Bellinger 
3013e48354ceSNicholas Bellinger /*
3014e48354ceSNicholas Bellinger  *	Unsolicited NOPIN, either requesting a response or not.
3015e48354ceSNicholas Bellinger  */
3016e48354ceSNicholas Bellinger static int iscsit_send_unsolicited_nopin(
3017e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
3018e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
3019e48354ceSNicholas Bellinger 	int want_response)
3020e48354ceSNicholas Bellinger {
30212ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
30222854bb23SVarun Prakash 	int ret;
3023e48354ceSNicholas Bellinger 
30242ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, false);
3025e48354ceSNicholas Bellinger 
3026e48354ceSNicholas Bellinger 	pr_debug("Sending Unsolicited NOPIN TTT: 0x%08x StatSN:"
3027e48354ceSNicholas Bellinger 		" 0x%08x CID: %hu\n", hdr->ttt, cmd->stat_sn, conn->cid);
3028e48354ceSNicholas Bellinger 
30292854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
30302854bb23SVarun Prakash 	if (ret < 0)
30316f3c0e69SAndy Grover 		return ret;
30326f3c0e69SAndy Grover 
30336f3c0e69SAndy Grover 	spin_lock_bh(&cmd->istate_lock);
30346f3c0e69SAndy Grover 	cmd->i_state = want_response ?
30356f3c0e69SAndy Grover 		ISTATE_SENT_NOPIN_WANT_RESPONSE : ISTATE_SENT_STATUS;
30366f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->istate_lock);
30376f3c0e69SAndy Grover 
3038e48354ceSNicholas Bellinger 	return 0;
3039e48354ceSNicholas Bellinger }
3040e48354ceSNicholas Bellinger 
30412ec5a8c1SNicholas Bellinger static int
30422ec5a8c1SNicholas Bellinger iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
3043e48354ceSNicholas Bellinger {
30442ec5a8c1SNicholas Bellinger 	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
30452ec5a8c1SNicholas Bellinger 
30462ec5a8c1SNicholas Bellinger 	iscsit_build_nopin_rsp(cmd, conn, hdr, true);
3047e48354ceSNicholas Bellinger 
3048e48354ceSNicholas Bellinger 	/*
3049e48354ceSNicholas Bellinger 	 * NOPOUT Ping Data is attached to struct iscsi_cmd->buf_ptr.
3050e48354ceSNicholas Bellinger 	 * NOPOUT DataSegmentLength is at struct iscsi_cmd->buf_ptr_size.
3051e48354ceSNicholas Bellinger 	 */
30522854bb23SVarun Prakash 	pr_debug("Echoing back %u bytes of ping data.\n", cmd->buf_ptr_size);
3053e48354ceSNicholas Bellinger 
30542854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
30552854bb23SVarun Prakash 						     cmd->buf_ptr,
30562854bb23SVarun Prakash 						     cmd->buf_ptr_size);
3057e48354ceSNicholas Bellinger }
3058e48354ceSNicholas Bellinger 
30596f3c0e69SAndy Grover static int iscsit_send_r2t(
3060e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
3061e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
3062e48354ceSNicholas Bellinger {
3063e48354ceSNicholas Bellinger 	struct iscsi_r2t *r2t;
3064e48354ceSNicholas Bellinger 	struct iscsi_r2t_rsp *hdr;
30656f3c0e69SAndy Grover 	int ret;
3066e48354ceSNicholas Bellinger 
3067e48354ceSNicholas Bellinger 	r2t = iscsit_get_r2t_from_list(cmd);
3068e48354ceSNicholas Bellinger 	if (!r2t)
3069e48354ceSNicholas Bellinger 		return -1;
3070e48354ceSNicholas Bellinger 
3071e48354ceSNicholas Bellinger 	hdr			= (struct iscsi_r2t_rsp *) cmd->pdu;
3072e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3073e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_R2T;
3074e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3075e48354ceSNicholas Bellinger 	int_to_scsilun(cmd->se_cmd.orig_fe_lun,
3076e48354ceSNicholas Bellinger 			(struct scsi_lun *)&hdr->lun);
307766c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
30788567270dSVarun Prakash 	if (conn->conn_transport->iscsit_get_r2t_ttt)
30798567270dSVarun Prakash 		conn->conn_transport->iscsit_get_r2t_ttt(conn, cmd, r2t);
30808567270dSVarun Prakash 	else
3081c1e34b64SSagi Grimberg 		r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
3082e48354ceSNicholas Bellinger 	hdr->ttt		= cpu_to_be32(r2t->targ_xfer_tag);
3083e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(conn->stat_sn);
3084e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3085109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3086e48354ceSNicholas Bellinger 	hdr->r2tsn		= cpu_to_be32(r2t->r2t_sn);
3087e48354ceSNicholas Bellinger 	hdr->data_offset	= cpu_to_be32(r2t->offset);
3088e48354ceSNicholas Bellinger 	hdr->data_length	= cpu_to_be32(r2t->xfer_len);
3089e48354ceSNicholas Bellinger 
3090e48354ceSNicholas Bellinger 	pr_debug("Built %sR2T, ITT: 0x%08x, TTT: 0x%08x, StatSN:"
3091e48354ceSNicholas Bellinger 		" 0x%08x, R2TSN: 0x%08x, Offset: %u, DDTL: %u, CID: %hu\n",
3092e48354ceSNicholas Bellinger 		(!r2t->recovery_r2t) ? "" : "Recovery ", cmd->init_task_tag,
3093e48354ceSNicholas Bellinger 		r2t->targ_xfer_tag, ntohl(hdr->statsn), r2t->r2t_sn,
3094e48354ceSNicholas Bellinger 			r2t->offset, r2t->xfer_len, conn->cid);
3095e48354ceSNicholas Bellinger 
3096e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3097e48354ceSNicholas Bellinger 	r2t->sent_r2t = 1;
3098e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3099e48354ceSNicholas Bellinger 
31002854bb23SVarun Prakash 	ret = conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
31016f3c0e69SAndy Grover 	if (ret < 0) {
31026f3c0e69SAndy Grover 		return ret;
31036f3c0e69SAndy Grover 	}
31046f3c0e69SAndy Grover 
31056f3c0e69SAndy Grover 	spin_lock_bh(&cmd->dataout_timeout_lock);
31066f3c0e69SAndy Grover 	iscsit_start_dataout_timer(cmd, conn);
31076f3c0e69SAndy Grover 	spin_unlock_bh(&cmd->dataout_timeout_lock);
31086f3c0e69SAndy Grover 
3109e48354ceSNicholas Bellinger 	return 0;
3110e48354ceSNicholas Bellinger }
3111e48354ceSNicholas Bellinger 
3112e48354ceSNicholas Bellinger /*
31138b1e1244SAndy Grover  *	@recovery: If called from iscsi_task_reassign_complete_write() for
3114e48354ceSNicholas Bellinger  *		connection recovery.
3115e48354ceSNicholas Bellinger  */
3116e48354ceSNicholas Bellinger int iscsit_build_r2ts_for_cmd(
3117e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
31183e1c81a9SNicholas Bellinger 	struct iscsi_cmd *cmd,
31198b1e1244SAndy Grover 	bool recovery)
3120e48354ceSNicholas Bellinger {
3121e48354ceSNicholas Bellinger 	int first_r2t = 1;
3122e48354ceSNicholas Bellinger 	u32 offset = 0, xfer_len = 0;
3123e48354ceSNicholas Bellinger 
3124e48354ceSNicholas Bellinger 	spin_lock_bh(&cmd->r2t_lock);
3125e48354ceSNicholas Bellinger 	if (cmd->cmd_flags & ICF_SENT_LAST_R2T) {
3126e48354ceSNicholas Bellinger 		spin_unlock_bh(&cmd->r2t_lock);
3127e48354ceSNicholas Bellinger 		return 0;
3128e48354ceSNicholas Bellinger 	}
3129e48354ceSNicholas Bellinger 
31308b1e1244SAndy Grover 	if (conn->sess->sess_ops->DataSequenceInOrder &&
31318b1e1244SAndy Grover 	    !recovery)
3132c6037cc5SAndy Grover 		cmd->r2t_offset = max(cmd->r2t_offset, cmd->write_data_done);
3133e48354ceSNicholas Bellinger 
3134e48354ceSNicholas Bellinger 	while (cmd->outstanding_r2ts < conn->sess->sess_ops->MaxOutstandingR2T) {
3135e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->DataSequenceInOrder) {
3136e48354ceSNicholas Bellinger 			offset = cmd->r2t_offset;
3137e48354ceSNicholas Bellinger 
31388b1e1244SAndy Grover 			if (first_r2t && recovery) {
31398b1e1244SAndy Grover 				int new_data_end = offset +
31408b1e1244SAndy Grover 					conn->sess->sess_ops->MaxBurstLength -
31418b1e1244SAndy Grover 					cmd->next_burst_len;
31428b1e1244SAndy Grover 
3143ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3144ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31458b1e1244SAndy Grover 				else
31468b1e1244SAndy Grover 					xfer_len =
31478b1e1244SAndy Grover 						conn->sess->sess_ops->MaxBurstLength -
31488b1e1244SAndy Grover 						cmd->next_burst_len;
3149e48354ceSNicholas Bellinger 			} else {
31508b1e1244SAndy Grover 				int new_data_end = offset +
3151e48354ceSNicholas Bellinger 					conn->sess->sess_ops->MaxBurstLength;
31528b1e1244SAndy Grover 
3153ebf1d95cSAndy Grover 				if (new_data_end > cmd->se_cmd.data_length)
3154ebf1d95cSAndy Grover 					xfer_len = cmd->se_cmd.data_length - offset;
31558b1e1244SAndy Grover 				else
31568b1e1244SAndy Grover 					xfer_len = conn->sess->sess_ops->MaxBurstLength;
3157e48354ceSNicholas Bellinger 			}
315896e8e26dSBart Van Assche 
315996e8e26dSBart Van Assche 			if ((s32)xfer_len < 0) {
316096e8e26dSBart Van Assche 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
316196e8e26dSBart Van Assche 				break;
316296e8e26dSBart Van Assche 			}
316396e8e26dSBart Van Assche 
3164e48354ceSNicholas Bellinger 			cmd->r2t_offset += xfer_len;
3165e48354ceSNicholas Bellinger 
3166ebf1d95cSAndy Grover 			if (cmd->r2t_offset == cmd->se_cmd.data_length)
3167e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3168e48354ceSNicholas Bellinger 		} else {
3169e48354ceSNicholas Bellinger 			struct iscsi_seq *seq;
3170e48354ceSNicholas Bellinger 
3171e48354ceSNicholas Bellinger 			seq = iscsit_get_seq_holder_for_r2t(cmd);
3172e48354ceSNicholas Bellinger 			if (!seq) {
3173e48354ceSNicholas Bellinger 				spin_unlock_bh(&cmd->r2t_lock);
3174e48354ceSNicholas Bellinger 				return -1;
3175e48354ceSNicholas Bellinger 			}
3176e48354ceSNicholas Bellinger 
3177e48354ceSNicholas Bellinger 			offset = seq->offset;
3178e48354ceSNicholas Bellinger 			xfer_len = seq->xfer_len;
3179e48354ceSNicholas Bellinger 
3180e48354ceSNicholas Bellinger 			if (cmd->seq_send_order == cmd->seq_count)
3181e48354ceSNicholas Bellinger 				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
3182e48354ceSNicholas Bellinger 		}
3183e48354ceSNicholas Bellinger 		cmd->outstanding_r2ts++;
3184e48354ceSNicholas Bellinger 		first_r2t = 0;
3185e48354ceSNicholas Bellinger 
3186e48354ceSNicholas Bellinger 		if (iscsit_add_r2t_to_list(cmd, offset, xfer_len, 0, 0) < 0) {
3187e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->r2t_lock);
3188e48354ceSNicholas Bellinger 			return -1;
3189e48354ceSNicholas Bellinger 		}
3190e48354ceSNicholas Bellinger 
3191e48354ceSNicholas Bellinger 		if (cmd->cmd_flags & ICF_SENT_LAST_R2T)
3192e48354ceSNicholas Bellinger 			break;
3193e48354ceSNicholas Bellinger 	}
3194e48354ceSNicholas Bellinger 	spin_unlock_bh(&cmd->r2t_lock);
3195e48354ceSNicholas Bellinger 
3196e48354ceSNicholas Bellinger 	return 0;
3197e48354ceSNicholas Bellinger }
3198d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_build_r2ts_for_cmd);
3199e48354ceSNicholas Bellinger 
32002ec5a8c1SNicholas Bellinger void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
32012ec5a8c1SNicholas Bellinger 			bool inc_stat_sn, struct iscsi_scsi_rsp *hdr)
3202e48354ceSNicholas Bellinger {
32032ec5a8c1SNicholas Bellinger 	if (inc_stat_sn)
3204e48354ceSNicholas Bellinger 		cmd->stat_sn = conn->stat_sn++;
3205e48354ceSNicholas Bellinger 
320604f3b31bSNicholas Bellinger 	atomic_long_inc(&conn->sess->rsp_pdus);
3207e48354ceSNicholas Bellinger 
3208e48354ceSNicholas Bellinger 	memset(hdr, 0, ISCSI_HDR_LEN);
3209e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_CMD_RSP;
3210e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3211e48354ceSNicholas Bellinger 	if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
3212e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW;
32137e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3214e48354ceSNicholas Bellinger 	} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
3215e48354ceSNicholas Bellinger 		hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
32167e46cf02SNicholas Bellinger 		hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3217e48354ceSNicholas Bellinger 	}
3218e48354ceSNicholas Bellinger 	hdr->response		= cmd->iscsi_response;
3219e48354ceSNicholas Bellinger 	hdr->cmd_status		= cmd->se_cmd.scsi_status;
322066c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3221e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3222e48354ceSNicholas Bellinger 
3223e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3224e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3225109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3226e48354ceSNicholas Bellinger 
32272ec5a8c1SNicholas Bellinger 	pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
32282ec5a8c1SNicholas Bellinger 		" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
32292ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, cmd->se_cmd.scsi_status,
32302ec5a8c1SNicholas Bellinger 		cmd->se_cmd.scsi_status, conn->cid);
32312ec5a8c1SNicholas Bellinger }
32322ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_rsp_pdu);
32332ec5a8c1SNicholas Bellinger 
32342ec5a8c1SNicholas Bellinger static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
32352ec5a8c1SNicholas Bellinger {
32362ec5a8c1SNicholas Bellinger 	struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)&cmd->pdu[0];
32372ec5a8c1SNicholas Bellinger 	bool inc_stat_sn = (cmd->i_state == ISTATE_SEND_STATUS);
32382854bb23SVarun Prakash 	void *data_buf = NULL;
32392854bb23SVarun Prakash 	u32 padding = 0, data_buf_len = 0;
32402ec5a8c1SNicholas Bellinger 
32412ec5a8c1SNicholas Bellinger 	iscsit_build_rsp_pdu(cmd, conn, inc_stat_sn, hdr);
32422ec5a8c1SNicholas Bellinger 
3243e48354ceSNicholas Bellinger 	/*
3244e48354ceSNicholas Bellinger 	 * Attach SENSE DATA payload to iSCSI Response PDU
3245e48354ceSNicholas Bellinger 	 */
3246e48354ceSNicholas Bellinger 	if (cmd->se_cmd.sense_buffer &&
3247e48354ceSNicholas Bellinger 	   ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
3248e48354ceSNicholas Bellinger 	    (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
32499c58b7ddSRoland Dreier 		put_unaligned_be16(cmd->se_cmd.scsi_sense_length, cmd->sense_buffer);
32509c58b7ddSRoland Dreier 		cmd->se_cmd.scsi_sense_length += sizeof (__be16);
32519c58b7ddSRoland Dreier 
3252e48354ceSNicholas Bellinger 		padding		= -(cmd->se_cmd.scsi_sense_length) & 3;
325350e5c87dSChristoph Hellwig 		hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length);
32542854bb23SVarun Prakash 		data_buf = cmd->sense_buffer;
32552854bb23SVarun Prakash 		data_buf_len = cmd->se_cmd.scsi_sense_length + padding;
3256e48354ceSNicholas Bellinger 
3257e48354ceSNicholas Bellinger 		if (padding) {
32589c58b7ddSRoland Dreier 			memset(cmd->sense_buffer +
3259e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length, 0, padding);
3260e48354ceSNicholas Bellinger 			pr_debug("Adding %u bytes of padding to"
3261e48354ceSNicholas Bellinger 				" SENSE.\n", padding);
3262e48354ceSNicholas Bellinger 		}
3263e48354ceSNicholas Bellinger 
3264e48354ceSNicholas Bellinger 		pr_debug("Attaching SENSE DATA: %u bytes to iSCSI"
3265e48354ceSNicholas Bellinger 				" Response PDU\n",
3266e48354ceSNicholas Bellinger 				cmd->se_cmd.scsi_sense_length);
3267e48354ceSNicholas Bellinger 	}
3268e48354ceSNicholas Bellinger 
32692854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, data_buf,
32702854bb23SVarun Prakash 						     data_buf_len);
3271e48354ceSNicholas Bellinger }
3272e48354ceSNicholas Bellinger 
3273e48354ceSNicholas Bellinger static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr)
3274e48354ceSNicholas Bellinger {
3275e48354ceSNicholas Bellinger 	switch (se_tmr->response) {
3276e48354ceSNicholas Bellinger 	case TMR_FUNCTION_COMPLETE:
3277e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_COMPLETE;
3278e48354ceSNicholas Bellinger 	case TMR_TASK_DOES_NOT_EXIST:
3279e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_TASK;
3280e48354ceSNicholas Bellinger 	case TMR_LUN_DOES_NOT_EXIST:
3281e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NO_LUN;
3282e48354ceSNicholas Bellinger 	case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
3283e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_NOT_SUPPORTED;
3284e48354ceSNicholas Bellinger 	case TMR_FUNCTION_REJECTED:
3285e48354ceSNicholas Bellinger 	default:
3286e48354ceSNicholas Bellinger 		return ISCSI_TMF_RSP_REJECTED;
3287e48354ceSNicholas Bellinger 	}
3288e48354ceSNicholas Bellinger }
3289e48354ceSNicholas Bellinger 
32902ec5a8c1SNicholas Bellinger void
32912ec5a8c1SNicholas Bellinger iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
32922ec5a8c1SNicholas Bellinger 			  struct iscsi_tm_rsp *hdr)
3293e48354ceSNicholas Bellinger {
3294e48354ceSNicholas Bellinger 	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
3295e48354ceSNicholas Bellinger 
3296e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_SCSI_TMFUNC_RSP;
32977ae0b103SNicholas Bellinger 	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
3298e48354ceSNicholas Bellinger 	hdr->response		= iscsit_convert_tcm_tmr_rsp(se_tmr);
329966c7db68SChristoph Hellwig 	hdr->itt		= cmd->init_task_tag;
3300e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3301e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3302e48354ceSNicholas Bellinger 
3303e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3304e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3305109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3306e48354ceSNicholas Bellinger 
33072ec5a8c1SNicholas Bellinger 	pr_debug("Built Task Management Response ITT: 0x%08x,"
33082ec5a8c1SNicholas Bellinger 		" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
33092ec5a8c1SNicholas Bellinger 		cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid);
33102ec5a8c1SNicholas Bellinger }
33112ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_task_mgt_rsp);
33122ec5a8c1SNicholas Bellinger 
33132ec5a8c1SNicholas Bellinger static int
33142ec5a8c1SNicholas Bellinger iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
33152ec5a8c1SNicholas Bellinger {
33162ec5a8c1SNicholas Bellinger 	struct iscsi_tm_rsp *hdr = (struct iscsi_tm_rsp *)&cmd->pdu[0];
33172ec5a8c1SNicholas Bellinger 
33182ec5a8c1SNicholas Bellinger 	iscsit_build_task_mgt_rsp(cmd, conn, hdr);
33192ec5a8c1SNicholas Bellinger 
33202854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL, NULL, 0);
3321e48354ceSNicholas Bellinger }
3322e48354ceSNicholas Bellinger 
33238b1e1244SAndy Grover #define SENDTARGETS_BUF_LIMIT 32768U
33248b1e1244SAndy Grover 
332522c7aaa5SSagi Grimberg static int
332622c7aaa5SSagi Grimberg iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
3327e4f4e801SSagi Grimberg 				  enum iscsit_transport_type network_transport,
3328e4f4e801SSagi Grimberg 				  int skip_bytes, bool *completed)
3329e48354ceSNicholas Bellinger {
3330e48354ceSNicholas Bellinger 	char *payload = NULL;
3331e48354ceSNicholas Bellinger 	struct iscsi_conn *conn = cmd->conn;
3332e48354ceSNicholas Bellinger 	struct iscsi_portal_group *tpg;
3333e48354ceSNicholas Bellinger 	struct iscsi_tiqn *tiqn;
3334e48354ceSNicholas Bellinger 	struct iscsi_tpg_np *tpg_np;
3335e48354ceSNicholas Bellinger 	int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
33362dd1d53fSThomas Glanzmann 	int target_name_printed;
33378b1e1244SAndy Grover 	unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
33386665889cSNicholas Bellinger 	unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
3339a6415cddSDavid Disseldorp 	bool active;
3340e48354ceSNicholas Bellinger 
3341be7dcfb6SSagi Grimberg 	buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength,
33428b1e1244SAndy Grover 			 SENDTARGETS_BUF_LIMIT);
3343e48354ceSNicholas Bellinger 
3344e48354ceSNicholas Bellinger 	payload = kzalloc(buffer_len, GFP_KERNEL);
3345c46e22f1SMarkus Elfring 	if (!payload)
3346e48354ceSNicholas Bellinger 		return -ENOMEM;
3347c46e22f1SMarkus Elfring 
33486665889cSNicholas Bellinger 	/*
33498060b8ddSAndy Grover 	 * Locate pointer to iqn./eui. string for ICF_SENDTARGETS_SINGLE
33506665889cSNicholas Bellinger 	 * explicit case..
33516665889cSNicholas Bellinger 	 */
33528060b8ddSAndy Grover 	if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) {
33536665889cSNicholas Bellinger 		text_ptr = strchr(text_in, '=');
33546665889cSNicholas Bellinger 		if (!text_ptr) {
33556665889cSNicholas Bellinger 			pr_err("Unable to locate '=' string in text_in:"
33566665889cSNicholas Bellinger 			       " %s\n", text_in);
33574f45d320SDan Carpenter 			kfree(payload);
33586665889cSNicholas Bellinger 			return -EINVAL;
33596665889cSNicholas Bellinger 		}
33606665889cSNicholas Bellinger 		/*
33616665889cSNicholas Bellinger 		 * Skip over '=' character..
33626665889cSNicholas Bellinger 		 */
33636665889cSNicholas Bellinger 		text_ptr += 1;
33646665889cSNicholas Bellinger 	}
3365e48354ceSNicholas Bellinger 
3366e48354ceSNicholas Bellinger 	spin_lock(&tiqn_lock);
3367e48354ceSNicholas Bellinger 	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
33688060b8ddSAndy Grover 		if ((cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) &&
33696665889cSNicholas Bellinger 		     strcmp(tiqn->tiqn, text_ptr)) {
33706665889cSNicholas Bellinger 			continue;
33716665889cSNicholas Bellinger 		}
33726665889cSNicholas Bellinger 
33732dd1d53fSThomas Glanzmann 		target_name_printed = 0;
3374e48354ceSNicholas Bellinger 
3375e48354ceSNicholas Bellinger 		spin_lock(&tiqn->tiqn_tpg_lock);
3376e48354ceSNicholas Bellinger 		list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
3377e48354ceSNicholas Bellinger 
33782dd1d53fSThomas Glanzmann 			/* If demo_mode_discovery=0 and generate_node_acls=0
33792dd1d53fSThomas Glanzmann 			 * (demo mode dislabed) do not return
33802dd1d53fSThomas Glanzmann 			 * TargetName+TargetAddress unless a NodeACL exists.
33812dd1d53fSThomas Glanzmann 			 */
33822dd1d53fSThomas Glanzmann 
33832dd1d53fSThomas Glanzmann 			if ((tpg->tpg_attrib.generate_node_acls == 0) &&
33842dd1d53fSThomas Glanzmann 			    (tpg->tpg_attrib.demo_mode_discovery == 0) &&
338521aaa23bSNicholas Bellinger 			    (!target_tpg_has_node_acl(&tpg->tpg_se_tpg,
33862dd1d53fSThomas Glanzmann 				cmd->conn->sess->sess_ops->InitiatorName))) {
33872dd1d53fSThomas Glanzmann 				continue;
33882dd1d53fSThomas Glanzmann 			}
33892dd1d53fSThomas Glanzmann 
3390e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_state_lock);
3391a6415cddSDavid Disseldorp 			active = (tpg->tpg_state == TPG_STATE_ACTIVE);
3392e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_state_lock);
3393a6415cddSDavid Disseldorp 
3394a6415cddSDavid Disseldorp 			if (!active && tpg->tpg_attrib.tpg_enabled_sendtargets)
3395e48354ceSNicholas Bellinger 				continue;
3396e48354ceSNicholas Bellinger 
3397e48354ceSNicholas Bellinger 			spin_lock(&tpg->tpg_np_lock);
3398e48354ceSNicholas Bellinger 			list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
3399e48354ceSNicholas Bellinger 						tpg_np_list) {
34002f9bc894SNicholas Bellinger 				struct iscsi_np *np = tpg_np->tpg_np;
340113a3cf08SAndy Grover 				struct sockaddr_storage *sockaddr;
34022f9bc894SNicholas Bellinger 
340322c7aaa5SSagi Grimberg 				if (np->np_network_transport != network_transport)
340422c7aaa5SSagi Grimberg 					continue;
340522c7aaa5SSagi Grimberg 
34062dd1d53fSThomas Glanzmann 				if (!target_name_printed) {
34072dd1d53fSThomas Glanzmann 					len = sprintf(buf, "TargetName=%s",
34082dd1d53fSThomas Glanzmann 						      tiqn->tiqn);
34092dd1d53fSThomas Glanzmann 					len += 1;
34102dd1d53fSThomas Glanzmann 
34112dd1d53fSThomas Glanzmann 					if ((len + payload_len) > buffer_len) {
34122dd1d53fSThomas Glanzmann 						spin_unlock(&tpg->tpg_np_lock);
34132dd1d53fSThomas Glanzmann 						spin_unlock(&tiqn->tiqn_tpg_lock);
34142dd1d53fSThomas Glanzmann 						end_of_buf = 1;
34152dd1d53fSThomas Glanzmann 						goto eob;
34162dd1d53fSThomas Glanzmann 					}
3417e4f4e801SSagi Grimberg 
3418e4f4e801SSagi Grimberg 					if (skip_bytes && len <= skip_bytes) {
3419e4f4e801SSagi Grimberg 						skip_bytes -= len;
3420e4f4e801SSagi Grimberg 					} else {
34212dd1d53fSThomas Glanzmann 						memcpy(payload + payload_len, buf, len);
34222dd1d53fSThomas Glanzmann 						payload_len += len;
34232dd1d53fSThomas Glanzmann 						target_name_printed = 1;
3424e4f4e801SSagi Grimberg 						if (len > skip_bytes)
3425e4f4e801SSagi Grimberg 							skip_bytes = 0;
3426e4f4e801SSagi Grimberg 					}
34272dd1d53fSThomas Glanzmann 				}
34282dd1d53fSThomas Glanzmann 
34297bfca0cfSSagi Grimberg 				if (inet_addr_is_any((struct sockaddr *)&np->np_sockaddr))
343069d75574SAndy Grover 					sockaddr = &conn->local_sockaddr;
34311997e625SAndy Grover 				else
343269d75574SAndy Grover 					sockaddr = &np->np_sockaddr;
34331997e625SAndy Grover 
343476c28f1fSAndy Grover 				len = sprintf(buf, "TargetAddress="
343576c28f1fSAndy Grover 					      "%pISpc,%hu",
343669d75574SAndy Grover 					      sockaddr,
3437e48354ceSNicholas Bellinger 					      tpg->tpgt);
3438e48354ceSNicholas Bellinger 				len += 1;
3439e48354ceSNicholas Bellinger 
3440e48354ceSNicholas Bellinger 				if ((len + payload_len) > buffer_len) {
3441e48354ceSNicholas Bellinger 					spin_unlock(&tpg->tpg_np_lock);
3442e48354ceSNicholas Bellinger 					spin_unlock(&tiqn->tiqn_tpg_lock);
3443e48354ceSNicholas Bellinger 					end_of_buf = 1;
3444e48354ceSNicholas Bellinger 					goto eob;
3445e48354ceSNicholas Bellinger 				}
3446e4f4e801SSagi Grimberg 
3447e4f4e801SSagi Grimberg 				if (skip_bytes && len <= skip_bytes) {
3448e4f4e801SSagi Grimberg 					skip_bytes -= len;
3449e4f4e801SSagi Grimberg 				} else {
34508359cf43SJörn Engel 					memcpy(payload + payload_len, buf, len);
3451e48354ceSNicholas Bellinger 					payload_len += len;
3452e4f4e801SSagi Grimberg 					if (len > skip_bytes)
3453e4f4e801SSagi Grimberg 						skip_bytes = 0;
3454e4f4e801SSagi Grimberg 				}
3455e48354ceSNicholas Bellinger 			}
3456e48354ceSNicholas Bellinger 			spin_unlock(&tpg->tpg_np_lock);
3457e48354ceSNicholas Bellinger 		}
3458e48354ceSNicholas Bellinger 		spin_unlock(&tiqn->tiqn_tpg_lock);
3459e48354ceSNicholas Bellinger eob:
3460e4f4e801SSagi Grimberg 		if (end_of_buf) {
3461e4f4e801SSagi Grimberg 			*completed = false;
3462e48354ceSNicholas Bellinger 			break;
3463e4f4e801SSagi Grimberg 		}
34646665889cSNicholas Bellinger 
34658060b8ddSAndy Grover 		if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE)
34666665889cSNicholas Bellinger 			break;
3467e48354ceSNicholas Bellinger 	}
3468e48354ceSNicholas Bellinger 	spin_unlock(&tiqn_lock);
3469e48354ceSNicholas Bellinger 
3470e48354ceSNicholas Bellinger 	cmd->buf_ptr = payload;
3471e48354ceSNicholas Bellinger 
3472e48354ceSNicholas Bellinger 	return payload_len;
3473e48354ceSNicholas Bellinger }
3474e48354ceSNicholas Bellinger 
3475889c8a68SNicholas Bellinger int
3476889c8a68SNicholas Bellinger iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
347722c7aaa5SSagi Grimberg 		      struct iscsi_text_rsp *hdr,
347822c7aaa5SSagi Grimberg 		      enum iscsit_transport_type network_transport)
3479e48354ceSNicholas Bellinger {
3480889c8a68SNicholas Bellinger 	int text_length, padding;
3481e4f4e801SSagi Grimberg 	bool completed = true;
3482e48354ceSNicholas Bellinger 
3483e4f4e801SSagi Grimberg 	text_length = iscsit_build_sendtargets_response(cmd, network_transport,
3484e4f4e801SSagi Grimberg 							cmd->read_data_done,
3485e4f4e801SSagi Grimberg 							&completed);
3486e48354ceSNicholas Bellinger 	if (text_length < 0)
3487e48354ceSNicholas Bellinger 		return text_length;
3488e48354ceSNicholas Bellinger 
3489e4f4e801SSagi Grimberg 	if (completed) {
3490310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
3491e4f4e801SSagi Grimberg 	} else {
3492310d40a9SVarun Prakash 		hdr->flags = ISCSI_FLAG_TEXT_CONTINUE;
3493e4f4e801SSagi Grimberg 		cmd->read_data_done += text_length;
3494e4f4e801SSagi Grimberg 		if (cmd->targ_xfer_tag == 0xFFFFFFFF)
3495e4f4e801SSagi Grimberg 			cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
3496e4f4e801SSagi Grimberg 	}
3497e4f4e801SSagi Grimberg 	hdr->opcode = ISCSI_OP_TEXT_RSP;
3498889c8a68SNicholas Bellinger 	padding = ((-text_length) & 3);
3499e48354ceSNicholas Bellinger 	hton24(hdr->dlength, text_length);
350066c7db68SChristoph Hellwig 	hdr->itt = cmd->init_task_tag;
3501e48354ceSNicholas Bellinger 	hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
3502e48354ceSNicholas Bellinger 	cmd->stat_sn = conn->stat_sn++;
3503e48354ceSNicholas Bellinger 	hdr->statsn = cpu_to_be32(cmd->stat_sn);
3504e48354ceSNicholas Bellinger 
3505e48354ceSNicholas Bellinger 	iscsit_increment_maxcmdsn(cmd, conn->sess);
3506e4f4e801SSagi Grimberg 	/*
3507e4f4e801SSagi Grimberg 	 * Reset maxcmdsn_inc in multi-part text payload exchanges to
3508e4f4e801SSagi Grimberg 	 * correctly increment MaxCmdSN for each response answering a
3509e4f4e801SSagi Grimberg 	 * non immediate text request with a valid CmdSN.
3510e4f4e801SSagi Grimberg 	 */
3511e4f4e801SSagi Grimberg 	cmd->maxcmdsn_inc = 0;
3512e48354ceSNicholas Bellinger 	hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
3513109e2381SRoland Dreier 	hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3514e48354ceSNicholas Bellinger 
3515e4f4e801SSagi Grimberg 	pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
3516e4f4e801SSagi Grimberg 		" Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
3517e4f4e801SSagi Grimberg 		cmd->targ_xfer_tag, cmd->stat_sn, text_length, conn->cid,
3518e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_CMD_FINAL),
3519e4f4e801SSagi Grimberg 		!!(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE));
3520e48354ceSNicholas Bellinger 
3521889c8a68SNicholas Bellinger 	return text_length + padding;
3522889c8a68SNicholas Bellinger }
3523889c8a68SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_text_rsp);
3524889c8a68SNicholas Bellinger 
3525889c8a68SNicholas Bellinger static int iscsit_send_text_rsp(
3526889c8a68SNicholas Bellinger 	struct iscsi_cmd *cmd,
3527889c8a68SNicholas Bellinger 	struct iscsi_conn *conn)
3528889c8a68SNicholas Bellinger {
3529889c8a68SNicholas Bellinger 	struct iscsi_text_rsp *hdr = (struct iscsi_text_rsp *)cmd->pdu;
35302854bb23SVarun Prakash 	int text_length;
3531889c8a68SNicholas Bellinger 
3532864e504aSVarun Prakash 	text_length = iscsit_build_text_rsp(cmd, conn, hdr,
3533864e504aSVarun Prakash 				conn->conn_transport->transport_type);
35342854bb23SVarun Prakash 	if (text_length < 0)
35352854bb23SVarun Prakash 		return text_length;
3536889c8a68SNicholas Bellinger 
35372854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35382854bb23SVarun Prakash 						     cmd->buf_ptr,
35392854bb23SVarun Prakash 						     text_length);
3540e48354ceSNicholas Bellinger }
3541e48354ceSNicholas Bellinger 
35422ec5a8c1SNicholas Bellinger void
35432ec5a8c1SNicholas Bellinger iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
35442ec5a8c1SNicholas Bellinger 		    struct iscsi_reject *hdr)
3545e48354ceSNicholas Bellinger {
3546e48354ceSNicholas Bellinger 	hdr->opcode		= ISCSI_OP_REJECT;
3547ba159914SNicholas Bellinger 	hdr->reason		= cmd->reject_reason;
3548e48354ceSNicholas Bellinger 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
3549e48354ceSNicholas Bellinger 	hton24(hdr->dlength, ISCSI_HDR_LEN);
355050e5c87dSChristoph Hellwig 	hdr->ffffffff		= cpu_to_be32(0xffffffff);
3551e48354ceSNicholas Bellinger 	cmd->stat_sn		= conn->stat_sn++;
3552e48354ceSNicholas Bellinger 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
3553e48354ceSNicholas Bellinger 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
3554109e2381SRoland Dreier 	hdr->max_cmdsn		= cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
3555e48354ceSNicholas Bellinger 
35562ec5a8c1SNicholas Bellinger }
35572ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_build_reject);
3558e48354ceSNicholas Bellinger 
35592ec5a8c1SNicholas Bellinger static int iscsit_send_reject(
35602ec5a8c1SNicholas Bellinger 	struct iscsi_cmd *cmd,
35612ec5a8c1SNicholas Bellinger 	struct iscsi_conn *conn)
35622ec5a8c1SNicholas Bellinger {
3563bfbdb31dSNicholas Bellinger 	struct iscsi_reject *hdr = (struct iscsi_reject *)&cmd->pdu[0];
35642ec5a8c1SNicholas Bellinger 
3565bfbdb31dSNicholas Bellinger 	iscsit_build_reject(cmd, conn, hdr);
35662ec5a8c1SNicholas Bellinger 
3567e48354ceSNicholas Bellinger 	pr_debug("Built Reject PDU StatSN: 0x%08x, Reason: 0x%02x,"
3568e48354ceSNicholas Bellinger 		" CID: %hu\n", ntohl(hdr->statsn), hdr->reason, conn->cid);
3569e48354ceSNicholas Bellinger 
35702854bb23SVarun Prakash 	return conn->conn_transport->iscsit_xmit_pdu(conn, cmd, NULL,
35712854bb23SVarun Prakash 						     cmd->buf_ptr,
35722854bb23SVarun Prakash 						     ISCSI_HDR_LEN);
3573e48354ceSNicholas Bellinger }
3574e48354ceSNicholas Bellinger 
3575e48354ceSNicholas Bellinger void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
3576e48354ceSNicholas Bellinger {
3577e48354ceSNicholas Bellinger 	int ord, cpu;
3578e48354ceSNicholas Bellinger 	/*
357988dcd2daSNicholas Bellinger 	 * bitmap_id is assigned from iscsit_global->ts_bitmap from
358088dcd2daSNicholas Bellinger 	 * within iscsit_start_kthreads()
3581e48354ceSNicholas Bellinger 	 *
358288dcd2daSNicholas Bellinger 	 * Here we use bitmap_id to determine which CPU that this
358388dcd2daSNicholas Bellinger 	 * iSCSI connection's RX/TX threads will be scheduled to
3584e48354ceSNicholas Bellinger 	 * execute upon.
3585e48354ceSNicholas Bellinger 	 */
358688dcd2daSNicholas Bellinger 	ord = conn->bitmap_id % cpumask_weight(cpu_online_mask);
3587e48354ceSNicholas Bellinger 	for_each_online_cpu(cpu) {
3588e48354ceSNicholas Bellinger 		if (ord-- == 0) {
3589e48354ceSNicholas Bellinger 			cpumask_set_cpu(cpu, conn->conn_cpumask);
3590e48354ceSNicholas Bellinger 			return;
3591e48354ceSNicholas Bellinger 		}
3592e48354ceSNicholas Bellinger 	}
3593e48354ceSNicholas Bellinger 	/*
3594e48354ceSNicholas Bellinger 	 * This should never be reached..
3595e48354ceSNicholas Bellinger 	 */
3596e48354ceSNicholas Bellinger 	dump_stack();
3597e48354ceSNicholas Bellinger 	cpumask_setall(conn->conn_cpumask);
3598e48354ceSNicholas Bellinger }
3599e48354ceSNicholas Bellinger 
3600d2faaefbSVarun Prakash int
36012ec5a8c1SNicholas Bellinger iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
3602e48354ceSNicholas Bellinger {
36032ec5a8c1SNicholas Bellinger 	int ret;
36042ec5a8c1SNicholas Bellinger 
36052ec5a8c1SNicholas Bellinger 	switch (state) {
36062ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_R2T:
36072ec5a8c1SNicholas Bellinger 		ret = iscsit_send_r2t(cmd, conn);
36082ec5a8c1SNicholas Bellinger 		if (ret < 0)
36092ec5a8c1SNicholas Bellinger 			goto err;
36102ec5a8c1SNicholas Bellinger 		break;
36112ec5a8c1SNicholas Bellinger 	case ISTATE_REMOVE:
36122ec5a8c1SNicholas Bellinger 		spin_lock_bh(&conn->cmd_lock);
36135159d763SNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
36142ec5a8c1SNicholas Bellinger 		spin_unlock_bh(&conn->cmd_lock);
36152ec5a8c1SNicholas Bellinger 
3616aafc9d15SNicholas Bellinger 		iscsit_free_cmd(cmd, false);
36172ec5a8c1SNicholas Bellinger 		break;
36182ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_WANT_RESPONSE:
36192ec5a8c1SNicholas Bellinger 		iscsit_mod_nopin_response_timer(conn);
36202ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 1);
36212ec5a8c1SNicholas Bellinger 		if (ret < 0)
36222ec5a8c1SNicholas Bellinger 			goto err;
36232ec5a8c1SNicholas Bellinger 		break;
36242ec5a8c1SNicholas Bellinger 	case ISTATE_SEND_NOPIN_NO_RESPONSE:
36252ec5a8c1SNicholas Bellinger 		ret = iscsit_send_unsolicited_nopin(cmd, conn, 0);
36262ec5a8c1SNicholas Bellinger 		if (ret < 0)
36272ec5a8c1SNicholas Bellinger 			goto err;
36282ec5a8c1SNicholas Bellinger 		break;
36292ec5a8c1SNicholas Bellinger 	default:
36302ec5a8c1SNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
36312ec5a8c1SNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
36322ec5a8c1SNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag, state,
36332ec5a8c1SNicholas Bellinger 		       conn->cid);
36342ec5a8c1SNicholas Bellinger 		goto err;
36352ec5a8c1SNicholas Bellinger 	}
36362ec5a8c1SNicholas Bellinger 
36372ec5a8c1SNicholas Bellinger 	return 0;
36382ec5a8c1SNicholas Bellinger 
36392ec5a8c1SNicholas Bellinger err:
36402ec5a8c1SNicholas Bellinger 	return -1;
36412ec5a8c1SNicholas Bellinger }
3642d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_immediate_queue);
36432ec5a8c1SNicholas Bellinger 
36442ec5a8c1SNicholas Bellinger static int
36452ec5a8c1SNicholas Bellinger iscsit_handle_immediate_queue(struct iscsi_conn *conn)
36462ec5a8c1SNicholas Bellinger {
36472ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
36486f3c0e69SAndy Grover 	struct iscsi_queue_req *qr;
36496f3c0e69SAndy Grover 	struct iscsi_cmd *cmd;
3650e48354ceSNicholas Bellinger 	u8 state;
36516f3c0e69SAndy Grover 	int ret;
3652e48354ceSNicholas Bellinger 
3653c6037cc5SAndy Grover 	while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) {
3654e48354ceSNicholas Bellinger 		atomic_set(&conn->check_immediate_queue, 0);
3655e48354ceSNicholas Bellinger 		cmd = qr->cmd;
3656e48354ceSNicholas Bellinger 		state = qr->state;
3657e48354ceSNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
3658e48354ceSNicholas Bellinger 
36592ec5a8c1SNicholas Bellinger 		ret = t->iscsit_immediate_queue(conn, cmd, state);
36606f3c0e69SAndy Grover 		if (ret < 0)
36612ec5a8c1SNicholas Bellinger 			return ret;
3662e48354ceSNicholas Bellinger 	}
3663e48354ceSNicholas Bellinger 
36646f3c0e69SAndy Grover 	return 0;
3665e48354ceSNicholas Bellinger }
36666f3c0e69SAndy Grover 
3667d2faaefbSVarun Prakash int
36682ec5a8c1SNicholas Bellinger iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
36696f3c0e69SAndy Grover {
36706f3c0e69SAndy Grover 	int ret;
3671e48354ceSNicholas Bellinger 
3672e48354ceSNicholas Bellinger check_rsp_state:
3673e48354ceSNicholas Bellinger 	switch (state) {
3674e48354ceSNicholas Bellinger 	case ISTATE_SEND_DATAIN:
36752ec5a8c1SNicholas Bellinger 		ret = iscsit_send_datain(cmd, conn);
36766f3c0e69SAndy Grover 		if (ret < 0)
36776f3c0e69SAndy Grover 			goto err;
36786f3c0e69SAndy Grover 		else if (!ret)
36796f3c0e69SAndy Grover 			/* more drs */
36806f3c0e69SAndy Grover 			goto check_rsp_state;
36816f3c0e69SAndy Grover 		else if (ret == 1) {
36826f3c0e69SAndy Grover 			/* all done */
36836f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
36846f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SENT_STATUS;
3685e48354ceSNicholas Bellinger 			spin_unlock_bh(&cmd->istate_lock);
3686fd3a9025SNicholas Bellinger 
3687fd3a9025SNicholas Bellinger 			if (atomic_read(&conn->check_immediate_queue))
3688fd3a9025SNicholas Bellinger 				return 1;
3689fd3a9025SNicholas Bellinger 
36902ec5a8c1SNicholas Bellinger 			return 0;
36916f3c0e69SAndy Grover 		} else if (ret == 2) {
36926f3c0e69SAndy Grover 			/* Still must send status,
36936f3c0e69SAndy Grover 			   SCF_TRANSPORT_TASK_SENSE was set */
36946f3c0e69SAndy Grover 			spin_lock_bh(&cmd->istate_lock);
36956f3c0e69SAndy Grover 			cmd->i_state = ISTATE_SEND_STATUS;
36966f3c0e69SAndy Grover 			spin_unlock_bh(&cmd->istate_lock);
36976f3c0e69SAndy Grover 			state = ISTATE_SEND_STATUS;
36986f3c0e69SAndy Grover 			goto check_rsp_state;
36996f3c0e69SAndy Grover 		}
37006f3c0e69SAndy Grover 
3701e48354ceSNicholas Bellinger 		break;
3702e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3703e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
37042ec5a8c1SNicholas Bellinger 		ret = iscsit_send_response(cmd, conn);
3705e48354ceSNicholas Bellinger 		break;
3706e48354ceSNicholas Bellinger 	case ISTATE_SEND_LOGOUTRSP:
37072ec5a8c1SNicholas Bellinger 		ret = iscsit_send_logout(cmd, conn);
3708e48354ceSNicholas Bellinger 		break;
3709e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3710e48354ceSNicholas Bellinger 		ret = iscsit_send_conn_drop_async_message(
3711e48354ceSNicholas Bellinger 			cmd, conn);
3712e48354ceSNicholas Bellinger 		break;
3713e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
37142ec5a8c1SNicholas Bellinger 		ret = iscsit_send_nopin(cmd, conn);
3715e48354ceSNicholas Bellinger 		break;
3716e48354ceSNicholas Bellinger 	case ISTATE_SEND_REJECT:
3717e48354ceSNicholas Bellinger 		ret = iscsit_send_reject(cmd, conn);
3718e48354ceSNicholas Bellinger 		break;
3719e48354ceSNicholas Bellinger 	case ISTATE_SEND_TASKMGTRSP:
3720e48354ceSNicholas Bellinger 		ret = iscsit_send_task_mgt_rsp(cmd, conn);
3721e48354ceSNicholas Bellinger 		if (ret != 0)
3722e48354ceSNicholas Bellinger 			break;
3723e48354ceSNicholas Bellinger 		ret = iscsit_tmr_post_handler(cmd, conn);
3724e48354ceSNicholas Bellinger 		if (ret != 0)
3725e48354ceSNicholas Bellinger 			iscsit_fall_back_to_erl0(conn->sess);
3726e48354ceSNicholas Bellinger 		break;
3727e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
3728e48354ceSNicholas Bellinger 		ret = iscsit_send_text_rsp(cmd, conn);
3729e48354ceSNicholas Bellinger 		break;
3730e48354ceSNicholas Bellinger 	default:
3731e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3732e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3733e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3734e48354ceSNicholas Bellinger 		       state, conn->cid);
37356f3c0e69SAndy Grover 		goto err;
3736e48354ceSNicholas Bellinger 	}
3737c6037cc5SAndy Grover 	if (ret < 0)
37386f3c0e69SAndy Grover 		goto err;
3739e48354ceSNicholas Bellinger 
3740e48354ceSNicholas Bellinger 	switch (state) {
37416f3c0e69SAndy Grover 	case ISTATE_SEND_LOGOUTRSP:
37426f3c0e69SAndy Grover 		if (!iscsit_logout_post_handler(cmd, conn))
374388dcd2daSNicholas Bellinger 			return -ECONNRESET;
37446f3c0e69SAndy Grover 		/* fall through */
3745e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS:
3746e48354ceSNicholas Bellinger 	case ISTATE_SEND_ASYNCMSG:
3747e48354ceSNicholas Bellinger 	case ISTATE_SEND_NOPIN:
3748e48354ceSNicholas Bellinger 	case ISTATE_SEND_STATUS_RECOVERY:
3749e48354ceSNicholas Bellinger 	case ISTATE_SEND_TEXTRSP:
37506f3c0e69SAndy Grover 	case ISTATE_SEND_TASKMGTRSP:
3751ba159914SNicholas Bellinger 	case ISTATE_SEND_REJECT:
37526f3c0e69SAndy Grover 		spin_lock_bh(&cmd->istate_lock);
37536f3c0e69SAndy Grover 		cmd->i_state = ISTATE_SENT_STATUS;
37546f3c0e69SAndy Grover 		spin_unlock_bh(&cmd->istate_lock);
3755e48354ceSNicholas Bellinger 		break;
3756e48354ceSNicholas Bellinger 	default:
3757e48354ceSNicholas Bellinger 		pr_err("Unknown Opcode: 0x%02x ITT:"
3758e48354ceSNicholas Bellinger 		       " 0x%08x, i_state: %d on CID: %hu\n",
3759e48354ceSNicholas Bellinger 		       cmd->iscsi_opcode, cmd->init_task_tag,
3760e48354ceSNicholas Bellinger 		       cmd->i_state, conn->cid);
37616f3c0e69SAndy Grover 		goto err;
3762e48354ceSNicholas Bellinger 	}
3763e48354ceSNicholas Bellinger 
3764e48354ceSNicholas Bellinger 	if (atomic_read(&conn->check_immediate_queue))
3765fd3a9025SNicholas Bellinger 		return 1;
37666f3c0e69SAndy Grover 
37676f3c0e69SAndy Grover 	return 0;
37686f3c0e69SAndy Grover 
37696f3c0e69SAndy Grover err:
37706f3c0e69SAndy Grover 	return -1;
37716f3c0e69SAndy Grover }
3772d2faaefbSVarun Prakash EXPORT_SYMBOL(iscsit_response_queue);
37736f3c0e69SAndy Grover 
37742ec5a8c1SNicholas Bellinger static int iscsit_handle_response_queue(struct iscsi_conn *conn)
37752ec5a8c1SNicholas Bellinger {
37762ec5a8c1SNicholas Bellinger 	struct iscsit_transport *t = conn->conn_transport;
37772ec5a8c1SNicholas Bellinger 	struct iscsi_queue_req *qr;
37782ec5a8c1SNicholas Bellinger 	struct iscsi_cmd *cmd;
37792ec5a8c1SNicholas Bellinger 	u8 state;
37802ec5a8c1SNicholas Bellinger 	int ret;
37812ec5a8c1SNicholas Bellinger 
37822ec5a8c1SNicholas Bellinger 	while ((qr = iscsit_get_cmd_from_response_queue(conn))) {
37832ec5a8c1SNicholas Bellinger 		cmd = qr->cmd;
37842ec5a8c1SNicholas Bellinger 		state = qr->state;
37852ec5a8c1SNicholas Bellinger 		kmem_cache_free(lio_qr_cache, qr);
37862ec5a8c1SNicholas Bellinger 
37872ec5a8c1SNicholas Bellinger 		ret = t->iscsit_response_queue(conn, cmd, state);
37882ec5a8c1SNicholas Bellinger 		if (ret == 1 || ret < 0)
37892ec5a8c1SNicholas Bellinger 			return ret;
37902ec5a8c1SNicholas Bellinger 	}
37912ec5a8c1SNicholas Bellinger 
37922ec5a8c1SNicholas Bellinger 	return 0;
37932ec5a8c1SNicholas Bellinger }
37942ec5a8c1SNicholas Bellinger 
37956f3c0e69SAndy Grover int iscsi_target_tx_thread(void *arg)
37966f3c0e69SAndy Grover {
37976f3c0e69SAndy Grover 	int ret = 0;
379888dcd2daSNicholas Bellinger 	struct iscsi_conn *conn = arg;
37995e0cf5e6SJiang Yi 	bool conn_freed = false;
38005e0cf5e6SJiang Yi 
38016f3c0e69SAndy Grover 	/*
38026f3c0e69SAndy Grover 	 * Allow ourselves to be interrupted by SIGINT so that a
38036f3c0e69SAndy Grover 	 * connection recovery / failure event can be triggered externally.
38046f3c0e69SAndy Grover 	 */
38056f3c0e69SAndy Grover 	allow_signal(SIGINT);
38066f3c0e69SAndy Grover 
38076f3c0e69SAndy Grover 	while (!kthread_should_stop()) {
38086f3c0e69SAndy Grover 		/*
38096f3c0e69SAndy Grover 		 * Ensure that both TX and RX per connection kthreads
38106f3c0e69SAndy Grover 		 * are scheduled to run on the same CPU.
38116f3c0e69SAndy Grover 		 */
38126f3c0e69SAndy Grover 		iscsit_thread_check_cpumask(conn, current, 1);
38136f3c0e69SAndy Grover 
3814d5627acbSRoland Dreier 		wait_event_interruptible(conn->queues_wq,
381588dcd2daSNicholas Bellinger 					 !iscsit_conn_all_queues_empty(conn));
38166f3c0e69SAndy Grover 
381788dcd2daSNicholas Bellinger 		if (signal_pending(current))
38186f3c0e69SAndy Grover 			goto transport_err;
38196f3c0e69SAndy Grover 
3820fd3a9025SNicholas Bellinger get_immediate:
38212ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_immediate_queue(conn);
38226f3c0e69SAndy Grover 		if (ret < 0)
38236f3c0e69SAndy Grover 			goto transport_err;
38246f3c0e69SAndy Grover 
38252ec5a8c1SNicholas Bellinger 		ret = iscsit_handle_response_queue(conn);
38265e0cf5e6SJiang Yi 		if (ret == 1) {
3827fd3a9025SNicholas Bellinger 			goto get_immediate;
38285e0cf5e6SJiang Yi 		} else if (ret == -ECONNRESET) {
38295e0cf5e6SJiang Yi 			conn_freed = true;
383088dcd2daSNicholas Bellinger 			goto out;
38315e0cf5e6SJiang Yi 		} else if (ret < 0) {
38326f3c0e69SAndy Grover 			goto transport_err;
3833e48354ceSNicholas Bellinger 		}
38345e0cf5e6SJiang Yi 	}
3835e48354ceSNicholas Bellinger 
3836e48354ceSNicholas Bellinger transport_err:
3837e5419865SNicholas Bellinger 	/*
3838e5419865SNicholas Bellinger 	 * Avoid the normal connection failure code-path if this connection
3839e5419865SNicholas Bellinger 	 * is still within LOGIN mode, and iscsi_np process context is
3840e5419865SNicholas Bellinger 	 * responsible for cleaning up the early connection failure.
3841e5419865SNicholas Bellinger 	 */
3842e5419865SNicholas Bellinger 	if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
38435e0cf5e6SJiang Yi 		iscsit_take_action_for_connection_exit(conn, &conn_freed);
3844e48354ceSNicholas Bellinger out:
38455e0cf5e6SJiang Yi 	if (!conn_freed) {
38465e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
38475e0cf5e6SJiang Yi 			msleep(100);
38485e0cf5e6SJiang Yi 		}
38495e0cf5e6SJiang Yi 	}
3850e48354ceSNicholas Bellinger 	return 0;
3851e48354ceSNicholas Bellinger }
3852e48354ceSNicholas Bellinger 
38533e1c81a9SNicholas Bellinger static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
38543e1c81a9SNicholas Bellinger {
38553e1c81a9SNicholas Bellinger 	struct iscsi_hdr *hdr = (struct iscsi_hdr *)buf;
38563e1c81a9SNicholas Bellinger 	struct iscsi_cmd *cmd;
38573e1c81a9SNicholas Bellinger 	int ret = 0;
38583e1c81a9SNicholas Bellinger 
38593e1c81a9SNicholas Bellinger 	switch (hdr->opcode & ISCSI_OPCODE_MASK) {
38603e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_CMD:
3861676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38623e1c81a9SNicholas Bellinger 		if (!cmd)
3863ba159914SNicholas Bellinger 			goto reject;
38643e1c81a9SNicholas Bellinger 
38653e1c81a9SNicholas Bellinger 		ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
38663e1c81a9SNicholas Bellinger 		break;
38673e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_DATA_OUT:
38683e1c81a9SNicholas Bellinger 		ret = iscsit_handle_data_out(conn, buf);
38693e1c81a9SNicholas Bellinger 		break;
38703e1c81a9SNicholas Bellinger 	case ISCSI_OP_NOOP_OUT:
38713e1c81a9SNicholas Bellinger 		cmd = NULL;
38723e1c81a9SNicholas Bellinger 		if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
3873676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38743e1c81a9SNicholas Bellinger 			if (!cmd)
3875ba159914SNicholas Bellinger 				goto reject;
38763e1c81a9SNicholas Bellinger 		}
38773e1c81a9SNicholas Bellinger 		ret = iscsit_handle_nop_out(conn, cmd, buf);
38783e1c81a9SNicholas Bellinger 		break;
38793e1c81a9SNicholas Bellinger 	case ISCSI_OP_SCSI_TMFUNC:
3880676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
38813e1c81a9SNicholas Bellinger 		if (!cmd)
3882ba159914SNicholas Bellinger 			goto reject;
38833e1c81a9SNicholas Bellinger 
38843e1c81a9SNicholas Bellinger 		ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
38853e1c81a9SNicholas Bellinger 		break;
38863e1c81a9SNicholas Bellinger 	case ISCSI_OP_TEXT:
3887e4f4e801SSagi Grimberg 		if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
3888e4f4e801SSagi Grimberg 			cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
3889e4f4e801SSagi Grimberg 			if (!cmd)
3890e4f4e801SSagi Grimberg 				goto reject;
3891e4f4e801SSagi Grimberg 		} else {
3892676687c6SNicholas Bellinger 			cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
389364534aa7SNicholas Bellinger 			if (!cmd)
3894ba159914SNicholas Bellinger 				goto reject;
3895e4f4e801SSagi Grimberg 		}
389664534aa7SNicholas Bellinger 
389764534aa7SNicholas Bellinger 		ret = iscsit_handle_text_cmd(conn, cmd, buf);
38983e1c81a9SNicholas Bellinger 		break;
38993e1c81a9SNicholas Bellinger 	case ISCSI_OP_LOGOUT:
3900676687c6SNicholas Bellinger 		cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
39013e1c81a9SNicholas Bellinger 		if (!cmd)
3902ba159914SNicholas Bellinger 			goto reject;
39033e1c81a9SNicholas Bellinger 
39043e1c81a9SNicholas Bellinger 		ret = iscsit_handle_logout_cmd(conn, cmd, buf);
39053e1c81a9SNicholas Bellinger 		if (ret > 0)
39063e1c81a9SNicholas Bellinger 			wait_for_completion_timeout(&conn->conn_logout_comp,
39073e1c81a9SNicholas Bellinger 					SECONDS_FOR_LOGOUT_COMP * HZ);
39083e1c81a9SNicholas Bellinger 		break;
39093e1c81a9SNicholas Bellinger 	case ISCSI_OP_SNACK:
39103e1c81a9SNicholas Bellinger 		ret = iscsit_handle_snack(conn, buf);
39113e1c81a9SNicholas Bellinger 		break;
39123e1c81a9SNicholas Bellinger 	default:
39133e1c81a9SNicholas Bellinger 		pr_err("Got unknown iSCSI OpCode: 0x%02x\n", hdr->opcode);
39143e1c81a9SNicholas Bellinger 		if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
39153e1c81a9SNicholas Bellinger 			pr_err("Cannot recover from unknown"
39163e1c81a9SNicholas Bellinger 			" opcode while ERL=0, closing iSCSI connection.\n");
39173e1c81a9SNicholas Bellinger 			return -1;
39183e1c81a9SNicholas Bellinger 		}
3919c04a6091SChristophe Vu-Brugier 		pr_err("Unable to recover from unknown opcode while OFMarker=No,"
3920c04a6091SChristophe Vu-Brugier 		       " closing iSCSI connection.\n");
3921c04a6091SChristophe Vu-Brugier 		ret = -1;
39223e1c81a9SNicholas Bellinger 		break;
39233e1c81a9SNicholas Bellinger 	}
39243e1c81a9SNicholas Bellinger 
39253e1c81a9SNicholas Bellinger 	return ret;
3926ba159914SNicholas Bellinger reject:
3927ba159914SNicholas Bellinger 	return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
39283e1c81a9SNicholas Bellinger }
39293e1c81a9SNicholas Bellinger 
3930ca82c2bdSNicholas Bellinger static bool iscsi_target_check_conn_state(struct iscsi_conn *conn)
3931ca82c2bdSNicholas Bellinger {
3932ca82c2bdSNicholas Bellinger 	bool ret;
3933ca82c2bdSNicholas Bellinger 
3934ca82c2bdSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
3935ca82c2bdSNicholas Bellinger 	ret = (conn->conn_state != TARG_CONN_STATE_LOGGED_IN);
3936ca82c2bdSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
3937ca82c2bdSNicholas Bellinger 
3938ca82c2bdSNicholas Bellinger 	return ret;
3939ca82c2bdSNicholas Bellinger }
3940ca82c2bdSNicholas Bellinger 
3941e8205ccaSVarun Prakash static void iscsit_get_rx_pdu(struct iscsi_conn *conn)
3942e48354ceSNicholas Bellinger {
3943e8205ccaSVarun Prakash 	int ret;
3944679fcae4SLaura Abbott 	u8 *buffer, opcode;
3945e48354ceSNicholas Bellinger 	u32 checksum = 0, digest = 0;
3946e48354ceSNicholas Bellinger 	struct kvec iov;
39473e1c81a9SNicholas Bellinger 
3948679fcae4SLaura Abbott 	buffer = kcalloc(ISCSI_HDR_LEN, sizeof(*buffer), GFP_KERNEL);
3949679fcae4SLaura Abbott 	if (!buffer)
3950679fcae4SLaura Abbott 		return;
3951679fcae4SLaura Abbott 
3952e48354ceSNicholas Bellinger 	while (!kthread_should_stop()) {
3953e48354ceSNicholas Bellinger 		/*
3954e48354ceSNicholas Bellinger 		 * Ensure that both TX and RX per connection kthreads
3955e48354ceSNicholas Bellinger 		 * are scheduled to run on the same CPU.
3956e48354ceSNicholas Bellinger 		 */
3957e48354ceSNicholas Bellinger 		iscsit_thread_check_cpumask(conn, current, 0);
3958e48354ceSNicholas Bellinger 
3959e48354ceSNicholas Bellinger 		memset(&iov, 0, sizeof(struct kvec));
3960e48354ceSNicholas Bellinger 
3961e48354ceSNicholas Bellinger 		iov.iov_base	= buffer;
3962e48354ceSNicholas Bellinger 		iov.iov_len	= ISCSI_HDR_LEN;
3963e48354ceSNicholas Bellinger 
3964e48354ceSNicholas Bellinger 		ret = rx_data(conn, &iov, 1, ISCSI_HDR_LEN);
3965e48354ceSNicholas Bellinger 		if (ret != ISCSI_HDR_LEN) {
3966e48354ceSNicholas Bellinger 			iscsit_rx_thread_wait_for_tcp(conn);
3967679fcae4SLaura Abbott 			break;
3968e48354ceSNicholas Bellinger 		}
3969e48354ceSNicholas Bellinger 
3970e48354ceSNicholas Bellinger 		if (conn->conn_ops->HeaderDigest) {
3971e48354ceSNicholas Bellinger 			iov.iov_base	= &digest;
3972e48354ceSNicholas Bellinger 			iov.iov_len	= ISCSI_CRC_LEN;
3973e48354ceSNicholas Bellinger 
3974e48354ceSNicholas Bellinger 			ret = rx_data(conn, &iov, 1, ISCSI_CRC_LEN);
3975e48354ceSNicholas Bellinger 			if (ret != ISCSI_CRC_LEN) {
3976e48354ceSNicholas Bellinger 				iscsit_rx_thread_wait_for_tcp(conn);
3977679fcae4SLaura Abbott 				break;
3978e48354ceSNicholas Bellinger 			}
3979e48354ceSNicholas Bellinger 
3980e1dfb21fSBart Van Assche 			iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer,
3981e1dfb21fSBart Van Assche 						  ISCSI_HDR_LEN, 0, NULL,
3982e1dfb21fSBart Van Assche 						  &checksum);
3983e48354ceSNicholas Bellinger 
3984e48354ceSNicholas Bellinger 			if (digest != checksum) {
3985e48354ceSNicholas Bellinger 				pr_err("HeaderDigest CRC32C failed,"
3986e48354ceSNicholas Bellinger 					" received 0x%08x, computed 0x%08x\n",
3987e48354ceSNicholas Bellinger 					digest, checksum);
3988e48354ceSNicholas Bellinger 				/*
3989e48354ceSNicholas Bellinger 				 * Set the PDU to 0xff so it will intentionally
3990e48354ceSNicholas Bellinger 				 * hit default in the switch below.
3991e48354ceSNicholas Bellinger 				 */
3992e48354ceSNicholas Bellinger 				memset(buffer, 0xff, ISCSI_HDR_LEN);
399304f3b31bSNicholas Bellinger 				atomic_long_inc(&conn->sess->conn_digest_errors);
3994e48354ceSNicholas Bellinger 			} else {
3995e48354ceSNicholas Bellinger 				pr_debug("Got HeaderDigest CRC32C"
3996e48354ceSNicholas Bellinger 						" 0x%08x\n", checksum);
3997e48354ceSNicholas Bellinger 			}
3998e48354ceSNicholas Bellinger 		}
3999e48354ceSNicholas Bellinger 
4000e48354ceSNicholas Bellinger 		if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT)
4001679fcae4SLaura Abbott 			break;
4002e48354ceSNicholas Bellinger 
4003e48354ceSNicholas Bellinger 		opcode = buffer[0] & ISCSI_OPCODE_MASK;
4004e48354ceSNicholas Bellinger 
4005e48354ceSNicholas Bellinger 		if (conn->sess->sess_ops->SessionType &&
4006e48354ceSNicholas Bellinger 		   ((!(opcode & ISCSI_OP_TEXT)) ||
4007e48354ceSNicholas Bellinger 		    (!(opcode & ISCSI_OP_LOGOUT)))) {
4008e48354ceSNicholas Bellinger 			pr_err("Received illegal iSCSI Opcode: 0x%02x"
4009e48354ceSNicholas Bellinger 			" while in Discovery Session, rejecting.\n", opcode);
4010ba159914SNicholas Bellinger 			iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
4011ba159914SNicholas Bellinger 					  buffer);
4012679fcae4SLaura Abbott 			break;
4013e48354ceSNicholas Bellinger 		}
4014e48354ceSNicholas Bellinger 
40153e1c81a9SNicholas Bellinger 		ret = iscsi_target_rx_opcode(conn, buffer);
40163e1c81a9SNicholas Bellinger 		if (ret < 0)
4017679fcae4SLaura Abbott 			break;
4018e8205ccaSVarun Prakash 	}
4019679fcae4SLaura Abbott 
4020679fcae4SLaura Abbott 	kfree(buffer);
4021e48354ceSNicholas Bellinger }
4022e48354ceSNicholas Bellinger 
4023e8205ccaSVarun Prakash int iscsi_target_rx_thread(void *arg)
4024e8205ccaSVarun Prakash {
4025e8205ccaSVarun Prakash 	int rc;
4026e8205ccaSVarun Prakash 	struct iscsi_conn *conn = arg;
40275e0cf5e6SJiang Yi 	bool conn_freed = false;
4028e8205ccaSVarun Prakash 
4029e8205ccaSVarun Prakash 	/*
4030e8205ccaSVarun Prakash 	 * Allow ourselves to be interrupted by SIGINT so that a
4031e8205ccaSVarun Prakash 	 * connection recovery / failure event can be triggered externally.
4032e8205ccaSVarun Prakash 	 */
4033e8205ccaSVarun Prakash 	allow_signal(SIGINT);
4034e8205ccaSVarun Prakash 	/*
4035e8205ccaSVarun Prakash 	 * Wait for iscsi_post_login_handler() to complete before allowing
4036e8205ccaSVarun Prakash 	 * incoming iscsi/tcp socket I/O, and/or failing the connection.
4037e8205ccaSVarun Prakash 	 */
4038e8205ccaSVarun Prakash 	rc = wait_for_completion_interruptible(&conn->rx_login_comp);
4039e8205ccaSVarun Prakash 	if (rc < 0 || iscsi_target_check_conn_state(conn))
40405e0cf5e6SJiang Yi 		goto out;
4041e8205ccaSVarun Prakash 
4042e8205ccaSVarun Prakash 	if (!conn->conn_transport->iscsit_get_rx_pdu)
4043e8205ccaSVarun Prakash 		return 0;
4044e8205ccaSVarun Prakash 
4045e8205ccaSVarun Prakash 	conn->conn_transport->iscsit_get_rx_pdu(conn);
4046e8205ccaSVarun Prakash 
4047e48354ceSNicholas Bellinger 	if (!signal_pending(current))
4048e48354ceSNicholas Bellinger 		atomic_set(&conn->transport_failed, 1);
40495e0cf5e6SJiang Yi 	iscsit_take_action_for_connection_exit(conn, &conn_freed);
40505e0cf5e6SJiang Yi 
40515e0cf5e6SJiang Yi out:
40525e0cf5e6SJiang Yi 	if (!conn_freed) {
40535e0cf5e6SJiang Yi 		while (!kthread_should_stop()) {
40545e0cf5e6SJiang Yi 			msleep(100);
40555e0cf5e6SJiang Yi 		}
40565e0cf5e6SJiang Yi 	}
40575e0cf5e6SJiang Yi 
4058e48354ceSNicholas Bellinger 	return 0;
4059e48354ceSNicholas Bellinger }
4060e48354ceSNicholas Bellinger 
4061e48354ceSNicholas Bellinger static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
4062e48354ceSNicholas Bellinger {
4063064cdd2dSNicholas Bellinger 	LIST_HEAD(tmp_list);
4064e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
4065e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4066e48354ceSNicholas Bellinger 	/*
4067e48354ceSNicholas Bellinger 	 * We expect this function to only ever be called from either RX or TX
4068e48354ceSNicholas Bellinger 	 * thread context via iscsit_close_connection() once the other context
4069e48354ceSNicholas Bellinger 	 * has been reset -> returned sleeping pre-handler state.
4070e48354ceSNicholas Bellinger 	 */
4071e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
4072064cdd2dSNicholas Bellinger 	list_splice_init(&conn->conn_cmd_list, &tmp_list);
4073e48354ceSNicholas Bellinger 
4074064cdd2dSNicholas Bellinger 	list_for_each_entry(cmd, &tmp_list, i_conn_node) {
4075064cdd2dSNicholas Bellinger 		struct se_cmd *se_cmd = &cmd->se_cmd;
4076e48354ceSNicholas Bellinger 
4077064cdd2dSNicholas Bellinger 		if (se_cmd->se_tfo != NULL) {
407832e36bfbSBart Van Assche 			spin_lock_irq(&se_cmd->t_state_lock);
4079064cdd2dSNicholas Bellinger 			se_cmd->transport_state |= CMD_T_FABRIC_STOP;
408032e36bfbSBart Van Assche 			spin_unlock_irq(&se_cmd->t_state_lock);
4081064cdd2dSNicholas Bellinger 		}
4082e48354ceSNicholas Bellinger 	}
4083e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4084064cdd2dSNicholas Bellinger 
4085064cdd2dSNicholas Bellinger 	list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
4086064cdd2dSNicholas Bellinger 		list_del_init(&cmd->i_conn_node);
4087064cdd2dSNicholas Bellinger 
4088064cdd2dSNicholas Bellinger 		iscsit_increment_maxcmdsn(cmd, sess);
4089064cdd2dSNicholas Bellinger 		iscsit_free_cmd(cmd, true);
4090064cdd2dSNicholas Bellinger 
4091064cdd2dSNicholas Bellinger 	}
4092e48354ceSNicholas Bellinger }
4093e48354ceSNicholas Bellinger 
4094e48354ceSNicholas Bellinger static void iscsit_stop_timers_for_cmds(
4095e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4096e48354ceSNicholas Bellinger {
4097e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd;
4098e48354ceSNicholas Bellinger 
4099e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->cmd_lock);
41002fbb471eSAndy Grover 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
4101e48354ceSNicholas Bellinger 		if (cmd->data_direction == DMA_TO_DEVICE)
4102e48354ceSNicholas Bellinger 			iscsit_stop_dataout_timer(cmd);
4103e48354ceSNicholas Bellinger 	}
4104e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->cmd_lock);
4105e48354ceSNicholas Bellinger }
4106e48354ceSNicholas Bellinger 
4107e48354ceSNicholas Bellinger int iscsit_close_connection(
4108e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4109e48354ceSNicholas Bellinger {
4110e48354ceSNicholas Bellinger 	int conn_logout = (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT);
4111e48354ceSNicholas Bellinger 	struct iscsi_session	*sess = conn->sess;
4112e48354ceSNicholas Bellinger 
4113e48354ceSNicholas Bellinger 	pr_debug("Closing iSCSI connection CID %hu on SID:"
4114e48354ceSNicholas Bellinger 		" %u\n", conn->cid, sess->sid);
4115e48354ceSNicholas Bellinger 	/*
4116b4869ee9SVarun Prakash 	 * Always up conn_logout_comp for the traditional TCP and HW_OFFLOAD
4117b4869ee9SVarun Prakash 	 * case just in case the RX Thread in iscsi_target_rx_opcode() is
4118b4869ee9SVarun Prakash 	 * sleeping and the logout response never got sent because the
4119b4869ee9SVarun Prakash 	 * connection failed.
4120f068fbc8SNicholas Bellinger 	 *
4121f068fbc8SNicholas Bellinger 	 * However for iser-target, isert_wait4logout() is using conn_logout_comp
4122f068fbc8SNicholas Bellinger 	 * to signal logout response TX interrupt completion.  Go ahead and skip
4123f068fbc8SNicholas Bellinger 	 * this for iser since isert_rx_opcode() does not wait on logout failure,
4124f068fbc8SNicholas Bellinger 	 * and to avoid iscsi_conn pointer dereference in iser-target code.
4125e48354ceSNicholas Bellinger 	 */
4126bd027d85SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown)
4127e48354ceSNicholas Bellinger 		complete(&conn->conn_logout_comp);
4128e48354ceSNicholas Bellinger 
412988dcd2daSNicholas Bellinger 	if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) {
413088dcd2daSNicholas Bellinger 		if (conn->tx_thread &&
413188dcd2daSNicholas Bellinger 		    cmpxchg(&conn->tx_thread_active, true, false)) {
413288dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->tx_thread, 1);
413388dcd2daSNicholas Bellinger 			kthread_stop(conn->tx_thread);
413488dcd2daSNicholas Bellinger 		}
413588dcd2daSNicholas Bellinger 	} else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) {
413688dcd2daSNicholas Bellinger 		if (conn->rx_thread &&
413788dcd2daSNicholas Bellinger 		    cmpxchg(&conn->rx_thread_active, true, false)) {
413888dcd2daSNicholas Bellinger 			send_sig(SIGINT, conn->rx_thread, 1);
413988dcd2daSNicholas Bellinger 			kthread_stop(conn->rx_thread);
414088dcd2daSNicholas Bellinger 		}
414188dcd2daSNicholas Bellinger 	}
414288dcd2daSNicholas Bellinger 
414388dcd2daSNicholas Bellinger 	spin_lock(&iscsit_global->ts_bitmap_lock);
414488dcd2daSNicholas Bellinger 	bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
414588dcd2daSNicholas Bellinger 			      get_order(1));
414688dcd2daSNicholas Bellinger 	spin_unlock(&iscsit_global->ts_bitmap_lock);
4147e48354ceSNicholas Bellinger 
4148e48354ceSNicholas Bellinger 	iscsit_stop_timers_for_cmds(conn);
4149e48354ceSNicholas Bellinger 	iscsit_stop_nopin_response_timer(conn);
4150e48354ceSNicholas Bellinger 	iscsit_stop_nopin_timer(conn);
4151defd8848SNicholas Bellinger 
415276261adaSBart Van Assche 	if (conn->conn_transport->iscsit_wait_conn)
415376261adaSBart Van Assche 		conn->conn_transport->iscsit_wait_conn(conn);
415476261adaSBart Van Assche 
4155e48354ceSNicholas Bellinger 	/*
4156e48354ceSNicholas Bellinger 	 * During Connection recovery drop unacknowledged out of order
4157e48354ceSNicholas Bellinger 	 * commands for this connection, and prepare the other commands
415853c561dcSBart Van Assche 	 * for reallegiance.
4159e48354ceSNicholas Bellinger 	 *
4160e48354ceSNicholas Bellinger 	 * During normal operation clear the out of order commands (but
4161e48354ceSNicholas Bellinger 	 * do not free the struct iscsi_ooo_cmdsn's) and release all
4162e48354ceSNicholas Bellinger 	 * struct iscsi_cmds.
4163e48354ceSNicholas Bellinger 	 */
4164e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery)) {
4165e48354ceSNicholas Bellinger 		iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(conn);
416653c561dcSBart Van Assche 		iscsit_prepare_cmds_for_reallegiance(conn);
4167e48354ceSNicholas Bellinger 	} else {
4168e48354ceSNicholas Bellinger 		iscsit_clear_ooo_cmdsns_for_conn(conn);
4169e48354ceSNicholas Bellinger 		iscsit_release_commands_from_conn(conn);
4170e48354ceSNicholas Bellinger 	}
4171bbc05048SNicholas Bellinger 	iscsit_free_queue_reqs_for_conn(conn);
4172e48354ceSNicholas Bellinger 
4173e48354ceSNicholas Bellinger 	/*
4174e48354ceSNicholas Bellinger 	 * Handle decrementing session or connection usage count if
4175e48354ceSNicholas Bellinger 	 * a logout response was not able to be sent because the
4176e48354ceSNicholas Bellinger 	 * connection failed.  Fall back to Session Recovery here.
4177e48354ceSNicholas Bellinger 	 */
4178e48354ceSNicholas Bellinger 	if (atomic_read(&conn->conn_logout_remove)) {
4179e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_SESSION) {
4180e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4181e48354ceSNicholas Bellinger 			iscsit_dec_session_usage_count(sess);
4182e48354ceSNicholas Bellinger 		}
4183e48354ceSNicholas Bellinger 		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION)
4184e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4185e48354ceSNicholas Bellinger 
4186e48354ceSNicholas Bellinger 		atomic_set(&conn->conn_logout_remove, 0);
4187e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 0);
4188e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4189e48354ceSNicholas Bellinger 	}
4190e48354ceSNicholas Bellinger 
4191e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4192e48354ceSNicholas Bellinger 	list_del(&conn->conn_list);
4193e48354ceSNicholas Bellinger 
4194e48354ceSNicholas Bellinger 	/*
4195e48354ceSNicholas Bellinger 	 * Attempt to let the Initiator know this connection failed by
4196e48354ceSNicholas Bellinger 	 * sending an Connection Dropped Async Message on another
4197e48354ceSNicholas Bellinger 	 * active connection.
4198e48354ceSNicholas Bellinger 	 */
4199e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_recovery))
4200e48354ceSNicholas Bellinger 		iscsit_build_conn_drop_async_message(conn);
4201e48354ceSNicholas Bellinger 
4202e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4203e48354ceSNicholas Bellinger 
4204e48354ceSNicholas Bellinger 	/*
4205e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection,
4206e48354ceSNicholas Bellinger 	 * up the connection reinstatement semaphore that is being blocked on
4207e48354ceSNicholas Bellinger 	 * in iscsit_cause_connection_reinstatement().
4208e48354ceSNicholas Bellinger 	 */
4209e48354ceSNicholas Bellinger 	spin_lock_bh(&conn->state_lock);
4210e48354ceSNicholas Bellinger 	if (atomic_read(&conn->sleep_on_conn_wait_comp)) {
4211e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4212e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_comp);
4213e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4214e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4215e48354ceSNicholas Bellinger 	}
4216e48354ceSNicholas Bellinger 
4217e48354ceSNicholas Bellinger 	/*
4218e48354ceSNicholas Bellinger 	 * If connection reinstatement is being performed on this connection
4219e48354ceSNicholas Bellinger 	 * by receiving a REMOVECONNFORRECOVERY logout request, up the
4220e48354ceSNicholas Bellinger 	 * connection wait rcfr semaphore that is being blocked on
4221e48354ceSNicholas Bellinger 	 * an iscsit_connection_reinstatement_rcfr().
4222e48354ceSNicholas Bellinger 	 */
4223e48354ceSNicholas Bellinger 	if (atomic_read(&conn->connection_wait_rcfr)) {
4224e48354ceSNicholas Bellinger 		spin_unlock_bh(&conn->state_lock);
4225e48354ceSNicholas Bellinger 		complete(&conn->conn_wait_rcfr_comp);
4226e48354ceSNicholas Bellinger 		wait_for_completion(&conn->conn_post_wait_comp);
4227e48354ceSNicholas Bellinger 		spin_lock_bh(&conn->state_lock);
4228e48354ceSNicholas Bellinger 	}
4229e48354ceSNicholas Bellinger 	atomic_set(&conn->connection_reinstatement, 1);
4230e48354ceSNicholas Bellinger 	spin_unlock_bh(&conn->state_lock);
4231e48354ceSNicholas Bellinger 
4232e48354ceSNicholas Bellinger 	/*
4233e48354ceSNicholas Bellinger 	 * If any other processes are accessing this connection pointer we
4234e48354ceSNicholas Bellinger 	 * must wait until they have completed.
4235e48354ceSNicholas Bellinger 	 */
4236e48354ceSNicholas Bellinger 	iscsit_check_conn_usage_count(conn);
4237e9d3009cSBart Van Assche 	target_sess_cmd_list_set_waiting(sess->se_sess);
4238e9d3009cSBart Van Assche 	target_wait_for_sess_cmds(sess->se_sess);
4239e48354ceSNicholas Bellinger 
424069110e3cSHerbert Xu 	ahash_request_free(conn->conn_tx_hash);
424169110e3cSHerbert Xu 	if (conn->conn_rx_hash) {
424269110e3cSHerbert Xu 		struct crypto_ahash *tfm;
424369110e3cSHerbert Xu 
424469110e3cSHerbert Xu 		tfm = crypto_ahash_reqtfm(conn->conn_rx_hash);
424569110e3cSHerbert Xu 		ahash_request_free(conn->conn_rx_hash);
424669110e3cSHerbert Xu 		crypto_free_ahash(tfm);
424769110e3cSHerbert Xu 	}
4248e48354ceSNicholas Bellinger 
4249bf6932f4SAl Viro 	if (conn->sock)
4250e48354ceSNicholas Bellinger 		sock_release(conn->sock);
4251baa4d64bSNicholas Bellinger 
4252baa4d64bSNicholas Bellinger 	if (conn->conn_transport->iscsit_free_conn)
4253baa4d64bSNicholas Bellinger 		conn->conn_transport->iscsit_free_conn(conn);
4254baa4d64bSNicholas Bellinger 
4255e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
4256e48354ceSNicholas Bellinger 	conn->conn_state = TARG_CONN_STATE_FREE;
425705a86e78SMike Christie 	iscsit_free_conn(conn);
4258e48354ceSNicholas Bellinger 
4259e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4260e48354ceSNicholas Bellinger 	atomic_dec(&sess->nconn);
4261e48354ceSNicholas Bellinger 	pr_debug("Decremented iSCSI connection count to %hu from node:"
4262e48354ceSNicholas Bellinger 		" %s\n", atomic_read(&sess->nconn),
4263e48354ceSNicholas Bellinger 		sess->sess_ops->InitiatorName);
4264e48354ceSNicholas Bellinger 	/*
4265e48354ceSNicholas Bellinger 	 * Make sure that if one connection fails in an non ERL=2 iSCSI
4266e48354ceSNicholas Bellinger 	 * Session that they all fail.
4267e48354ceSNicholas Bellinger 	 */
4268e48354ceSNicholas Bellinger 	if ((sess->sess_ops->ErrorRecoveryLevel != 2) && !conn_logout &&
4269e48354ceSNicholas Bellinger 	     !atomic_read(&sess->session_logout))
4270e48354ceSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4271e48354ceSNicholas Bellinger 
4272e48354ceSNicholas Bellinger 	/*
4273e48354ceSNicholas Bellinger 	 * If this was not the last connection in the session, and we are
4274e48354ceSNicholas Bellinger 	 * performing session reinstatement or falling back to ERL=0, call
4275e48354ceSNicholas Bellinger 	 * iscsit_stop_session() without sleeping to shutdown the other
4276e48354ceSNicholas Bellinger 	 * active connections.
4277e48354ceSNicholas Bellinger 	 */
4278e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4279e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_reinstatement) &&
4280e48354ceSNicholas Bellinger 		    !atomic_read(&sess->session_fall_back_to_erl0)) {
4281e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4282e48354ceSNicholas Bellinger 			return 0;
4283e48354ceSNicholas Bellinger 		}
4284e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_stop_active)) {
4285e48354ceSNicholas Bellinger 			atomic_set(&sess->session_stop_active, 1);
4286e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4287e48354ceSNicholas Bellinger 			iscsit_stop_session(sess, 0, 0);
4288e48354ceSNicholas Bellinger 			return 0;
4289e48354ceSNicholas Bellinger 		}
4290e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4291e48354ceSNicholas Bellinger 		return 0;
4292e48354ceSNicholas Bellinger 	}
4293e48354ceSNicholas Bellinger 
4294e48354ceSNicholas Bellinger 	/*
4295e48354ceSNicholas Bellinger 	 * If this was the last connection in the session and one of the
4296e48354ceSNicholas Bellinger 	 * following is occurring:
4297e48354ceSNicholas Bellinger 	 *
4298e48354ceSNicholas Bellinger 	 * Session Reinstatement is not being performed, and are falling back
4299e48354ceSNicholas Bellinger 	 * to ERL=0 call iscsit_close_session().
4300e48354ceSNicholas Bellinger 	 *
4301e48354ceSNicholas Bellinger 	 * Session Logout was requested.  iscsit_close_session() will be called
4302e48354ceSNicholas Bellinger 	 * elsewhere.
4303e48354ceSNicholas Bellinger 	 *
4304e48354ceSNicholas Bellinger 	 * Session Continuation is not being performed, start the Time2Retain
4305e48354ceSNicholas Bellinger 	 * handler and check if sleep_on_sess_wait_sem is active.
4306e48354ceSNicholas Bellinger 	 */
4307e48354ceSNicholas Bellinger 	if (!atomic_read(&sess->session_reinstatement) &&
4308e48354ceSNicholas Bellinger 	     atomic_read(&sess->session_fall_back_to_erl0)) {
4309e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
431044f33d0fSChristoph Hellwig 		iscsit_close_session(sess);
4311e48354ceSNicholas Bellinger 
4312e48354ceSNicholas Bellinger 		return 0;
4313e48354ceSNicholas Bellinger 	} else if (atomic_read(&sess->session_logout)) {
4314e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4315e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FREE;
4316e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4317e48354ceSNicholas Bellinger 
4318e48354ceSNicholas Bellinger 		if (atomic_read(&sess->sleep_on_sess_wait_comp))
4319e48354ceSNicholas Bellinger 			complete(&sess->session_wait_comp);
4320e48354ceSNicholas Bellinger 
4321e48354ceSNicholas Bellinger 		return 0;
4322e48354ceSNicholas Bellinger 	} else {
4323e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4324e48354ceSNicholas Bellinger 		sess->session_state = TARG_SESS_STATE_FAILED;
4325e48354ceSNicholas Bellinger 
4326e48354ceSNicholas Bellinger 		if (!atomic_read(&sess->session_continuation)) {
4327e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4328e48354ceSNicholas Bellinger 			iscsit_start_time2retain_handler(sess);
4329e48354ceSNicholas Bellinger 		} else
4330e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4331e48354ceSNicholas Bellinger 
4332e48354ceSNicholas Bellinger 		if (atomic_read(&sess->sleep_on_sess_wait_comp))
4333e48354ceSNicholas Bellinger 			complete(&sess->session_wait_comp);
4334e48354ceSNicholas Bellinger 
4335e48354ceSNicholas Bellinger 		return 0;
4336e48354ceSNicholas Bellinger 	}
4337e48354ceSNicholas Bellinger }
4338e48354ceSNicholas Bellinger 
433944f33d0fSChristoph Hellwig /*
434044f33d0fSChristoph Hellwig  * If the iSCSI Session for the iSCSI Initiator Node exists,
434144f33d0fSChristoph Hellwig  * forcefully shutdown the iSCSI NEXUS.
434244f33d0fSChristoph Hellwig  */
4343e48354ceSNicholas Bellinger int iscsit_close_session(struct iscsi_session *sess)
4344e48354ceSNicholas Bellinger {
434560bfcf8eSAndy Grover 	struct iscsi_portal_group *tpg = sess->tpg;
4346e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4347e48354ceSNicholas Bellinger 
4348e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4349e48354ceSNicholas Bellinger 		pr_err("%d connection(s) still exist for iSCSI session"
4350e48354ceSNicholas Bellinger 			" to %s\n", atomic_read(&sess->nconn),
4351e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4352e48354ceSNicholas Bellinger 		BUG();
4353e48354ceSNicholas Bellinger 	}
4354e48354ceSNicholas Bellinger 
4355e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4356e48354ceSNicholas Bellinger 	atomic_set(&sess->session_logout, 1);
4357e48354ceSNicholas Bellinger 	atomic_set(&sess->session_reinstatement, 1);
4358e48354ceSNicholas Bellinger 	iscsit_stop_time2retain_timer(sess);
4359e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4360e48354ceSNicholas Bellinger 
4361e48354ceSNicholas Bellinger 	/*
4362e48354ceSNicholas Bellinger 	 * transport_deregister_session_configfs() will clear the
4363e48354ceSNicholas Bellinger 	 * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context
4364e48354ceSNicholas Bellinger 	 * can be setting it again with __transport_register_session() in
4365e48354ceSNicholas Bellinger 	 * iscsi_post_login_handler() again after the iscsit_stop_session()
4366e48354ceSNicholas Bellinger 	 * completes in iscsi_np context.
4367e48354ceSNicholas Bellinger 	 */
4368e48354ceSNicholas Bellinger 	transport_deregister_session_configfs(sess->se_sess);
4369e48354ceSNicholas Bellinger 
4370e48354ceSNicholas Bellinger 	/*
4371e48354ceSNicholas Bellinger 	 * If any other processes are accessing this session pointer we must
4372e48354ceSNicholas Bellinger 	 * wait until they have completed.  If we are in an interrupt (the
4373e48354ceSNicholas Bellinger 	 * time2retain handler) and contain and active session usage count we
4374e48354ceSNicholas Bellinger 	 * restart the timer and exit.
4375e48354ceSNicholas Bellinger 	 */
4376e48354ceSNicholas Bellinger 	if (!in_interrupt()) {
4377e48354ceSNicholas Bellinger 		if (iscsit_check_session_usage_count(sess) == 1)
4378e48354ceSNicholas Bellinger 			iscsit_stop_session(sess, 1, 1);
4379e48354ceSNicholas Bellinger 	} else {
4380e48354ceSNicholas Bellinger 		if (iscsit_check_session_usage_count(sess) == 2) {
4381e48354ceSNicholas Bellinger 			atomic_set(&sess->session_logout, 0);
4382e48354ceSNicholas Bellinger 			iscsit_start_time2retain_handler(sess);
4383e48354ceSNicholas Bellinger 			return 0;
4384e48354ceSNicholas Bellinger 		}
4385e48354ceSNicholas Bellinger 	}
4386e48354ceSNicholas Bellinger 
4387e48354ceSNicholas Bellinger 	transport_deregister_session(sess->se_sess);
4388e48354ceSNicholas Bellinger 
4389e48354ceSNicholas Bellinger 	if (sess->sess_ops->ErrorRecoveryLevel == 2)
4390902ff860SColin Ian King 		iscsit_free_connection_recovery_entries(sess);
4391e48354ceSNicholas Bellinger 
4392e48354ceSNicholas Bellinger 	iscsit_free_all_ooo_cmdsns(sess);
4393e48354ceSNicholas Bellinger 
4394e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4395e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
4396e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FREE;
4397e48354ceSNicholas Bellinger 	pr_debug("Released iSCSI session from node: %s\n",
4398e48354ceSNicholas Bellinger 			sess->sess_ops->InitiatorName);
4399e48354ceSNicholas Bellinger 	tpg->nsessions--;
4400e48354ceSNicholas Bellinger 	if (tpg->tpg_tiqn)
4401e48354ceSNicholas Bellinger 		tpg->tpg_tiqn->tiqn_nsessions--;
4402e48354ceSNicholas Bellinger 
4403e48354ceSNicholas Bellinger 	pr_debug("Decremented number of active iSCSI Sessions on"
4404e48354ceSNicholas Bellinger 		" iSCSI TPG: %hu to %u\n", tpg->tpgt, tpg->nsessions);
4405e48354ceSNicholas Bellinger 
440631ff0ceeSMatthew Wilcox 	ida_free(&sess_ida, sess->session_index);
4407e48354ceSNicholas Bellinger 	kfree(sess->sess_ops);
4408e48354ceSNicholas Bellinger 	sess->sess_ops = NULL;
4409e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4410e48354ceSNicholas Bellinger 
4411e48354ceSNicholas Bellinger 	kfree(sess);
4412e48354ceSNicholas Bellinger 	return 0;
4413e48354ceSNicholas Bellinger }
4414e48354ceSNicholas Bellinger 
4415e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_closesession(
4416e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4417e48354ceSNicholas Bellinger {
4418e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4419007d038bSNicholas Bellinger 	int sleep = 1;
4420007d038bSNicholas Bellinger 	/*
4421007d038bSNicholas Bellinger 	 * Traditional iscsi/tcp will invoke this logic from TX thread
4422007d038bSNicholas Bellinger 	 * context during session logout, so clear tx_thread_active and
4423007d038bSNicholas Bellinger 	 * sleep if iscsit_close_connection() has not already occured.
4424007d038bSNicholas Bellinger 	 *
4425007d038bSNicholas Bellinger 	 * Since iser-target invokes this logic from it's own workqueue,
4426007d038bSNicholas Bellinger 	 * always sleep waiting for RX/TX thread shutdown to complete
4427007d038bSNicholas Bellinger 	 * within iscsit_close_connection().
4428007d038bSNicholas Bellinger 	 */
4429105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4430007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4431105fa2f4SNicholas Bellinger 		if (!sleep)
4432105fa2f4SNicholas Bellinger 			return;
4433105fa2f4SNicholas Bellinger 	}
4434e48354ceSNicholas Bellinger 
4435e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4436e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4437e48354ceSNicholas Bellinger 
4438e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
443988dcd2daSNicholas Bellinger 	iscsit_stop_session(sess, sleep, sleep);
4440e48354ceSNicholas Bellinger 	iscsit_dec_session_usage_count(sess);
444144f33d0fSChristoph Hellwig 	iscsit_close_session(sess);
4442e48354ceSNicholas Bellinger }
4443e48354ceSNicholas Bellinger 
4444e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_samecid(
4445e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4446e48354ceSNicholas Bellinger {
4447007d038bSNicholas Bellinger 	int sleep = 1;
4448007d038bSNicholas Bellinger 
4449105fa2f4SNicholas Bellinger 	if (!conn->conn_transport->rdma_shutdown) {
4450007d038bSNicholas Bellinger 		sleep = cmpxchg(&conn->tx_thread_active, true, false);
4451105fa2f4SNicholas Bellinger 		if (!sleep)
4452105fa2f4SNicholas Bellinger 			return;
4453105fa2f4SNicholas Bellinger 	}
4454e48354ceSNicholas Bellinger 
4455e48354ceSNicholas Bellinger 	atomic_set(&conn->conn_logout_remove, 0);
4456e48354ceSNicholas Bellinger 	complete(&conn->conn_logout_comp);
4457e48354ceSNicholas Bellinger 
445888dcd2daSNicholas Bellinger 	iscsit_cause_connection_reinstatement(conn, sleep);
4459e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(conn);
4460e48354ceSNicholas Bellinger }
4461e48354ceSNicholas Bellinger 
4462e48354ceSNicholas Bellinger static void iscsit_logout_post_handler_diffcid(
4463e48354ceSNicholas Bellinger 	struct iscsi_conn *conn,
4464e48354ceSNicholas Bellinger 	u16 cid)
4465e48354ceSNicholas Bellinger {
4466e48354ceSNicholas Bellinger 	struct iscsi_conn *l_conn;
4467e48354ceSNicholas Bellinger 	struct iscsi_session *sess = conn->sess;
4468b53b0d99SNicholas Bellinger 	bool conn_found = false;
4469e48354ceSNicholas Bellinger 
4470e48354ceSNicholas Bellinger 	if (!sess)
4471e48354ceSNicholas Bellinger 		return;
4472e48354ceSNicholas Bellinger 
4473e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4474e48354ceSNicholas Bellinger 	list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) {
4475e48354ceSNicholas Bellinger 		if (l_conn->cid == cid) {
4476e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(l_conn);
4477b53b0d99SNicholas Bellinger 			conn_found = true;
4478e48354ceSNicholas Bellinger 			break;
4479e48354ceSNicholas Bellinger 		}
4480e48354ceSNicholas Bellinger 	}
4481e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4482e48354ceSNicholas Bellinger 
4483b53b0d99SNicholas Bellinger 	if (!conn_found)
4484e48354ceSNicholas Bellinger 		return;
4485e48354ceSNicholas Bellinger 
4486e48354ceSNicholas Bellinger 	if (l_conn->sock)
4487e48354ceSNicholas Bellinger 		l_conn->sock->ops->shutdown(l_conn->sock, RCV_SHUTDOWN);
4488e48354ceSNicholas Bellinger 
4489e48354ceSNicholas Bellinger 	spin_lock_bh(&l_conn->state_lock);
4490e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
4491e48354ceSNicholas Bellinger 	l_conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
4492e48354ceSNicholas Bellinger 	spin_unlock_bh(&l_conn->state_lock);
4493e48354ceSNicholas Bellinger 
4494e48354ceSNicholas Bellinger 	iscsit_cause_connection_reinstatement(l_conn, 1);
4495e48354ceSNicholas Bellinger 	iscsit_dec_conn_usage_count(l_conn);
4496e48354ceSNicholas Bellinger }
4497e48354ceSNicholas Bellinger 
4498e48354ceSNicholas Bellinger /*
4499e48354ceSNicholas Bellinger  *	Return of 0 causes the TX thread to restart.
4500e48354ceSNicholas Bellinger  */
45012ec5a8c1SNicholas Bellinger int iscsit_logout_post_handler(
4502e48354ceSNicholas Bellinger 	struct iscsi_cmd *cmd,
4503e48354ceSNicholas Bellinger 	struct iscsi_conn *conn)
4504e48354ceSNicholas Bellinger {
4505e48354ceSNicholas Bellinger 	int ret = 0;
4506e48354ceSNicholas Bellinger 
4507e48354ceSNicholas Bellinger 	switch (cmd->logout_reason) {
4508e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
4509e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4510e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4511e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4512e48354ceSNicholas Bellinger 		default:
4513e48354ceSNicholas Bellinger 			iscsit_logout_post_handler_closesession(conn);
4514e48354ceSNicholas Bellinger 			break;
4515e48354ceSNicholas Bellinger 		}
4516e48354ceSNicholas Bellinger 		ret = 0;
4517e48354ceSNicholas Bellinger 		break;
4518e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
4519e48354ceSNicholas Bellinger 		if (conn->cid == cmd->logout_cid) {
4520e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4521e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4522e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4523e48354ceSNicholas Bellinger 			default:
4524e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_samecid(conn);
4525e48354ceSNicholas Bellinger 				break;
4526e48354ceSNicholas Bellinger 			}
4527e48354ceSNicholas Bellinger 			ret = 0;
4528e48354ceSNicholas Bellinger 		} else {
4529e48354ceSNicholas Bellinger 			switch (cmd->logout_response) {
4530e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_SUCCESS:
4531e48354ceSNicholas Bellinger 				iscsit_logout_post_handler_diffcid(conn,
4532e48354ceSNicholas Bellinger 					cmd->logout_cid);
4533e48354ceSNicholas Bellinger 				break;
4534e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CID_NOT_FOUND:
4535e48354ceSNicholas Bellinger 			case ISCSI_LOGOUT_CLEANUP_FAILED:
4536e48354ceSNicholas Bellinger 			default:
4537e48354ceSNicholas Bellinger 				break;
4538e48354ceSNicholas Bellinger 			}
4539e48354ceSNicholas Bellinger 			ret = 1;
4540e48354ceSNicholas Bellinger 		}
4541e48354ceSNicholas Bellinger 		break;
4542e48354ceSNicholas Bellinger 	case ISCSI_LOGOUT_REASON_RECOVERY:
4543e48354ceSNicholas Bellinger 		switch (cmd->logout_response) {
4544e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_SUCCESS:
4545e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CID_NOT_FOUND:
4546e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
4547e48354ceSNicholas Bellinger 		case ISCSI_LOGOUT_CLEANUP_FAILED:
4548e48354ceSNicholas Bellinger 		default:
4549e48354ceSNicholas Bellinger 			break;
4550e48354ceSNicholas Bellinger 		}
4551e48354ceSNicholas Bellinger 		ret = 1;
4552e48354ceSNicholas Bellinger 		break;
4553e48354ceSNicholas Bellinger 	default:
4554e48354ceSNicholas Bellinger 		break;
4555e48354ceSNicholas Bellinger 
4556e48354ceSNicholas Bellinger 	}
4557e48354ceSNicholas Bellinger 	return ret;
4558e48354ceSNicholas Bellinger }
45592ec5a8c1SNicholas Bellinger EXPORT_SYMBOL(iscsit_logout_post_handler);
4560e48354ceSNicholas Bellinger 
4561e48354ceSNicholas Bellinger void iscsit_fail_session(struct iscsi_session *sess)
4562e48354ceSNicholas Bellinger {
4563e48354ceSNicholas Bellinger 	struct iscsi_conn *conn;
4564e48354ceSNicholas Bellinger 
4565e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4566e48354ceSNicholas Bellinger 	list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
4567e48354ceSNicholas Bellinger 		pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
4568e48354ceSNicholas Bellinger 		conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
4569e48354ceSNicholas Bellinger 	}
4570e48354ceSNicholas Bellinger 	spin_unlock_bh(&sess->conn_lock);
4571e48354ceSNicholas Bellinger 
4572e48354ceSNicholas Bellinger 	pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
4573e48354ceSNicholas Bellinger 	sess->session_state = TARG_SESS_STATE_FAILED;
4574e48354ceSNicholas Bellinger }
4575e48354ceSNicholas Bellinger 
4576e48354ceSNicholas Bellinger int iscsit_free_session(struct iscsi_session *sess)
4577e48354ceSNicholas Bellinger {
4578e48354ceSNicholas Bellinger 	u16 conn_count = atomic_read(&sess->nconn);
4579e48354ceSNicholas Bellinger 	struct iscsi_conn *conn, *conn_tmp = NULL;
4580e48354ceSNicholas Bellinger 	int is_last;
4581e48354ceSNicholas Bellinger 
4582e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4583e48354ceSNicholas Bellinger 	atomic_set(&sess->sleep_on_sess_wait_comp, 1);
4584e48354ceSNicholas Bellinger 
4585e48354ceSNicholas Bellinger 	list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
4586e48354ceSNicholas Bellinger 			conn_list) {
4587e48354ceSNicholas Bellinger 		if (conn_count == 0)
4588e48354ceSNicholas Bellinger 			break;
4589e48354ceSNicholas Bellinger 
4590e48354ceSNicholas Bellinger 		if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
4591e48354ceSNicholas Bellinger 			is_last = 1;
4592e48354ceSNicholas Bellinger 		} else {
4593e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn_tmp);
4594e48354ceSNicholas Bellinger 			is_last = 0;
4595e48354ceSNicholas Bellinger 		}
4596e48354ceSNicholas Bellinger 		iscsit_inc_conn_usage_count(conn);
4597e48354ceSNicholas Bellinger 
4598e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4599e48354ceSNicholas Bellinger 		iscsit_cause_connection_reinstatement(conn, 1);
4600e48354ceSNicholas Bellinger 		spin_lock_bh(&sess->conn_lock);
4601e48354ceSNicholas Bellinger 
4602e48354ceSNicholas Bellinger 		iscsit_dec_conn_usage_count(conn);
4603e48354ceSNicholas Bellinger 		if (is_last == 0)
4604e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn_tmp);
4605e48354ceSNicholas Bellinger 
4606e48354ceSNicholas Bellinger 		conn_count--;
4607e48354ceSNicholas Bellinger 	}
4608e48354ceSNicholas Bellinger 
4609e48354ceSNicholas Bellinger 	if (atomic_read(&sess->nconn)) {
4610e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4611e48354ceSNicholas Bellinger 		wait_for_completion(&sess->session_wait_comp);
4612e48354ceSNicholas Bellinger 	} else
4613e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4614e48354ceSNicholas Bellinger 
461544f33d0fSChristoph Hellwig 	iscsit_close_session(sess);
4616e48354ceSNicholas Bellinger 	return 0;
4617e48354ceSNicholas Bellinger }
4618e48354ceSNicholas Bellinger 
4619e48354ceSNicholas Bellinger void iscsit_stop_session(
4620e48354ceSNicholas Bellinger 	struct iscsi_session *sess,
4621e48354ceSNicholas Bellinger 	int session_sleep,
4622e48354ceSNicholas Bellinger 	int connection_sleep)
4623e48354ceSNicholas Bellinger {
4624e48354ceSNicholas Bellinger 	u16 conn_count = atomic_read(&sess->nconn);
4625e48354ceSNicholas Bellinger 	struct iscsi_conn *conn, *conn_tmp = NULL;
4626e48354ceSNicholas Bellinger 	int is_last;
4627e48354ceSNicholas Bellinger 
4628e48354ceSNicholas Bellinger 	spin_lock_bh(&sess->conn_lock);
4629e48354ceSNicholas Bellinger 	if (session_sleep)
4630e48354ceSNicholas Bellinger 		atomic_set(&sess->sleep_on_sess_wait_comp, 1);
4631e48354ceSNicholas Bellinger 
4632e48354ceSNicholas Bellinger 	if (connection_sleep) {
4633e48354ceSNicholas Bellinger 		list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
4634e48354ceSNicholas Bellinger 				conn_list) {
4635e48354ceSNicholas Bellinger 			if (conn_count == 0)
4636e48354ceSNicholas Bellinger 				break;
4637e48354ceSNicholas Bellinger 
4638e48354ceSNicholas Bellinger 			if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
4639e48354ceSNicholas Bellinger 				is_last = 1;
4640e48354ceSNicholas Bellinger 			} else {
4641e48354ceSNicholas Bellinger 				iscsit_inc_conn_usage_count(conn_tmp);
4642e48354ceSNicholas Bellinger 				is_last = 0;
4643e48354ceSNicholas Bellinger 			}
4644e48354ceSNicholas Bellinger 			iscsit_inc_conn_usage_count(conn);
4645e48354ceSNicholas Bellinger 
4646e48354ceSNicholas Bellinger 			spin_unlock_bh(&sess->conn_lock);
4647e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 1);
4648e48354ceSNicholas Bellinger 			spin_lock_bh(&sess->conn_lock);
4649e48354ceSNicholas Bellinger 
4650e48354ceSNicholas Bellinger 			iscsit_dec_conn_usage_count(conn);
4651e48354ceSNicholas Bellinger 			if (is_last == 0)
4652e48354ceSNicholas Bellinger 				iscsit_dec_conn_usage_count(conn_tmp);
4653e48354ceSNicholas Bellinger 			conn_count--;
4654e48354ceSNicholas Bellinger 		}
4655e48354ceSNicholas Bellinger 	} else {
4656e48354ceSNicholas Bellinger 		list_for_each_entry(conn, &sess->sess_conn_list, conn_list)
4657e48354ceSNicholas Bellinger 			iscsit_cause_connection_reinstatement(conn, 0);
4658e48354ceSNicholas Bellinger 	}
4659e48354ceSNicholas Bellinger 
4660e48354ceSNicholas Bellinger 	if (session_sleep && atomic_read(&sess->nconn)) {
4661e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4662e48354ceSNicholas Bellinger 		wait_for_completion(&sess->session_wait_comp);
4663e48354ceSNicholas Bellinger 	} else
4664e48354ceSNicholas Bellinger 		spin_unlock_bh(&sess->conn_lock);
4665e48354ceSNicholas Bellinger }
4666e48354ceSNicholas Bellinger 
4667e48354ceSNicholas Bellinger int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
4668e48354ceSNicholas Bellinger {
4669e48354ceSNicholas Bellinger 	struct iscsi_session *sess;
4670e48354ceSNicholas Bellinger 	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
4671e48354ceSNicholas Bellinger 	struct se_session *se_sess, *se_sess_tmp;
4672417c20a9SNicholas Bellinger 	LIST_HEAD(free_list);
4673e48354ceSNicholas Bellinger 	int session_count = 0;
4674e48354ceSNicholas Bellinger 
4675e48354ceSNicholas Bellinger 	spin_lock_bh(&se_tpg->session_lock);
4676e48354ceSNicholas Bellinger 	if (tpg->nsessions && !force) {
4677e48354ceSNicholas Bellinger 		spin_unlock_bh(&se_tpg->session_lock);
4678e48354ceSNicholas Bellinger 		return -1;
4679e48354ceSNicholas Bellinger 	}
4680e48354ceSNicholas Bellinger 
4681e48354ceSNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
4682e48354ceSNicholas Bellinger 			sess_list) {
4683e48354ceSNicholas Bellinger 		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
4684e48354ceSNicholas Bellinger 
4685e48354ceSNicholas Bellinger 		spin_lock(&sess->conn_lock);
4686e48354ceSNicholas Bellinger 		if (atomic_read(&sess->session_fall_back_to_erl0) ||
4687e48354ceSNicholas Bellinger 		    atomic_read(&sess->session_logout) ||
4688e48354ceSNicholas Bellinger 		    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
4689e48354ceSNicholas Bellinger 			spin_unlock(&sess->conn_lock);
4690e48354ceSNicholas Bellinger 			continue;
4691e48354ceSNicholas Bellinger 		}
4692e48354ceSNicholas Bellinger 		atomic_set(&sess->session_reinstatement, 1);
4693197b806aSNicholas Bellinger 		atomic_set(&sess->session_fall_back_to_erl0, 1);
4694e48354ceSNicholas Bellinger 		spin_unlock(&sess->conn_lock);
4695e48354ceSNicholas Bellinger 
4696417c20a9SNicholas Bellinger 		list_move_tail(&se_sess->sess_list, &free_list);
4697e48354ceSNicholas Bellinger 	}
4698e48354ceSNicholas Bellinger 	spin_unlock_bh(&se_tpg->session_lock);
4699e48354ceSNicholas Bellinger 
4700417c20a9SNicholas Bellinger 	list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) {
4701417c20a9SNicholas Bellinger 		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
4702417c20a9SNicholas Bellinger 
4703417c20a9SNicholas Bellinger 		iscsit_free_session(sess);
4704417c20a9SNicholas Bellinger 		session_count++;
4705417c20a9SNicholas Bellinger 	}
4706417c20a9SNicholas Bellinger 
4707e48354ceSNicholas Bellinger 	pr_debug("Released %d iSCSI Session(s) from Target Portal"
4708e48354ceSNicholas Bellinger 			" Group: %hu\n", session_count, tpg->tpgt);
4709e48354ceSNicholas Bellinger 	return 0;
4710e48354ceSNicholas Bellinger }
4711e48354ceSNicholas Bellinger 
4712e48354ceSNicholas Bellinger MODULE_DESCRIPTION("iSCSI-Target Driver for mainline target infrastructure");
4713e48354ceSNicholas Bellinger MODULE_VERSION("4.1.x");
4714e48354ceSNicholas Bellinger MODULE_AUTHOR("nab@Linux-iSCSI.org");
4715e48354ceSNicholas Bellinger MODULE_LICENSE("GPL");
4716e48354ceSNicholas Bellinger 
4717e48354ceSNicholas Bellinger module_init(iscsi_target_init_module);
4718e48354ceSNicholas Bellinger module_exit(iscsi_target_cleanup_module);
4719