xref: /linux/drivers/infiniband/ulp/srp/ib_srp.c (revision 0fbb37dd82998b5c83355997b3bdba2806968ac7)
1aef9ec39SRoland Dreier /*
2aef9ec39SRoland Dreier  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
3aef9ec39SRoland Dreier  *
4aef9ec39SRoland Dreier  * This software is available to you under a choice of one of two
5aef9ec39SRoland Dreier  * licenses.  You may choose to be licensed under the terms of the GNU
6aef9ec39SRoland Dreier  * General Public License (GPL) Version 2, available from the file
7aef9ec39SRoland Dreier  * COPYING in the main directory of this source tree, or the
8aef9ec39SRoland Dreier  * OpenIB.org BSD license below:
9aef9ec39SRoland Dreier  *
10aef9ec39SRoland Dreier  *     Redistribution and use in source and binary forms, with or
11aef9ec39SRoland Dreier  *     without modification, are permitted provided that the following
12aef9ec39SRoland Dreier  *     conditions are met:
13aef9ec39SRoland Dreier  *
14aef9ec39SRoland Dreier  *      - Redistributions of source code must retain the above
15aef9ec39SRoland Dreier  *        copyright notice, this list of conditions and the following
16aef9ec39SRoland Dreier  *        disclaimer.
17aef9ec39SRoland Dreier  *
18aef9ec39SRoland Dreier  *      - Redistributions in binary form must reproduce the above
19aef9ec39SRoland Dreier  *        copyright notice, this list of conditions and the following
20aef9ec39SRoland Dreier  *        disclaimer in the documentation and/or other materials
21aef9ec39SRoland Dreier  *        provided with the distribution.
22aef9ec39SRoland Dreier  *
23aef9ec39SRoland Dreier  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24aef9ec39SRoland Dreier  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25aef9ec39SRoland Dreier  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26aef9ec39SRoland Dreier  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27aef9ec39SRoland Dreier  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28aef9ec39SRoland Dreier  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29aef9ec39SRoland Dreier  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30aef9ec39SRoland Dreier  * SOFTWARE.
31aef9ec39SRoland Dreier  */
32aef9ec39SRoland Dreier 
33d236cd0eSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34e0bda7d8SBart Van Assche 
35aef9ec39SRoland Dreier #include <linux/module.h>
36aef9ec39SRoland Dreier #include <linux/init.h>
37aef9ec39SRoland Dreier #include <linux/slab.h>
38aef9ec39SRoland Dreier #include <linux/err.h>
39aef9ec39SRoland Dreier #include <linux/string.h>
40aef9ec39SRoland Dreier #include <linux/parser.h>
41aef9ec39SRoland Dreier #include <linux/random.h>
42de25968cSTim Schmielau #include <linux/jiffies.h>
4393c76dbbSBart Van Assche #include <linux/lockdep.h>
4419f31343SBart Van Assche #include <linux/inet.h>
4556b5390cSBart Van Assche #include <rdma/ib_cache.h>
46aef9ec39SRoland Dreier 
4760063497SArun Sharma #include <linux/atomic.h>
48aef9ec39SRoland Dreier 
49aef9ec39SRoland Dreier #include <scsi/scsi.h>
50aef9ec39SRoland Dreier #include <scsi/scsi_device.h>
51aef9ec39SRoland Dreier #include <scsi/scsi_dbg.h>
5271444b97SJack Wang #include <scsi/scsi_tcq.h>
53aef9ec39SRoland Dreier #include <scsi/srp.h>
543236822bSFUJITA Tomonori #include <scsi/scsi_transport_srp.h>
55aef9ec39SRoland Dreier 
56aef9ec39SRoland Dreier #include "ib_srp.h"
57aef9ec39SRoland Dreier 
58aef9ec39SRoland Dreier #define DRV_NAME	"ib_srp"
59aef9ec39SRoland Dreier #define PFX		DRV_NAME ": "
60aef9ec39SRoland Dreier 
61aef9ec39SRoland Dreier MODULE_AUTHOR("Roland Dreier");
6233ab3e5bSBart Van Assche MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator");
63aef9ec39SRoland Dreier MODULE_LICENSE("Dual BSD/GPL");
64aef9ec39SRoland Dreier 
651a1faf7aSBart Van Assche #if !defined(CONFIG_DYNAMIC_DEBUG)
661a1faf7aSBart Van Assche #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
671a1faf7aSBart Van Assche #define DYNAMIC_DEBUG_BRANCH(descriptor) false
681a1faf7aSBart Van Assche #endif
691a1faf7aSBart Van Assche 
7049248644SDavid Dillow static unsigned int srp_sg_tablesize;
7149248644SDavid Dillow static unsigned int cmd_sg_entries;
72c07d424dSDavid Dillow static unsigned int indirect_sg_entries;
73c07d424dSDavid Dillow static bool allow_ext_sg;
7403f6fb93SBart Van Assche static bool prefer_fr = true;
7503f6fb93SBart Van Assche static bool register_always = true;
76c222a39fSBart Van Assche static bool never_register;
77aef9ec39SRoland Dreier static int topspin_workarounds = 1;
78aef9ec39SRoland Dreier 
7949248644SDavid Dillow module_param(srp_sg_tablesize, uint, 0444);
8049248644SDavid Dillow MODULE_PARM_DESC(srp_sg_tablesize, "Deprecated name for cmd_sg_entries");
8149248644SDavid Dillow 
8249248644SDavid Dillow module_param(cmd_sg_entries, uint, 0444);
8349248644SDavid Dillow MODULE_PARM_DESC(cmd_sg_entries,
8449248644SDavid Dillow 		 "Default number of gather/scatter entries in the SRP command (default is 12, max 255)");
8549248644SDavid Dillow 
86c07d424dSDavid Dillow module_param(indirect_sg_entries, uint, 0444);
87c07d424dSDavid Dillow MODULE_PARM_DESC(indirect_sg_entries,
8865e8617fSMing Lin 		 "Default max number of gather/scatter entries (default is 12, max is " __stringify(SG_MAX_SEGMENTS) ")");
89c07d424dSDavid Dillow 
90c07d424dSDavid Dillow module_param(allow_ext_sg, bool, 0444);
91c07d424dSDavid Dillow MODULE_PARM_DESC(allow_ext_sg,
92c07d424dSDavid Dillow 		  "Default behavior when there are more than cmd_sg_entries S/G entries after mapping; fails the request when false (default false)");
93c07d424dSDavid Dillow 
94aef9ec39SRoland Dreier module_param(topspin_workarounds, int, 0444);
95aef9ec39SRoland Dreier MODULE_PARM_DESC(topspin_workarounds,
96aef9ec39SRoland Dreier 		 "Enable workarounds for Topspin/Cisco SRP target bugs if != 0");
97aef9ec39SRoland Dreier 
985cfb1782SBart Van Assche module_param(prefer_fr, bool, 0444);
995cfb1782SBart Van Assche MODULE_PARM_DESC(prefer_fr,
1005cfb1782SBart Van Assche "Whether to use fast registration if both FMR and fast registration are supported");
1015cfb1782SBart Van Assche 
102b1b8854dSBart Van Assche module_param(register_always, bool, 0444);
103b1b8854dSBart Van Assche MODULE_PARM_DESC(register_always,
104b1b8854dSBart Van Assche 		 "Use memory registration even for contiguous memory regions");
105b1b8854dSBart Van Assche 
106c222a39fSBart Van Assche module_param(never_register, bool, 0444);
107c222a39fSBart Van Assche MODULE_PARM_DESC(never_register, "Never register memory");
108c222a39fSBart Van Assche 
1099c27847dSLuis R. Rodriguez static const struct kernel_param_ops srp_tmo_ops;
110ed9b2264SBart Van Assche 
111a95cadb9SBart Van Assche static int srp_reconnect_delay = 10;
112a95cadb9SBart Van Assche module_param_cb(reconnect_delay, &srp_tmo_ops, &srp_reconnect_delay,
113a95cadb9SBart Van Assche 		S_IRUGO | S_IWUSR);
114a95cadb9SBart Van Assche MODULE_PARM_DESC(reconnect_delay, "Time between successive reconnect attempts");
115a95cadb9SBart Van Assche 
116ed9b2264SBart Van Assche static int srp_fast_io_fail_tmo = 15;
117ed9b2264SBart Van Assche module_param_cb(fast_io_fail_tmo, &srp_tmo_ops, &srp_fast_io_fail_tmo,
118ed9b2264SBart Van Assche 		S_IRUGO | S_IWUSR);
119ed9b2264SBart Van Assche MODULE_PARM_DESC(fast_io_fail_tmo,
120ed9b2264SBart Van Assche 		 "Number of seconds between the observation of a transport"
121ed9b2264SBart Van Assche 		 " layer error and failing all I/O. \"off\" means that this"
122ed9b2264SBart Van Assche 		 " functionality is disabled.");
123ed9b2264SBart Van Assche 
124a95cadb9SBart Van Assche static int srp_dev_loss_tmo = 600;
125ed9b2264SBart Van Assche module_param_cb(dev_loss_tmo, &srp_tmo_ops, &srp_dev_loss_tmo,
126ed9b2264SBart Van Assche 		S_IRUGO | S_IWUSR);
127ed9b2264SBart Van Assche MODULE_PARM_DESC(dev_loss_tmo,
128ed9b2264SBart Van Assche 		 "Maximum number of seconds that the SRP transport should"
129ed9b2264SBart Van Assche 		 " insulate transport layer errors. After this time has been"
130ed9b2264SBart Van Assche 		 " exceeded the SCSI host is removed. Should be"
131ed9b2264SBart Van Assche 		 " between 1 and " __stringify(SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
132ed9b2264SBart Van Assche 		 " if fast_io_fail_tmo has not been set. \"off\" means that"
133ed9b2264SBart Van Assche 		 " this functionality is disabled.");
134ed9b2264SBart Van Assche 
135882981f4SBart Van Assche static bool srp_use_imm_data = true;
136882981f4SBart Van Assche module_param_named(use_imm_data, srp_use_imm_data, bool, 0644);
137882981f4SBart Van Assche MODULE_PARM_DESC(use_imm_data,
138882981f4SBart Van Assche 		 "Whether or not to request permission to use immediate data during SRP login.");
139882981f4SBart Van Assche 
140882981f4SBart Van Assche static unsigned int srp_max_imm_data = 8 * 1024;
141882981f4SBart Van Assche module_param_named(max_imm_data, srp_max_imm_data, uint, 0644);
142882981f4SBart Van Assche MODULE_PARM_DESC(max_imm_data, "Maximum immediate data size.");
143882981f4SBart Van Assche 
144d92c0da7SBart Van Assche static unsigned ch_count;
145d92c0da7SBart Van Assche module_param(ch_count, uint, 0444);
146d92c0da7SBart Van Assche MODULE_PARM_DESC(ch_count,
147d92c0da7SBart Van Assche 		 "Number of RDMA channels to use for communication with an SRP target. Using more than one channel improves performance if the HCA supports multiple completion vectors. The default value is the minimum of four times the number of online CPU sockets and the number of completion vectors supported by the HCA.");
148d92c0da7SBart Van Assche 
149aef9ec39SRoland Dreier static void srp_add_one(struct ib_device *device);
1507c1eb45aSHaggai Eran static void srp_remove_one(struct ib_device *device, void *client_data);
151dc1435c0SLeon Romanovsky static void srp_rename_dev(struct ib_device *device, void *client_data);
1521dc7b1f1SChristoph Hellwig static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc);
1531dc7b1f1SChristoph Hellwig static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
1541dc7b1f1SChristoph Hellwig 		const char *opname);
155e7ff98aeSParav Pandit static int srp_ib_cm_handler(struct ib_cm_id *cm_id,
156e7ff98aeSParav Pandit 			     const struct ib_cm_event *event);
15719f31343SBart Van Assche static int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
15819f31343SBart Van Assche 			       struct rdma_cm_event *event);
159aef9ec39SRoland Dreier 
1603236822bSFUJITA Tomonori static struct scsi_transport_template *ib_srp_transport_template;
161bcc05910SBart Van Assche static struct workqueue_struct *srp_remove_wq;
1623236822bSFUJITA Tomonori 
163aef9ec39SRoland Dreier static struct ib_client srp_client = {
164aef9ec39SRoland Dreier 	.name   = "srp",
165aef9ec39SRoland Dreier 	.add    = srp_add_one,
166dc1435c0SLeon Romanovsky 	.remove = srp_remove_one,
167dc1435c0SLeon Romanovsky 	.rename = srp_rename_dev
168aef9ec39SRoland Dreier };
169aef9ec39SRoland Dreier 
170c1a0b23bSMichael S. Tsirkin static struct ib_sa_client srp_sa_client;
171c1a0b23bSMichael S. Tsirkin 
172ed9b2264SBart Van Assche static int srp_tmo_get(char *buffer, const struct kernel_param *kp)
173ed9b2264SBart Van Assche {
174ed9b2264SBart Van Assche 	int tmo = *(int *)kp->arg;
175ed9b2264SBart Van Assche 
176ed9b2264SBart Van Assche 	if (tmo >= 0)
1775a0d5237SDonald Dutile 		return sprintf(buffer, "%d\n", tmo);
178ed9b2264SBart Van Assche 	else
1795a0d5237SDonald Dutile 		return sprintf(buffer, "off\n");
180ed9b2264SBart Van Assche }
181ed9b2264SBart Van Assche 
182ed9b2264SBart Van Assche static int srp_tmo_set(const char *val, const struct kernel_param *kp)
183ed9b2264SBart Van Assche {
184ed9b2264SBart Van Assche 	int tmo, res;
185ed9b2264SBart Van Assche 
1863fdf70acSSagi Grimberg 	res = srp_parse_tmo(&tmo, val);
187ed9b2264SBart Van Assche 	if (res)
188ed9b2264SBart Van Assche 		goto out;
1893fdf70acSSagi Grimberg 
190a95cadb9SBart Van Assche 	if (kp->arg == &srp_reconnect_delay)
191a95cadb9SBart Van Assche 		res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo,
192a95cadb9SBart Van Assche 				    srp_dev_loss_tmo);
193a95cadb9SBart Van Assche 	else if (kp->arg == &srp_fast_io_fail_tmo)
194a95cadb9SBart Van Assche 		res = srp_tmo_valid(srp_reconnect_delay, tmo, srp_dev_loss_tmo);
195ed9b2264SBart Van Assche 	else
196a95cadb9SBart Van Assche 		res = srp_tmo_valid(srp_reconnect_delay, srp_fast_io_fail_tmo,
197a95cadb9SBart Van Assche 				    tmo);
198ed9b2264SBart Van Assche 	if (res)
199ed9b2264SBart Van Assche 		goto out;
200ed9b2264SBart Van Assche 	*(int *)kp->arg = tmo;
201ed9b2264SBart Van Assche 
202ed9b2264SBart Van Assche out:
203ed9b2264SBart Van Assche 	return res;
204ed9b2264SBart Van Assche }
205ed9b2264SBart Van Assche 
2069c27847dSLuis R. Rodriguez static const struct kernel_param_ops srp_tmo_ops = {
207ed9b2264SBart Van Assche 	.get = srp_tmo_get,
208ed9b2264SBart Van Assche 	.set = srp_tmo_set,
209ed9b2264SBart Van Assche };
210ed9b2264SBart Van Assche 
211aef9ec39SRoland Dreier static inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
212aef9ec39SRoland Dreier {
213aef9ec39SRoland Dreier 	return (struct srp_target_port *) host->hostdata;
214aef9ec39SRoland Dreier }
215aef9ec39SRoland Dreier 
216aef9ec39SRoland Dreier static const char *srp_target_info(struct Scsi_Host *host)
217aef9ec39SRoland Dreier {
218aef9ec39SRoland Dreier 	return host_to_target(host)->target_name;
219aef9ec39SRoland Dreier }
220aef9ec39SRoland Dreier 
2215d7cbfd6SRoland Dreier static int srp_target_is_topspin(struct srp_target_port *target)
2225d7cbfd6SRoland Dreier {
2235d7cbfd6SRoland Dreier 	static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
2243d1ff48dSRaghava Kondapalli 	static const u8 cisco_oui[3]   = { 0x00, 0x1b, 0x0d };
2255d7cbfd6SRoland Dreier 
2265d7cbfd6SRoland Dreier 	return topspin_workarounds &&
2273d1ff48dSRaghava Kondapalli 		(!memcmp(&target->ioc_guid, topspin_oui, sizeof topspin_oui) ||
2283d1ff48dSRaghava Kondapalli 		 !memcmp(&target->ioc_guid, cisco_oui, sizeof cisco_oui));
2295d7cbfd6SRoland Dreier }
2305d7cbfd6SRoland Dreier 
231aef9ec39SRoland Dreier static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
232aef9ec39SRoland Dreier 				   gfp_t gfp_mask,
233aef9ec39SRoland Dreier 				   enum dma_data_direction direction)
234aef9ec39SRoland Dreier {
235aef9ec39SRoland Dreier 	struct srp_iu *iu;
236aef9ec39SRoland Dreier 
237aef9ec39SRoland Dreier 	iu = kmalloc(sizeof *iu, gfp_mask);
238aef9ec39SRoland Dreier 	if (!iu)
239aef9ec39SRoland Dreier 		goto out;
240aef9ec39SRoland Dreier 
241aef9ec39SRoland Dreier 	iu->buf = kzalloc(size, gfp_mask);
242aef9ec39SRoland Dreier 	if (!iu->buf)
243aef9ec39SRoland Dreier 		goto out_free_iu;
244aef9ec39SRoland Dreier 
24505321937SGreg Kroah-Hartman 	iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size,
24605321937SGreg Kroah-Hartman 				    direction);
24705321937SGreg Kroah-Hartman 	if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma))
248aef9ec39SRoland Dreier 		goto out_free_buf;
249aef9ec39SRoland Dreier 
250aef9ec39SRoland Dreier 	iu->size      = size;
251aef9ec39SRoland Dreier 	iu->direction = direction;
252aef9ec39SRoland Dreier 
253aef9ec39SRoland Dreier 	return iu;
254aef9ec39SRoland Dreier 
255aef9ec39SRoland Dreier out_free_buf:
256aef9ec39SRoland Dreier 	kfree(iu->buf);
257aef9ec39SRoland Dreier out_free_iu:
258aef9ec39SRoland Dreier 	kfree(iu);
259aef9ec39SRoland Dreier out:
260aef9ec39SRoland Dreier 	return NULL;
261aef9ec39SRoland Dreier }
262aef9ec39SRoland Dreier 
263aef9ec39SRoland Dreier static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
264aef9ec39SRoland Dreier {
265aef9ec39SRoland Dreier 	if (!iu)
266aef9ec39SRoland Dreier 		return;
267aef9ec39SRoland Dreier 
26805321937SGreg Kroah-Hartman 	ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size,
26905321937SGreg Kroah-Hartman 			    iu->direction);
270aef9ec39SRoland Dreier 	kfree(iu->buf);
271aef9ec39SRoland Dreier 	kfree(iu);
272aef9ec39SRoland Dreier }
273aef9ec39SRoland Dreier 
274aef9ec39SRoland Dreier static void srp_qp_event(struct ib_event *event, void *context)
275aef9ec39SRoland Dreier {
27657363d98SSagi Grimberg 	pr_debug("QP event %s (%d)\n",
27757363d98SSagi Grimberg 		 ib_event_msg(event->event), event->event);
278aef9ec39SRoland Dreier }
279aef9ec39SRoland Dreier 
28019f31343SBart Van Assche static int srp_init_ib_qp(struct srp_target_port *target,
281aef9ec39SRoland Dreier 			  struct ib_qp *qp)
282aef9ec39SRoland Dreier {
283aef9ec39SRoland Dreier 	struct ib_qp_attr *attr;
284aef9ec39SRoland Dreier 	int ret;
285aef9ec39SRoland Dreier 
286aef9ec39SRoland Dreier 	attr = kmalloc(sizeof *attr, GFP_KERNEL);
287aef9ec39SRoland Dreier 	if (!attr)
288aef9ec39SRoland Dreier 		return -ENOMEM;
289aef9ec39SRoland Dreier 
29056b5390cSBart Van Assche 	ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev,
291aef9ec39SRoland Dreier 				  target->srp_host->port,
29219f31343SBart Van Assche 				  be16_to_cpu(target->ib_cm.pkey),
293aef9ec39SRoland Dreier 				  &attr->pkey_index);
294aef9ec39SRoland Dreier 	if (ret)
295aef9ec39SRoland Dreier 		goto out;
296aef9ec39SRoland Dreier 
297aef9ec39SRoland Dreier 	attr->qp_state        = IB_QPS_INIT;
298aef9ec39SRoland Dreier 	attr->qp_access_flags = (IB_ACCESS_REMOTE_READ |
299aef9ec39SRoland Dreier 				    IB_ACCESS_REMOTE_WRITE);
300aef9ec39SRoland Dreier 	attr->port_num        = target->srp_host->port;
301aef9ec39SRoland Dreier 
302aef9ec39SRoland Dreier 	ret = ib_modify_qp(qp, attr,
303aef9ec39SRoland Dreier 			   IB_QP_STATE		|
304aef9ec39SRoland Dreier 			   IB_QP_PKEY_INDEX	|
305aef9ec39SRoland Dreier 			   IB_QP_ACCESS_FLAGS	|
306aef9ec39SRoland Dreier 			   IB_QP_PORT);
307aef9ec39SRoland Dreier 
308aef9ec39SRoland Dreier out:
309aef9ec39SRoland Dreier 	kfree(attr);
310aef9ec39SRoland Dreier 	return ret;
311aef9ec39SRoland Dreier }
312aef9ec39SRoland Dreier 
31319f31343SBart Van Assche static int srp_new_ib_cm_id(struct srp_rdma_ch *ch)
3149fe4bcf4SDavid Dillow {
315509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
3169fe4bcf4SDavid Dillow 	struct ib_cm_id *new_cm_id;
3179fe4bcf4SDavid Dillow 
31805321937SGreg Kroah-Hartman 	new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
31919f31343SBart Van Assche 				    srp_ib_cm_handler, ch);
3209fe4bcf4SDavid Dillow 	if (IS_ERR(new_cm_id))
3219fe4bcf4SDavid Dillow 		return PTR_ERR(new_cm_id);
3229fe4bcf4SDavid Dillow 
32319f31343SBart Van Assche 	if (ch->ib_cm.cm_id)
32419f31343SBart Van Assche 		ib_destroy_cm_id(ch->ib_cm.cm_id);
32519f31343SBart Van Assche 	ch->ib_cm.cm_id = new_cm_id;
3264c33bd19SDasaratharaman Chandramouli 	if (rdma_cap_opa_ah(target->srp_host->srp_dev->dev,
3274c33bd19SDasaratharaman Chandramouli 			    target->srp_host->port))
32819f31343SBart Van Assche 		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_OPA;
3294c33bd19SDasaratharaman Chandramouli 	else
33019f31343SBart Van Assche 		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_IB;
33119f31343SBart Van Assche 	ch->ib_cm.path.sgid = target->sgid;
33219f31343SBart Van Assche 	ch->ib_cm.path.dgid = target->ib_cm.orig_dgid;
33319f31343SBart Van Assche 	ch->ib_cm.path.pkey = target->ib_cm.pkey;
33419f31343SBart Van Assche 	ch->ib_cm.path.service_id = target->ib_cm.service_id;
3359fe4bcf4SDavid Dillow 
3369fe4bcf4SDavid Dillow 	return 0;
3379fe4bcf4SDavid Dillow }
3389fe4bcf4SDavid Dillow 
33919f31343SBart Van Assche static int srp_new_rdma_cm_id(struct srp_rdma_ch *ch)
34019f31343SBart Van Assche {
34119f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
34219f31343SBart Van Assche 	struct rdma_cm_id *new_cm_id;
34319f31343SBart Van Assche 	int ret;
34419f31343SBart Van Assche 
34519f31343SBart Van Assche 	new_cm_id = rdma_create_id(target->net, srp_rdma_cm_handler, ch,
34619f31343SBart Van Assche 				   RDMA_PS_TCP, IB_QPT_RC);
34719f31343SBart Van Assche 	if (IS_ERR(new_cm_id)) {
34819f31343SBart Van Assche 		ret = PTR_ERR(new_cm_id);
34919f31343SBart Van Assche 		new_cm_id = NULL;
35019f31343SBart Van Assche 		goto out;
35119f31343SBart Van Assche 	}
35219f31343SBart Van Assche 
35319f31343SBart Van Assche 	init_completion(&ch->done);
35419f31343SBart Van Assche 	ret = rdma_resolve_addr(new_cm_id, target->rdma_cm.src_specified ?
35514673778SBart Van Assche 				&target->rdma_cm.src.sa : NULL,
35614673778SBart Van Assche 				&target->rdma_cm.dst.sa,
35719f31343SBart Van Assche 				SRP_PATH_REC_TIMEOUT_MS);
35819f31343SBart Van Assche 	if (ret) {
359fdbcf5c0SBart Van Assche 		pr_err("No route available from %pISpsc to %pISpsc (%d)\n",
3607da09af9SBart Van Assche 		       &target->rdma_cm.src, &target->rdma_cm.dst, ret);
36119f31343SBart Van Assche 		goto out;
36219f31343SBart Van Assche 	}
36319f31343SBart Van Assche 	ret = wait_for_completion_interruptible(&ch->done);
36419f31343SBart Van Assche 	if (ret < 0)
36519f31343SBart Van Assche 		goto out;
36619f31343SBart Van Assche 
36719f31343SBart Van Assche 	ret = ch->status;
36819f31343SBart Van Assche 	if (ret) {
369fdbcf5c0SBart Van Assche 		pr_err("Resolving address %pISpsc failed (%d)\n",
3707da09af9SBart Van Assche 		       &target->rdma_cm.dst, ret);
37119f31343SBart Van Assche 		goto out;
37219f31343SBart Van Assche 	}
37319f31343SBart Van Assche 
37419f31343SBart Van Assche 	swap(ch->rdma_cm.cm_id, new_cm_id);
37519f31343SBart Van Assche 
37619f31343SBart Van Assche out:
37719f31343SBart Van Assche 	if (new_cm_id)
37819f31343SBart Van Assche 		rdma_destroy_id(new_cm_id);
37919f31343SBart Van Assche 
38019f31343SBart Van Assche 	return ret;
38119f31343SBart Van Assche }
38219f31343SBart Van Assche 
38319f31343SBart Van Assche static int srp_new_cm_id(struct srp_rdma_ch *ch)
38419f31343SBart Van Assche {
38519f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
38619f31343SBart Van Assche 
38719f31343SBart Van Assche 	return target->using_rdma_cm ? srp_new_rdma_cm_id(ch) :
38819f31343SBart Van Assche 		srp_new_ib_cm_id(ch);
38919f31343SBart Van Assche }
39019f31343SBart Van Assche 
391d1b4289eSBart Van Assche static struct ib_fmr_pool *srp_alloc_fmr_pool(struct srp_target_port *target)
392d1b4289eSBart Van Assche {
393d1b4289eSBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
394d1b4289eSBart Van Assche 	struct ib_fmr_pool_param fmr_param;
395d1b4289eSBart Van Assche 
396d1b4289eSBart Van Assche 	memset(&fmr_param, 0, sizeof(fmr_param));
397fa9863f8SBart Van Assche 	fmr_param.pool_size	    = target->mr_pool_size;
398d1b4289eSBart Van Assche 	fmr_param.dirty_watermark   = fmr_param.pool_size / 4;
399d1b4289eSBart Van Assche 	fmr_param.cache		    = 1;
40052ede08fSBart Van Assche 	fmr_param.max_pages_per_fmr = dev->max_pages_per_mr;
40152ede08fSBart Van Assche 	fmr_param.page_shift	    = ilog2(dev->mr_page_size);
402d1b4289eSBart Van Assche 	fmr_param.access	    = (IB_ACCESS_LOCAL_WRITE |
403d1b4289eSBart Van Assche 				       IB_ACCESS_REMOTE_WRITE |
404d1b4289eSBart Van Assche 				       IB_ACCESS_REMOTE_READ);
405d1b4289eSBart Van Assche 
406d1b4289eSBart Van Assche 	return ib_create_fmr_pool(dev->pd, &fmr_param);
407d1b4289eSBart Van Assche }
408d1b4289eSBart Van Assche 
4095cfb1782SBart Van Assche /**
4105cfb1782SBart Van Assche  * srp_destroy_fr_pool() - free the resources owned by a pool
4115cfb1782SBart Van Assche  * @pool: Fast registration pool to be destroyed.
4125cfb1782SBart Van Assche  */
4135cfb1782SBart Van Assche static void srp_destroy_fr_pool(struct srp_fr_pool *pool)
4145cfb1782SBart Van Assche {
4155cfb1782SBart Van Assche 	int i;
4165cfb1782SBart Van Assche 	struct srp_fr_desc *d;
4175cfb1782SBart Van Assche 
4185cfb1782SBart Van Assche 	if (!pool)
4195cfb1782SBart Van Assche 		return;
4205cfb1782SBart Van Assche 
4215cfb1782SBart Van Assche 	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
4225cfb1782SBart Van Assche 		if (d->mr)
4235cfb1782SBart Van Assche 			ib_dereg_mr(d->mr);
4245cfb1782SBart Van Assche 	}
4255cfb1782SBart Van Assche 	kfree(pool);
4265cfb1782SBart Van Assche }
4275cfb1782SBart Van Assche 
4285cfb1782SBart Van Assche /**
4295cfb1782SBart Van Assche  * srp_create_fr_pool() - allocate and initialize a pool for fast registration
4305cfb1782SBart Van Assche  * @device:            IB device to allocate fast registration descriptors for.
4315cfb1782SBart Van Assche  * @pd:                Protection domain associated with the FR descriptors.
4325cfb1782SBart Van Assche  * @pool_size:         Number of descriptors to allocate.
4335cfb1782SBart Van Assche  * @max_page_list_len: Maximum fast registration work request page list length.
4345cfb1782SBart Van Assche  */
4355cfb1782SBart Van Assche static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
4365cfb1782SBart Van Assche 					      struct ib_pd *pd, int pool_size,
4375cfb1782SBart Van Assche 					      int max_page_list_len)
4385cfb1782SBart Van Assche {
4395cfb1782SBart Van Assche 	struct srp_fr_pool *pool;
4405cfb1782SBart Van Assche 	struct srp_fr_desc *d;
4415cfb1782SBart Van Assche 	struct ib_mr *mr;
4425cfb1782SBart Van Assche 	int i, ret = -EINVAL;
443fbd36818SSergey Gorenko 	enum ib_mr_type mr_type;
4445cfb1782SBart Van Assche 
4455cfb1782SBart Van Assche 	if (pool_size <= 0)
4465cfb1782SBart Van Assche 		goto err;
4475cfb1782SBart Van Assche 	ret = -ENOMEM;
4487a7b0feaSGustavo A. R. Silva 	pool = kzalloc(struct_size(pool, desc, pool_size), GFP_KERNEL);
4495cfb1782SBart Van Assche 	if (!pool)
4505cfb1782SBart Van Assche 		goto err;
4515cfb1782SBart Van Assche 	pool->size = pool_size;
4525cfb1782SBart Van Assche 	pool->max_page_list_len = max_page_list_len;
4535cfb1782SBart Van Assche 	spin_lock_init(&pool->lock);
4545cfb1782SBart Van Assche 	INIT_LIST_HEAD(&pool->free_list);
4555cfb1782SBart Van Assche 
456fbd36818SSergey Gorenko 	if (device->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)
457fbd36818SSergey Gorenko 		mr_type = IB_MR_TYPE_SG_GAPS;
458fbd36818SSergey Gorenko 	else
459fbd36818SSergey Gorenko 		mr_type = IB_MR_TYPE_MEM_REG;
460fbd36818SSergey Gorenko 
4615cfb1782SBart Van Assche 	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
462fbd36818SSergey Gorenko 		mr = ib_alloc_mr(pd, mr_type, max_page_list_len);
4635cfb1782SBart Van Assche 		if (IS_ERR(mr)) {
4645cfb1782SBart Van Assche 			ret = PTR_ERR(mr);
4653787d990SBart Van Assche 			if (ret == -ENOMEM)
4663787d990SBart Van Assche 				pr_info("%s: ib_alloc_mr() failed. Try to reduce max_cmd_per_lun, max_sect or ch_count\n",
4673787d990SBart Van Assche 					dev_name(&device->dev));
4685cfb1782SBart Van Assche 			goto destroy_pool;
4695cfb1782SBart Van Assche 		}
4705cfb1782SBart Van Assche 		d->mr = mr;
4715cfb1782SBart Van Assche 		list_add_tail(&d->entry, &pool->free_list);
4725cfb1782SBart Van Assche 	}
4735cfb1782SBart Van Assche 
4745cfb1782SBart Van Assche out:
4755cfb1782SBart Van Assche 	return pool;
4765cfb1782SBart Van Assche 
4775cfb1782SBart Van Assche destroy_pool:
4785cfb1782SBart Van Assche 	srp_destroy_fr_pool(pool);
4795cfb1782SBart Van Assche 
4805cfb1782SBart Van Assche err:
4815cfb1782SBart Van Assche 	pool = ERR_PTR(ret);
4825cfb1782SBart Van Assche 	goto out;
4835cfb1782SBart Van Assche }
4845cfb1782SBart Van Assche 
4855cfb1782SBart Van Assche /**
4865cfb1782SBart Van Assche  * srp_fr_pool_get() - obtain a descriptor suitable for fast registration
4875cfb1782SBart Van Assche  * @pool: Pool to obtain descriptor from.
4885cfb1782SBart Van Assche  */
4895cfb1782SBart Van Assche static struct srp_fr_desc *srp_fr_pool_get(struct srp_fr_pool *pool)
4905cfb1782SBart Van Assche {
4915cfb1782SBart Van Assche 	struct srp_fr_desc *d = NULL;
4925cfb1782SBart Van Assche 	unsigned long flags;
4935cfb1782SBart Van Assche 
4945cfb1782SBart Van Assche 	spin_lock_irqsave(&pool->lock, flags);
4955cfb1782SBart Van Assche 	if (!list_empty(&pool->free_list)) {
4965cfb1782SBart Van Assche 		d = list_first_entry(&pool->free_list, typeof(*d), entry);
4975cfb1782SBart Van Assche 		list_del(&d->entry);
4985cfb1782SBart Van Assche 	}
4995cfb1782SBart Van Assche 	spin_unlock_irqrestore(&pool->lock, flags);
5005cfb1782SBart Van Assche 
5015cfb1782SBart Van Assche 	return d;
5025cfb1782SBart Van Assche }
5035cfb1782SBart Van Assche 
5045cfb1782SBart Van Assche /**
5055cfb1782SBart Van Assche  * srp_fr_pool_put() - put an FR descriptor back in the free list
5065cfb1782SBart Van Assche  * @pool: Pool the descriptor was allocated from.
5075cfb1782SBart Van Assche  * @desc: Pointer to an array of fast registration descriptor pointers.
5085cfb1782SBart Van Assche  * @n:    Number of descriptors to put back.
5095cfb1782SBart Van Assche  *
5105cfb1782SBart Van Assche  * Note: The caller must already have queued an invalidation request for
5115cfb1782SBart Van Assche  * desc->mr->rkey before calling this function.
5125cfb1782SBart Van Assche  */
5135cfb1782SBart Van Assche static void srp_fr_pool_put(struct srp_fr_pool *pool, struct srp_fr_desc **desc,
5145cfb1782SBart Van Assche 			    int n)
5155cfb1782SBart Van Assche {
5165cfb1782SBart Van Assche 	unsigned long flags;
5175cfb1782SBart Van Assche 	int i;
5185cfb1782SBart Van Assche 
5195cfb1782SBart Van Assche 	spin_lock_irqsave(&pool->lock, flags);
5205cfb1782SBart Van Assche 	for (i = 0; i < n; i++)
5215cfb1782SBart Van Assche 		list_add(&desc[i]->entry, &pool->free_list);
5225cfb1782SBart Van Assche 	spin_unlock_irqrestore(&pool->lock, flags);
5235cfb1782SBart Van Assche }
5245cfb1782SBart Van Assche 
5255cfb1782SBart Van Assche static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
5265cfb1782SBart Van Assche {
5275cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
5285cfb1782SBart Van Assche 
529fa9863f8SBart Van Assche 	return srp_create_fr_pool(dev->dev, dev->pd, target->mr_pool_size,
5305cfb1782SBart Van Assche 				  dev->max_pages_per_mr);
5315cfb1782SBart Van Assche }
5325cfb1782SBart Van Assche 
5337dad6b2eSBart Van Assche /**
5347dad6b2eSBart Van Assche  * srp_destroy_qp() - destroy an RDMA queue pair
5359566b054SBart Van Assche  * @ch: SRP RDMA channel.
5367dad6b2eSBart Van Assche  *
537561392d4SSteve Wise  * Drain the qp before destroying it.  This avoids that the receive
538561392d4SSteve Wise  * completion handler can access the queue pair while it is
5397dad6b2eSBart Van Assche  * being destroyed.
5407dad6b2eSBart Van Assche  */
5419566b054SBart Van Assche static void srp_destroy_qp(struct srp_rdma_ch *ch)
5427dad6b2eSBart Van Assche {
5439294000dSBart Van Assche 	spin_lock_irq(&ch->lock);
5449294000dSBart Van Assche 	ib_process_cq_direct(ch->send_cq, -1);
5459294000dSBart Van Assche 	spin_unlock_irq(&ch->lock);
5469294000dSBart Van Assche 
5479566b054SBart Van Assche 	ib_drain_qp(ch->qp);
5489566b054SBart Van Assche 	ib_destroy_qp(ch->qp);
5497dad6b2eSBart Van Assche }
5507dad6b2eSBart Van Assche 
551509c07bcSBart Van Assche static int srp_create_ch_ib(struct srp_rdma_ch *ch)
552aef9ec39SRoland Dreier {
553509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
55462154b2eSBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
555bf583470SBart Van Assche 	const struct ib_device_attr *attr = &dev->dev->attrs;
556aef9ec39SRoland Dreier 	struct ib_qp_init_attr *init_attr;
55773aa89edSIshai Rabinovitz 	struct ib_cq *recv_cq, *send_cq;
55873aa89edSIshai Rabinovitz 	struct ib_qp *qp;
559d1b4289eSBart Van Assche 	struct ib_fmr_pool *fmr_pool = NULL;
5605cfb1782SBart Van Assche 	struct srp_fr_pool *fr_pool = NULL;
561509c5f33SBart Van Assche 	const int m = 1 + dev->use_fast_reg * target->mr_per_cmd * 2;
562aef9ec39SRoland Dreier 	int ret;
563aef9ec39SRoland Dreier 
564aef9ec39SRoland Dreier 	init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
565aef9ec39SRoland Dreier 	if (!init_attr)
566aef9ec39SRoland Dreier 		return -ENOMEM;
567aef9ec39SRoland Dreier 
568561392d4SSteve Wise 	/* queue_size + 1 for ib_drain_rq() */
5691dc7b1f1SChristoph Hellwig 	recv_cq = ib_alloc_cq(dev->dev, ch, target->queue_size + 1,
5701dc7b1f1SChristoph Hellwig 				ch->comp_vector, IB_POLL_SOFTIRQ);
57173aa89edSIshai Rabinovitz 	if (IS_ERR(recv_cq)) {
57273aa89edSIshai Rabinovitz 		ret = PTR_ERR(recv_cq);
573da9d2f07SRoland Dreier 		goto err;
574aef9ec39SRoland Dreier 	}
575aef9ec39SRoland Dreier 
5761dc7b1f1SChristoph Hellwig 	send_cq = ib_alloc_cq(dev->dev, ch, m * target->queue_size,
5771dc7b1f1SChristoph Hellwig 				ch->comp_vector, IB_POLL_DIRECT);
57873aa89edSIshai Rabinovitz 	if (IS_ERR(send_cq)) {
57973aa89edSIshai Rabinovitz 		ret = PTR_ERR(send_cq);
580da9d2f07SRoland Dreier 		goto err_recv_cq;
5819c03dc9fSBart Van Assche 	}
5829c03dc9fSBart Van Assche 
583aef9ec39SRoland Dreier 	init_attr->event_handler       = srp_qp_event;
5845cfb1782SBart Van Assche 	init_attr->cap.max_send_wr     = m * target->queue_size;
5857dad6b2eSBart Van Assche 	init_attr->cap.max_recv_wr     = target->queue_size + 1;
586aef9ec39SRoland Dreier 	init_attr->cap.max_recv_sge    = 1;
587bf583470SBart Van Assche 	init_attr->cap.max_send_sge    = min(SRP_MAX_SGE, attr->max_send_sge);
5885cfb1782SBart Van Assche 	init_attr->sq_sig_type         = IB_SIGNAL_REQ_WR;
589aef9ec39SRoland Dreier 	init_attr->qp_type             = IB_QPT_RC;
59073aa89edSIshai Rabinovitz 	init_attr->send_cq             = send_cq;
59173aa89edSIshai Rabinovitz 	init_attr->recv_cq             = recv_cq;
592aef9ec39SRoland Dreier 
593bf583470SBart Van Assche 	ch->max_imm_sge = min(init_attr->cap.max_send_sge - 1U, 255U);
594bf583470SBart Van Assche 
59519f31343SBart Van Assche 	if (target->using_rdma_cm) {
59619f31343SBart Van Assche 		ret = rdma_create_qp(ch->rdma_cm.cm_id, dev->pd, init_attr);
59719f31343SBart Van Assche 		qp = ch->rdma_cm.cm_id->qp;
59819f31343SBart Van Assche 	} else {
59962154b2eSBart Van Assche 		qp = ib_create_qp(dev->pd, init_attr);
60019f31343SBart Van Assche 		if (!IS_ERR(qp)) {
60119f31343SBart Van Assche 			ret = srp_init_ib_qp(target, qp);
60219f31343SBart Van Assche 			if (ret)
60319f31343SBart Van Assche 				ib_destroy_qp(qp);
60419f31343SBart Van Assche 		} else {
60573aa89edSIshai Rabinovitz 			ret = PTR_ERR(qp);
60619f31343SBart Van Assche 		}
60719f31343SBart Van Assche 	}
60819f31343SBart Van Assche 	if (ret) {
60919f31343SBart Van Assche 		pr_err("QP creation failed for dev %s: %d\n",
61019f31343SBart Van Assche 		       dev_name(&dev->dev->dev), ret);
611da9d2f07SRoland Dreier 		goto err_send_cq;
612aef9ec39SRoland Dreier 	}
613aef9ec39SRoland Dreier 
614002f1567SBart Van Assche 	if (dev->use_fast_reg) {
6155cfb1782SBart Van Assche 		fr_pool = srp_alloc_fr_pool(target);
6165cfb1782SBart Van Assche 		if (IS_ERR(fr_pool)) {
6175cfb1782SBart Van Assche 			ret = PTR_ERR(fr_pool);
6185cfb1782SBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host, PFX
6195cfb1782SBart Van Assche 				     "FR pool allocation failed (%d)\n", ret);
6205cfb1782SBart Van Assche 			goto err_qp;
6215cfb1782SBart Van Assche 		}
622002f1567SBart Van Assche 	} else if (dev->use_fmr) {
623d1b4289eSBart Van Assche 		fmr_pool = srp_alloc_fmr_pool(target);
624d1b4289eSBart Van Assche 		if (IS_ERR(fmr_pool)) {
625d1b4289eSBart Van Assche 			ret = PTR_ERR(fmr_pool);
626d1b4289eSBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host, PFX
627d1b4289eSBart Van Assche 				     "FMR pool allocation failed (%d)\n", ret);
628d1b4289eSBart Van Assche 			goto err_qp;
629d1b4289eSBart Van Assche 		}
630d1b4289eSBart Van Assche 	}
631d1b4289eSBart Van Assche 
632509c07bcSBart Van Assche 	if (ch->qp)
6339566b054SBart Van Assche 		srp_destroy_qp(ch);
634509c07bcSBart Van Assche 	if (ch->recv_cq)
6351dc7b1f1SChristoph Hellwig 		ib_free_cq(ch->recv_cq);
636509c07bcSBart Van Assche 	if (ch->send_cq)
6371dc7b1f1SChristoph Hellwig 		ib_free_cq(ch->send_cq);
63873aa89edSIshai Rabinovitz 
639509c07bcSBart Van Assche 	ch->qp = qp;
640509c07bcSBart Van Assche 	ch->recv_cq = recv_cq;
641509c07bcSBart Van Assche 	ch->send_cq = send_cq;
64273aa89edSIshai Rabinovitz 
6437fbc67dfSSagi Grimberg 	if (dev->use_fast_reg) {
6447fbc67dfSSagi Grimberg 		if (ch->fr_pool)
6457fbc67dfSSagi Grimberg 			srp_destroy_fr_pool(ch->fr_pool);
6467fbc67dfSSagi Grimberg 		ch->fr_pool = fr_pool;
6477fbc67dfSSagi Grimberg 	} else if (dev->use_fmr) {
6487fbc67dfSSagi Grimberg 		if (ch->fmr_pool)
6497fbc67dfSSagi Grimberg 			ib_destroy_fmr_pool(ch->fmr_pool);
6507fbc67dfSSagi Grimberg 		ch->fmr_pool = fmr_pool;
6517fbc67dfSSagi Grimberg 	}
6527fbc67dfSSagi Grimberg 
653da9d2f07SRoland Dreier 	kfree(init_attr);
654da9d2f07SRoland Dreier 	return 0;
655da9d2f07SRoland Dreier 
656da9d2f07SRoland Dreier err_qp:
65719f31343SBart Van Assche 	if (target->using_rdma_cm)
65819f31343SBart Van Assche 		rdma_destroy_qp(ch->rdma_cm.cm_id);
65919f31343SBart Van Assche 	else
66095c2ef50SIsrael Rukshin 		ib_destroy_qp(qp);
661da9d2f07SRoland Dreier 
662da9d2f07SRoland Dreier err_send_cq:
6631dc7b1f1SChristoph Hellwig 	ib_free_cq(send_cq);
664da9d2f07SRoland Dreier 
665da9d2f07SRoland Dreier err_recv_cq:
6661dc7b1f1SChristoph Hellwig 	ib_free_cq(recv_cq);
667da9d2f07SRoland Dreier 
668da9d2f07SRoland Dreier err:
669aef9ec39SRoland Dreier 	kfree(init_attr);
670aef9ec39SRoland Dreier 	return ret;
671aef9ec39SRoland Dreier }
672aef9ec39SRoland Dreier 
6734d73f95fSBart Van Assche /*
6744d73f95fSBart Van Assche  * Note: this function may be called without srp_alloc_iu_bufs() having been
675509c07bcSBart Van Assche  * invoked. Hence the ch->[rt]x_ring checks.
6764d73f95fSBart Van Assche  */
677509c07bcSBart Van Assche static void srp_free_ch_ib(struct srp_target_port *target,
678509c07bcSBart Van Assche 			   struct srp_rdma_ch *ch)
679aef9ec39SRoland Dreier {
6805cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
681aef9ec39SRoland Dreier 	int i;
682aef9ec39SRoland Dreier 
683d92c0da7SBart Van Assche 	if (!ch->target)
684d92c0da7SBart Van Assche 		return;
685d92c0da7SBart Van Assche 
68619f31343SBart Van Assche 	if (target->using_rdma_cm) {
68719f31343SBart Van Assche 		if (ch->rdma_cm.cm_id) {
68819f31343SBart Van Assche 			rdma_destroy_id(ch->rdma_cm.cm_id);
68919f31343SBart Van Assche 			ch->rdma_cm.cm_id = NULL;
69019f31343SBart Van Assche 		}
69119f31343SBart Van Assche 	} else {
69219f31343SBart Van Assche 		if (ch->ib_cm.cm_id) {
69319f31343SBart Van Assche 			ib_destroy_cm_id(ch->ib_cm.cm_id);
69419f31343SBart Van Assche 			ch->ib_cm.cm_id = NULL;
69519f31343SBart Van Assche 		}
696394c595eSBart Van Assche 	}
697394c595eSBart Van Assche 
698d92c0da7SBart Van Assche 	/* If srp_new_cm_id() succeeded but srp_create_ch_ib() not, return. */
699d92c0da7SBart Van Assche 	if (!ch->qp)
700d92c0da7SBart Van Assche 		return;
701d92c0da7SBart Van Assche 
7025cfb1782SBart Van Assche 	if (dev->use_fast_reg) {
703509c07bcSBart Van Assche 		if (ch->fr_pool)
704509c07bcSBart Van Assche 			srp_destroy_fr_pool(ch->fr_pool);
705002f1567SBart Van Assche 	} else if (dev->use_fmr) {
706509c07bcSBart Van Assche 		if (ch->fmr_pool)
707509c07bcSBart Van Assche 			ib_destroy_fmr_pool(ch->fmr_pool);
7085cfb1782SBart Van Assche 	}
7091dc7b1f1SChristoph Hellwig 
7109566b054SBart Van Assche 	srp_destroy_qp(ch);
7111dc7b1f1SChristoph Hellwig 	ib_free_cq(ch->send_cq);
7121dc7b1f1SChristoph Hellwig 	ib_free_cq(ch->recv_cq);
713aef9ec39SRoland Dreier 
714d92c0da7SBart Van Assche 	/*
715d92c0da7SBart Van Assche 	 * Avoid that the SCSI error handler tries to use this channel after
716d92c0da7SBart Van Assche 	 * it has been freed. The SCSI error handler can namely continue
717d92c0da7SBart Van Assche 	 * trying to perform recovery actions after scsi_remove_host()
718d92c0da7SBart Van Assche 	 * returned.
719d92c0da7SBart Van Assche 	 */
720d92c0da7SBart Van Assche 	ch->target = NULL;
721d92c0da7SBart Van Assche 
722509c07bcSBart Van Assche 	ch->qp = NULL;
723509c07bcSBart Van Assche 	ch->send_cq = ch->recv_cq = NULL;
72473aa89edSIshai Rabinovitz 
725509c07bcSBart Van Assche 	if (ch->rx_ring) {
7264d73f95fSBart Van Assche 		for (i = 0; i < target->queue_size; ++i)
727509c07bcSBart Van Assche 			srp_free_iu(target->srp_host, ch->rx_ring[i]);
728509c07bcSBart Van Assche 		kfree(ch->rx_ring);
729509c07bcSBart Van Assche 		ch->rx_ring = NULL;
7304d73f95fSBart Van Assche 	}
731509c07bcSBart Van Assche 	if (ch->tx_ring) {
7324d73f95fSBart Van Assche 		for (i = 0; i < target->queue_size; ++i)
733509c07bcSBart Van Assche 			srp_free_iu(target->srp_host, ch->tx_ring[i]);
734509c07bcSBart Van Assche 		kfree(ch->tx_ring);
735509c07bcSBart Van Assche 		ch->tx_ring = NULL;
7364d73f95fSBart Van Assche 	}
737aef9ec39SRoland Dreier }
738aef9ec39SRoland Dreier 
739aef9ec39SRoland Dreier static void srp_path_rec_completion(int status,
740c2f8fc4eSDasaratharaman Chandramouli 				    struct sa_path_rec *pathrec,
741509c07bcSBart Van Assche 				    void *ch_ptr)
742aef9ec39SRoland Dreier {
743509c07bcSBart Van Assche 	struct srp_rdma_ch *ch = ch_ptr;
744509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
745aef9ec39SRoland Dreier 
746509c07bcSBart Van Assche 	ch->status = status;
747aef9ec39SRoland Dreier 	if (status)
7487aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
7497aa54bd7SDavid Dillow 			     PFX "Got failed path rec status %d\n", status);
750aef9ec39SRoland Dreier 	else
75119f31343SBart Van Assche 		ch->ib_cm.path = *pathrec;
752509c07bcSBart Van Assche 	complete(&ch->done);
753aef9ec39SRoland Dreier }
754aef9ec39SRoland Dreier 
75519f31343SBart Van Assche static int srp_ib_lookup_path(struct srp_rdma_ch *ch)
756aef9ec39SRoland Dreier {
757509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
758c74ff750SBart Van Assche 	int ret;
759a702adceSBart Van Assche 
76019f31343SBart Van Assche 	ch->ib_cm.path.numb_path = 1;
761aef9ec39SRoland Dreier 
762509c07bcSBart Van Assche 	init_completion(&ch->done);
763aef9ec39SRoland Dreier 
76419f31343SBart Van Assche 	ch->ib_cm.path_query_id = ib_sa_path_rec_get(&srp_sa_client,
76505321937SGreg Kroah-Hartman 					       target->srp_host->srp_dev->dev,
766aef9ec39SRoland Dreier 					       target->srp_host->port,
76719f31343SBart Van Assche 					       &ch->ib_cm.path,
768247e020eSSean Hefty 					       IB_SA_PATH_REC_SERVICE_ID |
769aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_DGID	 |
770aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_SGID	 |
771aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_NUMB_PATH	 |
772aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_PKEY,
773aef9ec39SRoland Dreier 					       SRP_PATH_REC_TIMEOUT_MS,
774aef9ec39SRoland Dreier 					       GFP_KERNEL,
775aef9ec39SRoland Dreier 					       srp_path_rec_completion,
77619f31343SBart Van Assche 					       ch, &ch->ib_cm.path_query);
777c74ff750SBart Van Assche 	if (ch->ib_cm.path_query_id < 0)
778c74ff750SBart Van Assche 		return ch->ib_cm.path_query_id;
779aef9ec39SRoland Dreier 
780509c07bcSBart Van Assche 	ret = wait_for_completion_interruptible(&ch->done);
781a702adceSBart Van Assche 	if (ret < 0)
782c74ff750SBart Van Assche 		return ret;
783aef9ec39SRoland Dreier 
784c74ff750SBart Van Assche 	if (ch->status < 0)
7857aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
78685769c6fSBart Van Assche 			     PFX "Path record query failed: sgid %pI6, dgid %pI6, pkey %#04x, service_id %#16llx\n",
78719f31343SBart Van Assche 			     ch->ib_cm.path.sgid.raw, ch->ib_cm.path.dgid.raw,
78819f31343SBart Van Assche 			     be16_to_cpu(target->ib_cm.pkey),
78919f31343SBart Van Assche 			     be64_to_cpu(target->ib_cm.service_id));
790aef9ec39SRoland Dreier 
791c74ff750SBart Van Assche 	return ch->status;
792aef9ec39SRoland Dreier }
793aef9ec39SRoland Dreier 
79419f31343SBart Van Assche static int srp_rdma_lookup_path(struct srp_rdma_ch *ch)
79519f31343SBart Van Assche {
79619f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
79719f31343SBart Van Assche 	int ret;
79819f31343SBart Van Assche 
79919f31343SBart Van Assche 	init_completion(&ch->done);
80019f31343SBart Van Assche 
80119f31343SBart Van Assche 	ret = rdma_resolve_route(ch->rdma_cm.cm_id, SRP_PATH_REC_TIMEOUT_MS);
80219f31343SBart Van Assche 	if (ret)
80319f31343SBart Van Assche 		return ret;
80419f31343SBart Van Assche 
80519f31343SBart Van Assche 	wait_for_completion_interruptible(&ch->done);
80619f31343SBart Van Assche 
80719f31343SBart Van Assche 	if (ch->status != 0)
80819f31343SBart Van Assche 		shost_printk(KERN_WARNING, target->scsi_host,
80919f31343SBart Van Assche 			     PFX "Path resolution failed\n");
81019f31343SBart Van Assche 
81119f31343SBart Van Assche 	return ch->status;
81219f31343SBart Van Assche }
81319f31343SBart Van Assche 
81419f31343SBart Van Assche static int srp_lookup_path(struct srp_rdma_ch *ch)
81519f31343SBart Van Assche {
81619f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
81719f31343SBart Van Assche 
81819f31343SBart Van Assche 	return target->using_rdma_cm ? srp_rdma_lookup_path(ch) :
81919f31343SBart Van Assche 		srp_ib_lookup_path(ch);
82019f31343SBart Van Assche }
82119f31343SBart Van Assche 
8224c532d6cSBart Van Assche static u8 srp_get_subnet_timeout(struct srp_host *host)
8234c532d6cSBart Van Assche {
8244c532d6cSBart Van Assche 	struct ib_port_attr attr;
8254c532d6cSBart Van Assche 	int ret;
8264c532d6cSBart Van Assche 	u8 subnet_timeout = 18;
8274c532d6cSBart Van Assche 
8284c532d6cSBart Van Assche 	ret = ib_query_port(host->srp_dev->dev, host->port, &attr);
8294c532d6cSBart Van Assche 	if (ret == 0)
8304c532d6cSBart Van Assche 		subnet_timeout = attr.subnet_timeout;
8314c532d6cSBart Van Assche 
8324c532d6cSBart Van Assche 	if (unlikely(subnet_timeout < 15))
8334c532d6cSBart Van Assche 		pr_warn("%s: subnet timeout %d may cause SRP login to fail.\n",
8344c532d6cSBart Van Assche 			dev_name(&host->srp_dev->dev->dev), subnet_timeout);
8354c532d6cSBart Van Assche 
8364c532d6cSBart Van Assche 	return subnet_timeout;
8374c532d6cSBart Van Assche }
8384c532d6cSBart Van Assche 
839513d5647SBart Van Assche static int srp_send_req(struct srp_rdma_ch *ch, uint32_t max_iu_len,
840513d5647SBart Van Assche 			bool multich)
841aef9ec39SRoland Dreier {
842509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
843aef9ec39SRoland Dreier 	struct {
84419f31343SBart Van Assche 		struct rdma_conn_param	  rdma_param;
84519f31343SBart Van Assche 		struct srp_login_req_rdma rdma_req;
84619f31343SBart Van Assche 		struct ib_cm_req_param	  ib_param;
84719f31343SBart Van Assche 		struct srp_login_req	  ib_req;
848aef9ec39SRoland Dreier 	} *req = NULL;
84948900a28SBart Van Assche 	char *ipi, *tpi;
850aef9ec39SRoland Dreier 	int status;
851aef9ec39SRoland Dreier 
852aef9ec39SRoland Dreier 	req = kzalloc(sizeof *req, GFP_KERNEL);
853aef9ec39SRoland Dreier 	if (!req)
854aef9ec39SRoland Dreier 		return -ENOMEM;
855aef9ec39SRoland Dreier 
85619f31343SBart Van Assche 	req->ib_param.flow_control = 1;
85719f31343SBart Van Assche 	req->ib_param.retry_count = target->tl_retry_count;
858aef9ec39SRoland Dreier 
859aef9ec39SRoland Dreier 	/*
860aef9ec39SRoland Dreier 	 * Pick some arbitrary defaults here; we could make these
861aef9ec39SRoland Dreier 	 * module parameters if anyone cared about setting them.
862aef9ec39SRoland Dreier 	 */
86319f31343SBart Van Assche 	req->ib_param.responder_resources = 4;
86419f31343SBart Van Assche 	req->ib_param.rnr_retry_count = 7;
86519f31343SBart Van Assche 	req->ib_param.max_cm_retries = 15;
866aef9ec39SRoland Dreier 
86719f31343SBart Van Assche 	req->ib_req.opcode = SRP_LOGIN_REQ;
86819f31343SBart Van Assche 	req->ib_req.tag = 0;
869513d5647SBart Van Assche 	req->ib_req.req_it_iu_len = cpu_to_be32(max_iu_len);
87019f31343SBart Van Assche 	req->ib_req.req_buf_fmt	= cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
871aef9ec39SRoland Dreier 					      SRP_BUF_FORMAT_INDIRECT);
87219f31343SBart Van Assche 	req->ib_req.req_flags = (multich ? SRP_MULTICHAN_MULTI :
873d92c0da7SBart Van Assche 				 SRP_MULTICHAN_SINGLE);
874882981f4SBart Van Assche 	if (srp_use_imm_data) {
875882981f4SBart Van Assche 		req->ib_req.req_flags |= SRP_IMMED_REQUESTED;
876882981f4SBart Van Assche 		req->ib_req.imm_data_offset = cpu_to_be16(SRP_IMM_DATA_OFFSET);
877882981f4SBart Van Assche 	}
87848900a28SBart Van Assche 
87919f31343SBart Van Assche 	if (target->using_rdma_cm) {
88019f31343SBart Van Assche 		req->rdma_param.flow_control = req->ib_param.flow_control;
88119f31343SBart Van Assche 		req->rdma_param.responder_resources =
88219f31343SBart Van Assche 			req->ib_param.responder_resources;
88319f31343SBart Van Assche 		req->rdma_param.initiator_depth = req->ib_param.initiator_depth;
88419f31343SBart Van Assche 		req->rdma_param.retry_count = req->ib_param.retry_count;
88519f31343SBart Van Assche 		req->rdma_param.rnr_retry_count = req->ib_param.rnr_retry_count;
88619f31343SBart Van Assche 		req->rdma_param.private_data = &req->rdma_req;
88719f31343SBart Van Assche 		req->rdma_param.private_data_len = sizeof(req->rdma_req);
88819f31343SBart Van Assche 
88919f31343SBart Van Assche 		req->rdma_req.opcode = req->ib_req.opcode;
89019f31343SBart Van Assche 		req->rdma_req.tag = req->ib_req.tag;
89119f31343SBart Van Assche 		req->rdma_req.req_it_iu_len = req->ib_req.req_it_iu_len;
89219f31343SBart Van Assche 		req->rdma_req.req_buf_fmt = req->ib_req.req_buf_fmt;
89319f31343SBart Van Assche 		req->rdma_req.req_flags	= req->ib_req.req_flags;
894882981f4SBart Van Assche 		req->rdma_req.imm_data_offset = req->ib_req.imm_data_offset;
89519f31343SBart Van Assche 
89619f31343SBart Van Assche 		ipi = req->rdma_req.initiator_port_id;
89719f31343SBart Van Assche 		tpi = req->rdma_req.target_port_id;
89819f31343SBart Van Assche 	} else {
89948900a28SBart Van Assche 		u8 subnet_timeout;
90048900a28SBart Van Assche 
90148900a28SBart Van Assche 		subnet_timeout = srp_get_subnet_timeout(target->srp_host);
90248900a28SBart Van Assche 
90319f31343SBart Van Assche 		req->ib_param.primary_path = &ch->ib_cm.path;
90419f31343SBart Van Assche 		req->ib_param.alternate_path = NULL;
90519f31343SBart Van Assche 		req->ib_param.service_id = target->ib_cm.service_id;
90619f31343SBart Van Assche 		get_random_bytes(&req->ib_param.starting_psn, 4);
90719f31343SBart Van Assche 		req->ib_param.starting_psn &= 0xffffff;
90819f31343SBart Van Assche 		req->ib_param.qp_num = ch->qp->qp_num;
90919f31343SBart Van Assche 		req->ib_param.qp_type = ch->qp->qp_type;
91019f31343SBart Van Assche 		req->ib_param.local_cm_response_timeout = subnet_timeout + 2;
91119f31343SBart Van Assche 		req->ib_param.remote_cm_response_timeout = subnet_timeout + 2;
91219f31343SBart Van Assche 		req->ib_param.private_data = &req->ib_req;
91319f31343SBart Van Assche 		req->ib_param.private_data_len = sizeof(req->ib_req);
91448900a28SBart Van Assche 
91519f31343SBart Van Assche 		ipi = req->ib_req.initiator_port_id;
91619f31343SBart Van Assche 		tpi = req->ib_req.target_port_id;
91748900a28SBart Van Assche 	}
91848900a28SBart Van Assche 
9190c0450dbSRamachandra K 	/*
9200c0450dbSRamachandra K 	 * In the published SRP specification (draft rev. 16a), the
9210c0450dbSRamachandra K 	 * port identifier format is 8 bytes of ID extension followed
9220c0450dbSRamachandra K 	 * by 8 bytes of GUID.  Older drafts put the two halves in the
9230c0450dbSRamachandra K 	 * opposite order, so that the GUID comes first.
9240c0450dbSRamachandra K 	 *
9250c0450dbSRamachandra K 	 * Targets conforming to these obsolete drafts can be
9260c0450dbSRamachandra K 	 * recognized by the I/O Class they report.
9270c0450dbSRamachandra K 	 */
9280c0450dbSRamachandra K 	if (target->io_class == SRP_REV10_IB_IO_CLASS) {
92948900a28SBart Van Assche 		memcpy(ipi,     &target->sgid.global.interface_id, 8);
93048900a28SBart Van Assche 		memcpy(ipi + 8, &target->initiator_ext, 8);
93148900a28SBart Van Assche 		memcpy(tpi,     &target->ioc_guid, 8);
93248900a28SBart Van Assche 		memcpy(tpi + 8, &target->id_ext, 8);
9330c0450dbSRamachandra K 	} else {
93448900a28SBart Van Assche 		memcpy(ipi,     &target->initiator_ext, 8);
93548900a28SBart Van Assche 		memcpy(ipi + 8, &target->sgid.global.interface_id, 8);
93648900a28SBart Van Assche 		memcpy(tpi,     &target->id_ext, 8);
93748900a28SBart Van Assche 		memcpy(tpi + 8, &target->ioc_guid, 8);
9380c0450dbSRamachandra K 	}
9390c0450dbSRamachandra K 
940aef9ec39SRoland Dreier 	/*
941aef9ec39SRoland Dreier 	 * Topspin/Cisco SRP targets will reject our login unless we
94201cb9bcbSIshai Rabinovitz 	 * zero out the first 8 bytes of our initiator port ID and set
94301cb9bcbSIshai Rabinovitz 	 * the second 8 bytes to the local node GUID.
944aef9ec39SRoland Dreier 	 */
9455d7cbfd6SRoland Dreier 	if (srp_target_is_topspin(target)) {
9467aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host,
9477aa54bd7SDavid Dillow 			     PFX "Topspin/Cisco initiator port ID workaround "
948aef9ec39SRoland Dreier 			     "activated for target GUID %016llx\n",
94945c37cadSBart Van Assche 			     be64_to_cpu(target->ioc_guid));
95048900a28SBart Van Assche 		memset(ipi, 0, 8);
95148900a28SBart Van Assche 		memcpy(ipi + 8, &target->srp_host->srp_dev->dev->node_guid, 8);
952aef9ec39SRoland Dreier 	}
953aef9ec39SRoland Dreier 
95419f31343SBart Van Assche 	if (target->using_rdma_cm)
95519f31343SBart Van Assche 		status = rdma_connect(ch->rdma_cm.cm_id, &req->rdma_param);
95619f31343SBart Van Assche 	else
95719f31343SBart Van Assche 		status = ib_send_cm_req(ch->ib_cm.cm_id, &req->ib_param);
958aef9ec39SRoland Dreier 
959aef9ec39SRoland Dreier 	kfree(req);
960aef9ec39SRoland Dreier 
961aef9ec39SRoland Dreier 	return status;
962aef9ec39SRoland Dreier }
963aef9ec39SRoland Dreier 
964ef6c49d8SBart Van Assche static bool srp_queue_remove_work(struct srp_target_port *target)
965ef6c49d8SBart Van Assche {
966ef6c49d8SBart Van Assche 	bool changed = false;
967ef6c49d8SBart Van Assche 
968ef6c49d8SBart Van Assche 	spin_lock_irq(&target->lock);
969ef6c49d8SBart Van Assche 	if (target->state != SRP_TARGET_REMOVED) {
970ef6c49d8SBart Van Assche 		target->state = SRP_TARGET_REMOVED;
971ef6c49d8SBart Van Assche 		changed = true;
972ef6c49d8SBart Van Assche 	}
973ef6c49d8SBart Van Assche 	spin_unlock_irq(&target->lock);
974ef6c49d8SBart Van Assche 
975ef6c49d8SBart Van Assche 	if (changed)
976bcc05910SBart Van Assche 		queue_work(srp_remove_wq, &target->remove_work);
977ef6c49d8SBart Van Assche 
978ef6c49d8SBart Van Assche 	return changed;
979ef6c49d8SBart Van Assche }
980ef6c49d8SBart Van Assche 
981aef9ec39SRoland Dreier static void srp_disconnect_target(struct srp_target_port *target)
982aef9ec39SRoland Dreier {
983d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
98419f31343SBart Van Assche 	int i, ret;
985509c07bcSBart Van Assche 
986aef9ec39SRoland Dreier 	/* XXX should send SRP_I_LOGOUT request */
987aef9ec39SRoland Dreier 
988d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
989d92c0da7SBart Van Assche 		ch = &target->ch[i];
990c014c8cdSBart Van Assche 		ch->connected = false;
99119f31343SBart Van Assche 		ret = 0;
99219f31343SBart Van Assche 		if (target->using_rdma_cm) {
99319f31343SBart Van Assche 			if (ch->rdma_cm.cm_id)
99419f31343SBart Van Assche 				rdma_disconnect(ch->rdma_cm.cm_id);
99519f31343SBart Van Assche 		} else {
99619f31343SBart Van Assche 			if (ch->ib_cm.cm_id)
99719f31343SBart Van Assche 				ret = ib_send_cm_dreq(ch->ib_cm.cm_id,
99819f31343SBart Van Assche 						      NULL, 0);
99919f31343SBart Van Assche 		}
100019f31343SBart Van Assche 		if (ret < 0) {
10017aa54bd7SDavid Dillow 			shost_printk(KERN_DEBUG, target->scsi_host,
10027aa54bd7SDavid Dillow 				     PFX "Sending CM DREQ failed\n");
1003aef9ec39SRoland Dreier 		}
1004294c875aSBart Van Assche 	}
1005294c875aSBart Van Assche }
1006aef9ec39SRoland Dreier 
1007509c07bcSBart Van Assche static void srp_free_req_data(struct srp_target_port *target,
1008509c07bcSBart Van Assche 			      struct srp_rdma_ch *ch)
10098f26c9ffSDavid Dillow {
10105cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
10115cfb1782SBart Van Assche 	struct ib_device *ibdev = dev->dev;
10128f26c9ffSDavid Dillow 	struct srp_request *req;
10138f26c9ffSDavid Dillow 	int i;
10148f26c9ffSDavid Dillow 
101547513cf4SBart Van Assche 	if (!ch->req_ring)
10164d73f95fSBart Van Assche 		return;
10174d73f95fSBart Van Assche 
10184d73f95fSBart Van Assche 	for (i = 0; i < target->req_ring_size; ++i) {
1019509c07bcSBart Van Assche 		req = &ch->req_ring[i];
10209a21be53SSagi Grimberg 		if (dev->use_fast_reg) {
10215cfb1782SBart Van Assche 			kfree(req->fr_list);
10229a21be53SSagi Grimberg 		} else {
10238f26c9ffSDavid Dillow 			kfree(req->fmr_list);
10248f26c9ffSDavid Dillow 			kfree(req->map_page);
10259a21be53SSagi Grimberg 		}
1026c07d424dSDavid Dillow 		if (req->indirect_dma_addr) {
1027c07d424dSDavid Dillow 			ib_dma_unmap_single(ibdev, req->indirect_dma_addr,
1028c07d424dSDavid Dillow 					    target->indirect_size,
1029c07d424dSDavid Dillow 					    DMA_TO_DEVICE);
1030c07d424dSDavid Dillow 		}
1031c07d424dSDavid Dillow 		kfree(req->indirect_desc);
10328f26c9ffSDavid Dillow 	}
10334d73f95fSBart Van Assche 
1034509c07bcSBart Van Assche 	kfree(ch->req_ring);
1035509c07bcSBart Van Assche 	ch->req_ring = NULL;
10368f26c9ffSDavid Dillow }
10378f26c9ffSDavid Dillow 
1038509c07bcSBart Van Assche static int srp_alloc_req_data(struct srp_rdma_ch *ch)
1039b81d00bdSBart Van Assche {
1040509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1041b81d00bdSBart Van Assche 	struct srp_device *srp_dev = target->srp_host->srp_dev;
1042b81d00bdSBart Van Assche 	struct ib_device *ibdev = srp_dev->dev;
1043b81d00bdSBart Van Assche 	struct srp_request *req;
10445cfb1782SBart Van Assche 	void *mr_list;
1045b81d00bdSBart Van Assche 	dma_addr_t dma_addr;
1046b81d00bdSBart Van Assche 	int i, ret = -ENOMEM;
1047b81d00bdSBart Van Assche 
1048509c07bcSBart Van Assche 	ch->req_ring = kcalloc(target->req_ring_size, sizeof(*ch->req_ring),
1049509c07bcSBart Van Assche 			       GFP_KERNEL);
1050509c07bcSBart Van Assche 	if (!ch->req_ring)
10514d73f95fSBart Van Assche 		goto out;
10524d73f95fSBart Van Assche 
10534d73f95fSBart Van Assche 	for (i = 0; i < target->req_ring_size; ++i) {
1054509c07bcSBart Van Assche 		req = &ch->req_ring[i];
10556da2ec56SKees Cook 		mr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *),
1056b81d00bdSBart Van Assche 					GFP_KERNEL);
10575cfb1782SBart Van Assche 		if (!mr_list)
10585cfb1782SBart Van Assche 			goto out;
10599a21be53SSagi Grimberg 		if (srp_dev->use_fast_reg) {
10605cfb1782SBart Van Assche 			req->fr_list = mr_list;
10619a21be53SSagi Grimberg 		} else {
10625cfb1782SBart Van Assche 			req->fmr_list = mr_list;
10636da2ec56SKees Cook 			req->map_page = kmalloc_array(srp_dev->max_pages_per_mr,
10646da2ec56SKees Cook 						      sizeof(void *),
10656da2ec56SKees Cook 						      GFP_KERNEL);
10665cfb1782SBart Van Assche 			if (!req->map_page)
10675cfb1782SBart Van Assche 				goto out;
10689a21be53SSagi Grimberg 		}
1069b81d00bdSBart Van Assche 		req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
10705cfb1782SBart Van Assche 		if (!req->indirect_desc)
1071b81d00bdSBart Van Assche 			goto out;
1072b81d00bdSBart Van Assche 
1073b81d00bdSBart Van Assche 		dma_addr = ib_dma_map_single(ibdev, req->indirect_desc,
1074b81d00bdSBart Van Assche 					     target->indirect_size,
1075b81d00bdSBart Van Assche 					     DMA_TO_DEVICE);
1076b81d00bdSBart Van Assche 		if (ib_dma_mapping_error(ibdev, dma_addr))
1077b81d00bdSBart Van Assche 			goto out;
1078b81d00bdSBart Van Assche 
1079b81d00bdSBart Van Assche 		req->indirect_dma_addr = dma_addr;
1080b81d00bdSBart Van Assche 	}
1081b81d00bdSBart Van Assche 	ret = 0;
1082b81d00bdSBart Van Assche 
1083b81d00bdSBart Van Assche out:
1084b81d00bdSBart Van Assche 	return ret;
1085b81d00bdSBart Van Assche }
1086b81d00bdSBart Van Assche 
1087683b159aSBart Van Assche /**
1088683b159aSBart Van Assche  * srp_del_scsi_host_attr() - Remove attributes defined in the host template.
1089683b159aSBart Van Assche  * @shost: SCSI host whose attributes to remove from sysfs.
1090683b159aSBart Van Assche  *
1091683b159aSBart Van Assche  * Note: Any attributes defined in the host template and that did not exist
1092683b159aSBart Van Assche  * before invocation of this function will be ignored.
1093683b159aSBart Van Assche  */
1094683b159aSBart Van Assche static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
1095683b159aSBart Van Assche {
1096683b159aSBart Van Assche 	struct device_attribute **attr;
1097683b159aSBart Van Assche 
1098683b159aSBart Van Assche 	for (attr = shost->hostt->shost_attrs; attr && *attr; ++attr)
1099683b159aSBart Van Assche 		device_remove_file(&shost->shost_dev, *attr);
1100683b159aSBart Van Assche }
1101683b159aSBart Van Assche 
1102ee12d6a8SBart Van Assche static void srp_remove_target(struct srp_target_port *target)
1103ee12d6a8SBart Van Assche {
1104d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1105d92c0da7SBart Van Assche 	int i;
1106509c07bcSBart Van Assche 
1107ef6c49d8SBart Van Assche 	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
1108ef6c49d8SBart Van Assche 
1109ee12d6a8SBart Van Assche 	srp_del_scsi_host_attr(target->scsi_host);
11109dd69a60SBart Van Assche 	srp_rport_get(target->rport);
1111ee12d6a8SBart Van Assche 	srp_remove_host(target->scsi_host);
1112ee12d6a8SBart Van Assche 	scsi_remove_host(target->scsi_host);
111393079162SBart Van Assche 	srp_stop_rport_timers(target->rport);
1114ef6c49d8SBart Van Assche 	srp_disconnect_target(target);
111519f31343SBart Van Assche 	kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
1116d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1117d92c0da7SBart Van Assche 		ch = &target->ch[i];
1118509c07bcSBart Van Assche 		srp_free_ch_ib(target, ch);
1119d92c0da7SBart Van Assche 	}
1120c1120f89SBart Van Assche 	cancel_work_sync(&target->tl_err_work);
11219dd69a60SBart Van Assche 	srp_rport_put(target->rport);
1122d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1123d92c0da7SBart Van Assche 		ch = &target->ch[i];
1124509c07bcSBart Van Assche 		srp_free_req_data(target, ch);
1125d92c0da7SBart Van Assche 	}
1126d92c0da7SBart Van Assche 	kfree(target->ch);
1127d92c0da7SBart Van Assche 	target->ch = NULL;
112865d7dd2fSVu Pham 
112965d7dd2fSVu Pham 	spin_lock(&target->srp_host->target_lock);
113065d7dd2fSVu Pham 	list_del(&target->list);
113165d7dd2fSVu Pham 	spin_unlock(&target->srp_host->target_lock);
113265d7dd2fSVu Pham 
1133ee12d6a8SBart Van Assche 	scsi_host_put(target->scsi_host);
1134ee12d6a8SBart Van Assche }
1135ee12d6a8SBart Van Assche 
1136c4028958SDavid Howells static void srp_remove_work(struct work_struct *work)
1137aef9ec39SRoland Dreier {
1138c4028958SDavid Howells 	struct srp_target_port *target =
1139ef6c49d8SBart Van Assche 		container_of(work, struct srp_target_port, remove_work);
1140aef9ec39SRoland Dreier 
1141ef6c49d8SBart Van Assche 	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
1142aef9ec39SRoland Dreier 
114396fc248aSBart Van Assche 	srp_remove_target(target);
1144aef9ec39SRoland Dreier }
1145aef9ec39SRoland Dreier 
1146dc1bdbd9SBart Van Assche static void srp_rport_delete(struct srp_rport *rport)
1147dc1bdbd9SBart Van Assche {
1148dc1bdbd9SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1149dc1bdbd9SBart Van Assche 
1150dc1bdbd9SBart Van Assche 	srp_queue_remove_work(target);
1151dc1bdbd9SBart Van Assche }
1152dc1bdbd9SBart Van Assche 
1153c014c8cdSBart Van Assche /**
1154c014c8cdSBart Van Assche  * srp_connected_ch() - number of connected channels
1155c014c8cdSBart Van Assche  * @target: SRP target port.
1156c014c8cdSBart Van Assche  */
1157c014c8cdSBart Van Assche static int srp_connected_ch(struct srp_target_port *target)
1158c014c8cdSBart Van Assche {
1159c014c8cdSBart Van Assche 	int i, c = 0;
1160c014c8cdSBart Van Assche 
1161c014c8cdSBart Van Assche 	for (i = 0; i < target->ch_count; i++)
1162c014c8cdSBart Van Assche 		c += target->ch[i].connected;
1163c014c8cdSBart Van Assche 
1164c014c8cdSBart Van Assche 	return c;
1165c014c8cdSBart Van Assche }
1166c014c8cdSBart Van Assche 
1167513d5647SBart Van Assche static int srp_connect_ch(struct srp_rdma_ch *ch, uint32_t max_iu_len,
1168513d5647SBart Van Assche 			  bool multich)
1169aef9ec39SRoland Dreier {
1170509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1171aef9ec39SRoland Dreier 	int ret;
1172aef9ec39SRoland Dreier 
1173c014c8cdSBart Van Assche 	WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0);
1174294c875aSBart Van Assche 
1175509c07bcSBart Van Assche 	ret = srp_lookup_path(ch);
1176aef9ec39SRoland Dreier 	if (ret)
11774d59ad29SBart Van Assche 		goto out;
1178aef9ec39SRoland Dreier 
1179aef9ec39SRoland Dreier 	while (1) {
1180509c07bcSBart Van Assche 		init_completion(&ch->done);
1181513d5647SBart Van Assche 		ret = srp_send_req(ch, max_iu_len, multich);
1182aef9ec39SRoland Dreier 		if (ret)
11834d59ad29SBart Van Assche 			goto out;
1184509c07bcSBart Van Assche 		ret = wait_for_completion_interruptible(&ch->done);
1185a702adceSBart Van Assche 		if (ret < 0)
11864d59ad29SBart Van Assche 			goto out;
1187aef9ec39SRoland Dreier 
1188aef9ec39SRoland Dreier 		/*
1189aef9ec39SRoland Dreier 		 * The CM event handling code will set status to
1190aef9ec39SRoland Dreier 		 * SRP_PORT_REDIRECT if we get a port redirect REJ
1191aef9ec39SRoland Dreier 		 * back, or SRP_DLID_REDIRECT if we get a lid/qp
1192aef9ec39SRoland Dreier 		 * redirect REJ back.
1193aef9ec39SRoland Dreier 		 */
11944d59ad29SBart Van Assche 		ret = ch->status;
11954d59ad29SBart Van Assche 		switch (ret) {
1196aef9ec39SRoland Dreier 		case 0:
1197c014c8cdSBart Van Assche 			ch->connected = true;
11984d59ad29SBart Van Assche 			goto out;
1199aef9ec39SRoland Dreier 
1200aef9ec39SRoland Dreier 		case SRP_PORT_REDIRECT:
1201509c07bcSBart Van Assche 			ret = srp_lookup_path(ch);
1202aef9ec39SRoland Dreier 			if (ret)
12034d59ad29SBart Van Assche 				goto out;
1204aef9ec39SRoland Dreier 			break;
1205aef9ec39SRoland Dreier 
1206aef9ec39SRoland Dreier 		case SRP_DLID_REDIRECT:
1207aef9ec39SRoland Dreier 			break;
1208aef9ec39SRoland Dreier 
12099fe4bcf4SDavid Dillow 		case SRP_STALE_CONN:
12109fe4bcf4SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host, PFX
12119fe4bcf4SDavid Dillow 				     "giving up on stale connection\n");
12124d59ad29SBart Van Assche 			ret = -ECONNRESET;
12134d59ad29SBart Van Assche 			goto out;
12149fe4bcf4SDavid Dillow 
1215aef9ec39SRoland Dreier 		default:
12164d59ad29SBart Van Assche 			goto out;
1217aef9ec39SRoland Dreier 		}
1218aef9ec39SRoland Dreier 	}
12194d59ad29SBart Van Assche 
12204d59ad29SBart Van Assche out:
12214d59ad29SBart Van Assche 	return ret <= 0 ? ret : -ENODEV;
1222aef9ec39SRoland Dreier }
1223aef9ec39SRoland Dreier 
12241dc7b1f1SChristoph Hellwig static void srp_inv_rkey_err_done(struct ib_cq *cq, struct ib_wc *wc)
12251dc7b1f1SChristoph Hellwig {
12261dc7b1f1SChristoph Hellwig 	srp_handle_qp_err(cq, wc, "INV RKEY");
12271dc7b1f1SChristoph Hellwig }
12281dc7b1f1SChristoph Hellwig 
12291dc7b1f1SChristoph Hellwig static int srp_inv_rkey(struct srp_request *req, struct srp_rdma_ch *ch,
12301dc7b1f1SChristoph Hellwig 		u32 rkey)
12315cfb1782SBart Van Assche {
12325cfb1782SBart Van Assche 	struct ib_send_wr wr = {
12335cfb1782SBart Van Assche 		.opcode		    = IB_WR_LOCAL_INV,
12345cfb1782SBart Van Assche 		.next		    = NULL,
12355cfb1782SBart Van Assche 		.num_sge	    = 0,
12365cfb1782SBart Van Assche 		.send_flags	    = 0,
12375cfb1782SBart Van Assche 		.ex.invalidate_rkey = rkey,
12385cfb1782SBart Van Assche 	};
12395cfb1782SBart Van Assche 
12401dc7b1f1SChristoph Hellwig 	wr.wr_cqe = &req->reg_cqe;
12411dc7b1f1SChristoph Hellwig 	req->reg_cqe.done = srp_inv_rkey_err_done;
124271347b0cSBart Van Assche 	return ib_post_send(ch->qp, &wr, NULL);
12435cfb1782SBart Van Assche }
12445cfb1782SBart Van Assche 
1245d945e1dfSRoland Dreier static void srp_unmap_data(struct scsi_cmnd *scmnd,
1246509c07bcSBart Van Assche 			   struct srp_rdma_ch *ch,
1247d945e1dfSRoland Dreier 			   struct srp_request *req)
1248d945e1dfSRoland Dreier {
1249509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
12505cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
12515cfb1782SBart Van Assche 	struct ib_device *ibdev = dev->dev;
12525cfb1782SBart Van Assche 	int i, res;
12538f26c9ffSDavid Dillow 
1254bb350d1dSFUJITA Tomonori 	if (!scsi_sglist(scmnd) ||
1255d945e1dfSRoland Dreier 	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
1256d945e1dfSRoland Dreier 	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
1257d945e1dfSRoland Dreier 		return;
1258d945e1dfSRoland Dreier 
12595cfb1782SBart Van Assche 	if (dev->use_fast_reg) {
12605cfb1782SBart Van Assche 		struct srp_fr_desc **pfr;
12615cfb1782SBart Van Assche 
12625cfb1782SBart Van Assche 		for (i = req->nmdesc, pfr = req->fr_list; i > 0; i--, pfr++) {
12631dc7b1f1SChristoph Hellwig 			res = srp_inv_rkey(req, ch, (*pfr)->mr->rkey);
12645cfb1782SBart Van Assche 			if (res < 0) {
12655cfb1782SBart Van Assche 				shost_printk(KERN_ERR, target->scsi_host, PFX
12665cfb1782SBart Van Assche 				  "Queueing INV WR for rkey %#x failed (%d)\n",
12675cfb1782SBart Van Assche 				  (*pfr)->mr->rkey, res);
12685cfb1782SBart Van Assche 				queue_work(system_long_wq,
12695cfb1782SBart Van Assche 					   &target->tl_err_work);
12705cfb1782SBart Van Assche 			}
12715cfb1782SBart Van Assche 		}
12725cfb1782SBart Van Assche 		if (req->nmdesc)
1273509c07bcSBart Van Assche 			srp_fr_pool_put(ch->fr_pool, req->fr_list,
12745cfb1782SBart Van Assche 					req->nmdesc);
1275002f1567SBart Van Assche 	} else if (dev->use_fmr) {
12765cfb1782SBart Van Assche 		struct ib_pool_fmr **pfmr;
12775cfb1782SBart Van Assche 
12785cfb1782SBart Van Assche 		for (i = req->nmdesc, pfmr = req->fmr_list; i > 0; i--, pfmr++)
12795cfb1782SBart Van Assche 			ib_fmr_pool_unmap(*pfmr);
12805cfb1782SBart Van Assche 	}
1281f5358a17SRoland Dreier 
12828f26c9ffSDavid Dillow 	ib_dma_unmap_sg(ibdev, scsi_sglist(scmnd), scsi_sg_count(scmnd),
12838f26c9ffSDavid Dillow 			scmnd->sc_data_direction);
1284d945e1dfSRoland Dreier }
1285d945e1dfSRoland Dreier 
128622032991SBart Van Assche /**
128722032991SBart Van Assche  * srp_claim_req - Take ownership of the scmnd associated with a request.
1288509c07bcSBart Van Assche  * @ch: SRP RDMA channel.
128922032991SBart Van Assche  * @req: SRP request.
1290b3fe628dSBart Van Assche  * @sdev: If not NULL, only take ownership for this SCSI device.
129122032991SBart Van Assche  * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
129222032991SBart Van Assche  *         ownership of @req->scmnd if it equals @scmnd.
129322032991SBart Van Assche  *
129422032991SBart Van Assche  * Return value:
129522032991SBart Van Assche  * Either NULL or a pointer to the SCSI command the caller became owner of.
129622032991SBart Van Assche  */
1297509c07bcSBart Van Assche static struct scsi_cmnd *srp_claim_req(struct srp_rdma_ch *ch,
129822032991SBart Van Assche 				       struct srp_request *req,
1299b3fe628dSBart Van Assche 				       struct scsi_device *sdev,
130022032991SBart Van Assche 				       struct scsi_cmnd *scmnd)
1301526b4caaSIshai Rabinovitz {
130294a9174cSBart Van Assche 	unsigned long flags;
130394a9174cSBart Van Assche 
1304509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1305b3fe628dSBart Van Assche 	if (req->scmnd &&
1306b3fe628dSBart Van Assche 	    (!sdev || req->scmnd->device == sdev) &&
1307b3fe628dSBart Van Assche 	    (!scmnd || req->scmnd == scmnd)) {
130822032991SBart Van Assche 		scmnd = req->scmnd;
130922032991SBart Van Assche 		req->scmnd = NULL;
131022032991SBart Van Assche 	} else {
131122032991SBart Van Assche 		scmnd = NULL;
131222032991SBart Van Assche 	}
1313509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
131422032991SBart Van Assche 
131522032991SBart Van Assche 	return scmnd;
131622032991SBart Van Assche }
131722032991SBart Van Assche 
131822032991SBart Van Assche /**
13196ec2ba02SBart Van Assche  * srp_free_req() - Unmap data and adjust ch->req_lim.
1320509c07bcSBart Van Assche  * @ch:     SRP RDMA channel.
1321af24663bSBart Van Assche  * @req:    Request to be freed.
1322af24663bSBart Van Assche  * @scmnd:  SCSI command associated with @req.
1323af24663bSBart Van Assche  * @req_lim_delta: Amount to be added to @target->req_lim.
132422032991SBart Van Assche  */
1325509c07bcSBart Van Assche static void srp_free_req(struct srp_rdma_ch *ch, struct srp_request *req,
1326509c07bcSBart Van Assche 			 struct scsi_cmnd *scmnd, s32 req_lim_delta)
132722032991SBart Van Assche {
132822032991SBart Van Assche 	unsigned long flags;
132922032991SBart Van Assche 
1330509c07bcSBart Van Assche 	srp_unmap_data(scmnd, ch, req);
133122032991SBart Van Assche 
1332509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1333509c07bcSBart Van Assche 	ch->req_lim += req_lim_delta;
1334509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
1335526b4caaSIshai Rabinovitz }
1336526b4caaSIshai Rabinovitz 
1337509c07bcSBart Van Assche static void srp_finish_req(struct srp_rdma_ch *ch, struct srp_request *req,
1338509c07bcSBart Van Assche 			   struct scsi_device *sdev, int result)
1339526b4caaSIshai Rabinovitz {
1340509c07bcSBart Van Assche 	struct scsi_cmnd *scmnd = srp_claim_req(ch, req, sdev, NULL);
134122032991SBart Van Assche 
134222032991SBart Van Assche 	if (scmnd) {
1343509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd, 0);
1344ed9b2264SBart Van Assche 		scmnd->result = result;
134522032991SBart Van Assche 		scmnd->scsi_done(scmnd);
134622032991SBart Van Assche 	}
1347526b4caaSIshai Rabinovitz }
1348526b4caaSIshai Rabinovitz 
1349ed9b2264SBart Van Assche static void srp_terminate_io(struct srp_rport *rport)
1350aef9ec39SRoland Dreier {
1351ed9b2264SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1352d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1353d92c0da7SBart Van Assche 	int i, j;
1354aef9ec39SRoland Dreier 
1355d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1356d92c0da7SBart Van Assche 		ch = &target->ch[i];
1357509c07bcSBart Van Assche 
1358d92c0da7SBart Van Assche 		for (j = 0; j < target->req_ring_size; ++j) {
1359d92c0da7SBart Van Assche 			struct srp_request *req = &ch->req_ring[j];
1360d92c0da7SBart Van Assche 
1361d92c0da7SBart Van Assche 			srp_finish_req(ch, req, NULL,
1362d92c0da7SBart Van Assche 				       DID_TRANSPORT_FAILFAST << 16);
1363d92c0da7SBart Van Assche 		}
1364ed9b2264SBart Van Assche 	}
1365ed9b2264SBart Van Assche }
1366ed9b2264SBart Van Assche 
1367513d5647SBart Van Assche /* Calculate maximum initiator to target information unit length. */
1368b2e872f4SHonggang Li static uint32_t srp_max_it_iu_len(int cmd_sg_cnt, bool use_imm_data,
1369b2e872f4SHonggang Li 				  uint32_t max_it_iu_size)
1370513d5647SBart Van Assche {
1371513d5647SBart Van Assche 	uint32_t max_iu_len = sizeof(struct srp_cmd) + SRP_MAX_ADD_CDB_LEN +
1372513d5647SBart Van Assche 		sizeof(struct srp_indirect_buf) +
1373513d5647SBart Van Assche 		cmd_sg_cnt * sizeof(struct srp_direct_buf);
1374513d5647SBart Van Assche 
1375882981f4SBart Van Assche 	if (use_imm_data)
1376882981f4SBart Van Assche 		max_iu_len = max(max_iu_len, SRP_IMM_DATA_OFFSET +
1377882981f4SBart Van Assche 				 srp_max_imm_data);
1378882981f4SBart Van Assche 
1379b2e872f4SHonggang Li 	if (max_it_iu_size)
1380b2e872f4SHonggang Li 		max_iu_len = min(max_iu_len, max_it_iu_size);
1381b2e872f4SHonggang Li 
1382b2e872f4SHonggang Li 	pr_debug("max_iu_len = %d\n", max_iu_len);
1383b2e872f4SHonggang Li 
1384513d5647SBart Van Assche 	return max_iu_len;
1385513d5647SBart Van Assche }
1386513d5647SBart Van Assche 
1387ed9b2264SBart Van Assche /*
1388ed9b2264SBart Van Assche  * It is up to the caller to ensure that srp_rport_reconnect() calls are
1389ed9b2264SBart Van Assche  * serialized and that no concurrent srp_queuecommand(), srp_abort(),
1390ed9b2264SBart Van Assche  * srp_reset_device() or srp_reset_host() calls will occur while this function
1391ed9b2264SBart Van Assche  * is in progress. One way to realize that is not to call this function
1392ed9b2264SBart Van Assche  * directly but to call srp_reconnect_rport() instead since that last function
1393ed9b2264SBart Van Assche  * serializes calls of this function via rport->mutex and also blocks
1394ed9b2264SBart Van Assche  * srp_queuecommand() calls before invoking this function.
1395ed9b2264SBart Van Assche  */
1396ed9b2264SBart Van Assche static int srp_rport_reconnect(struct srp_rport *rport)
1397ed9b2264SBart Van Assche {
1398ed9b2264SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1399d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1400882981f4SBart Van Assche 	uint32_t max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
1401b2e872f4SHonggang Li 						srp_use_imm_data,
1402b2e872f4SHonggang Li 						target->max_it_iu_size);
1403d92c0da7SBart Van Assche 	int i, j, ret = 0;
1404d92c0da7SBart Van Assche 	bool multich = false;
140509be70a2SBart Van Assche 
1406aef9ec39SRoland Dreier 	srp_disconnect_target(target);
140734aa654eSBart Van Assche 
140834aa654eSBart Van Assche 	if (target->state == SRP_TARGET_SCANNING)
140934aa654eSBart Van Assche 		return -ENODEV;
141034aa654eSBart Van Assche 
1411aef9ec39SRoland Dreier 	/*
1412c7c4e7ffSBart Van Assche 	 * Now get a new local CM ID so that we avoid confusing the target in
1413c7c4e7ffSBart Van Assche 	 * case things are really fouled up. Doing so also ensures that all CM
1414c7c4e7ffSBart Van Assche 	 * callbacks will have finished before a new QP is allocated.
1415aef9ec39SRoland Dreier 	 */
1416d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1417d92c0da7SBart Van Assche 		ch = &target->ch[i];
1418d92c0da7SBart Van Assche 		ret += srp_new_cm_id(ch);
1419d92c0da7SBart Van Assche 	}
1420d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1421d92c0da7SBart Van Assche 		ch = &target->ch[i];
1422d92c0da7SBart Van Assche 		for (j = 0; j < target->req_ring_size; ++j) {
1423d92c0da7SBart Van Assche 			struct srp_request *req = &ch->req_ring[j];
1424509c07bcSBart Van Assche 
1425509c07bcSBart Van Assche 			srp_finish_req(ch, req, NULL, DID_RESET << 16);
1426536ae14eSBart Van Assche 		}
1427d92c0da7SBart Van Assche 	}
1428d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1429d92c0da7SBart Van Assche 		ch = &target->ch[i];
14305cfb1782SBart Van Assche 		/*
14315cfb1782SBart Van Assche 		 * Whether or not creating a new CM ID succeeded, create a new
1432d92c0da7SBart Van Assche 		 * QP. This guarantees that all completion callback function
1433d92c0da7SBart Van Assche 		 * invocations have finished before request resetting starts.
14345cfb1782SBart Van Assche 		 */
1435509c07bcSBart Van Assche 		ret += srp_create_ch_ib(ch);
14365cfb1782SBart Van Assche 
1437509c07bcSBart Van Assche 		INIT_LIST_HEAD(&ch->free_tx);
1438d92c0da7SBart Van Assche 		for (j = 0; j < target->queue_size; ++j)
1439d92c0da7SBart Van Assche 			list_add(&ch->tx_ring[j]->list, &ch->free_tx);
1440d92c0da7SBart Van Assche 	}
14418de9fe3aSBart Van Assche 
14428de9fe3aSBart Van Assche 	target->qp_in_error = false;
14438de9fe3aSBart Van Assche 
1444d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1445d92c0da7SBart Van Assche 		ch = &target->ch[i];
1446bbac5ccfSBart Van Assche 		if (ret)
1447d92c0da7SBart Van Assche 			break;
1448513d5647SBart Van Assche 		ret = srp_connect_ch(ch, max_iu_len, multich);
1449d92c0da7SBart Van Assche 		multich = true;
1450d92c0da7SBart Van Assche 	}
145109be70a2SBart Van Assche 
1452ed9b2264SBart Van Assche 	if (ret == 0)
1453ed9b2264SBart Van Assche 		shost_printk(KERN_INFO, target->scsi_host,
1454ed9b2264SBart Van Assche 			     PFX "reconnect succeeded\n");
1455aef9ec39SRoland Dreier 
1456aef9ec39SRoland Dreier 	return ret;
1457aef9ec39SRoland Dreier }
1458aef9ec39SRoland Dreier 
14598f26c9ffSDavid Dillow static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr,
14608f26c9ffSDavid Dillow 			 unsigned int dma_len, u32 rkey)
1461f5358a17SRoland Dreier {
14628f26c9ffSDavid Dillow 	struct srp_direct_buf *desc = state->desc;
14638f26c9ffSDavid Dillow 
14643ae95da8SBart Van Assche 	WARN_ON_ONCE(!dma_len);
14653ae95da8SBart Van Assche 
14668f26c9ffSDavid Dillow 	desc->va = cpu_to_be64(dma_addr);
14678f26c9ffSDavid Dillow 	desc->key = cpu_to_be32(rkey);
14688f26c9ffSDavid Dillow 	desc->len = cpu_to_be32(dma_len);
14698f26c9ffSDavid Dillow 
14708f26c9ffSDavid Dillow 	state->total_len += dma_len;
14718f26c9ffSDavid Dillow 	state->desc++;
14728f26c9ffSDavid Dillow 	state->ndesc++;
14738f26c9ffSDavid Dillow }
14748f26c9ffSDavid Dillow 
14758f26c9ffSDavid Dillow static int srp_map_finish_fmr(struct srp_map_state *state,
1476509c07bcSBart Van Assche 			      struct srp_rdma_ch *ch)
14778f26c9ffSDavid Dillow {
1478186fbc66SBart Van Assche 	struct srp_target_port *target = ch->target;
1479186fbc66SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
14808f26c9ffSDavid Dillow 	struct ib_pool_fmr *fmr;
1481f5358a17SRoland Dreier 	u64 io_addr = 0;
14828f26c9ffSDavid Dillow 
1483290081b4SBart Van Assche 	if (state->fmr.next >= state->fmr.end) {
1484290081b4SBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host,
1485290081b4SBart Van Assche 			     PFX "Out of MRs (mr_per_cmd = %d)\n",
1486290081b4SBart Van Assche 			     ch->target->mr_per_cmd);
1487f731ed62SBart Van Assche 		return -ENOMEM;
1488290081b4SBart Van Assche 	}
1489f731ed62SBart Van Assche 
149026630e8aSSagi Grimberg 	WARN_ON_ONCE(!dev->use_fmr);
149126630e8aSSagi Grimberg 
149226630e8aSSagi Grimberg 	if (state->npages == 0)
149326630e8aSSagi Grimberg 		return 0;
149426630e8aSSagi Grimberg 
1495cee687b6SBart Van Assche 	if (state->npages == 1 && target->global_rkey) {
149626630e8aSSagi Grimberg 		srp_map_desc(state, state->base_dma_addr, state->dma_len,
1497cee687b6SBart Van Assche 			     target->global_rkey);
149826630e8aSSagi Grimberg 		goto reset_state;
149926630e8aSSagi Grimberg 	}
150026630e8aSSagi Grimberg 
1501509c07bcSBart Van Assche 	fmr = ib_fmr_pool_map_phys(ch->fmr_pool, state->pages,
15028f26c9ffSDavid Dillow 				   state->npages, io_addr);
15038f26c9ffSDavid Dillow 	if (IS_ERR(fmr))
15048f26c9ffSDavid Dillow 		return PTR_ERR(fmr);
15058f26c9ffSDavid Dillow 
1506f731ed62SBart Van Assche 	*state->fmr.next++ = fmr;
150752ede08fSBart Van Assche 	state->nmdesc++;
15088f26c9ffSDavid Dillow 
1509186fbc66SBart Van Assche 	srp_map_desc(state, state->base_dma_addr & ~dev->mr_page_mask,
1510186fbc66SBart Van Assche 		     state->dma_len, fmr->fmr->rkey);
1511539dde6fSBart Van Assche 
151226630e8aSSagi Grimberg reset_state:
151326630e8aSSagi Grimberg 	state->npages = 0;
151426630e8aSSagi Grimberg 	state->dma_len = 0;
151526630e8aSSagi Grimberg 
15168f26c9ffSDavid Dillow 	return 0;
15178f26c9ffSDavid Dillow }
15188f26c9ffSDavid Dillow 
15191dc7b1f1SChristoph Hellwig static void srp_reg_mr_err_done(struct ib_cq *cq, struct ib_wc *wc)
15201dc7b1f1SChristoph Hellwig {
15211dc7b1f1SChristoph Hellwig 	srp_handle_qp_err(cq, wc, "FAST REG");
15221dc7b1f1SChristoph Hellwig }
15231dc7b1f1SChristoph Hellwig 
1524509c5f33SBart Van Assche /*
1525509c5f33SBart Van Assche  * Map up to sg_nents elements of state->sg where *sg_offset_p is the offset
1526509c5f33SBart Van Assche  * where to start in the first element. If sg_offset_p != NULL then
1527509c5f33SBart Van Assche  * *sg_offset_p is updated to the offset in state->sg[retval] of the first
1528509c5f33SBart Van Assche  * byte that has not yet been mapped.
1529509c5f33SBart Van Assche  */
15305cfb1782SBart Van Assche static int srp_map_finish_fr(struct srp_map_state *state,
15311dc7b1f1SChristoph Hellwig 			     struct srp_request *req,
1532509c5f33SBart Van Assche 			     struct srp_rdma_ch *ch, int sg_nents,
1533509c5f33SBart Van Assche 			     unsigned int *sg_offset_p)
15345cfb1782SBart Van Assche {
1535509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
15365cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
1537f7f7aab1SSagi Grimberg 	struct ib_reg_wr wr;
15385cfb1782SBart Van Assche 	struct srp_fr_desc *desc;
15395cfb1782SBart Van Assche 	u32 rkey;
1540f7f7aab1SSagi Grimberg 	int n, err;
15415cfb1782SBart Van Assche 
1542290081b4SBart Van Assche 	if (state->fr.next >= state->fr.end) {
1543290081b4SBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host,
1544290081b4SBart Van Assche 			     PFX "Out of MRs (mr_per_cmd = %d)\n",
1545290081b4SBart Van Assche 			     ch->target->mr_per_cmd);
1546f731ed62SBart Van Assche 		return -ENOMEM;
1547290081b4SBart Van Assche 	}
1548f731ed62SBart Van Assche 
154926630e8aSSagi Grimberg 	WARN_ON_ONCE(!dev->use_fast_reg);
155026630e8aSSagi Grimberg 
1551cee687b6SBart Van Assche 	if (sg_nents == 1 && target->global_rkey) {
1552509c5f33SBart Van Assche 		unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
1553509c5f33SBart Van Assche 
1554509c5f33SBart Van Assche 		srp_map_desc(state, sg_dma_address(state->sg) + sg_offset,
1555509c5f33SBart Van Assche 			     sg_dma_len(state->sg) - sg_offset,
1556cee687b6SBart Van Assche 			     target->global_rkey);
1557509c5f33SBart Van Assche 		if (sg_offset_p)
1558509c5f33SBart Van Assche 			*sg_offset_p = 0;
1559f7f7aab1SSagi Grimberg 		return 1;
156026630e8aSSagi Grimberg 	}
156126630e8aSSagi Grimberg 
1562509c07bcSBart Van Assche 	desc = srp_fr_pool_get(ch->fr_pool);
15635cfb1782SBart Van Assche 	if (!desc)
15645cfb1782SBart Van Assche 		return -ENOMEM;
15655cfb1782SBart Van Assche 
15665cfb1782SBart Van Assche 	rkey = ib_inc_rkey(desc->mr->rkey);
15675cfb1782SBart Van Assche 	ib_update_fast_reg_key(desc->mr, rkey);
15685cfb1782SBart Van Assche 
1569509c5f33SBart Van Assche 	n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, sg_offset_p,
1570509c5f33SBart Van Assche 			 dev->mr_page_size);
15719d8e7d0dSBart Van Assche 	if (unlikely(n < 0)) {
15729d8e7d0dSBart Van Assche 		srp_fr_pool_put(ch->fr_pool, &desc, 1);
1573509c5f33SBart Van Assche 		pr_debug("%s: ib_map_mr_sg(%d, %d) returned %d.\n",
15749d8e7d0dSBart Van Assche 			 dev_name(&req->scmnd->device->sdev_gendev), sg_nents,
1575509c5f33SBart Van Assche 			 sg_offset_p ? *sg_offset_p : -1, n);
1576f7f7aab1SSagi Grimberg 		return n;
15779d8e7d0dSBart Van Assche 	}
15785cfb1782SBart Van Assche 
1579509c5f33SBart Van Assche 	WARN_ON_ONCE(desc->mr->length == 0);
15805cfb1782SBart Van Assche 
15811dc7b1f1SChristoph Hellwig 	req->reg_cqe.done = srp_reg_mr_err_done;
15821dc7b1f1SChristoph Hellwig 
1583f7f7aab1SSagi Grimberg 	wr.wr.next = NULL;
1584f7f7aab1SSagi Grimberg 	wr.wr.opcode = IB_WR_REG_MR;
15851dc7b1f1SChristoph Hellwig 	wr.wr.wr_cqe = &req->reg_cqe;
1586f7f7aab1SSagi Grimberg 	wr.wr.num_sge = 0;
1587f7f7aab1SSagi Grimberg 	wr.wr.send_flags = 0;
1588f7f7aab1SSagi Grimberg 	wr.mr = desc->mr;
1589f7f7aab1SSagi Grimberg 	wr.key = desc->mr->rkey;
1590f7f7aab1SSagi Grimberg 	wr.access = (IB_ACCESS_LOCAL_WRITE |
15915cfb1782SBart Van Assche 		     IB_ACCESS_REMOTE_READ |
15925cfb1782SBart Van Assche 		     IB_ACCESS_REMOTE_WRITE);
15935cfb1782SBart Van Assche 
1594f731ed62SBart Van Assche 	*state->fr.next++ = desc;
15955cfb1782SBart Van Assche 	state->nmdesc++;
15965cfb1782SBart Van Assche 
1597f7f7aab1SSagi Grimberg 	srp_map_desc(state, desc->mr->iova,
1598f7f7aab1SSagi Grimberg 		     desc->mr->length, desc->mr->rkey);
15995cfb1782SBart Van Assche 
160071347b0cSBart Van Assche 	err = ib_post_send(ch->qp, &wr.wr, NULL);
1601509c5f33SBart Van Assche 	if (unlikely(err)) {
1602509c5f33SBart Van Assche 		WARN_ON_ONCE(err == -ENOMEM);
160326630e8aSSagi Grimberg 		return err;
1604509c5f33SBart Van Assche 	}
160526630e8aSSagi Grimberg 
1606f7f7aab1SSagi Grimberg 	return n;
16075cfb1782SBart Van Assche }
16085cfb1782SBart Van Assche 
16098f26c9ffSDavid Dillow static int srp_map_sg_entry(struct srp_map_state *state,
1610509c07bcSBart Van Assche 			    struct srp_rdma_ch *ch,
161152bb8c62SBart Van Assche 			    struct scatterlist *sg)
16128f26c9ffSDavid Dillow {
1613509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
161405321937SGreg Kroah-Hartman 	struct srp_device *dev = target->srp_host->srp_dev;
1615a163afc8SBart Van Assche 	dma_addr_t dma_addr = sg_dma_address(sg);
1616a163afc8SBart Van Assche 	unsigned int dma_len = sg_dma_len(sg);
16173ae95da8SBart Van Assche 	unsigned int len = 0;
16188f26c9ffSDavid Dillow 	int ret;
161985507bccSRalph Campbell 
16203ae95da8SBart Van Assche 	WARN_ON_ONCE(!dma_len);
1621f5358a17SRoland Dreier 
16228f26c9ffSDavid Dillow 	while (dma_len) {
16235cfb1782SBart Van Assche 		unsigned offset = dma_addr & ~dev->mr_page_mask;
1624681cc360SBart Van Assche 
1625681cc360SBart Van Assche 		if (state->npages == dev->max_pages_per_mr ||
1626681cc360SBart Van Assche 		    (state->npages > 0 && offset != 0)) {
1627f7f7aab1SSagi Grimberg 			ret = srp_map_finish_fmr(state, ch);
16288f26c9ffSDavid Dillow 			if (ret)
16298f26c9ffSDavid Dillow 				return ret;
163085507bccSRalph Campbell 		}
1631f5358a17SRoland Dreier 
16325cfb1782SBart Van Assche 		len = min_t(unsigned int, dma_len, dev->mr_page_size - offset);
16338f26c9ffSDavid Dillow 
16348f26c9ffSDavid Dillow 		if (!state->npages)
16358f26c9ffSDavid Dillow 			state->base_dma_addr = dma_addr;
16365cfb1782SBart Van Assche 		state->pages[state->npages++] = dma_addr & dev->mr_page_mask;
163752ede08fSBart Van Assche 		state->dma_len += len;
16388f26c9ffSDavid Dillow 		dma_addr += len;
16398f26c9ffSDavid Dillow 		dma_len -= len;
1640f5358a17SRoland Dreier 	}
1641f5358a17SRoland Dreier 
16425cfb1782SBart Van Assche 	/*
1643681cc360SBart Van Assche 	 * If the end of the MR is not on a page boundary then we need to
16448f26c9ffSDavid Dillow 	 * close it out and start a new one -- we can only merge at page
16451d3d98c4SBart Van Assche 	 * boundaries.
16468f26c9ffSDavid Dillow 	 */
1647f5358a17SRoland Dreier 	ret = 0;
1648681cc360SBart Van Assche 	if ((dma_addr & ~dev->mr_page_mask) != 0)
1649f7f7aab1SSagi Grimberg 		ret = srp_map_finish_fmr(state, ch);
1650f5358a17SRoland Dreier 	return ret;
1651f5358a17SRoland Dreier }
1652f5358a17SRoland Dreier 
165326630e8aSSagi Grimberg static int srp_map_sg_fmr(struct srp_map_state *state, struct srp_rdma_ch *ch,
165426630e8aSSagi Grimberg 			  struct srp_request *req, struct scatterlist *scat,
165526630e8aSSagi Grimberg 			  int count)
165626630e8aSSagi Grimberg {
165726630e8aSSagi Grimberg 	struct scatterlist *sg;
165826630e8aSSagi Grimberg 	int i, ret;
165926630e8aSSagi Grimberg 
166026630e8aSSagi Grimberg 	state->pages = req->map_page;
166126630e8aSSagi Grimberg 	state->fmr.next = req->fmr_list;
1662509c5f33SBart Van Assche 	state->fmr.end = req->fmr_list + ch->target->mr_per_cmd;
166326630e8aSSagi Grimberg 
166426630e8aSSagi Grimberg 	for_each_sg(scat, sg, count, i) {
166552bb8c62SBart Van Assche 		ret = srp_map_sg_entry(state, ch, sg);
166626630e8aSSagi Grimberg 		if (ret)
166726630e8aSSagi Grimberg 			return ret;
166826630e8aSSagi Grimberg 	}
166926630e8aSSagi Grimberg 
1670f7f7aab1SSagi Grimberg 	ret = srp_map_finish_fmr(state, ch);
167126630e8aSSagi Grimberg 	if (ret)
167226630e8aSSagi Grimberg 		return ret;
167326630e8aSSagi Grimberg 
167426630e8aSSagi Grimberg 	return 0;
167526630e8aSSagi Grimberg }
167626630e8aSSagi Grimberg 
167726630e8aSSagi Grimberg static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
167826630e8aSSagi Grimberg 			 struct srp_request *req, struct scatterlist *scat,
167926630e8aSSagi Grimberg 			 int count)
168026630e8aSSagi Grimberg {
1681509c5f33SBart Van Assche 	unsigned int sg_offset = 0;
1682509c5f33SBart Van Assche 
1683f7f7aab1SSagi Grimberg 	state->fr.next = req->fr_list;
1684509c5f33SBart Van Assche 	state->fr.end = req->fr_list + ch->target->mr_per_cmd;
1685f7f7aab1SSagi Grimberg 	state->sg = scat;
168626630e8aSSagi Grimberg 
16873b59b7a6SBart Van Assche 	if (count == 0)
16883b59b7a6SBart Van Assche 		return 0;
16893b59b7a6SBart Van Assche 
169057b0be9cSBart Van Assche 	while (count) {
1691f7f7aab1SSagi Grimberg 		int i, n;
1692f7f7aab1SSagi Grimberg 
1693509c5f33SBart Van Assche 		n = srp_map_finish_fr(state, req, ch, count, &sg_offset);
1694f7f7aab1SSagi Grimberg 		if (unlikely(n < 0))
1695f7f7aab1SSagi Grimberg 			return n;
1696f7f7aab1SSagi Grimberg 
169757b0be9cSBart Van Assche 		count -= n;
1698f7f7aab1SSagi Grimberg 		for (i = 0; i < n; i++)
1699f7f7aab1SSagi Grimberg 			state->sg = sg_next(state->sg);
170026630e8aSSagi Grimberg 	}
170126630e8aSSagi Grimberg 
170226630e8aSSagi Grimberg 	return 0;
170326630e8aSSagi Grimberg }
170426630e8aSSagi Grimberg 
170526630e8aSSagi Grimberg static int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
1706509c07bcSBart Van Assche 			  struct srp_request *req, struct scatterlist *scat,
1707509c07bcSBart Van Assche 			  int count)
170876bc1e1dSBart Van Assche {
1709509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
171076bc1e1dSBart Van Assche 	struct scatterlist *sg;
171126630e8aSSagi Grimberg 	int i;
171276bc1e1dSBart Van Assche 
17133ae95da8SBart Van Assche 	for_each_sg(scat, sg, count, i) {
1714a163afc8SBart Van Assche 		srp_map_desc(state, sg_dma_address(sg), sg_dma_len(sg),
1715cee687b6SBart Van Assche 			     target->global_rkey);
17163ae95da8SBart Van Assche 	}
171776bc1e1dSBart Van Assche 
171826630e8aSSagi Grimberg 	return 0;
171976bc1e1dSBart Van Assche }
172076bc1e1dSBart Van Assche 
1721330179f2SBart Van Assche /*
1722330179f2SBart Van Assche  * Register the indirect data buffer descriptor with the HCA.
1723330179f2SBart Van Assche  *
1724330179f2SBart Van Assche  * Note: since the indirect data buffer descriptor has been allocated with
1725330179f2SBart Van Assche  * kmalloc() it is guaranteed that this buffer is a physically contiguous
1726330179f2SBart Van Assche  * memory buffer.
1727330179f2SBart Van Assche  */
1728330179f2SBart Van Assche static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
1729330179f2SBart Van Assche 		       void **next_mr, void **end_mr, u32 idb_len,
1730330179f2SBart Van Assche 		       __be32 *idb_rkey)
1731330179f2SBart Van Assche {
1732330179f2SBart Van Assche 	struct srp_target_port *target = ch->target;
1733330179f2SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
1734330179f2SBart Van Assche 	struct srp_map_state state;
1735330179f2SBart Van Assche 	struct srp_direct_buf idb_desc;
1736330179f2SBart Van Assche 	u64 idb_pages[1];
1737f7f7aab1SSagi Grimberg 	struct scatterlist idb_sg[1];
1738330179f2SBart Van Assche 	int ret;
1739330179f2SBart Van Assche 
1740330179f2SBart Van Assche 	memset(&state, 0, sizeof(state));
1741330179f2SBart Van Assche 	memset(&idb_desc, 0, sizeof(idb_desc));
1742330179f2SBart Van Assche 	state.gen.next = next_mr;
1743330179f2SBart Van Assche 	state.gen.end = end_mr;
1744330179f2SBart Van Assche 	state.desc = &idb_desc;
1745f7f7aab1SSagi Grimberg 	state.base_dma_addr = req->indirect_dma_addr;
1746f7f7aab1SSagi Grimberg 	state.dma_len = idb_len;
1747f7f7aab1SSagi Grimberg 
1748f7f7aab1SSagi Grimberg 	if (dev->use_fast_reg) {
1749f7f7aab1SSagi Grimberg 		state.sg = idb_sg;
175054f5c9c5SBart Van Assche 		sg_init_one(idb_sg, req->indirect_desc, idb_len);
1751f7f7aab1SSagi Grimberg 		idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
1752fc925518SChristoph Hellwig #ifdef CONFIG_NEED_SG_DMA_LENGTH
1753fc925518SChristoph Hellwig 		idb_sg->dma_length = idb_sg->length;	      /* hack^2 */
1754fc925518SChristoph Hellwig #endif
1755509c5f33SBart Van Assche 		ret = srp_map_finish_fr(&state, req, ch, 1, NULL);
1756f7f7aab1SSagi Grimberg 		if (ret < 0)
1757f7f7aab1SSagi Grimberg 			return ret;
1758509c5f33SBart Van Assche 		WARN_ON_ONCE(ret < 1);
1759f7f7aab1SSagi Grimberg 	} else if (dev->use_fmr) {
1760330179f2SBart Van Assche 		state.pages = idb_pages;
1761330179f2SBart Van Assche 		state.pages[0] = (req->indirect_dma_addr &
1762330179f2SBart Van Assche 				  dev->mr_page_mask);
1763330179f2SBart Van Assche 		state.npages = 1;
1764f7f7aab1SSagi Grimberg 		ret = srp_map_finish_fmr(&state, ch);
1765330179f2SBart Van Assche 		if (ret < 0)
1766f7f7aab1SSagi Grimberg 			return ret;
1767f7f7aab1SSagi Grimberg 	} else {
1768f7f7aab1SSagi Grimberg 		return -EINVAL;
1769f7f7aab1SSagi Grimberg 	}
1770330179f2SBart Van Assche 
1771330179f2SBart Van Assche 	*idb_rkey = idb_desc.key;
1772330179f2SBart Van Assche 
1773f7f7aab1SSagi Grimberg 	return 0;
1774330179f2SBart Van Assche }
1775330179f2SBart Van Assche 
1776509c5f33SBart Van Assche static void srp_check_mapping(struct srp_map_state *state,
1777509c5f33SBart Van Assche 			      struct srp_rdma_ch *ch, struct srp_request *req,
1778509c5f33SBart Van Assche 			      struct scatterlist *scat, int count)
1779509c5f33SBart Van Assche {
1780509c5f33SBart Van Assche 	struct srp_device *dev = ch->target->srp_host->srp_dev;
1781509c5f33SBart Van Assche 	struct srp_fr_desc **pfr;
1782509c5f33SBart Van Assche 	u64 desc_len = 0, mr_len = 0;
1783509c5f33SBart Van Assche 	int i;
1784509c5f33SBart Van Assche 
1785509c5f33SBart Van Assche 	for (i = 0; i < state->ndesc; i++)
1786509c5f33SBart Van Assche 		desc_len += be32_to_cpu(req->indirect_desc[i].len);
1787509c5f33SBart Van Assche 	if (dev->use_fast_reg)
1788509c5f33SBart Van Assche 		for (i = 0, pfr = req->fr_list; i < state->nmdesc; i++, pfr++)
1789509c5f33SBart Van Assche 			mr_len += (*pfr)->mr->length;
1790509c5f33SBart Van Assche 	else if (dev->use_fmr)
1791509c5f33SBart Van Assche 		for (i = 0; i < state->nmdesc; i++)
1792509c5f33SBart Van Assche 			mr_len += be32_to_cpu(req->indirect_desc[i].len);
1793509c5f33SBart Van Assche 	if (desc_len != scsi_bufflen(req->scmnd) ||
1794509c5f33SBart Van Assche 	    mr_len > scsi_bufflen(req->scmnd))
1795509c5f33SBart Van Assche 		pr_err("Inconsistent: scsi len %d <> desc len %lld <> mr len %lld; ndesc %d; nmdesc = %d\n",
1796509c5f33SBart Van Assche 		       scsi_bufflen(req->scmnd), desc_len, mr_len,
1797509c5f33SBart Van Assche 		       state->ndesc, state->nmdesc);
1798509c5f33SBart Van Assche }
1799509c5f33SBart Van Assche 
180077269cdfSBart Van Assche /**
180177269cdfSBart Van Assche  * srp_map_data() - map SCSI data buffer onto an SRP request
180277269cdfSBart Van Assche  * @scmnd: SCSI command to map
180377269cdfSBart Van Assche  * @ch: SRP RDMA channel
180477269cdfSBart Van Assche  * @req: SRP request
180577269cdfSBart Van Assche  *
180677269cdfSBart Van Assche  * Returns the length in bytes of the SRP_CMD IU or a negative value if
1807882981f4SBart Van Assche  * mapping failed. The size of any immediate data is not included in the
1808882981f4SBart Van Assche  * return value.
180977269cdfSBart Van Assche  */
1810509c07bcSBart Van Assche static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
1811aef9ec39SRoland Dreier 			struct srp_request *req)
1812aef9ec39SRoland Dreier {
1813509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1814882981f4SBart Van Assche 	struct scatterlist *scat, *sg;
1815aef9ec39SRoland Dreier 	struct srp_cmd *cmd = req->cmd->buf;
1816882981f4SBart Van Assche 	int i, len, nents, count, ret;
181785507bccSRalph Campbell 	struct srp_device *dev;
181885507bccSRalph Campbell 	struct ib_device *ibdev;
18198f26c9ffSDavid Dillow 	struct srp_map_state state;
18208f26c9ffSDavid Dillow 	struct srp_indirect_buf *indirect_hdr;
1821882981f4SBart Van Assche 	u64 data_len;
1822330179f2SBart Van Assche 	u32 idb_len, table_len;
1823330179f2SBart Van Assche 	__be32 idb_rkey;
18248f26c9ffSDavid Dillow 	u8 fmt;
1825aef9ec39SRoland Dreier 
1826882981f4SBart Van Assche 	req->cmd->num_sge = 1;
1827882981f4SBart Van Assche 
1828bb350d1dSFUJITA Tomonori 	if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
1829482fffc4SBart Van Assche 		return sizeof(struct srp_cmd) + cmd->add_cdb_len;
1830aef9ec39SRoland Dreier 
1831aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
1832aef9ec39SRoland Dreier 	    scmnd->sc_data_direction != DMA_TO_DEVICE) {
18337aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
18347aa54bd7SDavid Dillow 			     PFX "Unhandled data direction %d\n",
1835aef9ec39SRoland Dreier 			     scmnd->sc_data_direction);
1836aef9ec39SRoland Dreier 		return -EINVAL;
1837aef9ec39SRoland Dreier 	}
1838aef9ec39SRoland Dreier 
1839bb350d1dSFUJITA Tomonori 	nents = scsi_sg_count(scmnd);
1840bb350d1dSFUJITA Tomonori 	scat  = scsi_sglist(scmnd);
1841882981f4SBart Van Assche 	data_len = scsi_bufflen(scmnd);
1842aef9ec39SRoland Dreier 
184305321937SGreg Kroah-Hartman 	dev = target->srp_host->srp_dev;
184485507bccSRalph Campbell 	ibdev = dev->dev;
184585507bccSRalph Campbell 
184685507bccSRalph Campbell 	count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
18478f26c9ffSDavid Dillow 	if (unlikely(count == 0))
18488f26c9ffSDavid Dillow 		return -EIO;
1849aef9ec39SRoland Dreier 
1850882981f4SBart Van Assche 	if (ch->use_imm_data &&
1851bf583470SBart Van Assche 	    count <= ch->max_imm_sge &&
1852882981f4SBart Van Assche 	    SRP_IMM_DATA_OFFSET + data_len <= ch->max_it_iu_len &&
1853882981f4SBart Van Assche 	    scmnd->sc_data_direction == DMA_TO_DEVICE) {
1854882981f4SBart Van Assche 		struct srp_imm_buf *buf;
1855882981f4SBart Van Assche 		struct ib_sge *sge = &req->cmd->sge[1];
1856882981f4SBart Van Assche 
1857882981f4SBart Van Assche 		fmt = SRP_DATA_DESC_IMM;
1858882981f4SBart Van Assche 		len = SRP_IMM_DATA_OFFSET;
1859882981f4SBart Van Assche 		req->nmdesc = 0;
1860882981f4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1861882981f4SBart Van Assche 		buf->len = cpu_to_be32(data_len);
1862882981f4SBart Van Assche 		WARN_ON_ONCE((void *)(buf + 1) > (void *)cmd + len);
1863882981f4SBart Van Assche 		for_each_sg(scat, sg, count, i) {
1864a163afc8SBart Van Assche 			sge[i].addr   = sg_dma_address(sg);
1865a163afc8SBart Van Assche 			sge[i].length = sg_dma_len(sg);
1866882981f4SBart Van Assche 			sge[i].lkey   = target->lkey;
1867882981f4SBart Van Assche 		}
1868882981f4SBart Van Assche 		req->cmd->num_sge += count;
1869882981f4SBart Van Assche 		goto map_complete;
1870882981f4SBart Van Assche 	}
1871882981f4SBart Van Assche 
1872aef9ec39SRoland Dreier 	fmt = SRP_DATA_DESC_DIRECT;
1873482fffc4SBart Van Assche 	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
1874482fffc4SBart Van Assche 		sizeof(struct srp_direct_buf);
1875f5358a17SRoland Dreier 
1876cee687b6SBart Van Assche 	if (count == 1 && target->global_rkey) {
1877f5358a17SRoland Dreier 		/*
1878f5358a17SRoland Dreier 		 * The midlayer only generated a single gather/scatter
1879f5358a17SRoland Dreier 		 * entry, or DMA mapping coalesced everything to a
1880f5358a17SRoland Dreier 		 * single entry.  So a direct descriptor along with
1881f5358a17SRoland Dreier 		 * the DMA MR suffices.
1882f5358a17SRoland Dreier 		 */
1883482fffc4SBart Van Assche 		struct srp_direct_buf *buf;
1884aef9ec39SRoland Dreier 
1885482fffc4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1886a163afc8SBart Van Assche 		buf->va  = cpu_to_be64(sg_dma_address(scat));
1887cee687b6SBart Van Assche 		buf->key = cpu_to_be32(target->global_rkey);
1888a163afc8SBart Van Assche 		buf->len = cpu_to_be32(sg_dma_len(scat));
18898f26c9ffSDavid Dillow 
189052ede08fSBart Van Assche 		req->nmdesc = 0;
18918f26c9ffSDavid Dillow 		goto map_complete;
18928f26c9ffSDavid Dillow 	}
18938f26c9ffSDavid Dillow 
18945cfb1782SBart Van Assche 	/*
18955cfb1782SBart Van Assche 	 * We have more than one scatter/gather entry, so build our indirect
18965cfb1782SBart Van Assche 	 * descriptor table, trying to merge as many entries as we can.
1897f5358a17SRoland Dreier 	 */
1898482fffc4SBart Van Assche 	indirect_hdr = (void *)cmd->add_data + cmd->add_cdb_len;
18998f26c9ffSDavid Dillow 
1900c07d424dSDavid Dillow 	ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
1901c07d424dSDavid Dillow 				   target->indirect_size, DMA_TO_DEVICE);
1902c07d424dSDavid Dillow 
19038f26c9ffSDavid Dillow 	memset(&state, 0, sizeof(state));
19049edba790SBart Van Assche 	state.desc = req->indirect_desc;
190526630e8aSSagi Grimberg 	if (dev->use_fast_reg)
1906e012f363SBart Van Assche 		ret = srp_map_sg_fr(&state, ch, req, scat, count);
190726630e8aSSagi Grimberg 	else if (dev->use_fmr)
1908e012f363SBart Van Assche 		ret = srp_map_sg_fmr(&state, ch, req, scat, count);
190926630e8aSSagi Grimberg 	else
1910e012f363SBart Van Assche 		ret = srp_map_sg_dma(&state, ch, req, scat, count);
1911e012f363SBart Van Assche 	req->nmdesc = state.nmdesc;
1912e012f363SBart Van Assche 	if (ret < 0)
1913e012f363SBart Van Assche 		goto unmap;
19148f26c9ffSDavid Dillow 
1915509c5f33SBart Van Assche 	{
1916509c5f33SBart Van Assche 		DEFINE_DYNAMIC_DEBUG_METADATA(ddm,
1917509c5f33SBart Van Assche 			"Memory mapping consistency check");
19181a1faf7aSBart Van Assche 		if (DYNAMIC_DEBUG_BRANCH(ddm))
1919509c5f33SBart Van Assche 			srp_check_mapping(&state, ch, req, scat, count);
1920509c5f33SBart Van Assche 	}
19218f26c9ffSDavid Dillow 
1922c07d424dSDavid Dillow 	/* We've mapped the request, now pull as much of the indirect
1923c07d424dSDavid Dillow 	 * descriptor table as we can into the command buffer. If this
1924c07d424dSDavid Dillow 	 * target is not using an external indirect table, we are
1925c07d424dSDavid Dillow 	 * guaranteed to fit into the command, as the SCSI layer won't
1926c07d424dSDavid Dillow 	 * give us more S/G entries than we allow.
19278f26c9ffSDavid Dillow 	 */
19288f26c9ffSDavid Dillow 	if (state.ndesc == 1) {
19295cfb1782SBart Van Assche 		/*
19305cfb1782SBart Van Assche 		 * Memory registration collapsed the sg-list into one entry,
19318f26c9ffSDavid Dillow 		 * so use a direct descriptor.
19328f26c9ffSDavid Dillow 		 */
1933482fffc4SBart Van Assche 		struct srp_direct_buf *buf;
19348f26c9ffSDavid Dillow 
1935482fffc4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1936c07d424dSDavid Dillow 		*buf = req->indirect_desc[0];
19378f26c9ffSDavid Dillow 		goto map_complete;
19388f26c9ffSDavid Dillow 	}
19398f26c9ffSDavid Dillow 
1940c07d424dSDavid Dillow 	if (unlikely(target->cmd_sg_cnt < state.ndesc &&
1941c07d424dSDavid Dillow 						!target->allow_ext_sg)) {
1942c07d424dSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
1943c07d424dSDavid Dillow 			     "Could not fit S/G list into SRP_CMD\n");
1944e012f363SBart Van Assche 		ret = -EIO;
1945e012f363SBart Van Assche 		goto unmap;
1946c07d424dSDavid Dillow 	}
1947c07d424dSDavid Dillow 
1948c07d424dSDavid Dillow 	count = min(state.ndesc, target->cmd_sg_cnt);
19498f26c9ffSDavid Dillow 	table_len = state.ndesc * sizeof (struct srp_direct_buf);
1950330179f2SBart Van Assche 	idb_len = sizeof(struct srp_indirect_buf) + table_len;
1951aef9ec39SRoland Dreier 
1952aef9ec39SRoland Dreier 	fmt = SRP_DATA_DESC_INDIRECT;
1953482fffc4SBart Van Assche 	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
1954482fffc4SBart Van Assche 		sizeof(struct srp_indirect_buf);
1955c07d424dSDavid Dillow 	len += count * sizeof (struct srp_direct_buf);
1956f5358a17SRoland Dreier 
1957c07d424dSDavid Dillow 	memcpy(indirect_hdr->desc_list, req->indirect_desc,
1958c07d424dSDavid Dillow 	       count * sizeof (struct srp_direct_buf));
195985507bccSRalph Campbell 
1960cee687b6SBart Van Assche 	if (!target->global_rkey) {
1961330179f2SBart Van Assche 		ret = srp_map_idb(ch, req, state.gen.next, state.gen.end,
1962330179f2SBart Van Assche 				  idb_len, &idb_rkey);
1963330179f2SBart Van Assche 		if (ret < 0)
1964e012f363SBart Van Assche 			goto unmap;
1965330179f2SBart Van Assche 		req->nmdesc++;
1966330179f2SBart Van Assche 	} else {
1967cee687b6SBart Van Assche 		idb_rkey = cpu_to_be32(target->global_rkey);
1968330179f2SBart Van Assche 	}
1969330179f2SBart Van Assche 
1970c07d424dSDavid Dillow 	indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
1971330179f2SBart Van Assche 	indirect_hdr->table_desc.key = idb_rkey;
19728f26c9ffSDavid Dillow 	indirect_hdr->table_desc.len = cpu_to_be32(table_len);
19738f26c9ffSDavid Dillow 	indirect_hdr->len = cpu_to_be32(state.total_len);
1974aef9ec39SRoland Dreier 
1975aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
1976c07d424dSDavid Dillow 		cmd->data_out_desc_cnt = count;
1977aef9ec39SRoland Dreier 	else
1978c07d424dSDavid Dillow 		cmd->data_in_desc_cnt = count;
1979c07d424dSDavid Dillow 
1980c07d424dSDavid Dillow 	ib_dma_sync_single_for_device(ibdev, req->indirect_dma_addr, table_len,
1981c07d424dSDavid Dillow 				      DMA_TO_DEVICE);
1982aef9ec39SRoland Dreier 
19838f26c9ffSDavid Dillow map_complete:
1984aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
1985aef9ec39SRoland Dreier 		cmd->buf_fmt = fmt << 4;
1986aef9ec39SRoland Dreier 	else
1987aef9ec39SRoland Dreier 		cmd->buf_fmt = fmt;
1988aef9ec39SRoland Dreier 
1989aef9ec39SRoland Dreier 	return len;
1990e012f363SBart Van Assche 
1991e012f363SBart Van Assche unmap:
1992e012f363SBart Van Assche 	srp_unmap_data(scmnd, ch, req);
1993ffc548bbSBart Van Assche 	if (ret == -ENOMEM && req->nmdesc >= target->mr_pool_size)
1994ffc548bbSBart Van Assche 		ret = -E2BIG;
1995e012f363SBart Van Assche 	return ret;
1996aef9ec39SRoland Dreier }
1997aef9ec39SRoland Dreier 
199805a1d750SDavid Dillow /*
199976c75b25SBart Van Assche  * Return an IU and possible credit to the free pool
200076c75b25SBart Van Assche  */
2001509c07bcSBart Van Assche static void srp_put_tx_iu(struct srp_rdma_ch *ch, struct srp_iu *iu,
200276c75b25SBart Van Assche 			  enum srp_iu_type iu_type)
200376c75b25SBart Van Assche {
200476c75b25SBart Van Assche 	unsigned long flags;
200576c75b25SBart Van Assche 
2006509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
2007509c07bcSBart Van Assche 	list_add(&iu->list, &ch->free_tx);
200876c75b25SBart Van Assche 	if (iu_type != SRP_IU_RSP)
2009509c07bcSBart Van Assche 		++ch->req_lim;
2010509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
201176c75b25SBart Van Assche }
201276c75b25SBart Van Assche 
201376c75b25SBart Van Assche /*
2014509c07bcSBart Van Assche  * Must be called with ch->lock held to protect req_lim and free_tx.
2015e9684678SBart Van Assche  * If IU is not sent, it must be returned using srp_put_tx_iu().
201605a1d750SDavid Dillow  *
201705a1d750SDavid Dillow  * Note:
201805a1d750SDavid Dillow  * An upper limit for the number of allocated information units for each
201905a1d750SDavid Dillow  * request type is:
202005a1d750SDavid Dillow  * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
202105a1d750SDavid Dillow  *   more than Scsi_Host.can_queue requests.
202205a1d750SDavid Dillow  * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
202305a1d750SDavid Dillow  * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
202405a1d750SDavid Dillow  *   one unanswered SRP request to an initiator.
202505a1d750SDavid Dillow  */
2026509c07bcSBart Van Assche static struct srp_iu *__srp_get_tx_iu(struct srp_rdma_ch *ch,
202705a1d750SDavid Dillow 				      enum srp_iu_type iu_type)
202805a1d750SDavid Dillow {
2029509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
203005a1d750SDavid Dillow 	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
203105a1d750SDavid Dillow 	struct srp_iu *iu;
203205a1d750SDavid Dillow 
203393c76dbbSBart Van Assche 	lockdep_assert_held(&ch->lock);
203493c76dbbSBart Van Assche 
20351dc7b1f1SChristoph Hellwig 	ib_process_cq_direct(ch->send_cq, -1);
203605a1d750SDavid Dillow 
2037509c07bcSBart Van Assche 	if (list_empty(&ch->free_tx))
203805a1d750SDavid Dillow 		return NULL;
203905a1d750SDavid Dillow 
204005a1d750SDavid Dillow 	/* Initiator responses to target requests do not consume credits */
204176c75b25SBart Van Assche 	if (iu_type != SRP_IU_RSP) {
2042509c07bcSBart Van Assche 		if (ch->req_lim <= rsv) {
204305a1d750SDavid Dillow 			++target->zero_req_lim;
204405a1d750SDavid Dillow 			return NULL;
204505a1d750SDavid Dillow 		}
204605a1d750SDavid Dillow 
2047509c07bcSBart Van Assche 		--ch->req_lim;
204876c75b25SBart Van Assche 	}
204976c75b25SBart Van Assche 
2050509c07bcSBart Van Assche 	iu = list_first_entry(&ch->free_tx, struct srp_iu, list);
205176c75b25SBart Van Assche 	list_del(&iu->list);
205205a1d750SDavid Dillow 	return iu;
205305a1d750SDavid Dillow }
205405a1d750SDavid Dillow 
20559294000dSBart Van Assche /*
20569294000dSBart Van Assche  * Note: if this function is called from inside ib_drain_sq() then it will
20579294000dSBart Van Assche  * be called without ch->lock being held. If ib_drain_sq() dequeues a WQE
20589294000dSBart Van Assche  * with status IB_WC_SUCCESS then that's a bug.
20599294000dSBart Van Assche  */
20601dc7b1f1SChristoph Hellwig static void srp_send_done(struct ib_cq *cq, struct ib_wc *wc)
20611dc7b1f1SChristoph Hellwig {
20621dc7b1f1SChristoph Hellwig 	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
20631dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
20641dc7b1f1SChristoph Hellwig 
20651dc7b1f1SChristoph Hellwig 	if (unlikely(wc->status != IB_WC_SUCCESS)) {
20661dc7b1f1SChristoph Hellwig 		srp_handle_qp_err(cq, wc, "SEND");
20671dc7b1f1SChristoph Hellwig 		return;
20681dc7b1f1SChristoph Hellwig 	}
20691dc7b1f1SChristoph Hellwig 
207093c76dbbSBart Van Assche 	lockdep_assert_held(&ch->lock);
207193c76dbbSBart Van Assche 
20721dc7b1f1SChristoph Hellwig 	list_add(&iu->list, &ch->free_tx);
20731dc7b1f1SChristoph Hellwig }
20741dc7b1f1SChristoph Hellwig 
2075882981f4SBart Van Assche /**
2076882981f4SBart Van Assche  * srp_post_send() - send an SRP information unit
2077882981f4SBart Van Assche  * @ch: RDMA channel over which to send the information unit.
2078882981f4SBart Van Assche  * @iu: Information unit to send.
2079882981f4SBart Van Assche  * @len: Length of the information unit excluding immediate data.
2080882981f4SBart Van Assche  */
2081509c07bcSBart Van Assche static int srp_post_send(struct srp_rdma_ch *ch, struct srp_iu *iu, int len)
208205a1d750SDavid Dillow {
2083509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
208471347b0cSBart Van Assche 	struct ib_send_wr wr;
208505a1d750SDavid Dillow 
2086882981f4SBart Van Assche 	if (WARN_ON_ONCE(iu->num_sge > SRP_MAX_SGE))
2087882981f4SBart Van Assche 		return -EINVAL;
2088882981f4SBart Van Assche 
2089882981f4SBart Van Assche 	iu->sge[0].addr   = iu->dma;
2090882981f4SBart Van Assche 	iu->sge[0].length = len;
2091882981f4SBart Van Assche 	iu->sge[0].lkey   = target->lkey;
209205a1d750SDavid Dillow 
20931dc7b1f1SChristoph Hellwig 	iu->cqe.done = srp_send_done;
20941dc7b1f1SChristoph Hellwig 
209505a1d750SDavid Dillow 	wr.next       = NULL;
20961dc7b1f1SChristoph Hellwig 	wr.wr_cqe     = &iu->cqe;
2097882981f4SBart Van Assche 	wr.sg_list    = &iu->sge[0];
2098882981f4SBart Van Assche 	wr.num_sge    = iu->num_sge;
209905a1d750SDavid Dillow 	wr.opcode     = IB_WR_SEND;
210005a1d750SDavid Dillow 	wr.send_flags = IB_SEND_SIGNALED;
210105a1d750SDavid Dillow 
210271347b0cSBart Van Assche 	return ib_post_send(ch->qp, &wr, NULL);
210305a1d750SDavid Dillow }
210405a1d750SDavid Dillow 
2105509c07bcSBart Van Assche static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
2106c996bb47SBart Van Assche {
2107509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
210871347b0cSBart Van Assche 	struct ib_recv_wr wr;
2109dcb4cb85SBart Van Assche 	struct ib_sge list;
2110c996bb47SBart Van Assche 
2111c996bb47SBart Van Assche 	list.addr   = iu->dma;
2112c996bb47SBart Van Assche 	list.length = iu->size;
21139af76271SDavid Dillow 	list.lkey   = target->lkey;
2114c996bb47SBart Van Assche 
21151dc7b1f1SChristoph Hellwig 	iu->cqe.done = srp_recv_done;
21161dc7b1f1SChristoph Hellwig 
2117c996bb47SBart Van Assche 	wr.next     = NULL;
21181dc7b1f1SChristoph Hellwig 	wr.wr_cqe   = &iu->cqe;
2119c996bb47SBart Van Assche 	wr.sg_list  = &list;
2120c996bb47SBart Van Assche 	wr.num_sge  = 1;
2121c996bb47SBart Van Assche 
212271347b0cSBart Van Assche 	return ib_post_recv(ch->qp, &wr, NULL);
2123c996bb47SBart Van Assche }
2124c996bb47SBart Van Assche 
2125509c07bcSBart Van Assche static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
2126aef9ec39SRoland Dreier {
2127509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2128aef9ec39SRoland Dreier 	struct srp_request *req;
2129aef9ec39SRoland Dreier 	struct scsi_cmnd *scmnd;
2130aef9ec39SRoland Dreier 	unsigned long flags;
2131aef9ec39SRoland Dreier 
2132aef9ec39SRoland Dreier 	if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
2133509c07bcSBart Van Assche 		spin_lock_irqsave(&ch->lock, flags);
2134509c07bcSBart Van Assche 		ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
21350a6fdbdeSBart Van Assche 		if (rsp->tag == ch->tsk_mgmt_tag) {
2136509c07bcSBart Van Assche 			ch->tsk_mgmt_status = -1;
2137f8b6e31eSDavid Dillow 			if (be32_to_cpu(rsp->resp_data_len) >= 4)
2138509c07bcSBart Van Assche 				ch->tsk_mgmt_status = rsp->data[3];
2139509c07bcSBart Van Assche 			complete(&ch->tsk_mgmt_done);
2140aef9ec39SRoland Dreier 		} else {
21410a6fdbdeSBart Van Assche 			shost_printk(KERN_ERR, target->scsi_host,
21420a6fdbdeSBart Van Assche 				     "Received tsk mgmt response too late for tag %#llx\n",
21430a6fdbdeSBart Van Assche 				     rsp->tag);
21440a6fdbdeSBart Van Assche 		}
21450a6fdbdeSBart Van Assche 		spin_unlock_irqrestore(&ch->lock, flags);
21460a6fdbdeSBart Van Assche 	} else {
214777f2c1a4SBart Van Assche 		scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
21486cb72bc1SBart Van Assche 		if (scmnd && scmnd->host_scribble) {
214977f2c1a4SBart Van Assche 			req = (void *)scmnd->host_scribble;
215077f2c1a4SBart Van Assche 			scmnd = srp_claim_req(ch, req, NULL, scmnd);
21516cb72bc1SBart Van Assche 		} else {
21526cb72bc1SBart Van Assche 			scmnd = NULL;
215377f2c1a4SBart Van Assche 		}
215422032991SBart Van Assche 		if (!scmnd) {
21557aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
2156d92c0da7SBart Van Assche 				     "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
2157d92c0da7SBart Van Assche 				     rsp->tag, ch - target->ch, ch->qp->qp_num);
215822032991SBart Van Assche 
2159509c07bcSBart Van Assche 			spin_lock_irqsave(&ch->lock, flags);
2160509c07bcSBart Van Assche 			ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
2161509c07bcSBart Van Assche 			spin_unlock_irqrestore(&ch->lock, flags);
216222032991SBart Van Assche 
216322032991SBart Van Assche 			return;
216422032991SBart Van Assche 		}
2165aef9ec39SRoland Dreier 		scmnd->result = rsp->status;
2166aef9ec39SRoland Dreier 
2167aef9ec39SRoland Dreier 		if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
2168aef9ec39SRoland Dreier 			memcpy(scmnd->sense_buffer, rsp->data +
2169aef9ec39SRoland Dreier 			       be32_to_cpu(rsp->resp_data_len),
2170aef9ec39SRoland Dreier 			       min_t(int, be32_to_cpu(rsp->sense_data_len),
2171aef9ec39SRoland Dreier 				     SCSI_SENSE_BUFFERSIZE));
2172aef9ec39SRoland Dreier 		}
2173aef9ec39SRoland Dreier 
2174e714531aSBart Van Assche 		if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
2175bb350d1dSFUJITA Tomonori 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
2176e714531aSBart Van Assche 		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DIOVER))
2177e714531aSBart Van Assche 			scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_in_res_cnt));
2178e714531aSBart Van Assche 		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOUNDER))
2179e714531aSBart Van Assche 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
2180e714531aSBart Van Assche 		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOOVER))
2181e714531aSBart Van Assche 			scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_out_res_cnt));
2182aef9ec39SRoland Dreier 
2183509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd,
218422032991SBart Van Assche 			     be32_to_cpu(rsp->req_lim_delta));
218522032991SBart Van Assche 
2186f8b6e31eSDavid Dillow 		scmnd->host_scribble = NULL;
2187aef9ec39SRoland Dreier 		scmnd->scsi_done(scmnd);
2188aef9ec39SRoland Dreier 	}
2189aef9ec39SRoland Dreier }
2190aef9ec39SRoland Dreier 
2191509c07bcSBart Van Assche static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
2192bb12588aSDavid Dillow 			       void *rsp, int len)
2193bb12588aSDavid Dillow {
2194509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
219576c75b25SBart Van Assche 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2196bb12588aSDavid Dillow 	unsigned long flags;
2197bb12588aSDavid Dillow 	struct srp_iu *iu;
219876c75b25SBart Van Assche 	int err;
2199bb12588aSDavid Dillow 
2200509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
2201509c07bcSBart Van Assche 	ch->req_lim += req_delta;
2202509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_RSP);
2203509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
220476c75b25SBart Van Assche 
2205bb12588aSDavid Dillow 	if (!iu) {
2206bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2207bb12588aSDavid Dillow 			     "no IU available to send response\n");
220876c75b25SBart Van Assche 		return 1;
2209bb12588aSDavid Dillow 	}
2210bb12588aSDavid Dillow 
2211882981f4SBart Van Assche 	iu->num_sge = 1;
2212bb12588aSDavid Dillow 	ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
2213bb12588aSDavid Dillow 	memcpy(iu->buf, rsp, len);
2214bb12588aSDavid Dillow 	ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
2215bb12588aSDavid Dillow 
2216509c07bcSBart Van Assche 	err = srp_post_send(ch, iu, len);
221776c75b25SBart Van Assche 	if (err) {
2218bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2219bb12588aSDavid Dillow 			     "unable to post response: %d\n", err);
2220509c07bcSBart Van Assche 		srp_put_tx_iu(ch, iu, SRP_IU_RSP);
222176c75b25SBart Van Assche 	}
2222bb12588aSDavid Dillow 
2223bb12588aSDavid Dillow 	return err;
2224bb12588aSDavid Dillow }
2225bb12588aSDavid Dillow 
2226509c07bcSBart Van Assche static void srp_process_cred_req(struct srp_rdma_ch *ch,
2227bb12588aSDavid Dillow 				 struct srp_cred_req *req)
2228bb12588aSDavid Dillow {
2229bb12588aSDavid Dillow 	struct srp_cred_rsp rsp = {
2230bb12588aSDavid Dillow 		.opcode = SRP_CRED_RSP,
2231bb12588aSDavid Dillow 		.tag = req->tag,
2232bb12588aSDavid Dillow 	};
2233bb12588aSDavid Dillow 	s32 delta = be32_to_cpu(req->req_lim_delta);
2234bb12588aSDavid Dillow 
2235509c07bcSBart Van Assche 	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
2236509c07bcSBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host, PFX
2237bb12588aSDavid Dillow 			     "problems processing SRP_CRED_REQ\n");
2238bb12588aSDavid Dillow }
2239bb12588aSDavid Dillow 
2240509c07bcSBart Van Assche static void srp_process_aer_req(struct srp_rdma_ch *ch,
2241bb12588aSDavid Dillow 				struct srp_aer_req *req)
2242bb12588aSDavid Dillow {
2243509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2244bb12588aSDavid Dillow 	struct srp_aer_rsp rsp = {
2245bb12588aSDavid Dillow 		.opcode = SRP_AER_RSP,
2246bb12588aSDavid Dillow 		.tag = req->tag,
2247bb12588aSDavid Dillow 	};
2248bb12588aSDavid Dillow 	s32 delta = be32_to_cpu(req->req_lim_delta);
2249bb12588aSDavid Dillow 
2250bb12588aSDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, PFX
2251985aa495SBart Van Assche 		     "ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
2252bb12588aSDavid Dillow 
2253509c07bcSBart Van Assche 	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
2254bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2255bb12588aSDavid Dillow 			     "problems processing SRP_AER_REQ\n");
2256bb12588aSDavid Dillow }
2257bb12588aSDavid Dillow 
22581dc7b1f1SChristoph Hellwig static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
2259aef9ec39SRoland Dreier {
22601dc7b1f1SChristoph Hellwig 	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
22611dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
2262509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2263dcb4cb85SBart Van Assche 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2264c996bb47SBart Van Assche 	int res;
2265aef9ec39SRoland Dreier 	u8 opcode;
2266aef9ec39SRoland Dreier 
22671dc7b1f1SChristoph Hellwig 	if (unlikely(wc->status != IB_WC_SUCCESS)) {
22681dc7b1f1SChristoph Hellwig 		srp_handle_qp_err(cq, wc, "RECV");
22691dc7b1f1SChristoph Hellwig 		return;
22701dc7b1f1SChristoph Hellwig 	}
22711dc7b1f1SChristoph Hellwig 
2272509c07bcSBart Van Assche 	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_ti_iu_len,
227385507bccSRalph Campbell 				   DMA_FROM_DEVICE);
2274aef9ec39SRoland Dreier 
2275aef9ec39SRoland Dreier 	opcode = *(u8 *) iu->buf;
2276aef9ec39SRoland Dreier 
2277aef9ec39SRoland Dreier 	if (0) {
22787aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
22797aa54bd7SDavid Dillow 			     PFX "recv completion, opcode 0x%02x\n", opcode);
22807a700811SBart Van Assche 		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 8, 1,
22817a700811SBart Van Assche 			       iu->buf, wc->byte_len, true);
2282aef9ec39SRoland Dreier 	}
2283aef9ec39SRoland Dreier 
2284aef9ec39SRoland Dreier 	switch (opcode) {
2285aef9ec39SRoland Dreier 	case SRP_RSP:
2286509c07bcSBart Van Assche 		srp_process_rsp(ch, iu->buf);
2287aef9ec39SRoland Dreier 		break;
2288aef9ec39SRoland Dreier 
2289bb12588aSDavid Dillow 	case SRP_CRED_REQ:
2290509c07bcSBart Van Assche 		srp_process_cred_req(ch, iu->buf);
2291bb12588aSDavid Dillow 		break;
2292bb12588aSDavid Dillow 
2293bb12588aSDavid Dillow 	case SRP_AER_REQ:
2294509c07bcSBart Van Assche 		srp_process_aer_req(ch, iu->buf);
2295bb12588aSDavid Dillow 		break;
2296bb12588aSDavid Dillow 
2297aef9ec39SRoland Dreier 	case SRP_T_LOGOUT:
2298aef9ec39SRoland Dreier 		/* XXX Handle target logout */
22997aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
23007aa54bd7SDavid Dillow 			     PFX "Got target logout request\n");
2301aef9ec39SRoland Dreier 		break;
2302aef9ec39SRoland Dreier 
2303aef9ec39SRoland Dreier 	default:
23047aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
23057aa54bd7SDavid Dillow 			     PFX "Unhandled SRP opcode 0x%02x\n", opcode);
2306aef9ec39SRoland Dreier 		break;
2307aef9ec39SRoland Dreier 	}
2308aef9ec39SRoland Dreier 
2309509c07bcSBart Van Assche 	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_ti_iu_len,
231085507bccSRalph Campbell 				      DMA_FROM_DEVICE);
2311c996bb47SBart Van Assche 
2312509c07bcSBart Van Assche 	res = srp_post_recv(ch, iu);
2313c996bb47SBart Van Assche 	if (res != 0)
2314c996bb47SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
2315c996bb47SBart Van Assche 			     PFX "Recv failed with error code %d\n", res);
2316aef9ec39SRoland Dreier }
2317aef9ec39SRoland Dreier 
2318c1120f89SBart Van Assche /**
2319c1120f89SBart Van Assche  * srp_tl_err_work() - handle a transport layer error
2320af24663bSBart Van Assche  * @work: Work structure embedded in an SRP target port.
2321c1120f89SBart Van Assche  *
2322c1120f89SBart Van Assche  * Note: This function may get invoked before the rport has been created,
2323c1120f89SBart Van Assche  * hence the target->rport test.
2324c1120f89SBart Van Assche  */
2325c1120f89SBart Van Assche static void srp_tl_err_work(struct work_struct *work)
2326c1120f89SBart Van Assche {
2327c1120f89SBart Van Assche 	struct srp_target_port *target;
2328c1120f89SBart Van Assche 
2329c1120f89SBart Van Assche 	target = container_of(work, struct srp_target_port, tl_err_work);
2330c1120f89SBart Van Assche 	if (target->rport)
2331c1120f89SBart Van Assche 		srp_start_tl_fail_timers(target->rport);
2332c1120f89SBart Van Assche }
2333c1120f89SBart Van Assche 
23341dc7b1f1SChristoph Hellwig static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
23351dc7b1f1SChristoph Hellwig 		const char *opname)
2336948d1e88SBart Van Assche {
23371dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
23387dad6b2eSBart Van Assche 	struct srp_target_port *target = ch->target;
23397dad6b2eSBart Van Assche 
2340c014c8cdSBart Van Assche 	if (ch->connected && !target->qp_in_error) {
23415cfb1782SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
23421dc7b1f1SChristoph Hellwig 			     PFX "failed %s status %s (%d) for CQE %p\n",
23431dc7b1f1SChristoph Hellwig 			     opname, ib_wc_status_msg(wc->status), wc->status,
23441dc7b1f1SChristoph Hellwig 			     wc->wr_cqe);
2345c1120f89SBart Van Assche 		queue_work(system_long_wq, &target->tl_err_work);
23464f0af697SBart Van Assche 	}
2347948d1e88SBart Van Assche 	target->qp_in_error = true;
2348948d1e88SBart Van Assche }
2349948d1e88SBart Van Assche 
235076c75b25SBart Van Assche static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
2351aef9ec39SRoland Dreier {
235276c75b25SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
2353509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
2354aef9ec39SRoland Dreier 	struct srp_request *req;
2355aef9ec39SRoland Dreier 	struct srp_iu *iu;
2356aef9ec39SRoland Dreier 	struct srp_cmd *cmd;
235785507bccSRalph Campbell 	struct ib_device *dev;
235876c75b25SBart Van Assche 	unsigned long flags;
235977f2c1a4SBart Van Assche 	u32 tag;
236077f2c1a4SBart Van Assche 	u16 idx;
2361d1b4289eSBart Van Assche 	int len, ret;
2362aef9ec39SRoland Dreier 
2363d1b4289eSBart Van Assche 	scmnd->result = srp_chkready(target->rport);
2364d1b4289eSBart Van Assche 	if (unlikely(scmnd->result))
2365d1b4289eSBart Van Assche 		goto err;
23662ce19e72SBart Van Assche 
236777f2c1a4SBart Van Assche 	WARN_ON_ONCE(scmnd->request->tag < 0);
236877f2c1a4SBart Van Assche 	tag = blk_mq_unique_tag(scmnd->request);
2369d92c0da7SBart Van Assche 	ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
237077f2c1a4SBart Van Assche 	idx = blk_mq_unique_tag_to_tag(tag);
237177f2c1a4SBart Van Assche 	WARN_ONCE(idx >= target->req_ring_size, "%s: tag %#x: idx %d >= %d\n",
237277f2c1a4SBart Van Assche 		  dev_name(&shost->shost_gendev), tag, idx,
237377f2c1a4SBart Van Assche 		  target->req_ring_size);
2374509c07bcSBart Van Assche 
2375509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
2376509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_CMD);
2377509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
2378aef9ec39SRoland Dreier 
237977f2c1a4SBart Van Assche 	if (!iu)
238077f2c1a4SBart Van Assche 		goto err;
238177f2c1a4SBart Van Assche 
238277f2c1a4SBart Van Assche 	req = &ch->req_ring[idx];
238305321937SGreg Kroah-Hartman 	dev = target->srp_host->srp_dev->dev;
2384513d5647SBart Van Assche 	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_it_iu_len,
238585507bccSRalph Campbell 				   DMA_TO_DEVICE);
2386aef9ec39SRoland Dreier 
2387f8b6e31eSDavid Dillow 	scmnd->host_scribble = (void *) req;
2388aef9ec39SRoland Dreier 
2389aef9ec39SRoland Dreier 	cmd = iu->buf;
2390aef9ec39SRoland Dreier 	memset(cmd, 0, sizeof *cmd);
2391aef9ec39SRoland Dreier 
2392aef9ec39SRoland Dreier 	cmd->opcode = SRP_CMD;
2393985aa495SBart Van Assche 	int_to_scsilun(scmnd->device->lun, &cmd->lun);
239477f2c1a4SBart Van Assche 	cmd->tag    = tag;
2395aef9ec39SRoland Dreier 	memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
2396482fffc4SBart Van Assche 	if (unlikely(scmnd->cmd_len > sizeof(cmd->cdb))) {
2397482fffc4SBart Van Assche 		cmd->add_cdb_len = round_up(scmnd->cmd_len - sizeof(cmd->cdb),
2398482fffc4SBart Van Assche 					    4);
2399482fffc4SBart Van Assche 		if (WARN_ON_ONCE(cmd->add_cdb_len > SRP_MAX_ADD_CDB_LEN))
2400482fffc4SBart Van Assche 			goto err_iu;
2401482fffc4SBart Van Assche 	}
2402aef9ec39SRoland Dreier 
2403aef9ec39SRoland Dreier 	req->scmnd    = scmnd;
2404aef9ec39SRoland Dreier 	req->cmd      = iu;
2405aef9ec39SRoland Dreier 
2406509c07bcSBart Van Assche 	len = srp_map_data(scmnd, ch, req);
2407aef9ec39SRoland Dreier 	if (len < 0) {
24087aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
2409d1b4289eSBart Van Assche 			     PFX "Failed to map data (%d)\n", len);
2410d1b4289eSBart Van Assche 		/*
2411d1b4289eSBart Van Assche 		 * If we ran out of memory descriptors (-ENOMEM) because an
2412d1b4289eSBart Van Assche 		 * application is queuing many requests with more than
241352ede08fSBart Van Assche 		 * max_pages_per_mr sg-list elements, tell the SCSI mid-layer
2414d1b4289eSBart Van Assche 		 * to reduce queue depth temporarily.
2415d1b4289eSBart Van Assche 		 */
2416d1b4289eSBart Van Assche 		scmnd->result = len == -ENOMEM ?
2417d1b4289eSBart Van Assche 			DID_OK << 16 | QUEUE_FULL << 1 : DID_ERROR << 16;
241876c75b25SBart Van Assche 		goto err_iu;
2419aef9ec39SRoland Dreier 	}
2420aef9ec39SRoland Dreier 
2421513d5647SBart Van Assche 	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_it_iu_len,
242285507bccSRalph Campbell 				      DMA_TO_DEVICE);
2423aef9ec39SRoland Dreier 
2424509c07bcSBart Van Assche 	if (srp_post_send(ch, iu, len)) {
24257aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
24262ee00f6aSBart Van Assche 		scmnd->result = DID_ERROR << 16;
2427aef9ec39SRoland Dreier 		goto err_unmap;
2428aef9ec39SRoland Dreier 	}
2429aef9ec39SRoland Dreier 
2430fd561412SBart Van Assche 	return 0;
2431aef9ec39SRoland Dreier 
2432aef9ec39SRoland Dreier err_unmap:
2433509c07bcSBart Van Assche 	srp_unmap_data(scmnd, ch, req);
2434aef9ec39SRoland Dreier 
243576c75b25SBart Van Assche err_iu:
2436509c07bcSBart Van Assche 	srp_put_tx_iu(ch, iu, SRP_IU_CMD);
243776c75b25SBart Van Assche 
2438024ca901SBart Van Assche 	/*
2439024ca901SBart Van Assche 	 * Avoid that the loops that iterate over the request ring can
2440024ca901SBart Van Assche 	 * encounter a dangling SCSI command pointer.
2441024ca901SBart Van Assche 	 */
2442024ca901SBart Van Assche 	req->scmnd = NULL;
2443024ca901SBart Van Assche 
2444d1b4289eSBart Van Assche err:
2445d1b4289eSBart Van Assche 	if (scmnd->result) {
2446d1b4289eSBart Van Assche 		scmnd->scsi_done(scmnd);
2447d1b4289eSBart Van Assche 		ret = 0;
2448d1b4289eSBart Van Assche 	} else {
2449d1b4289eSBart Van Assche 		ret = SCSI_MLQUEUE_HOST_BUSY;
2450d1b4289eSBart Van Assche 	}
2451a95cadb9SBart Van Assche 
2452fd561412SBart Van Assche 	return ret;
2453aef9ec39SRoland Dreier }
2454aef9ec39SRoland Dreier 
24554d73f95fSBart Van Assche /*
24564d73f95fSBart Van Assche  * Note: the resources allocated in this function are freed in
2457509c07bcSBart Van Assche  * srp_free_ch_ib().
24584d73f95fSBart Van Assche  */
2459509c07bcSBart Van Assche static int srp_alloc_iu_bufs(struct srp_rdma_ch *ch)
2460aef9ec39SRoland Dreier {
2461509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2462aef9ec39SRoland Dreier 	int i;
2463aef9ec39SRoland Dreier 
2464509c07bcSBart Van Assche 	ch->rx_ring = kcalloc(target->queue_size, sizeof(*ch->rx_ring),
24654d73f95fSBart Van Assche 			      GFP_KERNEL);
2466509c07bcSBart Van Assche 	if (!ch->rx_ring)
24674d73f95fSBart Van Assche 		goto err_no_ring;
2468509c07bcSBart Van Assche 	ch->tx_ring = kcalloc(target->queue_size, sizeof(*ch->tx_ring),
24694d73f95fSBart Van Assche 			      GFP_KERNEL);
2470509c07bcSBart Van Assche 	if (!ch->tx_ring)
24714d73f95fSBart Van Assche 		goto err_no_ring;
24724d73f95fSBart Van Assche 
24734d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2474509c07bcSBart Van Assche 		ch->rx_ring[i] = srp_alloc_iu(target->srp_host,
2475509c07bcSBart Van Assche 					      ch->max_ti_iu_len,
2476aef9ec39SRoland Dreier 					      GFP_KERNEL, DMA_FROM_DEVICE);
2477509c07bcSBart Van Assche 		if (!ch->rx_ring[i])
2478aef9ec39SRoland Dreier 			goto err;
2479aef9ec39SRoland Dreier 	}
2480aef9ec39SRoland Dreier 
24814d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2482509c07bcSBart Van Assche 		ch->tx_ring[i] = srp_alloc_iu(target->srp_host,
2483513d5647SBart Van Assche 					      ch->max_it_iu_len,
2484aef9ec39SRoland Dreier 					      GFP_KERNEL, DMA_TO_DEVICE);
2485509c07bcSBart Van Assche 		if (!ch->tx_ring[i])
2486aef9ec39SRoland Dreier 			goto err;
2487dcb4cb85SBart Van Assche 
2488509c07bcSBart Van Assche 		list_add(&ch->tx_ring[i]->list, &ch->free_tx);
2489aef9ec39SRoland Dreier 	}
2490aef9ec39SRoland Dreier 
2491aef9ec39SRoland Dreier 	return 0;
2492aef9ec39SRoland Dreier 
2493aef9ec39SRoland Dreier err:
24944d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2495509c07bcSBart Van Assche 		srp_free_iu(target->srp_host, ch->rx_ring[i]);
2496509c07bcSBart Van Assche 		srp_free_iu(target->srp_host, ch->tx_ring[i]);
2497aef9ec39SRoland Dreier 	}
2498aef9ec39SRoland Dreier 
24994d73f95fSBart Van Assche 
25004d73f95fSBart Van Assche err_no_ring:
2501509c07bcSBart Van Assche 	kfree(ch->tx_ring);
2502509c07bcSBart Van Assche 	ch->tx_ring = NULL;
2503509c07bcSBart Van Assche 	kfree(ch->rx_ring);
2504509c07bcSBart Van Assche 	ch->rx_ring = NULL;
2505aef9ec39SRoland Dreier 
2506aef9ec39SRoland Dreier 	return -ENOMEM;
2507aef9ec39SRoland Dreier }
2508aef9ec39SRoland Dreier 
2509c9b03c1aSBart Van Assche static uint32_t srp_compute_rq_tmo(struct ib_qp_attr *qp_attr, int attr_mask)
2510c9b03c1aSBart Van Assche {
2511c9b03c1aSBart Van Assche 	uint64_t T_tr_ns, max_compl_time_ms;
2512c9b03c1aSBart Van Assche 	uint32_t rq_tmo_jiffies;
2513c9b03c1aSBart Van Assche 
2514c9b03c1aSBart Van Assche 	/*
2515c9b03c1aSBart Van Assche 	 * According to section 11.2.4.2 in the IBTA spec (Modify Queue Pair,
2516c9b03c1aSBart Van Assche 	 * table 91), both the QP timeout and the retry count have to be set
2517c9b03c1aSBart Van Assche 	 * for RC QP's during the RTR to RTS transition.
2518c9b03c1aSBart Van Assche 	 */
2519c9b03c1aSBart Van Assche 	WARN_ON_ONCE((attr_mask & (IB_QP_TIMEOUT | IB_QP_RETRY_CNT)) !=
2520c9b03c1aSBart Van Assche 		     (IB_QP_TIMEOUT | IB_QP_RETRY_CNT));
2521c9b03c1aSBart Van Assche 
2522c9b03c1aSBart Van Assche 	/*
2523c9b03c1aSBart Van Assche 	 * Set target->rq_tmo_jiffies to one second more than the largest time
2524c9b03c1aSBart Van Assche 	 * it can take before an error completion is generated. See also
2525c9b03c1aSBart Van Assche 	 * C9-140..142 in the IBTA spec for more information about how to
2526c9b03c1aSBart Van Assche 	 * convert the QP Local ACK Timeout value to nanoseconds.
2527c9b03c1aSBart Van Assche 	 */
2528c9b03c1aSBart Van Assche 	T_tr_ns = 4096 * (1ULL << qp_attr->timeout);
2529c9b03c1aSBart Van Assche 	max_compl_time_ms = qp_attr->retry_cnt * 4 * T_tr_ns;
2530c9b03c1aSBart Van Assche 	do_div(max_compl_time_ms, NSEC_PER_MSEC);
2531c9b03c1aSBart Van Assche 	rq_tmo_jiffies = msecs_to_jiffies(max_compl_time_ms + 1000);
2532c9b03c1aSBart Van Assche 
2533c9b03c1aSBart Van Assche 	return rq_tmo_jiffies;
2534c9b03c1aSBart Van Assche }
2535c9b03c1aSBart Van Assche 
2536961e0be8SDavid Dillow static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
2537e6300cbdSBart Van Assche 			       const struct srp_login_rsp *lrsp,
2538509c07bcSBart Van Assche 			       struct srp_rdma_ch *ch)
2539961e0be8SDavid Dillow {
2540509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2541961e0be8SDavid Dillow 	struct ib_qp_attr *qp_attr = NULL;
2542961e0be8SDavid Dillow 	int attr_mask = 0;
254319f31343SBart Van Assche 	int ret = 0;
2544961e0be8SDavid Dillow 	int i;
2545961e0be8SDavid Dillow 
2546961e0be8SDavid Dillow 	if (lrsp->opcode == SRP_LOGIN_RSP) {
2547509c07bcSBart Van Assche 		ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
2548509c07bcSBart Van Assche 		ch->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
2549*0fbb37ddSSergey Gorenko 		ch->use_imm_data  = srp_use_imm_data &&
2550*0fbb37ddSSergey Gorenko 			(lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP);
2551882981f4SBart Van Assche 		ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
2552b2e872f4SHonggang Li 						      ch->use_imm_data,
2553b2e872f4SHonggang Li 						      target->max_it_iu_size);
2554513d5647SBart Van Assche 		WARN_ON_ONCE(ch->max_it_iu_len >
2555513d5647SBart Van Assche 			     be32_to_cpu(lrsp->max_it_iu_len));
2556961e0be8SDavid Dillow 
2557882981f4SBart Van Assche 		if (ch->use_imm_data)
2558882981f4SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host,
2559882981f4SBart Van Assche 				     PFX "using immediate data\n");
2560961e0be8SDavid Dillow 
2561961e0be8SDavid Dillow 		/*
2562961e0be8SDavid Dillow 		 * Reserve credits for task management so we don't
2563961e0be8SDavid Dillow 		 * bounce requests back to the SCSI mid-layer.
2564961e0be8SDavid Dillow 		 */
2565961e0be8SDavid Dillow 		target->scsi_host->can_queue
2566509c07bcSBart Van Assche 			= min(ch->req_lim - SRP_TSK_MGMT_SQ_SIZE,
2567961e0be8SDavid Dillow 			      target->scsi_host->can_queue);
25684d73f95fSBart Van Assche 		target->scsi_host->cmd_per_lun
25694d73f95fSBart Van Assche 			= min_t(int, target->scsi_host->can_queue,
25704d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun);
2571961e0be8SDavid Dillow 	} else {
2572961e0be8SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
2573961e0be8SDavid Dillow 			     PFX "Unhandled RSP opcode %#x\n", lrsp->opcode);
2574961e0be8SDavid Dillow 		ret = -ECONNRESET;
2575961e0be8SDavid Dillow 		goto error;
2576961e0be8SDavid Dillow 	}
2577961e0be8SDavid Dillow 
2578509c07bcSBart Van Assche 	if (!ch->rx_ring) {
2579509c07bcSBart Van Assche 		ret = srp_alloc_iu_bufs(ch);
2580961e0be8SDavid Dillow 		if (ret)
2581961e0be8SDavid Dillow 			goto error;
2582961e0be8SDavid Dillow 	}
2583961e0be8SDavid Dillow 
258419f31343SBart Van Assche 	for (i = 0; i < target->queue_size; i++) {
258519f31343SBart Van Assche 		struct srp_iu *iu = ch->rx_ring[i];
258619f31343SBart Van Assche 
258719f31343SBart Van Assche 		ret = srp_post_recv(ch, iu);
258819f31343SBart Van Assche 		if (ret)
258919f31343SBart Van Assche 			goto error;
259019f31343SBart Van Assche 	}
259119f31343SBart Van Assche 
259219f31343SBart Van Assche 	if (!target->using_rdma_cm) {
2593961e0be8SDavid Dillow 		ret = -ENOMEM;
259419f31343SBart Van Assche 		qp_attr = kmalloc(sizeof(*qp_attr), GFP_KERNEL);
2595961e0be8SDavid Dillow 		if (!qp_attr)
2596961e0be8SDavid Dillow 			goto error;
2597961e0be8SDavid Dillow 
2598961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTR;
2599961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2600961e0be8SDavid Dillow 		if (ret)
2601961e0be8SDavid Dillow 			goto error_free;
2602961e0be8SDavid Dillow 
2603509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2604961e0be8SDavid Dillow 		if (ret)
2605961e0be8SDavid Dillow 			goto error_free;
2606961e0be8SDavid Dillow 
2607961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTS;
2608961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2609961e0be8SDavid Dillow 		if (ret)
2610961e0be8SDavid Dillow 			goto error_free;
2611961e0be8SDavid Dillow 
2612c9b03c1aSBart Van Assche 		target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
2613c9b03c1aSBart Van Assche 
2614509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2615961e0be8SDavid Dillow 		if (ret)
2616961e0be8SDavid Dillow 			goto error_free;
2617961e0be8SDavid Dillow 
2618961e0be8SDavid Dillow 		ret = ib_send_cm_rtu(cm_id, NULL, 0);
261919f31343SBart Van Assche 	}
2620961e0be8SDavid Dillow 
2621961e0be8SDavid Dillow error_free:
2622961e0be8SDavid Dillow 	kfree(qp_attr);
2623961e0be8SDavid Dillow 
2624961e0be8SDavid Dillow error:
2625509c07bcSBart Van Assche 	ch->status = ret;
2626961e0be8SDavid Dillow }
2627961e0be8SDavid Dillow 
262819f31343SBart Van Assche static void srp_ib_cm_rej_handler(struct ib_cm_id *cm_id,
2629e7ff98aeSParav Pandit 				  const struct ib_cm_event *event,
2630509c07bcSBart Van Assche 				  struct srp_rdma_ch *ch)
2631aef9ec39SRoland Dreier {
2632509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
26337aa54bd7SDavid Dillow 	struct Scsi_Host *shost = target->scsi_host;
2634aef9ec39SRoland Dreier 	struct ib_class_port_info *cpi;
2635aef9ec39SRoland Dreier 	int opcode;
263619f31343SBart Van Assche 	u16 dlid;
2637aef9ec39SRoland Dreier 
2638aef9ec39SRoland Dreier 	switch (event->param.rej_rcvd.reason) {
2639aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_CM_REDIRECT:
2640aef9ec39SRoland Dreier 		cpi = event->param.rej_rcvd.ari;
264119f31343SBart Van Assche 		dlid = be16_to_cpu(cpi->redirect_lid);
264219f31343SBart Van Assche 		sa_path_set_dlid(&ch->ib_cm.path, dlid);
264319f31343SBart Van Assche 		ch->ib_cm.path.pkey = cpi->redirect_pkey;
2644aef9ec39SRoland Dreier 		cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
264519f31343SBart Van Assche 		memcpy(ch->ib_cm.path.dgid.raw, cpi->redirect_gid, 16);
2646aef9ec39SRoland Dreier 
264719f31343SBart Van Assche 		ch->status = dlid ? SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
2648aef9ec39SRoland Dreier 		break;
2649aef9ec39SRoland Dreier 
2650aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_REDIRECT:
26515d7cbfd6SRoland Dreier 		if (srp_target_is_topspin(target)) {
265219f31343SBart Van Assche 			union ib_gid *dgid = &ch->ib_cm.path.dgid;
265319f31343SBart Van Assche 
2654aef9ec39SRoland Dreier 			/*
2655aef9ec39SRoland Dreier 			 * Topspin/Cisco SRP gateways incorrectly send
2656aef9ec39SRoland Dreier 			 * reject reason code 25 when they mean 24
2657aef9ec39SRoland Dreier 			 * (port redirect).
2658aef9ec39SRoland Dreier 			 */
265919f31343SBart Van Assche 			memcpy(dgid->raw, event->param.rej_rcvd.ari, 16);
2660aef9ec39SRoland Dreier 
26617aa54bd7SDavid Dillow 			shost_printk(KERN_DEBUG, shost,
26627aa54bd7SDavid Dillow 				     PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
266319f31343SBart Van Assche 				     be64_to_cpu(dgid->global.subnet_prefix),
266419f31343SBart Van Assche 				     be64_to_cpu(dgid->global.interface_id));
2665aef9ec39SRoland Dreier 
2666509c07bcSBart Van Assche 			ch->status = SRP_PORT_REDIRECT;
2667aef9ec39SRoland Dreier 		} else {
26687aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
26697aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
2670509c07bcSBart Van Assche 			ch->status = -ECONNRESET;
2671aef9ec39SRoland Dreier 		}
2672aef9ec39SRoland Dreier 		break;
2673aef9ec39SRoland Dreier 
2674aef9ec39SRoland Dreier 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
26757aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost,
26767aa54bd7SDavid Dillow 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
2677509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2678aef9ec39SRoland Dreier 		break;
2679aef9ec39SRoland Dreier 
2680aef9ec39SRoland Dreier 	case IB_CM_REJ_CONSUMER_DEFINED:
2681aef9ec39SRoland Dreier 		opcode = *(u8 *) event->private_data;
2682aef9ec39SRoland Dreier 		if (opcode == SRP_LOGIN_REJ) {
2683aef9ec39SRoland Dreier 			struct srp_login_rej *rej = event->private_data;
2684aef9ec39SRoland Dreier 			u32 reason = be32_to_cpu(rej->reason);
2685aef9ec39SRoland Dreier 
2686aef9ec39SRoland Dreier 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
26877aa54bd7SDavid Dillow 				shost_printk(KERN_WARNING, shost,
26887aa54bd7SDavid Dillow 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
2689aef9ec39SRoland Dreier 			else
2690e7ffde01SBart Van Assche 				shost_printk(KERN_WARNING, shost, PFX
2691e7ffde01SBart Van Assche 					     "SRP LOGIN from %pI6 to %pI6 REJECTED, reason 0x%08x\n",
2692747fe000SBart Van Assche 					     target->sgid.raw,
269319f31343SBart Van Assche 					     target->ib_cm.orig_dgid.raw,
269419f31343SBart Van Assche 					     reason);
2695aef9ec39SRoland Dreier 		} else
26967aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
26977aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
2698aef9ec39SRoland Dreier 				     " opcode 0x%02x\n", opcode);
2699509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2700aef9ec39SRoland Dreier 		break;
2701aef9ec39SRoland Dreier 
27029fe4bcf4SDavid Dillow 	case IB_CM_REJ_STALE_CONN:
27039fe4bcf4SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason: stale connection\n");
2704509c07bcSBart Van Assche 		ch->status = SRP_STALE_CONN;
27059fe4bcf4SDavid Dillow 		break;
27069fe4bcf4SDavid Dillow 
2707aef9ec39SRoland Dreier 	default:
27087aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
2709aef9ec39SRoland Dreier 			     event->param.rej_rcvd.reason);
2710509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2711aef9ec39SRoland Dreier 	}
2712aef9ec39SRoland Dreier }
2713aef9ec39SRoland Dreier 
2714e7ff98aeSParav Pandit static int srp_ib_cm_handler(struct ib_cm_id *cm_id,
2715e7ff98aeSParav Pandit 			     const struct ib_cm_event *event)
2716aef9ec39SRoland Dreier {
2717509c07bcSBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
2718509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2719aef9ec39SRoland Dreier 	int comp = 0;
2720aef9ec39SRoland Dreier 
2721aef9ec39SRoland Dreier 	switch (event->event) {
2722aef9ec39SRoland Dreier 	case IB_CM_REQ_ERROR:
27237aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host,
27247aa54bd7SDavid Dillow 			     PFX "Sending CM REQ failed\n");
2725aef9ec39SRoland Dreier 		comp = 1;
2726509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2727aef9ec39SRoland Dreier 		break;
2728aef9ec39SRoland Dreier 
2729aef9ec39SRoland Dreier 	case IB_CM_REP_RECEIVED:
2730aef9ec39SRoland Dreier 		comp = 1;
2731509c07bcSBart Van Assche 		srp_cm_rep_handler(cm_id, event->private_data, ch);
2732aef9ec39SRoland Dreier 		break;
2733aef9ec39SRoland Dreier 
2734aef9ec39SRoland Dreier 	case IB_CM_REJ_RECEIVED:
27357aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
2736aef9ec39SRoland Dreier 		comp = 1;
2737aef9ec39SRoland Dreier 
273819f31343SBart Van Assche 		srp_ib_cm_rej_handler(cm_id, event, ch);
2739aef9ec39SRoland Dreier 		break;
2740aef9ec39SRoland Dreier 
2741b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_RECEIVED:
27427aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
27437aa54bd7SDavid Dillow 			     PFX "DREQ received - connection closed\n");
2744c014c8cdSBart Van Assche 		ch->connected = false;
2745b7ac4ab4SIshai Rabinovitz 		if (ib_send_cm_drep(cm_id, NULL, 0))
27467aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
27477aa54bd7SDavid Dillow 				     PFX "Sending CM DREP failed\n");
2748c1120f89SBart Van Assche 		queue_work(system_long_wq, &target->tl_err_work);
2749aef9ec39SRoland Dreier 		break;
2750aef9ec39SRoland Dreier 
2751aef9ec39SRoland Dreier 	case IB_CM_TIMEWAIT_EXIT:
27527aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
27537aa54bd7SDavid Dillow 			     PFX "connection closed\n");
2754ac72d766SBart Van Assche 		comp = 1;
2755aef9ec39SRoland Dreier 
2756509c07bcSBart Van Assche 		ch->status = 0;
2757aef9ec39SRoland Dreier 		break;
2758aef9ec39SRoland Dreier 
2759b7ac4ab4SIshai Rabinovitz 	case IB_CM_MRA_RECEIVED:
2760b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_ERROR:
2761b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREP_RECEIVED:
2762b7ac4ab4SIshai Rabinovitz 		break;
2763b7ac4ab4SIshai Rabinovitz 
2764aef9ec39SRoland Dreier 	default:
27657aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
27667aa54bd7SDavid Dillow 			     PFX "Unhandled CM event %d\n", event->event);
2767aef9ec39SRoland Dreier 		break;
2768aef9ec39SRoland Dreier 	}
2769aef9ec39SRoland Dreier 
2770aef9ec39SRoland Dreier 	if (comp)
2771509c07bcSBart Van Assche 		complete(&ch->done);
2772aef9ec39SRoland Dreier 
2773aef9ec39SRoland Dreier 	return 0;
2774aef9ec39SRoland Dreier }
2775aef9ec39SRoland Dreier 
277619f31343SBart Van Assche static void srp_rdma_cm_rej_handler(struct srp_rdma_ch *ch,
277719f31343SBart Van Assche 				    struct rdma_cm_event *event)
277819f31343SBart Van Assche {
277919f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
278019f31343SBart Van Assche 	struct Scsi_Host *shost = target->scsi_host;
278119f31343SBart Van Assche 	int opcode;
278219f31343SBart Van Assche 
278319f31343SBart Van Assche 	switch (event->status) {
278419f31343SBart Van Assche 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
278519f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
278619f31343SBart Van Assche 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
278719f31343SBart Van Assche 		ch->status = -ECONNRESET;
278819f31343SBart Van Assche 		break;
278919f31343SBart Van Assche 
279019f31343SBart Van Assche 	case IB_CM_REJ_CONSUMER_DEFINED:
279119f31343SBart Van Assche 		opcode = *(u8 *) event->param.conn.private_data;
279219f31343SBart Van Assche 		if (opcode == SRP_LOGIN_REJ) {
279319f31343SBart Van Assche 			struct srp_login_rej *rej =
279419f31343SBart Van Assche 				(struct srp_login_rej *)
279519f31343SBart Van Assche 				event->param.conn.private_data;
279619f31343SBart Van Assche 			u32 reason = be32_to_cpu(rej->reason);
279719f31343SBart Van Assche 
279819f31343SBart Van Assche 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
279919f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
280019f31343SBart Van Assche 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
280119f31343SBart Van Assche 			else
280219f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
280319f31343SBart Van Assche 					    PFX "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
280419f31343SBart Van Assche 		} else {
280519f31343SBart Van Assche 			shost_printk(KERN_WARNING, shost,
280619f31343SBart Van Assche 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED, opcode 0x%02x\n",
280719f31343SBart Van Assche 				     opcode);
280819f31343SBart Van Assche 		}
280919f31343SBart Van Assche 		ch->status = -ECONNRESET;
281019f31343SBart Van Assche 		break;
281119f31343SBart Van Assche 
281219f31343SBart Van Assche 	case IB_CM_REJ_STALE_CONN:
281319f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
281419f31343SBart Van Assche 			     "  REJ reason: stale connection\n");
281519f31343SBart Van Assche 		ch->status = SRP_STALE_CONN;
281619f31343SBart Van Assche 		break;
281719f31343SBart Van Assche 
281819f31343SBart Van Assche 	default:
281919f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
282019f31343SBart Van Assche 			     event->status);
282119f31343SBart Van Assche 		ch->status = -ECONNRESET;
282219f31343SBart Van Assche 		break;
282319f31343SBart Van Assche 	}
282419f31343SBart Van Assche }
282519f31343SBart Van Assche 
282619f31343SBart Van Assche static int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
282719f31343SBart Van Assche 			       struct rdma_cm_event *event)
282819f31343SBart Van Assche {
282919f31343SBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
283019f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
283119f31343SBart Van Assche 	int comp = 0;
283219f31343SBart Van Assche 
283319f31343SBart Van Assche 	switch (event->event) {
283419f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_RESOLVED:
283519f31343SBart Van Assche 		ch->status = 0;
283619f31343SBart Van Assche 		comp = 1;
283719f31343SBart Van Assche 		break;
283819f31343SBart Van Assche 
283919f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_ERROR:
284019f31343SBart Van Assche 		ch->status = -ENXIO;
284119f31343SBart Van Assche 		comp = 1;
284219f31343SBart Van Assche 		break;
284319f31343SBart Van Assche 
284419f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_RESOLVED:
284519f31343SBart Van Assche 		ch->status = 0;
284619f31343SBart Van Assche 		comp = 1;
284719f31343SBart Van Assche 		break;
284819f31343SBart Van Assche 
284919f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_ERROR:
285019f31343SBart Van Assche 	case RDMA_CM_EVENT_UNREACHABLE:
285119f31343SBart Van Assche 		ch->status = -EHOSTUNREACH;
285219f31343SBart Van Assche 		comp = 1;
285319f31343SBart Van Assche 		break;
285419f31343SBart Van Assche 
285519f31343SBart Van Assche 	case RDMA_CM_EVENT_CONNECT_ERROR:
285619f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host,
285719f31343SBart Van Assche 			     PFX "Sending CM REQ failed\n");
285819f31343SBart Van Assche 		comp = 1;
285919f31343SBart Van Assche 		ch->status = -ECONNRESET;
286019f31343SBart Van Assche 		break;
286119f31343SBart Van Assche 
286219f31343SBart Van Assche 	case RDMA_CM_EVENT_ESTABLISHED:
286319f31343SBart Van Assche 		comp = 1;
286419f31343SBart Van Assche 		srp_cm_rep_handler(NULL, event->param.conn.private_data, ch);
286519f31343SBart Van Assche 		break;
286619f31343SBart Van Assche 
286719f31343SBart Van Assche 	case RDMA_CM_EVENT_REJECTED:
286819f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
286919f31343SBart Van Assche 		comp = 1;
287019f31343SBart Van Assche 
287119f31343SBart Van Assche 		srp_rdma_cm_rej_handler(ch, event);
287219f31343SBart Van Assche 		break;
287319f31343SBart Van Assche 
287419f31343SBart Van Assche 	case RDMA_CM_EVENT_DISCONNECTED:
287519f31343SBart Van Assche 		if (ch->connected) {
287619f31343SBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host,
287719f31343SBart Van Assche 				     PFX "received DREQ\n");
287819f31343SBart Van Assche 			rdma_disconnect(ch->rdma_cm.cm_id);
287919f31343SBart Van Assche 			comp = 1;
288019f31343SBart Van Assche 			ch->status = 0;
288119f31343SBart Van Assche 			queue_work(system_long_wq, &target->tl_err_work);
288219f31343SBart Van Assche 		}
288319f31343SBart Van Assche 		break;
288419f31343SBart Van Assche 
288519f31343SBart Van Assche 	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
288619f31343SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
288719f31343SBart Van Assche 			     PFX "connection closed\n");
288819f31343SBart Van Assche 
288919f31343SBart Van Assche 		comp = 1;
289019f31343SBart Van Assche 		ch->status = 0;
289119f31343SBart Van Assche 		break;
289219f31343SBart Van Assche 
289319f31343SBart Van Assche 	default:
289419f31343SBart Van Assche 		shost_printk(KERN_WARNING, target->scsi_host,
289519f31343SBart Van Assche 			     PFX "Unhandled CM event %d\n", event->event);
289619f31343SBart Van Assche 		break;
289719f31343SBart Van Assche 	}
289819f31343SBart Van Assche 
289919f31343SBart Van Assche 	if (comp)
290019f31343SBart Van Assche 		complete(&ch->done);
290119f31343SBart Van Assche 
290219f31343SBart Van Assche 	return 0;
290319f31343SBart Van Assche }
290419f31343SBart Van Assche 
290571444b97SJack Wang /**
290671444b97SJack Wang  * srp_change_queue_depth - setting device queue depth
290771444b97SJack Wang  * @sdev: scsi device struct
290871444b97SJack Wang  * @qdepth: requested queue depth
290971444b97SJack Wang  *
291071444b97SJack Wang  * Returns queue depth.
291171444b97SJack Wang  */
291271444b97SJack Wang static int
2913db5ed4dfSChristoph Hellwig srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
291471444b97SJack Wang {
291571444b97SJack Wang 	if (!sdev->tagged_supported)
29161e6f2416SChristoph Hellwig 		qdepth = 1;
2917db5ed4dfSChristoph Hellwig 	return scsi_change_queue_depth(sdev, qdepth);
291871444b97SJack Wang }
291971444b97SJack Wang 
2920985aa495SBart Van Assche static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
29210a6fdbdeSBart Van Assche 			     u8 func, u8 *status)
2922aef9ec39SRoland Dreier {
2923509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2924a95cadb9SBart Van Assche 	struct srp_rport *rport = target->rport;
292519081f31SDavid Dillow 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2926aef9ec39SRoland Dreier 	struct srp_iu *iu;
2927aef9ec39SRoland Dreier 	struct srp_tsk_mgmt *tsk_mgmt;
29280a6fdbdeSBart Van Assche 	int res;
2929aef9ec39SRoland Dreier 
2930c014c8cdSBart Van Assche 	if (!ch->connected || target->qp_in_error)
29313780d1f0SBart Van Assche 		return -1;
29323780d1f0SBart Van Assche 
2933a95cadb9SBart Van Assche 	/*
2934509c07bcSBart Van Assche 	 * Lock the rport mutex to avoid that srp_create_ch_ib() is
2935a95cadb9SBart Van Assche 	 * invoked while a task management function is being sent.
2936a95cadb9SBart Van Assche 	 */
2937a95cadb9SBart Van Assche 	mutex_lock(&rport->mutex);
2938509c07bcSBart Van Assche 	spin_lock_irq(&ch->lock);
2939509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_TSK_MGMT);
2940509c07bcSBart Van Assche 	spin_unlock_irq(&ch->lock);
294176c75b25SBart Van Assche 
2942a95cadb9SBart Van Assche 	if (!iu) {
2943a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2944a95cadb9SBart Van Assche 
294576c75b25SBart Van Assche 		return -1;
2946a95cadb9SBart Van Assche 	}
2947aef9ec39SRoland Dreier 
2948882981f4SBart Van Assche 	iu->num_sge = 1;
2949882981f4SBart Van Assche 
295019081f31SDavid Dillow 	ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
295119081f31SDavid Dillow 				   DMA_TO_DEVICE);
2952aef9ec39SRoland Dreier 	tsk_mgmt = iu->buf;
2953aef9ec39SRoland Dreier 	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
2954aef9ec39SRoland Dreier 
2955aef9ec39SRoland Dreier 	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
2956985aa495SBart Van Assche 	int_to_scsilun(lun, &tsk_mgmt->lun);
2957aef9ec39SRoland Dreier 	tsk_mgmt->tsk_mgmt_func = func;
2958f8b6e31eSDavid Dillow 	tsk_mgmt->task_tag	= req_tag;
2959aef9ec39SRoland Dreier 
29600a6fdbdeSBart Van Assche 	spin_lock_irq(&ch->lock);
29610a6fdbdeSBart Van Assche 	ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT;
29620a6fdbdeSBart Van Assche 	tsk_mgmt->tag = ch->tsk_mgmt_tag;
29630a6fdbdeSBart Van Assche 	spin_unlock_irq(&ch->lock);
29640a6fdbdeSBart Van Assche 
29650a6fdbdeSBart Van Assche 	init_completion(&ch->tsk_mgmt_done);
29660a6fdbdeSBart Van Assche 
296719081f31SDavid Dillow 	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
296819081f31SDavid Dillow 				      DMA_TO_DEVICE);
2969509c07bcSBart Van Assche 	if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
2970509c07bcSBart Van Assche 		srp_put_tx_iu(ch, iu, SRP_IU_TSK_MGMT);
2971a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2972a95cadb9SBart Van Assche 
297376c75b25SBart Van Assche 		return -1;
297476c75b25SBart Van Assche 	}
29750a6fdbdeSBart Van Assche 	res = wait_for_completion_timeout(&ch->tsk_mgmt_done,
29760a6fdbdeSBart Van Assche 					msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS));
29770a6fdbdeSBart Van Assche 	if (res > 0 && status)
29780a6fdbdeSBart Van Assche 		*status = ch->tsk_mgmt_status;
2979a95cadb9SBart Van Assche 	mutex_unlock(&rport->mutex);
2980d945e1dfSRoland Dreier 
29810a6fdbdeSBart Van Assche 	WARN_ON_ONCE(res < 0);
2982aef9ec39SRoland Dreier 
29830a6fdbdeSBart Van Assche 	return res > 0 ? 0 : -1;
2984d945e1dfSRoland Dreier }
2985d945e1dfSRoland Dreier 
2986aef9ec39SRoland Dreier static int srp_abort(struct scsi_cmnd *scmnd)
2987aef9ec39SRoland Dreier {
2988d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
2989f8b6e31eSDavid Dillow 	struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
299077f2c1a4SBart Van Assche 	u32 tag;
2991d92c0da7SBart Van Assche 	u16 ch_idx;
2992509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
2993086f44f5SBart Van Assche 	int ret;
2994d945e1dfSRoland Dreier 
29957aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
2996aef9ec39SRoland Dreier 
2997d92c0da7SBart Van Assche 	if (!req)
299899b6697aSBart Van Assche 		return SUCCESS;
299977f2c1a4SBart Van Assche 	tag = blk_mq_unique_tag(scmnd->request);
3000d92c0da7SBart Van Assche 	ch_idx = blk_mq_unique_tag_to_hwq(tag);
3001d92c0da7SBart Van Assche 	if (WARN_ON_ONCE(ch_idx >= target->ch_count))
3002d92c0da7SBart Van Assche 		return SUCCESS;
3003d92c0da7SBart Van Assche 	ch = &target->ch[ch_idx];
3004d92c0da7SBart Van Assche 	if (!srp_claim_req(ch, req, NULL, scmnd))
3005d92c0da7SBart Van Assche 		return SUCCESS;
3006d92c0da7SBart Van Assche 	shost_printk(KERN_ERR, target->scsi_host,
3007d92c0da7SBart Van Assche 		     "Sending SRP abort for tag %#x\n", tag);
300877f2c1a4SBart Van Assche 	if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
30090a6fdbdeSBart Van Assche 			      SRP_TSK_ABORT_TASK, NULL) == 0)
3010086f44f5SBart Van Assche 		ret = SUCCESS;
3011ed9b2264SBart Van Assche 	else if (target->rport->state == SRP_RPORT_LOST)
301299e1c139SBart Van Assche 		ret = FAST_IO_FAIL;
3013086f44f5SBart Van Assche 	else
3014086f44f5SBart Van Assche 		ret = FAILED;
3015e68088e7SBart Van Assche 	if (ret == SUCCESS) {
3016509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd, 0);
3017d945e1dfSRoland Dreier 		scmnd->result = DID_ABORT << 16;
3018d8536670SBart Van Assche 		scmnd->scsi_done(scmnd);
3019e68088e7SBart Van Assche 	}
3020d945e1dfSRoland Dreier 
3021086f44f5SBart Van Assche 	return ret;
3022aef9ec39SRoland Dreier }
3023aef9ec39SRoland Dreier 
3024aef9ec39SRoland Dreier static int srp_reset_device(struct scsi_cmnd *scmnd)
3025aef9ec39SRoland Dreier {
3026d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
3027d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
30280a6fdbdeSBart Van Assche 	u8 status;
3029d945e1dfSRoland Dreier 
30307aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
3031aef9ec39SRoland Dreier 
3032d92c0da7SBart Van Assche 	ch = &target->ch[0];
3033509c07bcSBart Van Assche 	if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
30340a6fdbdeSBart Van Assche 			      SRP_TSK_LUN_RESET, &status))
3035d945e1dfSRoland Dreier 		return FAILED;
30360a6fdbdeSBart Van Assche 	if (status)
3037d945e1dfSRoland Dreier 		return FAILED;
3038d945e1dfSRoland Dreier 
3039d945e1dfSRoland Dreier 	return SUCCESS;
3040aef9ec39SRoland Dreier }
3041aef9ec39SRoland Dreier 
3042aef9ec39SRoland Dreier static int srp_reset_host(struct scsi_cmnd *scmnd)
3043aef9ec39SRoland Dreier {
3044aef9ec39SRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
3045aef9ec39SRoland Dreier 
30467aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, PFX "SRP reset_host called\n");
3047aef9ec39SRoland Dreier 
3048ed9b2264SBart Van Assche 	return srp_reconnect_rport(target->rport) == 0 ? SUCCESS : FAILED;
3049aef9ec39SRoland Dreier }
3050aef9ec39SRoland Dreier 
3051b0780ee5SBart Van Assche static int srp_target_alloc(struct scsi_target *starget)
3052b0780ee5SBart Van Assche {
3053b0780ee5SBart Van Assche 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
3054b0780ee5SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
3055b0780ee5SBart Van Assche 
3056b0780ee5SBart Van Assche 	if (target->target_can_queue)
3057b0780ee5SBart Van Assche 		starget->can_queue = target->target_can_queue;
3058b0780ee5SBart Van Assche 	return 0;
3059b0780ee5SBart Van Assche }
3060b0780ee5SBart Van Assche 
3061c9b03c1aSBart Van Assche static int srp_slave_configure(struct scsi_device *sdev)
3062c9b03c1aSBart Van Assche {
3063c9b03c1aSBart Van Assche 	struct Scsi_Host *shost = sdev->host;
3064c9b03c1aSBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
3065c9b03c1aSBart Van Assche 	struct request_queue *q = sdev->request_queue;
3066c9b03c1aSBart Van Assche 	unsigned long timeout;
3067c9b03c1aSBart Van Assche 
3068c9b03c1aSBart Van Assche 	if (sdev->type == TYPE_DISK) {
3069c9b03c1aSBart Van Assche 		timeout = max_t(unsigned, 30 * HZ, target->rq_tmo_jiffies);
3070c9b03c1aSBart Van Assche 		blk_queue_rq_timeout(q, timeout);
3071c9b03c1aSBart Van Assche 	}
3072c9b03c1aSBart Van Assche 
3073c9b03c1aSBart Van Assche 	return 0;
3074c9b03c1aSBart Van Assche }
3075c9b03c1aSBart Van Assche 
3076ee959b00STony Jones static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
3077ee959b00STony Jones 			   char *buf)
30786ecb0c84SRoland Dreier {
3079ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30806ecb0c84SRoland Dreier 
308145c37cadSBart Van Assche 	return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->id_ext));
30826ecb0c84SRoland Dreier }
30836ecb0c84SRoland Dreier 
3084ee959b00STony Jones static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
3085ee959b00STony Jones 			     char *buf)
30866ecb0c84SRoland Dreier {
3087ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30886ecb0c84SRoland Dreier 
308945c37cadSBart Van Assche 	return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid));
30906ecb0c84SRoland Dreier }
30916ecb0c84SRoland Dreier 
3092ee959b00STony Jones static ssize_t show_service_id(struct device *dev,
3093ee959b00STony Jones 			       struct device_attribute *attr, char *buf)
30946ecb0c84SRoland Dreier {
3095ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30966ecb0c84SRoland Dreier 
309719f31343SBart Van Assche 	if (target->using_rdma_cm)
309819f31343SBart Van Assche 		return -ENOENT;
309919f31343SBart Van Assche 	return sprintf(buf, "0x%016llx\n",
310019f31343SBart Van Assche 		       be64_to_cpu(target->ib_cm.service_id));
31016ecb0c84SRoland Dreier }
31026ecb0c84SRoland Dreier 
3103ee959b00STony Jones static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
3104ee959b00STony Jones 			 char *buf)
31056ecb0c84SRoland Dreier {
3106ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31076ecb0c84SRoland Dreier 
310819f31343SBart Van Assche 	if (target->using_rdma_cm)
310919f31343SBart Van Assche 		return -ENOENT;
311019f31343SBart Van Assche 	return sprintf(buf, "0x%04x\n", be16_to_cpu(target->ib_cm.pkey));
31116ecb0c84SRoland Dreier }
31126ecb0c84SRoland Dreier 
3113848b3082SBart Van Assche static ssize_t show_sgid(struct device *dev, struct device_attribute *attr,
3114848b3082SBart Van Assche 			 char *buf)
3115848b3082SBart Van Assche {
3116848b3082SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3117848b3082SBart Van Assche 
3118747fe000SBart Van Assche 	return sprintf(buf, "%pI6\n", target->sgid.raw);
3119848b3082SBart Van Assche }
3120848b3082SBart Van Assche 
3121ee959b00STony Jones static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
3122ee959b00STony Jones 			 char *buf)
31236ecb0c84SRoland Dreier {
3124ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3125d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch = &target->ch[0];
31266ecb0c84SRoland Dreier 
312719f31343SBart Van Assche 	if (target->using_rdma_cm)
312819f31343SBart Van Assche 		return -ENOENT;
312919f31343SBart Van Assche 	return sprintf(buf, "%pI6\n", ch->ib_cm.path.dgid.raw);
31306ecb0c84SRoland Dreier }
31316ecb0c84SRoland Dreier 
3132ee959b00STony Jones static ssize_t show_orig_dgid(struct device *dev,
3133ee959b00STony Jones 			      struct device_attribute *attr, char *buf)
31343633b3d0SIshai Rabinovitz {
3135ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31363633b3d0SIshai Rabinovitz 
313719f31343SBart Van Assche 	if (target->using_rdma_cm)
313819f31343SBart Van Assche 		return -ENOENT;
313919f31343SBart Van Assche 	return sprintf(buf, "%pI6\n", target->ib_cm.orig_dgid.raw);
31403633b3d0SIshai Rabinovitz }
31413633b3d0SIshai Rabinovitz 
314289de7486SBart Van Assche static ssize_t show_req_lim(struct device *dev,
314389de7486SBart Van Assche 			    struct device_attribute *attr, char *buf)
314489de7486SBart Van Assche {
314589de7486SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3146d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
3147d92c0da7SBart Van Assche 	int i, req_lim = INT_MAX;
314889de7486SBart Van Assche 
3149d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
3150d92c0da7SBart Van Assche 		ch = &target->ch[i];
3151d92c0da7SBart Van Assche 		req_lim = min(req_lim, ch->req_lim);
3152d92c0da7SBart Van Assche 	}
3153d92c0da7SBart Van Assche 	return sprintf(buf, "%d\n", req_lim);
315489de7486SBart Van Assche }
315589de7486SBart Van Assche 
3156ee959b00STony Jones static ssize_t show_zero_req_lim(struct device *dev,
3157ee959b00STony Jones 				 struct device_attribute *attr, char *buf)
31586bfa24faSRoland Dreier {
3159ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31606bfa24faSRoland Dreier 
31616bfa24faSRoland Dreier 	return sprintf(buf, "%d\n", target->zero_req_lim);
31626bfa24faSRoland Dreier }
31636bfa24faSRoland Dreier 
3164ee959b00STony Jones static ssize_t show_local_ib_port(struct device *dev,
3165ee959b00STony Jones 				  struct device_attribute *attr, char *buf)
3166ded7f1a1SIshai Rabinovitz {
3167ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3168ded7f1a1SIshai Rabinovitz 
3169ded7f1a1SIshai Rabinovitz 	return sprintf(buf, "%d\n", target->srp_host->port);
3170ded7f1a1SIshai Rabinovitz }
3171ded7f1a1SIshai Rabinovitz 
3172ee959b00STony Jones static ssize_t show_local_ib_device(struct device *dev,
3173ee959b00STony Jones 				    struct device_attribute *attr, char *buf)
3174ded7f1a1SIshai Rabinovitz {
3175ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3176ded7f1a1SIshai Rabinovitz 
31776c854111SJason Gunthorpe 	return sprintf(buf, "%s\n",
31786c854111SJason Gunthorpe 		       dev_name(&target->srp_host->srp_dev->dev->dev));
3179ded7f1a1SIshai Rabinovitz }
3180ded7f1a1SIshai Rabinovitz 
3181d92c0da7SBart Van Assche static ssize_t show_ch_count(struct device *dev, struct device_attribute *attr,
3182d92c0da7SBart Van Assche 			     char *buf)
3183d92c0da7SBart Van Assche {
3184d92c0da7SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3185d92c0da7SBart Van Assche 
3186d92c0da7SBart Van Assche 	return sprintf(buf, "%d\n", target->ch_count);
3187d92c0da7SBart Van Assche }
3188d92c0da7SBart Van Assche 
31894b5e5f41SBart Van Assche static ssize_t show_comp_vector(struct device *dev,
31904b5e5f41SBart Van Assche 				struct device_attribute *attr, char *buf)
31914b5e5f41SBart Van Assche {
31924b5e5f41SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31934b5e5f41SBart Van Assche 
31944b5e5f41SBart Van Assche 	return sprintf(buf, "%d\n", target->comp_vector);
31954b5e5f41SBart Van Assche }
31964b5e5f41SBart Van Assche 
31977bb312e4SVu Pham static ssize_t show_tl_retry_count(struct device *dev,
31987bb312e4SVu Pham 				   struct device_attribute *attr, char *buf)
31997bb312e4SVu Pham {
32007bb312e4SVu Pham 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
32017bb312e4SVu Pham 
32027bb312e4SVu Pham 	return sprintf(buf, "%d\n", target->tl_retry_count);
32037bb312e4SVu Pham }
32047bb312e4SVu Pham 
320549248644SDavid Dillow static ssize_t show_cmd_sg_entries(struct device *dev,
320649248644SDavid Dillow 				   struct device_attribute *attr, char *buf)
320749248644SDavid Dillow {
320849248644SDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
320949248644SDavid Dillow 
321049248644SDavid Dillow 	return sprintf(buf, "%u\n", target->cmd_sg_cnt);
321149248644SDavid Dillow }
321249248644SDavid Dillow 
3213c07d424dSDavid Dillow static ssize_t show_allow_ext_sg(struct device *dev,
3214c07d424dSDavid Dillow 				 struct device_attribute *attr, char *buf)
3215c07d424dSDavid Dillow {
3216c07d424dSDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3217c07d424dSDavid Dillow 
3218c07d424dSDavid Dillow 	return sprintf(buf, "%s\n", target->allow_ext_sg ? "true" : "false");
3219c07d424dSDavid Dillow }
3220c07d424dSDavid Dillow 
3221ee959b00STony Jones static DEVICE_ATTR(id_ext,	    S_IRUGO, show_id_ext,	   NULL);
3222ee959b00STony Jones static DEVICE_ATTR(ioc_guid,	    S_IRUGO, show_ioc_guid,	   NULL);
3223ee959b00STony Jones static DEVICE_ATTR(service_id,	    S_IRUGO, show_service_id,	   NULL);
3224ee959b00STony Jones static DEVICE_ATTR(pkey,	    S_IRUGO, show_pkey,		   NULL);
3225848b3082SBart Van Assche static DEVICE_ATTR(sgid,	    S_IRUGO, show_sgid,		   NULL);
3226ee959b00STony Jones static DEVICE_ATTR(dgid,	    S_IRUGO, show_dgid,		   NULL);
3227ee959b00STony Jones static DEVICE_ATTR(orig_dgid,	    S_IRUGO, show_orig_dgid,	   NULL);
322889de7486SBart Van Assche static DEVICE_ATTR(req_lim,         S_IRUGO, show_req_lim,         NULL);
3229ee959b00STony Jones static DEVICE_ATTR(zero_req_lim,    S_IRUGO, show_zero_req_lim,	   NULL);
3230ee959b00STony Jones static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
3231ee959b00STony Jones static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
3232d92c0da7SBart Van Assche static DEVICE_ATTR(ch_count,        S_IRUGO, show_ch_count,        NULL);
32334b5e5f41SBart Van Assche static DEVICE_ATTR(comp_vector,     S_IRUGO, show_comp_vector,     NULL);
32347bb312e4SVu Pham static DEVICE_ATTR(tl_retry_count,  S_IRUGO, show_tl_retry_count,  NULL);
323549248644SDavid Dillow static DEVICE_ATTR(cmd_sg_entries,  S_IRUGO, show_cmd_sg_entries,  NULL);
3236c07d424dSDavid Dillow static DEVICE_ATTR(allow_ext_sg,    S_IRUGO, show_allow_ext_sg,    NULL);
32376ecb0c84SRoland Dreier 
3238ee959b00STony Jones static struct device_attribute *srp_host_attrs[] = {
3239ee959b00STony Jones 	&dev_attr_id_ext,
3240ee959b00STony Jones 	&dev_attr_ioc_guid,
3241ee959b00STony Jones 	&dev_attr_service_id,
3242ee959b00STony Jones 	&dev_attr_pkey,
3243848b3082SBart Van Assche 	&dev_attr_sgid,
3244ee959b00STony Jones 	&dev_attr_dgid,
3245ee959b00STony Jones 	&dev_attr_orig_dgid,
324689de7486SBart Van Assche 	&dev_attr_req_lim,
3247ee959b00STony Jones 	&dev_attr_zero_req_lim,
3248ee959b00STony Jones 	&dev_attr_local_ib_port,
3249ee959b00STony Jones 	&dev_attr_local_ib_device,
3250d92c0da7SBart Van Assche 	&dev_attr_ch_count,
32514b5e5f41SBart Van Assche 	&dev_attr_comp_vector,
32527bb312e4SVu Pham 	&dev_attr_tl_retry_count,
325349248644SDavid Dillow 	&dev_attr_cmd_sg_entries,
3254c07d424dSDavid Dillow 	&dev_attr_allow_ext_sg,
32556ecb0c84SRoland Dreier 	NULL
32566ecb0c84SRoland Dreier };
32576ecb0c84SRoland Dreier 
3258aef9ec39SRoland Dreier static struct scsi_host_template srp_template = {
3259aef9ec39SRoland Dreier 	.module				= THIS_MODULE,
3260b7f008fdSRoland Dreier 	.name				= "InfiniBand SRP initiator",
3261b7f008fdSRoland Dreier 	.proc_name			= DRV_NAME,
3262b0780ee5SBart Van Assche 	.target_alloc			= srp_target_alloc,
3263c9b03c1aSBart Van Assche 	.slave_configure		= srp_slave_configure,
3264aef9ec39SRoland Dreier 	.info				= srp_target_info,
3265aef9ec39SRoland Dreier 	.queuecommand			= srp_queuecommand,
326671444b97SJack Wang 	.change_queue_depth             = srp_change_queue_depth,
3267b6a05c82SChristoph Hellwig 	.eh_timed_out			= srp_timed_out,
3268aef9ec39SRoland Dreier 	.eh_abort_handler		= srp_abort,
3269aef9ec39SRoland Dreier 	.eh_device_reset_handler	= srp_reset_device,
3270aef9ec39SRoland Dreier 	.eh_host_reset_handler		= srp_reset_host,
32712742c1daSBart Van Assche 	.skip_settle_delay		= true,
327249248644SDavid Dillow 	.sg_tablesize			= SRP_DEF_SG_TABLESIZE,
32734d73f95fSBart Van Assche 	.can_queue			= SRP_DEFAULT_CMD_SQ_SIZE,
3274aef9ec39SRoland Dreier 	.this_id			= -1,
32754d73f95fSBart Van Assche 	.cmd_per_lun			= SRP_DEFAULT_CMD_SQ_SIZE,
327677f2c1a4SBart Van Assche 	.shost_attrs			= srp_host_attrs,
3277c40ecc12SChristoph Hellwig 	.track_queue_depth		= 1,
3278aef9ec39SRoland Dreier };
3279aef9ec39SRoland Dreier 
328034aa654eSBart Van Assche static int srp_sdev_count(struct Scsi_Host *host)
328134aa654eSBart Van Assche {
328234aa654eSBart Van Assche 	struct scsi_device *sdev;
328334aa654eSBart Van Assche 	int c = 0;
328434aa654eSBart Van Assche 
328534aa654eSBart Van Assche 	shost_for_each_device(sdev, host)
328634aa654eSBart Van Assche 		c++;
328734aa654eSBart Van Assche 
328834aa654eSBart Van Assche 	return c;
328934aa654eSBart Van Assche }
329034aa654eSBart Van Assche 
3291bc44bd1dSBart Van Assche /*
3292bc44bd1dSBart Van Assche  * Return values:
3293bc44bd1dSBart Van Assche  * < 0 upon failure. Caller is responsible for SRP target port cleanup.
3294bc44bd1dSBart Van Assche  * 0 and target->state == SRP_TARGET_REMOVED if asynchronous target port
3295bc44bd1dSBart Van Assche  *    removal has been scheduled.
3296bc44bd1dSBart Van Assche  * 0 and target->state != SRP_TARGET_REMOVED upon success.
3297bc44bd1dSBart Van Assche  */
3298aef9ec39SRoland Dreier static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
3299aef9ec39SRoland Dreier {
33003236822bSFUJITA Tomonori 	struct srp_rport_identifiers ids;
33013236822bSFUJITA Tomonori 	struct srp_rport *rport;
33023236822bSFUJITA Tomonori 
330334aa654eSBart Van Assche 	target->state = SRP_TARGET_SCANNING;
3304aef9ec39SRoland Dreier 	sprintf(target->target_name, "SRP.T10:%016llX",
330545c37cadSBart Van Assche 		be64_to_cpu(target->id_ext));
3306aef9ec39SRoland Dreier 
3307dee2b82aSBart Van Assche 	if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dev.parent))
3308aef9ec39SRoland Dreier 		return -ENODEV;
3309aef9ec39SRoland Dreier 
33103236822bSFUJITA Tomonori 	memcpy(ids.port_id, &target->id_ext, 8);
33113236822bSFUJITA Tomonori 	memcpy(ids.port_id + 8, &target->ioc_guid, 8);
3312aebd5e47SFUJITA Tomonori 	ids.roles = SRP_RPORT_ROLE_TARGET;
33133236822bSFUJITA Tomonori 	rport = srp_rport_add(target->scsi_host, &ids);
33143236822bSFUJITA Tomonori 	if (IS_ERR(rport)) {
33153236822bSFUJITA Tomonori 		scsi_remove_host(target->scsi_host);
33163236822bSFUJITA Tomonori 		return PTR_ERR(rport);
33173236822bSFUJITA Tomonori 	}
33183236822bSFUJITA Tomonori 
3319dc1bdbd9SBart Van Assche 	rport->lld_data = target;
33209dd69a60SBart Van Assche 	target->rport = rport;
3321dc1bdbd9SBart Van Assche 
3322b3589fd4SMatthew Wilcox 	spin_lock(&host->target_lock);
3323aef9ec39SRoland Dreier 	list_add_tail(&target->list, &host->target_list);
3324b3589fd4SMatthew Wilcox 	spin_unlock(&host->target_lock);
3325aef9ec39SRoland Dreier 
3326aef9ec39SRoland Dreier 	scsi_scan_target(&target->scsi_host->shost_gendev,
33271d645088SHannes Reinecke 			 0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
3328aef9ec39SRoland Dreier 
3329c014c8cdSBart Van Assche 	if (srp_connected_ch(target) < target->ch_count ||
3330c014c8cdSBart Van Assche 	    target->qp_in_error) {
333134aa654eSBart Van Assche 		shost_printk(KERN_INFO, target->scsi_host,
333234aa654eSBart Van Assche 			     PFX "SCSI scan failed - removing SCSI host\n");
333334aa654eSBart Van Assche 		srp_queue_remove_work(target);
333434aa654eSBart Van Assche 		goto out;
333534aa654eSBart Van Assche 	}
333634aa654eSBart Van Assche 
3337cf1acab7SBart Van Assche 	pr_debug("%s: SCSI scan succeeded - detected %d LUNs\n",
333834aa654eSBart Van Assche 		 dev_name(&target->scsi_host->shost_gendev),
333934aa654eSBart Van Assche 		 srp_sdev_count(target->scsi_host));
334034aa654eSBart Van Assche 
334134aa654eSBart Van Assche 	spin_lock_irq(&target->lock);
334234aa654eSBart Van Assche 	if (target->state == SRP_TARGET_SCANNING)
334334aa654eSBart Van Assche 		target->state = SRP_TARGET_LIVE;
334434aa654eSBart Van Assche 	spin_unlock_irq(&target->lock);
334534aa654eSBart Van Assche 
334634aa654eSBart Van Assche out:
3347aef9ec39SRoland Dreier 	return 0;
3348aef9ec39SRoland Dreier }
3349aef9ec39SRoland Dreier 
3350ee959b00STony Jones static void srp_release_dev(struct device *dev)
3351aef9ec39SRoland Dreier {
3352aef9ec39SRoland Dreier 	struct srp_host *host =
3353ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3354aef9ec39SRoland Dreier 
3355aef9ec39SRoland Dreier 	complete(&host->released);
3356aef9ec39SRoland Dreier }
3357aef9ec39SRoland Dreier 
3358aef9ec39SRoland Dreier static struct class srp_class = {
3359aef9ec39SRoland Dreier 	.name    = "infiniband_srp",
3360ee959b00STony Jones 	.dev_release = srp_release_dev
3361aef9ec39SRoland Dreier };
3362aef9ec39SRoland Dreier 
336396fc248aSBart Van Assche /**
336496fc248aSBart Van Assche  * srp_conn_unique() - check whether the connection to a target is unique
3365af24663bSBart Van Assche  * @host:   SRP host.
3366af24663bSBart Van Assche  * @target: SRP target port.
336796fc248aSBart Van Assche  */
336896fc248aSBart Van Assche static bool srp_conn_unique(struct srp_host *host,
336996fc248aSBart Van Assche 			    struct srp_target_port *target)
337096fc248aSBart Van Assche {
337196fc248aSBart Van Assche 	struct srp_target_port *t;
337296fc248aSBart Van Assche 	bool ret = false;
337396fc248aSBart Van Assche 
337496fc248aSBart Van Assche 	if (target->state == SRP_TARGET_REMOVED)
337596fc248aSBart Van Assche 		goto out;
337696fc248aSBart Van Assche 
337796fc248aSBart Van Assche 	ret = true;
337896fc248aSBart Van Assche 
337996fc248aSBart Van Assche 	spin_lock(&host->target_lock);
338096fc248aSBart Van Assche 	list_for_each_entry(t, &host->target_list, list) {
338196fc248aSBart Van Assche 		if (t != target &&
338296fc248aSBart Van Assche 		    target->id_ext == t->id_ext &&
338396fc248aSBart Van Assche 		    target->ioc_guid == t->ioc_guid &&
338496fc248aSBart Van Assche 		    target->initiator_ext == t->initiator_ext) {
338596fc248aSBart Van Assche 			ret = false;
338696fc248aSBart Van Assche 			break;
338796fc248aSBart Van Assche 		}
338896fc248aSBart Van Assche 	}
338996fc248aSBart Van Assche 	spin_unlock(&host->target_lock);
339096fc248aSBart Van Assche 
339196fc248aSBart Van Assche out:
339296fc248aSBart Van Assche 	return ret;
339396fc248aSBart Van Assche }
339496fc248aSBart Van Assche 
3395aef9ec39SRoland Dreier /*
3396aef9ec39SRoland Dreier  * Target ports are added by writing
3397aef9ec39SRoland Dreier  *
3398aef9ec39SRoland Dreier  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>,
3399aef9ec39SRoland Dreier  *     pkey=<P_Key>,service_id=<service ID>
340019f31343SBart Van Assche  * or
340119f31343SBart Van Assche  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,
340219f31343SBart Van Assche  *     [src=<IPv4 address>,]dest=<IPv4 address>:<port number>
3403aef9ec39SRoland Dreier  *
3404aef9ec39SRoland Dreier  * to the add_target sysfs attribute.
3405aef9ec39SRoland Dreier  */
3406aef9ec39SRoland Dreier enum {
3407aef9ec39SRoland Dreier 	SRP_OPT_ERR		= 0,
3408aef9ec39SRoland Dreier 	SRP_OPT_ID_EXT		= 1 << 0,
3409aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	= 1 << 1,
3410aef9ec39SRoland Dreier 	SRP_OPT_DGID		= 1 << 2,
3411aef9ec39SRoland Dreier 	SRP_OPT_PKEY		= 1 << 3,
3412aef9ec39SRoland Dreier 	SRP_OPT_SERVICE_ID	= 1 << 4,
3413aef9ec39SRoland Dreier 	SRP_OPT_MAX_SECT	= 1 << 5,
341452fb2b50SVu Pham 	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
34150c0450dbSRamachandra K 	SRP_OPT_IO_CLASS	= 1 << 7,
341601cb9bcbSIshai Rabinovitz 	SRP_OPT_INITIATOR_EXT	= 1 << 8,
341749248644SDavid Dillow 	SRP_OPT_CMD_SG_ENTRIES	= 1 << 9,
3418c07d424dSDavid Dillow 	SRP_OPT_ALLOW_EXT_SG	= 1 << 10,
3419c07d424dSDavid Dillow 	SRP_OPT_SG_TABLESIZE	= 1 << 11,
34204b5e5f41SBart Van Assche 	SRP_OPT_COMP_VECTOR	= 1 << 12,
34217bb312e4SVu Pham 	SRP_OPT_TL_RETRY_COUNT	= 1 << 13,
34224d73f95fSBart Van Assche 	SRP_OPT_QUEUE_SIZE	= 1 << 14,
342319f31343SBart Van Assche 	SRP_OPT_IP_SRC		= 1 << 15,
342419f31343SBart Van Assche 	SRP_OPT_IP_DEST		= 1 << 16,
3425b0780ee5SBart Van Assche 	SRP_OPT_TARGET_CAN_QUEUE= 1 << 17,
3426547ed331SHonggang Li 	SRP_OPT_MAX_IT_IU_SIZE  = 1 << 18,
342719f31343SBart Van Assche };
342819f31343SBart Van Assche 
342919f31343SBart Van Assche static unsigned int srp_opt_mandatory[] = {
343019f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
3431aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	|
3432aef9ec39SRoland Dreier 	SRP_OPT_DGID		|
3433aef9ec39SRoland Dreier 	SRP_OPT_PKEY		|
343419f31343SBart Van Assche 	SRP_OPT_SERVICE_ID,
343519f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
343619f31343SBart Van Assche 	SRP_OPT_IOC_GUID	|
343719f31343SBart Van Assche 	SRP_OPT_IP_DEST,
3438aef9ec39SRoland Dreier };
3439aef9ec39SRoland Dreier 
3440a447c093SSteven Whitehouse static const match_table_t srp_opt_tokens = {
3441aef9ec39SRoland Dreier 	{ SRP_OPT_ID_EXT,		"id_ext=%s" 		},
3442aef9ec39SRoland Dreier 	{ SRP_OPT_IOC_GUID,		"ioc_guid=%s" 		},
3443aef9ec39SRoland Dreier 	{ SRP_OPT_DGID,			"dgid=%s" 		},
3444aef9ec39SRoland Dreier 	{ SRP_OPT_PKEY,			"pkey=%x" 		},
3445aef9ec39SRoland Dreier 	{ SRP_OPT_SERVICE_ID,		"service_id=%s"		},
3446aef9ec39SRoland Dreier 	{ SRP_OPT_MAX_SECT,		"max_sect=%d" 		},
344752fb2b50SVu Pham 	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
3448b0780ee5SBart Van Assche 	{ SRP_OPT_TARGET_CAN_QUEUE,	"target_can_queue=%d"	},
34490c0450dbSRamachandra K 	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
345001cb9bcbSIshai Rabinovitz 	{ SRP_OPT_INITIATOR_EXT,	"initiator_ext=%s"	},
345149248644SDavid Dillow 	{ SRP_OPT_CMD_SG_ENTRIES,	"cmd_sg_entries=%u"	},
3452c07d424dSDavid Dillow 	{ SRP_OPT_ALLOW_EXT_SG,		"allow_ext_sg=%u"	},
3453c07d424dSDavid Dillow 	{ SRP_OPT_SG_TABLESIZE,		"sg_tablesize=%u"	},
34544b5e5f41SBart Van Assche 	{ SRP_OPT_COMP_VECTOR,		"comp_vector=%u"	},
34557bb312e4SVu Pham 	{ SRP_OPT_TL_RETRY_COUNT,	"tl_retry_count=%u"	},
34564d73f95fSBart Van Assche 	{ SRP_OPT_QUEUE_SIZE,		"queue_size=%d"		},
345719f31343SBart Van Assche 	{ SRP_OPT_IP_SRC,		"src=%s"		},
345819f31343SBart Van Assche 	{ SRP_OPT_IP_DEST,		"dest=%s"		},
3459547ed331SHonggang Li 	{ SRP_OPT_MAX_IT_IU_SIZE,	"max_it_iu_size=%d"	},
3460aef9ec39SRoland Dreier 	{ SRP_OPT_ERR,			NULL 			}
3461aef9ec39SRoland Dreier };
3462aef9ec39SRoland Dreier 
3463c62adb7dSBart Van Assche /**
3464c62adb7dSBart Van Assche  * srp_parse_in - parse an IP address and port number combination
3465e37df2d5SBart Van Assche  * @net:	   [in]  Network namespace.
3466e37df2d5SBart Van Assche  * @sa:		   [out] Address family, IP address and port number.
3467e37df2d5SBart Van Assche  * @addr_port_str: [in]  IP address and port number.
3468bcef5b72SBart Van Assche  * @has_port:	   [out] Whether or not @addr_port_str includes a port number.
3469c62adb7dSBart Van Assche  *
3470c62adb7dSBart Van Assche  * Parse the following address formats:
3471c62adb7dSBart Van Assche  * - IPv4: <ip_address>:<port>, e.g. 1.2.3.4:5.
3472c62adb7dSBart Van Assche  * - IPv6: \[<ipv6_address>\]:<port>, e.g. [1::2:3%4]:5.
3473c62adb7dSBart Van Assche  */
347419f31343SBart Van Assche static int srp_parse_in(struct net *net, struct sockaddr_storage *sa,
3475bcef5b72SBart Van Assche 			const char *addr_port_str, bool *has_port)
347619f31343SBart Van Assche {
3477c62adb7dSBart Van Assche 	char *addr_end, *addr = kstrdup(addr_port_str, GFP_KERNEL);
3478c62adb7dSBart Van Assche 	char *port_str;
347919f31343SBart Van Assche 	int ret;
348019f31343SBart Van Assche 
348119f31343SBart Van Assche 	if (!addr)
348219f31343SBart Van Assche 		return -ENOMEM;
3483c62adb7dSBart Van Assche 	port_str = strrchr(addr, ':');
3484bcef5b72SBart Van Assche 	if (port_str && strchr(port_str, ']'))
3485bcef5b72SBart Van Assche 		port_str = NULL;
3486bcef5b72SBart Van Assche 	if (port_str)
3487c62adb7dSBart Van Assche 		*port_str++ = '\0';
3488bcef5b72SBart Van Assche 	if (has_port)
3489bcef5b72SBart Van Assche 		*has_port = port_str != NULL;
3490c62adb7dSBart Van Assche 	ret = inet_pton_with_scope(net, AF_INET, addr, port_str, sa);
3491c62adb7dSBart Van Assche 	if (ret && addr[0]) {
3492c62adb7dSBart Van Assche 		addr_end = addr + strlen(addr) - 1;
3493c62adb7dSBart Van Assche 		if (addr[0] == '[' && *addr_end == ']') {
3494c62adb7dSBart Van Assche 			*addr_end = '\0';
3495c62adb7dSBart Van Assche 			ret = inet_pton_with_scope(net, AF_INET6, addr + 1,
3496c62adb7dSBart Van Assche 						   port_str, sa);
3497c62adb7dSBart Van Assche 		}
3498c62adb7dSBart Van Assche 	}
349919f31343SBart Van Assche 	kfree(addr);
3500c62adb7dSBart Van Assche 	pr_debug("%s -> %pISpfsc\n", addr_port_str, sa);
350119f31343SBart Van Assche 	return ret;
350219f31343SBart Van Assche }
350319f31343SBart Van Assche 
350419f31343SBart Van Assche static int srp_parse_options(struct net *net, const char *buf,
350519f31343SBart Van Assche 			     struct srp_target_port *target)
3506aef9ec39SRoland Dreier {
3507aef9ec39SRoland Dreier 	char *options, *sep_opt;
3508aef9ec39SRoland Dreier 	char *p;
3509aef9ec39SRoland Dreier 	substring_t args[MAX_OPT_ARGS];
35102a174df0SBart Van Assche 	unsigned long long ull;
3511bcef5b72SBart Van Assche 	bool has_port;
3512aef9ec39SRoland Dreier 	int opt_mask = 0;
3513aef9ec39SRoland Dreier 	int token;
3514aef9ec39SRoland Dreier 	int ret = -EINVAL;
3515aef9ec39SRoland Dreier 	int i;
3516aef9ec39SRoland Dreier 
3517aef9ec39SRoland Dreier 	options = kstrdup(buf, GFP_KERNEL);
3518aef9ec39SRoland Dreier 	if (!options)
3519aef9ec39SRoland Dreier 		return -ENOMEM;
3520aef9ec39SRoland Dreier 
3521aef9ec39SRoland Dreier 	sep_opt = options;
35227dcf9c19SSagi Grimberg 	while ((p = strsep(&sep_opt, ",\n")) != NULL) {
3523aef9ec39SRoland Dreier 		if (!*p)
3524aef9ec39SRoland Dreier 			continue;
3525aef9ec39SRoland Dreier 
3526aef9ec39SRoland Dreier 		token = match_token(p, srp_opt_tokens, args);
3527aef9ec39SRoland Dreier 		opt_mask |= token;
3528aef9ec39SRoland Dreier 
3529aef9ec39SRoland Dreier 		switch (token) {
3530aef9ec39SRoland Dreier 		case SRP_OPT_ID_EXT:
3531aef9ec39SRoland Dreier 			p = match_strdup(args);
3532a20f3a6dSIshai Rabinovitz 			if (!p) {
3533a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3534a20f3a6dSIshai Rabinovitz 				goto out;
3535a20f3a6dSIshai Rabinovitz 			}
35362a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35372a174df0SBart Van Assche 			if (ret) {
35382a174df0SBart Van Assche 				pr_warn("invalid id_ext parameter '%s'\n", p);
35392a174df0SBart Van Assche 				kfree(p);
35402a174df0SBart Van Assche 				goto out;
35412a174df0SBart Van Assche 			}
35422a174df0SBart Van Assche 			target->id_ext = cpu_to_be64(ull);
3543aef9ec39SRoland Dreier 			kfree(p);
3544aef9ec39SRoland Dreier 			break;
3545aef9ec39SRoland Dreier 
3546aef9ec39SRoland Dreier 		case SRP_OPT_IOC_GUID:
3547aef9ec39SRoland Dreier 			p = match_strdup(args);
3548a20f3a6dSIshai Rabinovitz 			if (!p) {
3549a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3550a20f3a6dSIshai Rabinovitz 				goto out;
3551a20f3a6dSIshai Rabinovitz 			}
35522a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35532a174df0SBart Van Assche 			if (ret) {
35542a174df0SBart Van Assche 				pr_warn("invalid ioc_guid parameter '%s'\n", p);
35552a174df0SBart Van Assche 				kfree(p);
35562a174df0SBart Van Assche 				goto out;
35572a174df0SBart Van Assche 			}
35582a174df0SBart Van Assche 			target->ioc_guid = cpu_to_be64(ull);
3559aef9ec39SRoland Dreier 			kfree(p);
3560aef9ec39SRoland Dreier 			break;
3561aef9ec39SRoland Dreier 
3562aef9ec39SRoland Dreier 		case SRP_OPT_DGID:
3563aef9ec39SRoland Dreier 			p = match_strdup(args);
3564a20f3a6dSIshai Rabinovitz 			if (!p) {
3565a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3566a20f3a6dSIshai Rabinovitz 				goto out;
3567a20f3a6dSIshai Rabinovitz 			}
3568aef9ec39SRoland Dreier 			if (strlen(p) != 32) {
3569e0bda7d8SBart Van Assche 				pr_warn("bad dest GID parameter '%s'\n", p);
3570ce1823f0SRoland Dreier 				kfree(p);
3571aef9ec39SRoland Dreier 				goto out;
3572aef9ec39SRoland Dreier 			}
3573aef9ec39SRoland Dreier 
357419f31343SBart Van Assche 			ret = hex2bin(target->ib_cm.orig_dgid.raw, p, 16);
3575747fe000SBart Van Assche 			kfree(p);
3576e711f968SAndy Shevchenko 			if (ret < 0)
3577747fe000SBart Van Assche 				goto out;
3578aef9ec39SRoland Dreier 			break;
3579aef9ec39SRoland Dreier 
3580aef9ec39SRoland Dreier 		case SRP_OPT_PKEY:
3581aef9ec39SRoland Dreier 			if (match_hex(args, &token)) {
3582e0bda7d8SBart Van Assche 				pr_warn("bad P_Key parameter '%s'\n", p);
3583aef9ec39SRoland Dreier 				goto out;
3584aef9ec39SRoland Dreier 			}
358519f31343SBart Van Assche 			target->ib_cm.pkey = cpu_to_be16(token);
3586aef9ec39SRoland Dreier 			break;
3587aef9ec39SRoland Dreier 
3588aef9ec39SRoland Dreier 		case SRP_OPT_SERVICE_ID:
3589aef9ec39SRoland Dreier 			p = match_strdup(args);
3590a20f3a6dSIshai Rabinovitz 			if (!p) {
3591a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3592a20f3a6dSIshai Rabinovitz 				goto out;
3593a20f3a6dSIshai Rabinovitz 			}
35942a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35952a174df0SBart Van Assche 			if (ret) {
35962a174df0SBart Van Assche 				pr_warn("bad service_id parameter '%s'\n", p);
35972a174df0SBart Van Assche 				kfree(p);
35982a174df0SBart Van Assche 				goto out;
35992a174df0SBart Van Assche 			}
360019f31343SBart Van Assche 			target->ib_cm.service_id = cpu_to_be64(ull);
360119f31343SBart Van Assche 			kfree(p);
360219f31343SBart Van Assche 			break;
360319f31343SBart Van Assche 
360419f31343SBart Van Assche 		case SRP_OPT_IP_SRC:
360519f31343SBart Van Assche 			p = match_strdup(args);
360619f31343SBart Van Assche 			if (!p) {
360719f31343SBart Van Assche 				ret = -ENOMEM;
360819f31343SBart Van Assche 				goto out;
360919f31343SBart Van Assche 			}
3610bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.src.ss, p,
3611bcef5b72SBart Van Assche 					   NULL);
361219f31343SBart Van Assche 			if (ret < 0) {
361319f31343SBart Van Assche 				pr_warn("bad source parameter '%s'\n", p);
361419f31343SBart Van Assche 				kfree(p);
361519f31343SBart Van Assche 				goto out;
361619f31343SBart Van Assche 			}
361719f31343SBart Van Assche 			target->rdma_cm.src_specified = true;
361819f31343SBart Van Assche 			kfree(p);
361919f31343SBart Van Assche 			break;
362019f31343SBart Van Assche 
362119f31343SBart Van Assche 		case SRP_OPT_IP_DEST:
362219f31343SBart Van Assche 			p = match_strdup(args);
362319f31343SBart Van Assche 			if (!p) {
362419f31343SBart Van Assche 				ret = -ENOMEM;
362519f31343SBart Van Assche 				goto out;
362619f31343SBart Van Assche 			}
3627bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.dst.ss, p,
3628bcef5b72SBart Van Assche 					   &has_port);
3629bcef5b72SBart Van Assche 			if (!has_port)
3630bcef5b72SBart Van Assche 				ret = -EINVAL;
363119f31343SBart Van Assche 			if (ret < 0) {
363219f31343SBart Van Assche 				pr_warn("bad dest parameter '%s'\n", p);
363319f31343SBart Van Assche 				kfree(p);
363419f31343SBart Van Assche 				goto out;
363519f31343SBart Van Assche 			}
363619f31343SBart Van Assche 			target->using_rdma_cm = true;
3637aef9ec39SRoland Dreier 			kfree(p);
3638aef9ec39SRoland Dreier 			break;
3639aef9ec39SRoland Dreier 
3640aef9ec39SRoland Dreier 		case SRP_OPT_MAX_SECT:
3641aef9ec39SRoland Dreier 			if (match_int(args, &token)) {
3642e0bda7d8SBart Van Assche 				pr_warn("bad max sect parameter '%s'\n", p);
3643aef9ec39SRoland Dreier 				goto out;
3644aef9ec39SRoland Dreier 			}
3645aef9ec39SRoland Dreier 			target->scsi_host->max_sectors = token;
3646aef9ec39SRoland Dreier 			break;
3647aef9ec39SRoland Dreier 
36484d73f95fSBart Van Assche 		case SRP_OPT_QUEUE_SIZE:
36494d73f95fSBart Van Assche 			if (match_int(args, &token) || token < 1) {
36504d73f95fSBart Van Assche 				pr_warn("bad queue_size parameter '%s'\n", p);
36514d73f95fSBart Van Assche 				goto out;
36524d73f95fSBart Van Assche 			}
36534d73f95fSBart Van Assche 			target->scsi_host->can_queue = token;
36544d73f95fSBart Van Assche 			target->queue_size = token + SRP_RSP_SQ_SIZE +
36554d73f95fSBart Van Assche 					     SRP_TSK_MGMT_SQ_SIZE;
36564d73f95fSBart Van Assche 			if (!(opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
36574d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun = token;
36584d73f95fSBart Van Assche 			break;
36594d73f95fSBart Van Assche 
366052fb2b50SVu Pham 		case SRP_OPT_MAX_CMD_PER_LUN:
36614d73f95fSBart Van Assche 			if (match_int(args, &token) || token < 1) {
3662e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_per_lun parameter '%s'\n",
3663e0bda7d8SBart Van Assche 					p);
366452fb2b50SVu Pham 				goto out;
366552fb2b50SVu Pham 			}
36664d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun = token;
366752fb2b50SVu Pham 			break;
366852fb2b50SVu Pham 
3669b0780ee5SBart Van Assche 		case SRP_OPT_TARGET_CAN_QUEUE:
3670b0780ee5SBart Van Assche 			if (match_int(args, &token) || token < 1) {
3671b0780ee5SBart Van Assche 				pr_warn("bad max target_can_queue parameter '%s'\n",
3672b0780ee5SBart Van Assche 					p);
3673b0780ee5SBart Van Assche 				goto out;
3674b0780ee5SBart Van Assche 			}
3675b0780ee5SBart Van Assche 			target->target_can_queue = token;
3676b0780ee5SBart Van Assche 			break;
3677b0780ee5SBart Van Assche 
36780c0450dbSRamachandra K 		case SRP_OPT_IO_CLASS:
36790c0450dbSRamachandra K 			if (match_hex(args, &token)) {
3680e0bda7d8SBart Van Assche 				pr_warn("bad IO class parameter '%s'\n", p);
36810c0450dbSRamachandra K 				goto out;
36820c0450dbSRamachandra K 			}
36830c0450dbSRamachandra K 			if (token != SRP_REV10_IB_IO_CLASS &&
36840c0450dbSRamachandra K 			    token != SRP_REV16A_IB_IO_CLASS) {
3685e0bda7d8SBart Van Assche 				pr_warn("unknown IO class parameter value %x specified (use %x or %x).\n",
3686e0bda7d8SBart Van Assche 					token, SRP_REV10_IB_IO_CLASS,
3687e0bda7d8SBart Van Assche 					SRP_REV16A_IB_IO_CLASS);
36880c0450dbSRamachandra K 				goto out;
36890c0450dbSRamachandra K 			}
36900c0450dbSRamachandra K 			target->io_class = token;
36910c0450dbSRamachandra K 			break;
36920c0450dbSRamachandra K 
369301cb9bcbSIshai Rabinovitz 		case SRP_OPT_INITIATOR_EXT:
369401cb9bcbSIshai Rabinovitz 			p = match_strdup(args);
3695a20f3a6dSIshai Rabinovitz 			if (!p) {
3696a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3697a20f3a6dSIshai Rabinovitz 				goto out;
3698a20f3a6dSIshai Rabinovitz 			}
36992a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
37002a174df0SBart Van Assche 			if (ret) {
37012a174df0SBart Van Assche 				pr_warn("bad initiator_ext value '%s'\n", p);
37022a174df0SBart Van Assche 				kfree(p);
37032a174df0SBart Van Assche 				goto out;
37042a174df0SBart Van Assche 			}
37052a174df0SBart Van Assche 			target->initiator_ext = cpu_to_be64(ull);
370601cb9bcbSIshai Rabinovitz 			kfree(p);
370701cb9bcbSIshai Rabinovitz 			break;
370801cb9bcbSIshai Rabinovitz 
370949248644SDavid Dillow 		case SRP_OPT_CMD_SG_ENTRIES:
371049248644SDavid Dillow 			if (match_int(args, &token) || token < 1 || token > 255) {
3711e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_sg_entries parameter '%s'\n",
3712e0bda7d8SBart Van Assche 					p);
371349248644SDavid Dillow 				goto out;
371449248644SDavid Dillow 			}
371549248644SDavid Dillow 			target->cmd_sg_cnt = token;
371649248644SDavid Dillow 			break;
371749248644SDavid Dillow 
3718c07d424dSDavid Dillow 		case SRP_OPT_ALLOW_EXT_SG:
3719c07d424dSDavid Dillow 			if (match_int(args, &token)) {
3720e0bda7d8SBart Van Assche 				pr_warn("bad allow_ext_sg parameter '%s'\n", p);
3721c07d424dSDavid Dillow 				goto out;
3722c07d424dSDavid Dillow 			}
3723c07d424dSDavid Dillow 			target->allow_ext_sg = !!token;
3724c07d424dSDavid Dillow 			break;
3725c07d424dSDavid Dillow 
3726c07d424dSDavid Dillow 		case SRP_OPT_SG_TABLESIZE:
3727c07d424dSDavid Dillow 			if (match_int(args, &token) || token < 1 ||
372865e8617fSMing Lin 					token > SG_MAX_SEGMENTS) {
3729e0bda7d8SBart Van Assche 				pr_warn("bad max sg_tablesize parameter '%s'\n",
3730e0bda7d8SBart Van Assche 					p);
3731c07d424dSDavid Dillow 				goto out;
3732c07d424dSDavid Dillow 			}
3733c07d424dSDavid Dillow 			target->sg_tablesize = token;
3734c07d424dSDavid Dillow 			break;
3735c07d424dSDavid Dillow 
37364b5e5f41SBart Van Assche 		case SRP_OPT_COMP_VECTOR:
37374b5e5f41SBart Van Assche 			if (match_int(args, &token) || token < 0) {
37384b5e5f41SBart Van Assche 				pr_warn("bad comp_vector parameter '%s'\n", p);
37394b5e5f41SBart Van Assche 				goto out;
37404b5e5f41SBart Van Assche 			}
37414b5e5f41SBart Van Assche 			target->comp_vector = token;
37424b5e5f41SBart Van Assche 			break;
37434b5e5f41SBart Van Assche 
37447bb312e4SVu Pham 		case SRP_OPT_TL_RETRY_COUNT:
37457bb312e4SVu Pham 			if (match_int(args, &token) || token < 2 || token > 7) {
37467bb312e4SVu Pham 				pr_warn("bad tl_retry_count parameter '%s' (must be a number between 2 and 7)\n",
37477bb312e4SVu Pham 					p);
37487bb312e4SVu Pham 				goto out;
37497bb312e4SVu Pham 			}
37507bb312e4SVu Pham 			target->tl_retry_count = token;
37517bb312e4SVu Pham 			break;
37527bb312e4SVu Pham 
3753547ed331SHonggang Li 		case SRP_OPT_MAX_IT_IU_SIZE:
3754547ed331SHonggang Li 			if (match_int(args, &token) || token < 0) {
3755547ed331SHonggang Li 				pr_warn("bad maximum initiator to target IU size '%s'\n", p);
3756547ed331SHonggang Li 				goto out;
3757547ed331SHonggang Li 			}
3758547ed331SHonggang Li 			target->max_it_iu_size = token;
3759547ed331SHonggang Li 			break;
3760547ed331SHonggang Li 
3761aef9ec39SRoland Dreier 		default:
3762e0bda7d8SBart Van Assche 			pr_warn("unknown parameter or missing value '%s' in target creation request\n",
3763e0bda7d8SBart Van Assche 				p);
3764aef9ec39SRoland Dreier 			goto out;
3765aef9ec39SRoland Dreier 		}
3766aef9ec39SRoland Dreier 	}
3767aef9ec39SRoland Dreier 
376819f31343SBart Van Assche 	for (i = 0; i < ARRAY_SIZE(srp_opt_mandatory); i++) {
376919f31343SBart Van Assche 		if ((opt_mask & srp_opt_mandatory[i]) == srp_opt_mandatory[i]) {
3770aef9ec39SRoland Dreier 			ret = 0;
377119f31343SBart Van Assche 			break;
377219f31343SBart Van Assche 		}
377319f31343SBart Van Assche 	}
377419f31343SBart Van Assche 	if (ret)
377519f31343SBart Van Assche 		pr_warn("target creation request is missing one or more parameters\n");
3776aef9ec39SRoland Dreier 
37774d73f95fSBart Van Assche 	if (target->scsi_host->cmd_per_lun > target->scsi_host->can_queue
37784d73f95fSBart Van Assche 	    && (opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
37794d73f95fSBart Van Assche 		pr_warn("cmd_per_lun = %d > queue_size = %d\n",
37804d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun,
37814d73f95fSBart Van Assche 			target->scsi_host->can_queue);
37824d73f95fSBart Van Assche 
3783aef9ec39SRoland Dreier out:
3784aef9ec39SRoland Dreier 	kfree(options);
3785aef9ec39SRoland Dreier 	return ret;
3786aef9ec39SRoland Dreier }
3787aef9ec39SRoland Dreier 
3788ee959b00STony Jones static ssize_t srp_create_target(struct device *dev,
3789ee959b00STony Jones 				 struct device_attribute *attr,
3790aef9ec39SRoland Dreier 				 const char *buf, size_t count)
3791aef9ec39SRoland Dreier {
3792aef9ec39SRoland Dreier 	struct srp_host *host =
3793ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3794aef9ec39SRoland Dreier 	struct Scsi_Host *target_host;
3795aef9ec39SRoland Dreier 	struct srp_target_port *target;
3796509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
3797d1b4289eSBart Van Assche 	struct srp_device *srp_dev = host->srp_dev;
3798d1b4289eSBart Van Assche 	struct ib_device *ibdev = srp_dev->dev;
3799d92c0da7SBart Van Assche 	int ret, node_idx, node, cpu, i;
3800509c5f33SBart Van Assche 	unsigned int max_sectors_per_mr, mr_per_cmd = 0;
3801d92c0da7SBart Van Assche 	bool multich = false;
3802513d5647SBart Van Assche 	uint32_t max_iu_len;
3803aef9ec39SRoland Dreier 
3804aef9ec39SRoland Dreier 	target_host = scsi_host_alloc(&srp_template,
3805aef9ec39SRoland Dreier 				      sizeof (struct srp_target_port));
3806aef9ec39SRoland Dreier 	if (!target_host)
3807aef9ec39SRoland Dreier 		return -ENOMEM;
3808aef9ec39SRoland Dreier 
38093236822bSFUJITA Tomonori 	target_host->transportt  = ib_srp_transport_template;
3810fd1b6c4aSBart Van Assche 	target_host->max_channel = 0;
3811fd1b6c4aSBart Van Assche 	target_host->max_id      = 1;
3812985aa495SBart Van Assche 	target_host->max_lun     = -1LL;
38133c8edf0eSArne Redlich 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
38140b5cb330SBart Van Assche 	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
38155f068992SRoland Dreier 
38168c175d31SChristoph Hellwig 	if (!(ibdev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG))
38178c175d31SChristoph Hellwig 		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
38188c175d31SChristoph Hellwig 
3819aef9ec39SRoland Dreier 	target = host_to_target(target_host);
3820aef9ec39SRoland Dreier 
382119f31343SBart Van Assche 	target->net		= kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
38220c0450dbSRamachandra K 	target->io_class	= SRP_REV16A_IB_IO_CLASS;
3823aef9ec39SRoland Dreier 	target->scsi_host	= target_host;
3824aef9ec39SRoland Dreier 	target->srp_host	= host;
3825e6bf5f48SJason Gunthorpe 	target->lkey		= host->srp_dev->pd->local_dma_lkey;
3826cee687b6SBart Van Assche 	target->global_rkey	= host->srp_dev->global_rkey;
382749248644SDavid Dillow 	target->cmd_sg_cnt	= cmd_sg_entries;
3828c07d424dSDavid Dillow 	target->sg_tablesize	= indirect_sg_entries ? : cmd_sg_entries;
3829c07d424dSDavid Dillow 	target->allow_ext_sg	= allow_ext_sg;
38307bb312e4SVu Pham 	target->tl_retry_count	= 7;
38314d73f95fSBart Van Assche 	target->queue_size	= SRP_DEFAULT_QUEUE_SIZE;
3832aef9ec39SRoland Dreier 
383334aa654eSBart Van Assche 	/*
383434aa654eSBart Van Assche 	 * Avoid that the SCSI host can be removed by srp_remove_target()
383534aa654eSBart Van Assche 	 * before this function returns.
383634aa654eSBart Van Assche 	 */
383734aa654eSBart Van Assche 	scsi_host_get(target->scsi_host);
383834aa654eSBart Van Assche 
38394fa354c9SBart Van Assche 	ret = mutex_lock_interruptible(&host->add_target_mutex);
38404fa354c9SBart Van Assche 	if (ret < 0)
38414fa354c9SBart Van Assche 		goto put;
38422d7091bcSBart Van Assche 
384319f31343SBart Van Assche 	ret = srp_parse_options(target->net, buf, target);
3844aef9ec39SRoland Dreier 	if (ret)
3845fb49c8bbSBart Van Assche 		goto out;
3846aef9ec39SRoland Dreier 
38474d73f95fSBart Van Assche 	target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
38484d73f95fSBart Van Assche 
384996fc248aSBart Van Assche 	if (!srp_conn_unique(target->srp_host, target)) {
385019f31343SBart Van Assche 		if (target->using_rdma_cm) {
385119f31343SBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
38527da09af9SBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;dest=%pIS\n",
385319f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
385419f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
38557da09af9SBart Van Assche 				     &target->rdma_cm.dst);
385619f31343SBart Van Assche 		} else {
385796fc248aSBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
385896fc248aSBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n",
385996fc248aSBart Van Assche 				     be64_to_cpu(target->id_ext),
386096fc248aSBart Van Assche 				     be64_to_cpu(target->ioc_guid),
386196fc248aSBart Van Assche 				     be64_to_cpu(target->initiator_ext));
386219f31343SBart Van Assche 		}
386396fc248aSBart Van Assche 		ret = -EEXIST;
3864fb49c8bbSBart Van Assche 		goto out;
386596fc248aSBart Van Assche 	}
386696fc248aSBart Van Assche 
38675cfb1782SBart Van Assche 	if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg &&
3868c07d424dSDavid Dillow 	    target->cmd_sg_cnt < target->sg_tablesize) {
38695cfb1782SBart Van Assche 		pr_warn("No MR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
3870c07d424dSDavid Dillow 		target->sg_tablesize = target->cmd_sg_cnt;
3871c07d424dSDavid Dillow 	}
3872c07d424dSDavid Dillow 
3873509c5f33SBart Van Assche 	if (srp_dev->use_fast_reg || srp_dev->use_fmr) {
3874fbd36818SSergey Gorenko 		bool gaps_reg = (ibdev->attrs.device_cap_flags &
3875fbd36818SSergey Gorenko 				 IB_DEVICE_SG_GAPS_REG);
3876fbd36818SSergey Gorenko 
3877509c5f33SBart Van Assche 		max_sectors_per_mr = srp_dev->max_pages_per_mr <<
3878509c5f33SBart Van Assche 				  (ilog2(srp_dev->mr_page_size) - 9);
3879fbd36818SSergey Gorenko 		if (!gaps_reg) {
3880fbd36818SSergey Gorenko 			/*
3881fbd36818SSergey Gorenko 			 * FR and FMR can only map one HCA page per entry. If
3882fbd36818SSergey Gorenko 			 * the start address is not aligned on a HCA page
3883fbd36818SSergey Gorenko 			 * boundary two entries will be used for the head and
3884fbd36818SSergey Gorenko 			 * the tail although these two entries combined
3885fbd36818SSergey Gorenko 			 * contain at most one HCA page of data. Hence the "+
3886fbd36818SSergey Gorenko 			 * 1" in the calculation below.
3887fbd36818SSergey Gorenko 			 *
3888fbd36818SSergey Gorenko 			 * The indirect data buffer descriptor is contiguous
3889fbd36818SSergey Gorenko 			 * so the memory for that buffer will only be
3890fbd36818SSergey Gorenko 			 * registered if register_always is true. Hence add
3891fbd36818SSergey Gorenko 			 * one to mr_per_cmd if register_always has been set.
3892fbd36818SSergey Gorenko 			 */
3893509c5f33SBart Van Assche 			mr_per_cmd = register_always +
3894509c5f33SBart Van Assche 				(target->scsi_host->max_sectors + 1 +
3895509c5f33SBart Van Assche 				 max_sectors_per_mr - 1) / max_sectors_per_mr;
3896fbd36818SSergey Gorenko 		} else {
3897fbd36818SSergey Gorenko 			mr_per_cmd = register_always +
3898fbd36818SSergey Gorenko 				(target->sg_tablesize +
3899fbd36818SSergey Gorenko 				 srp_dev->max_pages_per_mr - 1) /
3900fbd36818SSergey Gorenko 				srp_dev->max_pages_per_mr;
3901fbd36818SSergey Gorenko 		}
3902509c5f33SBart Van Assche 		pr_debug("max_sectors = %u; max_pages_per_mr = %u; mr_page_size = %u; max_sectors_per_mr = %u; mr_per_cmd = %u\n",
3903fbd36818SSergey Gorenko 			 target->scsi_host->max_sectors, srp_dev->max_pages_per_mr, srp_dev->mr_page_size,
3904509c5f33SBart Van Assche 			 max_sectors_per_mr, mr_per_cmd);
3905509c5f33SBart Van Assche 	}
3906509c5f33SBart Van Assche 
3907c07d424dSDavid Dillow 	target_host->sg_tablesize = target->sg_tablesize;
3908509c5f33SBart Van Assche 	target->mr_pool_size = target->scsi_host->can_queue * mr_per_cmd;
3909509c5f33SBart Van Assche 	target->mr_per_cmd = mr_per_cmd;
3910c07d424dSDavid Dillow 	target->indirect_size = target->sg_tablesize *
3911c07d424dSDavid Dillow 				sizeof (struct srp_direct_buf);
3912b2e872f4SHonggang Li 	max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
3913b2e872f4SHonggang Li 				       srp_use_imm_data,
3914b2e872f4SHonggang Li 				       target->max_it_iu_size);
391549248644SDavid Dillow 
3916c1120f89SBart Van Assche 	INIT_WORK(&target->tl_err_work, srp_tl_err_work);
3917ef6c49d8SBart Van Assche 	INIT_WORK(&target->remove_work, srp_remove_work);
39188f26c9ffSDavid Dillow 	spin_lock_init(&target->lock);
39191dfce294SParav Pandit 	ret = rdma_query_gid(ibdev, host->port, 0, &target->sgid);
39202088ca66SSagi Grimberg 	if (ret)
3921fb49c8bbSBart Van Assche 		goto out;
3922d92c0da7SBart Van Assche 
3923d92c0da7SBart Van Assche 	ret = -ENOMEM;
3924d92c0da7SBart Van Assche 	target->ch_count = max_t(unsigned, num_online_nodes(),
3925d92c0da7SBart Van Assche 				 min(ch_count ? :
3926d92c0da7SBart Van Assche 				     min(4 * num_online_nodes(),
3927d92c0da7SBart Van Assche 					 ibdev->num_comp_vectors),
3928d92c0da7SBart Van Assche 				     num_online_cpus()));
3929d92c0da7SBart Van Assche 	target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
3930d92c0da7SBart Van Assche 			     GFP_KERNEL);
3931d92c0da7SBart Van Assche 	if (!target->ch)
3932fb49c8bbSBart Van Assche 		goto out;
3933d92c0da7SBart Van Assche 
3934d92c0da7SBart Van Assche 	node_idx = 0;
3935d92c0da7SBart Van Assche 	for_each_online_node(node) {
3936d92c0da7SBart Van Assche 		const int ch_start = (node_idx * target->ch_count /
3937d92c0da7SBart Van Assche 				      num_online_nodes());
3938d92c0da7SBart Van Assche 		const int ch_end = ((node_idx + 1) * target->ch_count /
3939d92c0da7SBart Van Assche 				    num_online_nodes());
39403a148896SBart Van Assche 		const int cv_start = node_idx * ibdev->num_comp_vectors /
39413a148896SBart Van Assche 				     num_online_nodes();
39423a148896SBart Van Assche 		const int cv_end = (node_idx + 1) * ibdev->num_comp_vectors /
39433a148896SBart Van Assche 				   num_online_nodes();
3944d92c0da7SBart Van Assche 		int cpu_idx = 0;
3945d92c0da7SBart Van Assche 
3946d92c0da7SBart Van Assche 		for_each_online_cpu(cpu) {
3947d92c0da7SBart Van Assche 			if (cpu_to_node(cpu) != node)
3948d92c0da7SBart Van Assche 				continue;
3949d92c0da7SBart Van Assche 			if (ch_start + cpu_idx >= ch_end)
3950d92c0da7SBart Van Assche 				continue;
3951d92c0da7SBart Van Assche 			ch = &target->ch[ch_start + cpu_idx];
3952d92c0da7SBart Van Assche 			ch->target = target;
3953d92c0da7SBart Van Assche 			ch->comp_vector = cv_start == cv_end ? cv_start :
3954d92c0da7SBart Van Assche 				cv_start + cpu_idx % (cv_end - cv_start);
3955d92c0da7SBart Van Assche 			spin_lock_init(&ch->lock);
3956d92c0da7SBart Van Assche 			INIT_LIST_HEAD(&ch->free_tx);
3957d92c0da7SBart Van Assche 			ret = srp_new_cm_id(ch);
3958d92c0da7SBart Van Assche 			if (ret)
3959d92c0da7SBart Van Assche 				goto err_disconnect;
3960aef9ec39SRoland Dreier 
3961509c07bcSBart Van Assche 			ret = srp_create_ch_ib(ch);
3962aef9ec39SRoland Dreier 			if (ret)
3963d92c0da7SBart Van Assche 				goto err_disconnect;
3964aef9ec39SRoland Dreier 
3965d92c0da7SBart Van Assche 			ret = srp_alloc_req_data(ch);
39669fe4bcf4SDavid Dillow 			if (ret)
3967d92c0da7SBart Van Assche 				goto err_disconnect;
3968aef9ec39SRoland Dreier 
3969513d5647SBart Van Assche 			ret = srp_connect_ch(ch, max_iu_len, multich);
3970aef9ec39SRoland Dreier 			if (ret) {
397119f31343SBart Van Assche 				char dst[64];
397219f31343SBart Van Assche 
397319f31343SBart Van Assche 				if (target->using_rdma_cm)
39747da09af9SBart Van Assche 					snprintf(dst, sizeof(dst), "%pIS",
39757da09af9SBart Van Assche 						 &target->rdma_cm.dst);
397619f31343SBart Van Assche 				else
397719f31343SBart Van Assche 					snprintf(dst, sizeof(dst), "%pI6",
397819f31343SBart Van Assche 						 target->ib_cm.orig_dgid.raw);
39797aa54bd7SDavid Dillow 				shost_printk(KERN_ERR, target->scsi_host,
398019f31343SBart Van Assche 					     PFX "Connection %d/%d to %s failed\n",
3981d92c0da7SBart Van Assche 					     ch_start + cpu_idx,
398219f31343SBart Van Assche 					     target->ch_count, dst);
3983d92c0da7SBart Van Assche 				if (node_idx == 0 && cpu_idx == 0) {
3984b02c1536SBart Van Assche 					goto free_ch;
3985d92c0da7SBart Van Assche 				} else {
3986d92c0da7SBart Van Assche 					srp_free_ch_ib(target, ch);
3987d92c0da7SBart Van Assche 					srp_free_req_data(target, ch);
3988d92c0da7SBart Van Assche 					target->ch_count = ch - target->ch;
3989c257ea6fSBart Van Assche 					goto connected;
3990aef9ec39SRoland Dreier 				}
3991d92c0da7SBart Van Assche 			}
3992d92c0da7SBart Van Assche 
3993d92c0da7SBart Van Assche 			multich = true;
3994d92c0da7SBart Van Assche 			cpu_idx++;
3995d92c0da7SBart Van Assche 		}
3996d92c0da7SBart Van Assche 		node_idx++;
3997d92c0da7SBart Van Assche 	}
3998d92c0da7SBart Van Assche 
3999c257ea6fSBart Van Assche connected:
4000d92c0da7SBart Van Assche 	target->scsi_host->nr_hw_queues = target->ch_count;
4001aef9ec39SRoland Dreier 
4002aef9ec39SRoland Dreier 	ret = srp_add_target(host, target);
4003aef9ec39SRoland Dreier 	if (ret)
4004aef9ec39SRoland Dreier 		goto err_disconnect;
4005aef9ec39SRoland Dreier 
400634aa654eSBart Van Assche 	if (target->state != SRP_TARGET_REMOVED) {
400719f31343SBart Van Assche 		if (target->using_rdma_cm) {
400819f31343SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
40097da09af9SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx sgid %pI6 dest %pIS\n",
401019f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
401119f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
40127da09af9SBart Van Assche 				     target->sgid.raw, &target->rdma_cm.dst);
401319f31343SBart Van Assche 		} else {
4014e7ffde01SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
4015e7ffde01SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
4016e7ffde01SBart Van Assche 				     be64_to_cpu(target->id_ext),
4017e7ffde01SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
401819f31343SBart Van Assche 				     be16_to_cpu(target->ib_cm.pkey),
401919f31343SBart Van Assche 				     be64_to_cpu(target->ib_cm.service_id),
402019f31343SBart Van Assche 				     target->sgid.raw,
402119f31343SBart Van Assche 				     target->ib_cm.orig_dgid.raw);
402219f31343SBart Van Assche 		}
402334aa654eSBart Van Assche 	}
4024e7ffde01SBart Van Assche 
40252d7091bcSBart Van Assche 	ret = count;
40262d7091bcSBart Van Assche 
40272d7091bcSBart Van Assche out:
40282d7091bcSBart Van Assche 	mutex_unlock(&host->add_target_mutex);
402934aa654eSBart Van Assche 
40304fa354c9SBart Van Assche put:
403134aa654eSBart Van Assche 	scsi_host_put(target->scsi_host);
403219f31343SBart Van Assche 	if (ret < 0) {
403319f31343SBart Van Assche 		/*
403419f31343SBart Van Assche 		 * If a call to srp_remove_target() has not been scheduled,
403519f31343SBart Van Assche 		 * drop the network namespace reference now that was obtained
403619f31343SBart Van Assche 		 * earlier in this function.
403719f31343SBart Van Assche 		 */
403819f31343SBart Van Assche 		if (target->state != SRP_TARGET_REMOVED)
403919f31343SBart Van Assche 			kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
4040bc44bd1dSBart Van Assche 		scsi_host_put(target->scsi_host);
404119f31343SBart Van Assche 	}
404234aa654eSBart Van Assche 
40432d7091bcSBart Van Assche 	return ret;
4044aef9ec39SRoland Dreier 
4045aef9ec39SRoland Dreier err_disconnect:
4046aef9ec39SRoland Dreier 	srp_disconnect_target(target);
4047aef9ec39SRoland Dreier 
4048b02c1536SBart Van Assche free_ch:
4049d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
4050d92c0da7SBart Van Assche 		ch = &target->ch[i];
4051509c07bcSBart Van Assche 		srp_free_ch_ib(target, ch);
4052509c07bcSBart Van Assche 		srp_free_req_data(target, ch);
4053d92c0da7SBart Van Assche 	}
4054d92c0da7SBart Van Assche 
4055d92c0da7SBart Van Assche 	kfree(target->ch);
40562d7091bcSBart Van Assche 	goto out;
4057aef9ec39SRoland Dreier }
4058aef9ec39SRoland Dreier 
4059ee959b00STony Jones static DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
4060aef9ec39SRoland Dreier 
4061ee959b00STony Jones static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
4062ee959b00STony Jones 			  char *buf)
4063aef9ec39SRoland Dreier {
4064ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
4065aef9ec39SRoland Dreier 
40666c854111SJason Gunthorpe 	return sprintf(buf, "%s\n", dev_name(&host->srp_dev->dev->dev));
4067aef9ec39SRoland Dreier }
4068aef9ec39SRoland Dreier 
4069ee959b00STony Jones static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
4070aef9ec39SRoland Dreier 
4071ee959b00STony Jones static ssize_t show_port(struct device *dev, struct device_attribute *attr,
4072ee959b00STony Jones 			 char *buf)
4073aef9ec39SRoland Dreier {
4074ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
4075aef9ec39SRoland Dreier 
4076aef9ec39SRoland Dreier 	return sprintf(buf, "%d\n", host->port);
4077aef9ec39SRoland Dreier }
4078aef9ec39SRoland Dreier 
4079ee959b00STony Jones static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
4080aef9ec39SRoland Dreier 
4081f5358a17SRoland Dreier static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
4082aef9ec39SRoland Dreier {
4083aef9ec39SRoland Dreier 	struct srp_host *host;
4084aef9ec39SRoland Dreier 
4085aef9ec39SRoland Dreier 	host = kzalloc(sizeof *host, GFP_KERNEL);
4086aef9ec39SRoland Dreier 	if (!host)
4087aef9ec39SRoland Dreier 		return NULL;
4088aef9ec39SRoland Dreier 
4089aef9ec39SRoland Dreier 	INIT_LIST_HEAD(&host->target_list);
4090b3589fd4SMatthew Wilcox 	spin_lock_init(&host->target_lock);
4091aef9ec39SRoland Dreier 	init_completion(&host->released);
40922d7091bcSBart Van Assche 	mutex_init(&host->add_target_mutex);
409305321937SGreg Kroah-Hartman 	host->srp_dev = device;
4094aef9ec39SRoland Dreier 	host->port = port;
4095aef9ec39SRoland Dreier 
4096ee959b00STony Jones 	host->dev.class = &srp_class;
4097dee2b82aSBart Van Assche 	host->dev.parent = device->dev->dev.parent;
40986c854111SJason Gunthorpe 	dev_set_name(&host->dev, "srp-%s-%d", dev_name(&device->dev->dev),
40996c854111SJason Gunthorpe 		     port);
4100aef9ec39SRoland Dreier 
4101ee959b00STony Jones 	if (device_register(&host->dev))
4102f5358a17SRoland Dreier 		goto free_host;
4103ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_add_target))
4104aef9ec39SRoland Dreier 		goto err_class;
4105ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_ibdev))
4106aef9ec39SRoland Dreier 		goto err_class;
4107ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_port))
4108aef9ec39SRoland Dreier 		goto err_class;
4109aef9ec39SRoland Dreier 
4110aef9ec39SRoland Dreier 	return host;
4111aef9ec39SRoland Dreier 
4112aef9ec39SRoland Dreier err_class:
4113ee959b00STony Jones 	device_unregister(&host->dev);
4114aef9ec39SRoland Dreier 
4115f5358a17SRoland Dreier free_host:
4116aef9ec39SRoland Dreier 	kfree(host);
4117aef9ec39SRoland Dreier 
4118aef9ec39SRoland Dreier 	return NULL;
4119aef9ec39SRoland Dreier }
4120aef9ec39SRoland Dreier 
4121dc1435c0SLeon Romanovsky static void srp_rename_dev(struct ib_device *device, void *client_data)
4122dc1435c0SLeon Romanovsky {
4123dc1435c0SLeon Romanovsky 	struct srp_device *srp_dev = client_data;
4124dc1435c0SLeon Romanovsky 	struct srp_host *host, *tmp_host;
4125dc1435c0SLeon Romanovsky 
4126dc1435c0SLeon Romanovsky 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
4127dc1435c0SLeon Romanovsky 		char name[IB_DEVICE_NAME_MAX + 8];
4128dc1435c0SLeon Romanovsky 
4129dc1435c0SLeon Romanovsky 		snprintf(name, sizeof(name), "srp-%s-%d",
4130dc1435c0SLeon Romanovsky 			 dev_name(&device->dev), host->port);
4131dc1435c0SLeon Romanovsky 		device_rename(&host->dev, name);
4132dc1435c0SLeon Romanovsky 	}
4133dc1435c0SLeon Romanovsky }
4134dc1435c0SLeon Romanovsky 
4135aef9ec39SRoland Dreier static void srp_add_one(struct ib_device *device)
4136aef9ec39SRoland Dreier {
4137f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4138042dd765SBart Van Assche 	struct ib_device_attr *attr = &device->attrs;
4139aef9ec39SRoland Dreier 	struct srp_host *host;
4140ea1075edSJason Gunthorpe 	int mr_page_shift;
4141ea1075edSJason Gunthorpe 	unsigned int p;
414252ede08fSBart Van Assche 	u64 max_pages_per_mr;
41435f071777SChristoph Hellwig 	unsigned int flags = 0;
4144aef9ec39SRoland Dreier 
4145249f0656SBart Van Assche 	srp_dev = kzalloc(sizeof(*srp_dev), GFP_KERNEL);
4146f5358a17SRoland Dreier 	if (!srp_dev)
41474a061b28SOr Gerlitz 		return;
4148f5358a17SRoland Dreier 
4149f5358a17SRoland Dreier 	/*
4150f5358a17SRoland Dreier 	 * Use the smallest page size supported by the HCA, down to a
41518f26c9ffSDavid Dillow 	 * minimum of 4096 bytes. We're unlikely to build large sglists
41528f26c9ffSDavid Dillow 	 * out of smaller entries.
4153f5358a17SRoland Dreier 	 */
4154042dd765SBart Van Assche 	mr_page_shift		= max(12, ffs(attr->page_size_cap) - 1);
415552ede08fSBart Van Assche 	srp_dev->mr_page_size	= 1 << mr_page_shift;
415652ede08fSBart Van Assche 	srp_dev->mr_page_mask	= ~((u64) srp_dev->mr_page_size - 1);
4157042dd765SBart Van Assche 	max_pages_per_mr	= attr->max_mr_size;
415852ede08fSBart Van Assche 	do_div(max_pages_per_mr, srp_dev->mr_page_size);
4159509c5f33SBart Van Assche 	pr_debug("%s: %llu / %u = %llu <> %u\n", __func__,
4160042dd765SBart Van Assche 		 attr->max_mr_size, srp_dev->mr_page_size,
4161509c5f33SBart Van Assche 		 max_pages_per_mr, SRP_MAX_PAGES_PER_MR);
416252ede08fSBart Van Assche 	srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR,
416352ede08fSBart Van Assche 					  max_pages_per_mr);
4164835ee624SBart Van Assche 
41653023a1e9SKamal Heib 	srp_dev->has_fmr = (device->ops.alloc_fmr &&
41663023a1e9SKamal Heib 			    device->ops.dealloc_fmr &&
41673023a1e9SKamal Heib 			    device->ops.map_phys_fmr &&
41683023a1e9SKamal Heib 			    device->ops.unmap_fmr);
4169042dd765SBart Van Assche 	srp_dev->has_fr = (attr->device_cap_flags &
4170835ee624SBart Van Assche 			   IB_DEVICE_MEM_MGT_EXTENSIONS);
4171c222a39fSBart Van Assche 	if (!never_register && !srp_dev->has_fmr && !srp_dev->has_fr) {
4172835ee624SBart Van Assche 		dev_warn(&device->dev, "neither FMR nor FR is supported\n");
4173c222a39fSBart Van Assche 	} else if (!never_register &&
4174042dd765SBart Van Assche 		   attr->max_mr_size >= 2 * srp_dev->mr_page_size) {
4175835ee624SBart Van Assche 		srp_dev->use_fast_reg = (srp_dev->has_fr &&
4176835ee624SBart Van Assche 					 (!srp_dev->has_fmr || prefer_fr));
4177835ee624SBart Van Assche 		srp_dev->use_fmr = !srp_dev->use_fast_reg && srp_dev->has_fmr;
4178509c5f33SBart Van Assche 	}
4179835ee624SBart Van Assche 
41805f071777SChristoph Hellwig 	if (never_register || !register_always ||
41815f071777SChristoph Hellwig 	    (!srp_dev->has_fmr && !srp_dev->has_fr))
41825f071777SChristoph Hellwig 		flags |= IB_PD_UNSAFE_GLOBAL_RKEY;
41835f071777SChristoph Hellwig 
41845cfb1782SBart Van Assche 	if (srp_dev->use_fast_reg) {
41855cfb1782SBart Van Assche 		srp_dev->max_pages_per_mr =
41865cfb1782SBart Van Assche 			min_t(u32, srp_dev->max_pages_per_mr,
4187042dd765SBart Van Assche 			      attr->max_fast_reg_page_list_len);
41885cfb1782SBart Van Assche 	}
418952ede08fSBart Van Assche 	srp_dev->mr_max_size	= srp_dev->mr_page_size *
419052ede08fSBart Van Assche 				   srp_dev->max_pages_per_mr;
41914a061b28SOr Gerlitz 	pr_debug("%s: mr_page_shift = %d, device->max_mr_size = %#llx, device->max_fast_reg_page_list_len = %u, max_pages_per_mr = %d, mr_max_size = %#x\n",
41926c854111SJason Gunthorpe 		 dev_name(&device->dev), mr_page_shift, attr->max_mr_size,
4193042dd765SBart Van Assche 		 attr->max_fast_reg_page_list_len,
419452ede08fSBart Van Assche 		 srp_dev->max_pages_per_mr, srp_dev->mr_max_size);
4195f5358a17SRoland Dreier 
4196f5358a17SRoland Dreier 	INIT_LIST_HEAD(&srp_dev->dev_list);
4197f5358a17SRoland Dreier 
4198f5358a17SRoland Dreier 	srp_dev->dev = device;
41995f071777SChristoph Hellwig 	srp_dev->pd  = ib_alloc_pd(device, flags);
4200f5358a17SRoland Dreier 	if (IS_ERR(srp_dev->pd))
4201f5358a17SRoland Dreier 		goto free_dev;
4202f5358a17SRoland Dreier 
4203cee687b6SBart Van Assche 	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
4204cee687b6SBart Van Assche 		srp_dev->global_rkey = srp_dev->pd->unsafe_global_rkey;
4205cee687b6SBart Van Assche 		WARN_ON_ONCE(srp_dev->global_rkey == 0);
4206cee687b6SBart Van Assche 	}
4207f5358a17SRoland Dreier 
4208ea1075edSJason Gunthorpe 	rdma_for_each_port (device, p) {
4209f5358a17SRoland Dreier 		host = srp_add_port(srp_dev, p);
4210aef9ec39SRoland Dreier 		if (host)
4211f5358a17SRoland Dreier 			list_add_tail(&host->list, &srp_dev->dev_list);
4212aef9ec39SRoland Dreier 	}
4213aef9ec39SRoland Dreier 
4214f5358a17SRoland Dreier 	ib_set_client_data(device, &srp_client, srp_dev);
42154a061b28SOr Gerlitz 	return;
4216f5358a17SRoland Dreier 
4217f5358a17SRoland Dreier free_dev:
4218f5358a17SRoland Dreier 	kfree(srp_dev);
4219aef9ec39SRoland Dreier }
4220aef9ec39SRoland Dreier 
42217c1eb45aSHaggai Eran static void srp_remove_one(struct ib_device *device, void *client_data)
4222aef9ec39SRoland Dreier {
4223f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4224aef9ec39SRoland Dreier 	struct srp_host *host, *tmp_host;
4225ef6c49d8SBart Van Assche 	struct srp_target_port *target;
4226aef9ec39SRoland Dreier 
42277c1eb45aSHaggai Eran 	srp_dev = client_data;
42281fe0cb84SDotan Barak 	if (!srp_dev)
42291fe0cb84SDotan Barak 		return;
4230aef9ec39SRoland Dreier 
4231f5358a17SRoland Dreier 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
4232ee959b00STony Jones 		device_unregister(&host->dev);
4233aef9ec39SRoland Dreier 		/*
4234aef9ec39SRoland Dreier 		 * Wait for the sysfs entry to go away, so that no new
4235aef9ec39SRoland Dreier 		 * target ports can be created.
4236aef9ec39SRoland Dreier 		 */
4237aef9ec39SRoland Dreier 		wait_for_completion(&host->released);
4238aef9ec39SRoland Dreier 
4239aef9ec39SRoland Dreier 		/*
4240ef6c49d8SBart Van Assche 		 * Remove all target ports.
4241aef9ec39SRoland Dreier 		 */
4242b3589fd4SMatthew Wilcox 		spin_lock(&host->target_lock);
4243ef6c49d8SBart Van Assche 		list_for_each_entry(target, &host->target_list, list)
4244ef6c49d8SBart Van Assche 			srp_queue_remove_work(target);
4245b3589fd4SMatthew Wilcox 		spin_unlock(&host->target_lock);
4246aef9ec39SRoland Dreier 
4247aef9ec39SRoland Dreier 		/*
4248bcc05910SBart Van Assche 		 * Wait for tl_err and target port removal tasks.
4249aef9ec39SRoland Dreier 		 */
4250ef6c49d8SBart Van Assche 		flush_workqueue(system_long_wq);
4251bcc05910SBart Van Assche 		flush_workqueue(srp_remove_wq);
4252aef9ec39SRoland Dreier 
4253aef9ec39SRoland Dreier 		kfree(host);
4254aef9ec39SRoland Dreier 	}
4255aef9ec39SRoland Dreier 
4256f5358a17SRoland Dreier 	ib_dealloc_pd(srp_dev->pd);
4257f5358a17SRoland Dreier 
4258f5358a17SRoland Dreier 	kfree(srp_dev);
4259aef9ec39SRoland Dreier }
4260aef9ec39SRoland Dreier 
42613236822bSFUJITA Tomonori static struct srp_function_template ib_srp_transport_functions = {
4262ed9b2264SBart Van Assche 	.has_rport_state	 = true,
4263ed9b2264SBart Van Assche 	.reset_timer_if_blocked	 = true,
4264a95cadb9SBart Van Assche 	.reconnect_delay	 = &srp_reconnect_delay,
4265ed9b2264SBart Van Assche 	.fast_io_fail_tmo	 = &srp_fast_io_fail_tmo,
4266ed9b2264SBart Van Assche 	.dev_loss_tmo		 = &srp_dev_loss_tmo,
4267ed9b2264SBart Van Assche 	.reconnect		 = srp_rport_reconnect,
4268dc1bdbd9SBart Van Assche 	.rport_delete		 = srp_rport_delete,
4269ed9b2264SBart Van Assche 	.terminate_rport_io	 = srp_terminate_io,
42703236822bSFUJITA Tomonori };
42713236822bSFUJITA Tomonori 
4272aef9ec39SRoland Dreier static int __init srp_init_module(void)
4273aef9ec39SRoland Dreier {
4274aef9ec39SRoland Dreier 	int ret;
4275aef9ec39SRoland Dreier 
427616d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_imm_buf) != 4);
427716d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req) != 64);
427816d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req_rdma) != 56);
427916d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_cmd) != 48);
428016d14e01SBart Van Assche 
428149248644SDavid Dillow 	if (srp_sg_tablesize) {
4282e0bda7d8SBart Van Assche 		pr_warn("srp_sg_tablesize is deprecated, please use cmd_sg_entries\n");
428349248644SDavid Dillow 		if (!cmd_sg_entries)
428449248644SDavid Dillow 			cmd_sg_entries = srp_sg_tablesize;
428549248644SDavid Dillow 	}
428649248644SDavid Dillow 
428749248644SDavid Dillow 	if (!cmd_sg_entries)
428849248644SDavid Dillow 		cmd_sg_entries = SRP_DEF_SG_TABLESIZE;
428949248644SDavid Dillow 
429049248644SDavid Dillow 	if (cmd_sg_entries > 255) {
4291e0bda7d8SBart Van Assche 		pr_warn("Clamping cmd_sg_entries to 255\n");
429249248644SDavid Dillow 		cmd_sg_entries = 255;
42931e89a194SDavid Dillow 	}
42941e89a194SDavid Dillow 
4295c07d424dSDavid Dillow 	if (!indirect_sg_entries)
4296c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4297c07d424dSDavid Dillow 	else if (indirect_sg_entries < cmd_sg_entries) {
4298e0bda7d8SBart Van Assche 		pr_warn("Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n",
4299e0bda7d8SBart Van Assche 			cmd_sg_entries);
4300c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4301c07d424dSDavid Dillow 	}
4302c07d424dSDavid Dillow 
43030a475ef4SIsrael Rukshin 	if (indirect_sg_entries > SG_MAX_SEGMENTS) {
43040a475ef4SIsrael Rukshin 		pr_warn("Clamping indirect_sg_entries to %u\n",
43050a475ef4SIsrael Rukshin 			SG_MAX_SEGMENTS);
43060a475ef4SIsrael Rukshin 		indirect_sg_entries = SG_MAX_SEGMENTS;
43070a475ef4SIsrael Rukshin 	}
43080a475ef4SIsrael Rukshin 
4309bcc05910SBart Van Assche 	srp_remove_wq = create_workqueue("srp_remove");
4310da05be29SWei Yongjun 	if (!srp_remove_wq) {
4311da05be29SWei Yongjun 		ret = -ENOMEM;
4312bcc05910SBart Van Assche 		goto out;
4313bcc05910SBart Van Assche 	}
4314bcc05910SBart Van Assche 
4315bcc05910SBart Van Assche 	ret = -ENOMEM;
43163236822bSFUJITA Tomonori 	ib_srp_transport_template =
43173236822bSFUJITA Tomonori 		srp_attach_transport(&ib_srp_transport_functions);
43183236822bSFUJITA Tomonori 	if (!ib_srp_transport_template)
4319bcc05910SBart Van Assche 		goto destroy_wq;
43203236822bSFUJITA Tomonori 
4321aef9ec39SRoland Dreier 	ret = class_register(&srp_class);
4322aef9ec39SRoland Dreier 	if (ret) {
4323e0bda7d8SBart Van Assche 		pr_err("couldn't register class infiniband_srp\n");
4324bcc05910SBart Van Assche 		goto release_tr;
4325aef9ec39SRoland Dreier 	}
4326aef9ec39SRoland Dreier 
4327c1a0b23bSMichael S. Tsirkin 	ib_sa_register_client(&srp_sa_client);
4328c1a0b23bSMichael S. Tsirkin 
4329aef9ec39SRoland Dreier 	ret = ib_register_client(&srp_client);
4330aef9ec39SRoland Dreier 	if (ret) {
4331e0bda7d8SBart Van Assche 		pr_err("couldn't register IB client\n");
4332bcc05910SBart Van Assche 		goto unreg_sa;
4333aef9ec39SRoland Dreier 	}
4334aef9ec39SRoland Dreier 
4335bcc05910SBart Van Assche out:
4336bcc05910SBart Van Assche 	return ret;
4337bcc05910SBart Van Assche 
4338bcc05910SBart Van Assche unreg_sa:
4339bcc05910SBart Van Assche 	ib_sa_unregister_client(&srp_sa_client);
4340bcc05910SBart Van Assche 	class_unregister(&srp_class);
4341bcc05910SBart Van Assche 
4342bcc05910SBart Van Assche release_tr:
4343bcc05910SBart Van Assche 	srp_release_transport(ib_srp_transport_template);
4344bcc05910SBart Van Assche 
4345bcc05910SBart Van Assche destroy_wq:
4346bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4347bcc05910SBart Van Assche 	goto out;
4348aef9ec39SRoland Dreier }
4349aef9ec39SRoland Dreier 
4350aef9ec39SRoland Dreier static void __exit srp_cleanup_module(void)
4351aef9ec39SRoland Dreier {
4352aef9ec39SRoland Dreier 	ib_unregister_client(&srp_client);
4353c1a0b23bSMichael S. Tsirkin 	ib_sa_unregister_client(&srp_sa_client);
4354aef9ec39SRoland Dreier 	class_unregister(&srp_class);
43553236822bSFUJITA Tomonori 	srp_release_transport(ib_srp_transport_template);
4356bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4357aef9ec39SRoland Dreier }
4358aef9ec39SRoland Dreier 
4359aef9ec39SRoland Dreier module_init(srp_init_module);
4360aef9ec39SRoland Dreier module_exit(srp_cleanup_module);
4361