xref: /linux/drivers/infiniband/ulp/srp/ib_srp.c (revision b2e872f451992e5ac3d6b79a62b66f1721e29521)
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)
177ed9b2264SBart Van Assche 		return sprintf(buffer, "%d", tmo);
178ed9b2264SBart Van Assche 	else
179ed9b2264SBart Van Assche 		return sprintf(buffer, "off");
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. */
1368*b2e872f4SHonggang Li static uint32_t srp_max_it_iu_len(int cmd_sg_cnt, bool use_imm_data,
1369*b2e872f4SHonggang 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 
1379*b2e872f4SHonggang Li 	if (max_it_iu_size)
1380*b2e872f4SHonggang Li 		max_iu_len = min(max_iu_len, max_it_iu_size);
1381*b2e872f4SHonggang Li 
1382*b2e872f4SHonggang Li 	pr_debug("max_iu_len = %d\n", max_iu_len);
1383*b2e872f4SHonggang 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,
1401*b2e872f4SHonggang Li 						srp_use_imm_data,
1402*b2e872f4SHonggang 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);
2549882981f4SBart Van Assche 		ch->use_imm_data  = lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP;
2550882981f4SBart Van Assche 		ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
2551*b2e872f4SHonggang Li 						      ch->use_imm_data,
2552*b2e872f4SHonggang Li 						      target->max_it_iu_size);
2553513d5647SBart Van Assche 		WARN_ON_ONCE(ch->max_it_iu_len >
2554513d5647SBart Van Assche 			     be32_to_cpu(lrsp->max_it_iu_len));
2555961e0be8SDavid Dillow 
2556882981f4SBart Van Assche 		if (ch->use_imm_data)
2557882981f4SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host,
2558882981f4SBart Van Assche 				     PFX "using immediate data\n");
2559961e0be8SDavid Dillow 
2560961e0be8SDavid Dillow 		/*
2561961e0be8SDavid Dillow 		 * Reserve credits for task management so we don't
2562961e0be8SDavid Dillow 		 * bounce requests back to the SCSI mid-layer.
2563961e0be8SDavid Dillow 		 */
2564961e0be8SDavid Dillow 		target->scsi_host->can_queue
2565509c07bcSBart Van Assche 			= min(ch->req_lim - SRP_TSK_MGMT_SQ_SIZE,
2566961e0be8SDavid Dillow 			      target->scsi_host->can_queue);
25674d73f95fSBart Van Assche 		target->scsi_host->cmd_per_lun
25684d73f95fSBart Van Assche 			= min_t(int, target->scsi_host->can_queue,
25694d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun);
2570961e0be8SDavid Dillow 	} else {
2571961e0be8SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
2572961e0be8SDavid Dillow 			     PFX "Unhandled RSP opcode %#x\n", lrsp->opcode);
2573961e0be8SDavid Dillow 		ret = -ECONNRESET;
2574961e0be8SDavid Dillow 		goto error;
2575961e0be8SDavid Dillow 	}
2576961e0be8SDavid Dillow 
2577509c07bcSBart Van Assche 	if (!ch->rx_ring) {
2578509c07bcSBart Van Assche 		ret = srp_alloc_iu_bufs(ch);
2579961e0be8SDavid Dillow 		if (ret)
2580961e0be8SDavid Dillow 			goto error;
2581961e0be8SDavid Dillow 	}
2582961e0be8SDavid Dillow 
258319f31343SBart Van Assche 	for (i = 0; i < target->queue_size; i++) {
258419f31343SBart Van Assche 		struct srp_iu *iu = ch->rx_ring[i];
258519f31343SBart Van Assche 
258619f31343SBart Van Assche 		ret = srp_post_recv(ch, iu);
258719f31343SBart Van Assche 		if (ret)
258819f31343SBart Van Assche 			goto error;
258919f31343SBart Van Assche 	}
259019f31343SBart Van Assche 
259119f31343SBart Van Assche 	if (!target->using_rdma_cm) {
2592961e0be8SDavid Dillow 		ret = -ENOMEM;
259319f31343SBart Van Assche 		qp_attr = kmalloc(sizeof(*qp_attr), GFP_KERNEL);
2594961e0be8SDavid Dillow 		if (!qp_attr)
2595961e0be8SDavid Dillow 			goto error;
2596961e0be8SDavid Dillow 
2597961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTR;
2598961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2599961e0be8SDavid Dillow 		if (ret)
2600961e0be8SDavid Dillow 			goto error_free;
2601961e0be8SDavid Dillow 
2602509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2603961e0be8SDavid Dillow 		if (ret)
2604961e0be8SDavid Dillow 			goto error_free;
2605961e0be8SDavid Dillow 
2606961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTS;
2607961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2608961e0be8SDavid Dillow 		if (ret)
2609961e0be8SDavid Dillow 			goto error_free;
2610961e0be8SDavid Dillow 
2611c9b03c1aSBart Van Assche 		target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
2612c9b03c1aSBart Van Assche 
2613509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2614961e0be8SDavid Dillow 		if (ret)
2615961e0be8SDavid Dillow 			goto error_free;
2616961e0be8SDavid Dillow 
2617961e0be8SDavid Dillow 		ret = ib_send_cm_rtu(cm_id, NULL, 0);
261819f31343SBart Van Assche 	}
2619961e0be8SDavid Dillow 
2620961e0be8SDavid Dillow error_free:
2621961e0be8SDavid Dillow 	kfree(qp_attr);
2622961e0be8SDavid Dillow 
2623961e0be8SDavid Dillow error:
2624509c07bcSBart Van Assche 	ch->status = ret;
2625961e0be8SDavid Dillow }
2626961e0be8SDavid Dillow 
262719f31343SBart Van Assche static void srp_ib_cm_rej_handler(struct ib_cm_id *cm_id,
2628e7ff98aeSParav Pandit 				  const struct ib_cm_event *event,
2629509c07bcSBart Van Assche 				  struct srp_rdma_ch *ch)
2630aef9ec39SRoland Dreier {
2631509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
26327aa54bd7SDavid Dillow 	struct Scsi_Host *shost = target->scsi_host;
2633aef9ec39SRoland Dreier 	struct ib_class_port_info *cpi;
2634aef9ec39SRoland Dreier 	int opcode;
263519f31343SBart Van Assche 	u16 dlid;
2636aef9ec39SRoland Dreier 
2637aef9ec39SRoland Dreier 	switch (event->param.rej_rcvd.reason) {
2638aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_CM_REDIRECT:
2639aef9ec39SRoland Dreier 		cpi = event->param.rej_rcvd.ari;
264019f31343SBart Van Assche 		dlid = be16_to_cpu(cpi->redirect_lid);
264119f31343SBart Van Assche 		sa_path_set_dlid(&ch->ib_cm.path, dlid);
264219f31343SBart Van Assche 		ch->ib_cm.path.pkey = cpi->redirect_pkey;
2643aef9ec39SRoland Dreier 		cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
264419f31343SBart Van Assche 		memcpy(ch->ib_cm.path.dgid.raw, cpi->redirect_gid, 16);
2645aef9ec39SRoland Dreier 
264619f31343SBart Van Assche 		ch->status = dlid ? SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
2647aef9ec39SRoland Dreier 		break;
2648aef9ec39SRoland Dreier 
2649aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_REDIRECT:
26505d7cbfd6SRoland Dreier 		if (srp_target_is_topspin(target)) {
265119f31343SBart Van Assche 			union ib_gid *dgid = &ch->ib_cm.path.dgid;
265219f31343SBart Van Assche 
2653aef9ec39SRoland Dreier 			/*
2654aef9ec39SRoland Dreier 			 * Topspin/Cisco SRP gateways incorrectly send
2655aef9ec39SRoland Dreier 			 * reject reason code 25 when they mean 24
2656aef9ec39SRoland Dreier 			 * (port redirect).
2657aef9ec39SRoland Dreier 			 */
265819f31343SBart Van Assche 			memcpy(dgid->raw, event->param.rej_rcvd.ari, 16);
2659aef9ec39SRoland Dreier 
26607aa54bd7SDavid Dillow 			shost_printk(KERN_DEBUG, shost,
26617aa54bd7SDavid Dillow 				     PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
266219f31343SBart Van Assche 				     be64_to_cpu(dgid->global.subnet_prefix),
266319f31343SBart Van Assche 				     be64_to_cpu(dgid->global.interface_id));
2664aef9ec39SRoland Dreier 
2665509c07bcSBart Van Assche 			ch->status = SRP_PORT_REDIRECT;
2666aef9ec39SRoland Dreier 		} else {
26677aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
26687aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
2669509c07bcSBart Van Assche 			ch->status = -ECONNRESET;
2670aef9ec39SRoland Dreier 		}
2671aef9ec39SRoland Dreier 		break;
2672aef9ec39SRoland Dreier 
2673aef9ec39SRoland Dreier 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
26747aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost,
26757aa54bd7SDavid Dillow 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
2676509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2677aef9ec39SRoland Dreier 		break;
2678aef9ec39SRoland Dreier 
2679aef9ec39SRoland Dreier 	case IB_CM_REJ_CONSUMER_DEFINED:
2680aef9ec39SRoland Dreier 		opcode = *(u8 *) event->private_data;
2681aef9ec39SRoland Dreier 		if (opcode == SRP_LOGIN_REJ) {
2682aef9ec39SRoland Dreier 			struct srp_login_rej *rej = event->private_data;
2683aef9ec39SRoland Dreier 			u32 reason = be32_to_cpu(rej->reason);
2684aef9ec39SRoland Dreier 
2685aef9ec39SRoland Dreier 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
26867aa54bd7SDavid Dillow 				shost_printk(KERN_WARNING, shost,
26877aa54bd7SDavid Dillow 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
2688aef9ec39SRoland Dreier 			else
2689e7ffde01SBart Van Assche 				shost_printk(KERN_WARNING, shost, PFX
2690e7ffde01SBart Van Assche 					     "SRP LOGIN from %pI6 to %pI6 REJECTED, reason 0x%08x\n",
2691747fe000SBart Van Assche 					     target->sgid.raw,
269219f31343SBart Van Assche 					     target->ib_cm.orig_dgid.raw,
269319f31343SBart Van Assche 					     reason);
2694aef9ec39SRoland Dreier 		} else
26957aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
26967aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
2697aef9ec39SRoland Dreier 				     " opcode 0x%02x\n", opcode);
2698509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2699aef9ec39SRoland Dreier 		break;
2700aef9ec39SRoland Dreier 
27019fe4bcf4SDavid Dillow 	case IB_CM_REJ_STALE_CONN:
27029fe4bcf4SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason: stale connection\n");
2703509c07bcSBart Van Assche 		ch->status = SRP_STALE_CONN;
27049fe4bcf4SDavid Dillow 		break;
27059fe4bcf4SDavid Dillow 
2706aef9ec39SRoland Dreier 	default:
27077aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
2708aef9ec39SRoland Dreier 			     event->param.rej_rcvd.reason);
2709509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2710aef9ec39SRoland Dreier 	}
2711aef9ec39SRoland Dreier }
2712aef9ec39SRoland Dreier 
2713e7ff98aeSParav Pandit static int srp_ib_cm_handler(struct ib_cm_id *cm_id,
2714e7ff98aeSParav Pandit 			     const struct ib_cm_event *event)
2715aef9ec39SRoland Dreier {
2716509c07bcSBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
2717509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2718aef9ec39SRoland Dreier 	int comp = 0;
2719aef9ec39SRoland Dreier 
2720aef9ec39SRoland Dreier 	switch (event->event) {
2721aef9ec39SRoland Dreier 	case IB_CM_REQ_ERROR:
27227aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host,
27237aa54bd7SDavid Dillow 			     PFX "Sending CM REQ failed\n");
2724aef9ec39SRoland Dreier 		comp = 1;
2725509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2726aef9ec39SRoland Dreier 		break;
2727aef9ec39SRoland Dreier 
2728aef9ec39SRoland Dreier 	case IB_CM_REP_RECEIVED:
2729aef9ec39SRoland Dreier 		comp = 1;
2730509c07bcSBart Van Assche 		srp_cm_rep_handler(cm_id, event->private_data, ch);
2731aef9ec39SRoland Dreier 		break;
2732aef9ec39SRoland Dreier 
2733aef9ec39SRoland Dreier 	case IB_CM_REJ_RECEIVED:
27347aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
2735aef9ec39SRoland Dreier 		comp = 1;
2736aef9ec39SRoland Dreier 
273719f31343SBart Van Assche 		srp_ib_cm_rej_handler(cm_id, event, ch);
2738aef9ec39SRoland Dreier 		break;
2739aef9ec39SRoland Dreier 
2740b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_RECEIVED:
27417aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
27427aa54bd7SDavid Dillow 			     PFX "DREQ received - connection closed\n");
2743c014c8cdSBart Van Assche 		ch->connected = false;
2744b7ac4ab4SIshai Rabinovitz 		if (ib_send_cm_drep(cm_id, NULL, 0))
27457aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
27467aa54bd7SDavid Dillow 				     PFX "Sending CM DREP failed\n");
2747c1120f89SBart Van Assche 		queue_work(system_long_wq, &target->tl_err_work);
2748aef9ec39SRoland Dreier 		break;
2749aef9ec39SRoland Dreier 
2750aef9ec39SRoland Dreier 	case IB_CM_TIMEWAIT_EXIT:
27517aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
27527aa54bd7SDavid Dillow 			     PFX "connection closed\n");
2753ac72d766SBart Van Assche 		comp = 1;
2754aef9ec39SRoland Dreier 
2755509c07bcSBart Van Assche 		ch->status = 0;
2756aef9ec39SRoland Dreier 		break;
2757aef9ec39SRoland Dreier 
2758b7ac4ab4SIshai Rabinovitz 	case IB_CM_MRA_RECEIVED:
2759b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_ERROR:
2760b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREP_RECEIVED:
2761b7ac4ab4SIshai Rabinovitz 		break;
2762b7ac4ab4SIshai Rabinovitz 
2763aef9ec39SRoland Dreier 	default:
27647aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
27657aa54bd7SDavid Dillow 			     PFX "Unhandled CM event %d\n", event->event);
2766aef9ec39SRoland Dreier 		break;
2767aef9ec39SRoland Dreier 	}
2768aef9ec39SRoland Dreier 
2769aef9ec39SRoland Dreier 	if (comp)
2770509c07bcSBart Van Assche 		complete(&ch->done);
2771aef9ec39SRoland Dreier 
2772aef9ec39SRoland Dreier 	return 0;
2773aef9ec39SRoland Dreier }
2774aef9ec39SRoland Dreier 
277519f31343SBart Van Assche static void srp_rdma_cm_rej_handler(struct srp_rdma_ch *ch,
277619f31343SBart Van Assche 				    struct rdma_cm_event *event)
277719f31343SBart Van Assche {
277819f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
277919f31343SBart Van Assche 	struct Scsi_Host *shost = target->scsi_host;
278019f31343SBart Van Assche 	int opcode;
278119f31343SBart Van Assche 
278219f31343SBart Van Assche 	switch (event->status) {
278319f31343SBart Van Assche 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
278419f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
278519f31343SBart Van Assche 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
278619f31343SBart Van Assche 		ch->status = -ECONNRESET;
278719f31343SBart Van Assche 		break;
278819f31343SBart Van Assche 
278919f31343SBart Van Assche 	case IB_CM_REJ_CONSUMER_DEFINED:
279019f31343SBart Van Assche 		opcode = *(u8 *) event->param.conn.private_data;
279119f31343SBart Van Assche 		if (opcode == SRP_LOGIN_REJ) {
279219f31343SBart Van Assche 			struct srp_login_rej *rej =
279319f31343SBart Van Assche 				(struct srp_login_rej *)
279419f31343SBart Van Assche 				event->param.conn.private_data;
279519f31343SBart Van Assche 			u32 reason = be32_to_cpu(rej->reason);
279619f31343SBart Van Assche 
279719f31343SBart Van Assche 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
279819f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
279919f31343SBart Van Assche 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
280019f31343SBart Van Assche 			else
280119f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
280219f31343SBart Van Assche 					    PFX "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
280319f31343SBart Van Assche 		} else {
280419f31343SBart Van Assche 			shost_printk(KERN_WARNING, shost,
280519f31343SBart Van Assche 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED, opcode 0x%02x\n",
280619f31343SBart Van Assche 				     opcode);
280719f31343SBart Van Assche 		}
280819f31343SBart Van Assche 		ch->status = -ECONNRESET;
280919f31343SBart Van Assche 		break;
281019f31343SBart Van Assche 
281119f31343SBart Van Assche 	case IB_CM_REJ_STALE_CONN:
281219f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
281319f31343SBart Van Assche 			     "  REJ reason: stale connection\n");
281419f31343SBart Van Assche 		ch->status = SRP_STALE_CONN;
281519f31343SBart Van Assche 		break;
281619f31343SBart Van Assche 
281719f31343SBart Van Assche 	default:
281819f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
281919f31343SBart Van Assche 			     event->status);
282019f31343SBart Van Assche 		ch->status = -ECONNRESET;
282119f31343SBart Van Assche 		break;
282219f31343SBart Van Assche 	}
282319f31343SBart Van Assche }
282419f31343SBart Van Assche 
282519f31343SBart Van Assche static int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
282619f31343SBart Van Assche 			       struct rdma_cm_event *event)
282719f31343SBart Van Assche {
282819f31343SBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
282919f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
283019f31343SBart Van Assche 	int comp = 0;
283119f31343SBart Van Assche 
283219f31343SBart Van Assche 	switch (event->event) {
283319f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_RESOLVED:
283419f31343SBart Van Assche 		ch->status = 0;
283519f31343SBart Van Assche 		comp = 1;
283619f31343SBart Van Assche 		break;
283719f31343SBart Van Assche 
283819f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_ERROR:
283919f31343SBart Van Assche 		ch->status = -ENXIO;
284019f31343SBart Van Assche 		comp = 1;
284119f31343SBart Van Assche 		break;
284219f31343SBart Van Assche 
284319f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_RESOLVED:
284419f31343SBart Van Assche 		ch->status = 0;
284519f31343SBart Van Assche 		comp = 1;
284619f31343SBart Van Assche 		break;
284719f31343SBart Van Assche 
284819f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_ERROR:
284919f31343SBart Van Assche 	case RDMA_CM_EVENT_UNREACHABLE:
285019f31343SBart Van Assche 		ch->status = -EHOSTUNREACH;
285119f31343SBart Van Assche 		comp = 1;
285219f31343SBart Van Assche 		break;
285319f31343SBart Van Assche 
285419f31343SBart Van Assche 	case RDMA_CM_EVENT_CONNECT_ERROR:
285519f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host,
285619f31343SBart Van Assche 			     PFX "Sending CM REQ failed\n");
285719f31343SBart Van Assche 		comp = 1;
285819f31343SBart Van Assche 		ch->status = -ECONNRESET;
285919f31343SBart Van Assche 		break;
286019f31343SBart Van Assche 
286119f31343SBart Van Assche 	case RDMA_CM_EVENT_ESTABLISHED:
286219f31343SBart Van Assche 		comp = 1;
286319f31343SBart Van Assche 		srp_cm_rep_handler(NULL, event->param.conn.private_data, ch);
286419f31343SBart Van Assche 		break;
286519f31343SBart Van Assche 
286619f31343SBart Van Assche 	case RDMA_CM_EVENT_REJECTED:
286719f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
286819f31343SBart Van Assche 		comp = 1;
286919f31343SBart Van Assche 
287019f31343SBart Van Assche 		srp_rdma_cm_rej_handler(ch, event);
287119f31343SBart Van Assche 		break;
287219f31343SBart Van Assche 
287319f31343SBart Van Assche 	case RDMA_CM_EVENT_DISCONNECTED:
287419f31343SBart Van Assche 		if (ch->connected) {
287519f31343SBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host,
287619f31343SBart Van Assche 				     PFX "received DREQ\n");
287719f31343SBart Van Assche 			rdma_disconnect(ch->rdma_cm.cm_id);
287819f31343SBart Van Assche 			comp = 1;
287919f31343SBart Van Assche 			ch->status = 0;
288019f31343SBart Van Assche 			queue_work(system_long_wq, &target->tl_err_work);
288119f31343SBart Van Assche 		}
288219f31343SBart Van Assche 		break;
288319f31343SBart Van Assche 
288419f31343SBart Van Assche 	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
288519f31343SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
288619f31343SBart Van Assche 			     PFX "connection closed\n");
288719f31343SBart Van Assche 
288819f31343SBart Van Assche 		comp = 1;
288919f31343SBart Van Assche 		ch->status = 0;
289019f31343SBart Van Assche 		break;
289119f31343SBart Van Assche 
289219f31343SBart Van Assche 	default:
289319f31343SBart Van Assche 		shost_printk(KERN_WARNING, target->scsi_host,
289419f31343SBart Van Assche 			     PFX "Unhandled CM event %d\n", event->event);
289519f31343SBart Van Assche 		break;
289619f31343SBart Van Assche 	}
289719f31343SBart Van Assche 
289819f31343SBart Van Assche 	if (comp)
289919f31343SBart Van Assche 		complete(&ch->done);
290019f31343SBart Van Assche 
290119f31343SBart Van Assche 	return 0;
290219f31343SBart Van Assche }
290319f31343SBart Van Assche 
290471444b97SJack Wang /**
290571444b97SJack Wang  * srp_change_queue_depth - setting device queue depth
290671444b97SJack Wang  * @sdev: scsi device struct
290771444b97SJack Wang  * @qdepth: requested queue depth
290871444b97SJack Wang  *
290971444b97SJack Wang  * Returns queue depth.
291071444b97SJack Wang  */
291171444b97SJack Wang static int
2912db5ed4dfSChristoph Hellwig srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
291371444b97SJack Wang {
291471444b97SJack Wang 	if (!sdev->tagged_supported)
29151e6f2416SChristoph Hellwig 		qdepth = 1;
2916db5ed4dfSChristoph Hellwig 	return scsi_change_queue_depth(sdev, qdepth);
291771444b97SJack Wang }
291871444b97SJack Wang 
2919985aa495SBart Van Assche static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
29200a6fdbdeSBart Van Assche 			     u8 func, u8 *status)
2921aef9ec39SRoland Dreier {
2922509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2923a95cadb9SBart Van Assche 	struct srp_rport *rport = target->rport;
292419081f31SDavid Dillow 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2925aef9ec39SRoland Dreier 	struct srp_iu *iu;
2926aef9ec39SRoland Dreier 	struct srp_tsk_mgmt *tsk_mgmt;
29270a6fdbdeSBart Van Assche 	int res;
2928aef9ec39SRoland Dreier 
2929c014c8cdSBart Van Assche 	if (!ch->connected || target->qp_in_error)
29303780d1f0SBart Van Assche 		return -1;
29313780d1f0SBart Van Assche 
2932a95cadb9SBart Van Assche 	/*
2933509c07bcSBart Van Assche 	 * Lock the rport mutex to avoid that srp_create_ch_ib() is
2934a95cadb9SBart Van Assche 	 * invoked while a task management function is being sent.
2935a95cadb9SBart Van Assche 	 */
2936a95cadb9SBart Van Assche 	mutex_lock(&rport->mutex);
2937509c07bcSBart Van Assche 	spin_lock_irq(&ch->lock);
2938509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_TSK_MGMT);
2939509c07bcSBart Van Assche 	spin_unlock_irq(&ch->lock);
294076c75b25SBart Van Assche 
2941a95cadb9SBart Van Assche 	if (!iu) {
2942a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2943a95cadb9SBart Van Assche 
294476c75b25SBart Van Assche 		return -1;
2945a95cadb9SBart Van Assche 	}
2946aef9ec39SRoland Dreier 
2947882981f4SBart Van Assche 	iu->num_sge = 1;
2948882981f4SBart Van Assche 
294919081f31SDavid Dillow 	ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
295019081f31SDavid Dillow 				   DMA_TO_DEVICE);
2951aef9ec39SRoland Dreier 	tsk_mgmt = iu->buf;
2952aef9ec39SRoland Dreier 	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
2953aef9ec39SRoland Dreier 
2954aef9ec39SRoland Dreier 	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
2955985aa495SBart Van Assche 	int_to_scsilun(lun, &tsk_mgmt->lun);
2956aef9ec39SRoland Dreier 	tsk_mgmt->tsk_mgmt_func = func;
2957f8b6e31eSDavid Dillow 	tsk_mgmt->task_tag	= req_tag;
2958aef9ec39SRoland Dreier 
29590a6fdbdeSBart Van Assche 	spin_lock_irq(&ch->lock);
29600a6fdbdeSBart Van Assche 	ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT;
29610a6fdbdeSBart Van Assche 	tsk_mgmt->tag = ch->tsk_mgmt_tag;
29620a6fdbdeSBart Van Assche 	spin_unlock_irq(&ch->lock);
29630a6fdbdeSBart Van Assche 
29640a6fdbdeSBart Van Assche 	init_completion(&ch->tsk_mgmt_done);
29650a6fdbdeSBart Van Assche 
296619081f31SDavid Dillow 	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
296719081f31SDavid Dillow 				      DMA_TO_DEVICE);
2968509c07bcSBart Van Assche 	if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
2969509c07bcSBart Van Assche 		srp_put_tx_iu(ch, iu, SRP_IU_TSK_MGMT);
2970a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2971a95cadb9SBart Van Assche 
297276c75b25SBart Van Assche 		return -1;
297376c75b25SBart Van Assche 	}
29740a6fdbdeSBart Van Assche 	res = wait_for_completion_timeout(&ch->tsk_mgmt_done,
29750a6fdbdeSBart Van Assche 					msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS));
29760a6fdbdeSBart Van Assche 	if (res > 0 && status)
29770a6fdbdeSBart Van Assche 		*status = ch->tsk_mgmt_status;
2978a95cadb9SBart Van Assche 	mutex_unlock(&rport->mutex);
2979d945e1dfSRoland Dreier 
29800a6fdbdeSBart Van Assche 	WARN_ON_ONCE(res < 0);
2981aef9ec39SRoland Dreier 
29820a6fdbdeSBart Van Assche 	return res > 0 ? 0 : -1;
2983d945e1dfSRoland Dreier }
2984d945e1dfSRoland Dreier 
2985aef9ec39SRoland Dreier static int srp_abort(struct scsi_cmnd *scmnd)
2986aef9ec39SRoland Dreier {
2987d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
2988f8b6e31eSDavid Dillow 	struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
298977f2c1a4SBart Van Assche 	u32 tag;
2990d92c0da7SBart Van Assche 	u16 ch_idx;
2991509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
2992086f44f5SBart Van Assche 	int ret;
2993d945e1dfSRoland Dreier 
29947aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
2995aef9ec39SRoland Dreier 
2996d92c0da7SBart Van Assche 	if (!req)
299799b6697aSBart Van Assche 		return SUCCESS;
299877f2c1a4SBart Van Assche 	tag = blk_mq_unique_tag(scmnd->request);
2999d92c0da7SBart Van Assche 	ch_idx = blk_mq_unique_tag_to_hwq(tag);
3000d92c0da7SBart Van Assche 	if (WARN_ON_ONCE(ch_idx >= target->ch_count))
3001d92c0da7SBart Van Assche 		return SUCCESS;
3002d92c0da7SBart Van Assche 	ch = &target->ch[ch_idx];
3003d92c0da7SBart Van Assche 	if (!srp_claim_req(ch, req, NULL, scmnd))
3004d92c0da7SBart Van Assche 		return SUCCESS;
3005d92c0da7SBart Van Assche 	shost_printk(KERN_ERR, target->scsi_host,
3006d92c0da7SBart Van Assche 		     "Sending SRP abort for tag %#x\n", tag);
300777f2c1a4SBart Van Assche 	if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
30080a6fdbdeSBart Van Assche 			      SRP_TSK_ABORT_TASK, NULL) == 0)
3009086f44f5SBart Van Assche 		ret = SUCCESS;
3010ed9b2264SBart Van Assche 	else if (target->rport->state == SRP_RPORT_LOST)
301199e1c139SBart Van Assche 		ret = FAST_IO_FAIL;
3012086f44f5SBart Van Assche 	else
3013086f44f5SBart Van Assche 		ret = FAILED;
3014e68088e7SBart Van Assche 	if (ret == SUCCESS) {
3015509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd, 0);
3016d945e1dfSRoland Dreier 		scmnd->result = DID_ABORT << 16;
3017d8536670SBart Van Assche 		scmnd->scsi_done(scmnd);
3018e68088e7SBart Van Assche 	}
3019d945e1dfSRoland Dreier 
3020086f44f5SBart Van Assche 	return ret;
3021aef9ec39SRoland Dreier }
3022aef9ec39SRoland Dreier 
3023aef9ec39SRoland Dreier static int srp_reset_device(struct scsi_cmnd *scmnd)
3024aef9ec39SRoland Dreier {
3025d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
3026d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
30270a6fdbdeSBart Van Assche 	u8 status;
3028d945e1dfSRoland Dreier 
30297aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
3030aef9ec39SRoland Dreier 
3031d92c0da7SBart Van Assche 	ch = &target->ch[0];
3032509c07bcSBart Van Assche 	if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
30330a6fdbdeSBart Van Assche 			      SRP_TSK_LUN_RESET, &status))
3034d945e1dfSRoland Dreier 		return FAILED;
30350a6fdbdeSBart Van Assche 	if (status)
3036d945e1dfSRoland Dreier 		return FAILED;
3037d945e1dfSRoland Dreier 
3038d945e1dfSRoland Dreier 	return SUCCESS;
3039aef9ec39SRoland Dreier }
3040aef9ec39SRoland Dreier 
3041aef9ec39SRoland Dreier static int srp_reset_host(struct scsi_cmnd *scmnd)
3042aef9ec39SRoland Dreier {
3043aef9ec39SRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
3044aef9ec39SRoland Dreier 
30457aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, PFX "SRP reset_host called\n");
3046aef9ec39SRoland Dreier 
3047ed9b2264SBart Van Assche 	return srp_reconnect_rport(target->rport) == 0 ? SUCCESS : FAILED;
3048aef9ec39SRoland Dreier }
3049aef9ec39SRoland Dreier 
3050b0780ee5SBart Van Assche static int srp_target_alloc(struct scsi_target *starget)
3051b0780ee5SBart Van Assche {
3052b0780ee5SBart Van Assche 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
3053b0780ee5SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
3054b0780ee5SBart Van Assche 
3055b0780ee5SBart Van Assche 	if (target->target_can_queue)
3056b0780ee5SBart Van Assche 		starget->can_queue = target->target_can_queue;
3057b0780ee5SBart Van Assche 	return 0;
3058b0780ee5SBart Van Assche }
3059b0780ee5SBart Van Assche 
3060c9b03c1aSBart Van Assche static int srp_slave_configure(struct scsi_device *sdev)
3061c9b03c1aSBart Van Assche {
3062c9b03c1aSBart Van Assche 	struct Scsi_Host *shost = sdev->host;
3063c9b03c1aSBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
3064c9b03c1aSBart Van Assche 	struct request_queue *q = sdev->request_queue;
3065c9b03c1aSBart Van Assche 	unsigned long timeout;
3066c9b03c1aSBart Van Assche 
3067c9b03c1aSBart Van Assche 	if (sdev->type == TYPE_DISK) {
3068c9b03c1aSBart Van Assche 		timeout = max_t(unsigned, 30 * HZ, target->rq_tmo_jiffies);
3069c9b03c1aSBart Van Assche 		blk_queue_rq_timeout(q, timeout);
3070c9b03c1aSBart Van Assche 	}
3071c9b03c1aSBart Van Assche 
3072c9b03c1aSBart Van Assche 	return 0;
3073c9b03c1aSBart Van Assche }
3074c9b03c1aSBart Van Assche 
3075ee959b00STony Jones static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
3076ee959b00STony Jones 			   char *buf)
30776ecb0c84SRoland Dreier {
3078ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30796ecb0c84SRoland Dreier 
308045c37cadSBart Van Assche 	return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->id_ext));
30816ecb0c84SRoland Dreier }
30826ecb0c84SRoland Dreier 
3083ee959b00STony Jones static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
3084ee959b00STony Jones 			     char *buf)
30856ecb0c84SRoland Dreier {
3086ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30876ecb0c84SRoland Dreier 
308845c37cadSBart Van Assche 	return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid));
30896ecb0c84SRoland Dreier }
30906ecb0c84SRoland Dreier 
3091ee959b00STony Jones static ssize_t show_service_id(struct device *dev,
3092ee959b00STony Jones 			       struct device_attribute *attr, char *buf)
30936ecb0c84SRoland Dreier {
3094ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30956ecb0c84SRoland Dreier 
309619f31343SBart Van Assche 	if (target->using_rdma_cm)
309719f31343SBart Van Assche 		return -ENOENT;
309819f31343SBart Van Assche 	return sprintf(buf, "0x%016llx\n",
309919f31343SBart Van Assche 		       be64_to_cpu(target->ib_cm.service_id));
31006ecb0c84SRoland Dreier }
31016ecb0c84SRoland Dreier 
3102ee959b00STony Jones static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
3103ee959b00STony Jones 			 char *buf)
31046ecb0c84SRoland Dreier {
3105ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31066ecb0c84SRoland Dreier 
310719f31343SBart Van Assche 	if (target->using_rdma_cm)
310819f31343SBart Van Assche 		return -ENOENT;
310919f31343SBart Van Assche 	return sprintf(buf, "0x%04x\n", be16_to_cpu(target->ib_cm.pkey));
31106ecb0c84SRoland Dreier }
31116ecb0c84SRoland Dreier 
3112848b3082SBart Van Assche static ssize_t show_sgid(struct device *dev, struct device_attribute *attr,
3113848b3082SBart Van Assche 			 char *buf)
3114848b3082SBart Van Assche {
3115848b3082SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3116848b3082SBart Van Assche 
3117747fe000SBart Van Assche 	return sprintf(buf, "%pI6\n", target->sgid.raw);
3118848b3082SBart Van Assche }
3119848b3082SBart Van Assche 
3120ee959b00STony Jones static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
3121ee959b00STony Jones 			 char *buf)
31226ecb0c84SRoland Dreier {
3123ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3124d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch = &target->ch[0];
31256ecb0c84SRoland Dreier 
312619f31343SBart Van Assche 	if (target->using_rdma_cm)
312719f31343SBart Van Assche 		return -ENOENT;
312819f31343SBart Van Assche 	return sprintf(buf, "%pI6\n", ch->ib_cm.path.dgid.raw);
31296ecb0c84SRoland Dreier }
31306ecb0c84SRoland Dreier 
3131ee959b00STony Jones static ssize_t show_orig_dgid(struct device *dev,
3132ee959b00STony Jones 			      struct device_attribute *attr, char *buf)
31333633b3d0SIshai Rabinovitz {
3134ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31353633b3d0SIshai Rabinovitz 
313619f31343SBart Van Assche 	if (target->using_rdma_cm)
313719f31343SBart Van Assche 		return -ENOENT;
313819f31343SBart Van Assche 	return sprintf(buf, "%pI6\n", target->ib_cm.orig_dgid.raw);
31393633b3d0SIshai Rabinovitz }
31403633b3d0SIshai Rabinovitz 
314189de7486SBart Van Assche static ssize_t show_req_lim(struct device *dev,
314289de7486SBart Van Assche 			    struct device_attribute *attr, char *buf)
314389de7486SBart Van Assche {
314489de7486SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3145d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
3146d92c0da7SBart Van Assche 	int i, req_lim = INT_MAX;
314789de7486SBart Van Assche 
3148d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
3149d92c0da7SBart Van Assche 		ch = &target->ch[i];
3150d92c0da7SBart Van Assche 		req_lim = min(req_lim, ch->req_lim);
3151d92c0da7SBart Van Assche 	}
3152d92c0da7SBart Van Assche 	return sprintf(buf, "%d\n", req_lim);
315389de7486SBart Van Assche }
315489de7486SBart Van Assche 
3155ee959b00STony Jones static ssize_t show_zero_req_lim(struct device *dev,
3156ee959b00STony Jones 				 struct device_attribute *attr, char *buf)
31576bfa24faSRoland Dreier {
3158ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31596bfa24faSRoland Dreier 
31606bfa24faSRoland Dreier 	return sprintf(buf, "%d\n", target->zero_req_lim);
31616bfa24faSRoland Dreier }
31626bfa24faSRoland Dreier 
3163ee959b00STony Jones static ssize_t show_local_ib_port(struct device *dev,
3164ee959b00STony Jones 				  struct device_attribute *attr, char *buf)
3165ded7f1a1SIshai Rabinovitz {
3166ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3167ded7f1a1SIshai Rabinovitz 
3168ded7f1a1SIshai Rabinovitz 	return sprintf(buf, "%d\n", target->srp_host->port);
3169ded7f1a1SIshai Rabinovitz }
3170ded7f1a1SIshai Rabinovitz 
3171ee959b00STony Jones static ssize_t show_local_ib_device(struct device *dev,
3172ee959b00STony Jones 				    struct device_attribute *attr, char *buf)
3173ded7f1a1SIshai Rabinovitz {
3174ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3175ded7f1a1SIshai Rabinovitz 
31766c854111SJason Gunthorpe 	return sprintf(buf, "%s\n",
31776c854111SJason Gunthorpe 		       dev_name(&target->srp_host->srp_dev->dev->dev));
3178ded7f1a1SIshai Rabinovitz }
3179ded7f1a1SIshai Rabinovitz 
3180d92c0da7SBart Van Assche static ssize_t show_ch_count(struct device *dev, struct device_attribute *attr,
3181d92c0da7SBart Van Assche 			     char *buf)
3182d92c0da7SBart Van Assche {
3183d92c0da7SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3184d92c0da7SBart Van Assche 
3185d92c0da7SBart Van Assche 	return sprintf(buf, "%d\n", target->ch_count);
3186d92c0da7SBart Van Assche }
3187d92c0da7SBart Van Assche 
31884b5e5f41SBart Van Assche static ssize_t show_comp_vector(struct device *dev,
31894b5e5f41SBart Van Assche 				struct device_attribute *attr, char *buf)
31904b5e5f41SBart Van Assche {
31914b5e5f41SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31924b5e5f41SBart Van Assche 
31934b5e5f41SBart Van Assche 	return sprintf(buf, "%d\n", target->comp_vector);
31944b5e5f41SBart Van Assche }
31954b5e5f41SBart Van Assche 
31967bb312e4SVu Pham static ssize_t show_tl_retry_count(struct device *dev,
31977bb312e4SVu Pham 				   struct device_attribute *attr, char *buf)
31987bb312e4SVu Pham {
31997bb312e4SVu Pham 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
32007bb312e4SVu Pham 
32017bb312e4SVu Pham 	return sprintf(buf, "%d\n", target->tl_retry_count);
32027bb312e4SVu Pham }
32037bb312e4SVu Pham 
320449248644SDavid Dillow static ssize_t show_cmd_sg_entries(struct device *dev,
320549248644SDavid Dillow 				   struct device_attribute *attr, char *buf)
320649248644SDavid Dillow {
320749248644SDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
320849248644SDavid Dillow 
320949248644SDavid Dillow 	return sprintf(buf, "%u\n", target->cmd_sg_cnt);
321049248644SDavid Dillow }
321149248644SDavid Dillow 
3212c07d424dSDavid Dillow static ssize_t show_allow_ext_sg(struct device *dev,
3213c07d424dSDavid Dillow 				 struct device_attribute *attr, char *buf)
3214c07d424dSDavid Dillow {
3215c07d424dSDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3216c07d424dSDavid Dillow 
3217c07d424dSDavid Dillow 	return sprintf(buf, "%s\n", target->allow_ext_sg ? "true" : "false");
3218c07d424dSDavid Dillow }
3219c07d424dSDavid Dillow 
3220ee959b00STony Jones static DEVICE_ATTR(id_ext,	    S_IRUGO, show_id_ext,	   NULL);
3221ee959b00STony Jones static DEVICE_ATTR(ioc_guid,	    S_IRUGO, show_ioc_guid,	   NULL);
3222ee959b00STony Jones static DEVICE_ATTR(service_id,	    S_IRUGO, show_service_id,	   NULL);
3223ee959b00STony Jones static DEVICE_ATTR(pkey,	    S_IRUGO, show_pkey,		   NULL);
3224848b3082SBart Van Assche static DEVICE_ATTR(sgid,	    S_IRUGO, show_sgid,		   NULL);
3225ee959b00STony Jones static DEVICE_ATTR(dgid,	    S_IRUGO, show_dgid,		   NULL);
3226ee959b00STony Jones static DEVICE_ATTR(orig_dgid,	    S_IRUGO, show_orig_dgid,	   NULL);
322789de7486SBart Van Assche static DEVICE_ATTR(req_lim,         S_IRUGO, show_req_lim,         NULL);
3228ee959b00STony Jones static DEVICE_ATTR(zero_req_lim,    S_IRUGO, show_zero_req_lim,	   NULL);
3229ee959b00STony Jones static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
3230ee959b00STony Jones static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
3231d92c0da7SBart Van Assche static DEVICE_ATTR(ch_count,        S_IRUGO, show_ch_count,        NULL);
32324b5e5f41SBart Van Assche static DEVICE_ATTR(comp_vector,     S_IRUGO, show_comp_vector,     NULL);
32337bb312e4SVu Pham static DEVICE_ATTR(tl_retry_count,  S_IRUGO, show_tl_retry_count,  NULL);
323449248644SDavid Dillow static DEVICE_ATTR(cmd_sg_entries,  S_IRUGO, show_cmd_sg_entries,  NULL);
3235c07d424dSDavid Dillow static DEVICE_ATTR(allow_ext_sg,    S_IRUGO, show_allow_ext_sg,    NULL);
32366ecb0c84SRoland Dreier 
3237ee959b00STony Jones static struct device_attribute *srp_host_attrs[] = {
3238ee959b00STony Jones 	&dev_attr_id_ext,
3239ee959b00STony Jones 	&dev_attr_ioc_guid,
3240ee959b00STony Jones 	&dev_attr_service_id,
3241ee959b00STony Jones 	&dev_attr_pkey,
3242848b3082SBart Van Assche 	&dev_attr_sgid,
3243ee959b00STony Jones 	&dev_attr_dgid,
3244ee959b00STony Jones 	&dev_attr_orig_dgid,
324589de7486SBart Van Assche 	&dev_attr_req_lim,
3246ee959b00STony Jones 	&dev_attr_zero_req_lim,
3247ee959b00STony Jones 	&dev_attr_local_ib_port,
3248ee959b00STony Jones 	&dev_attr_local_ib_device,
3249d92c0da7SBart Van Assche 	&dev_attr_ch_count,
32504b5e5f41SBart Van Assche 	&dev_attr_comp_vector,
32517bb312e4SVu Pham 	&dev_attr_tl_retry_count,
325249248644SDavid Dillow 	&dev_attr_cmd_sg_entries,
3253c07d424dSDavid Dillow 	&dev_attr_allow_ext_sg,
32546ecb0c84SRoland Dreier 	NULL
32556ecb0c84SRoland Dreier };
32566ecb0c84SRoland Dreier 
3257aef9ec39SRoland Dreier static struct scsi_host_template srp_template = {
3258aef9ec39SRoland Dreier 	.module				= THIS_MODULE,
3259b7f008fdSRoland Dreier 	.name				= "InfiniBand SRP initiator",
3260b7f008fdSRoland Dreier 	.proc_name			= DRV_NAME,
3261b0780ee5SBart Van Assche 	.target_alloc			= srp_target_alloc,
3262c9b03c1aSBart Van Assche 	.slave_configure		= srp_slave_configure,
3263aef9ec39SRoland Dreier 	.info				= srp_target_info,
3264aef9ec39SRoland Dreier 	.queuecommand			= srp_queuecommand,
326571444b97SJack Wang 	.change_queue_depth             = srp_change_queue_depth,
3266b6a05c82SChristoph Hellwig 	.eh_timed_out			= srp_timed_out,
3267aef9ec39SRoland Dreier 	.eh_abort_handler		= srp_abort,
3268aef9ec39SRoland Dreier 	.eh_device_reset_handler	= srp_reset_device,
3269aef9ec39SRoland Dreier 	.eh_host_reset_handler		= srp_reset_host,
32702742c1daSBart Van Assche 	.skip_settle_delay		= true,
327149248644SDavid Dillow 	.sg_tablesize			= SRP_DEF_SG_TABLESIZE,
32724d73f95fSBart Van Assche 	.can_queue			= SRP_DEFAULT_CMD_SQ_SIZE,
3273aef9ec39SRoland Dreier 	.this_id			= -1,
32744d73f95fSBart Van Assche 	.cmd_per_lun			= SRP_DEFAULT_CMD_SQ_SIZE,
327577f2c1a4SBart Van Assche 	.shost_attrs			= srp_host_attrs,
3276c40ecc12SChristoph Hellwig 	.track_queue_depth		= 1,
3277aef9ec39SRoland Dreier };
3278aef9ec39SRoland Dreier 
327934aa654eSBart Van Assche static int srp_sdev_count(struct Scsi_Host *host)
328034aa654eSBart Van Assche {
328134aa654eSBart Van Assche 	struct scsi_device *sdev;
328234aa654eSBart Van Assche 	int c = 0;
328334aa654eSBart Van Assche 
328434aa654eSBart Van Assche 	shost_for_each_device(sdev, host)
328534aa654eSBart Van Assche 		c++;
328634aa654eSBart Van Assche 
328734aa654eSBart Van Assche 	return c;
328834aa654eSBart Van Assche }
328934aa654eSBart Van Assche 
3290bc44bd1dSBart Van Assche /*
3291bc44bd1dSBart Van Assche  * Return values:
3292bc44bd1dSBart Van Assche  * < 0 upon failure. Caller is responsible for SRP target port cleanup.
3293bc44bd1dSBart Van Assche  * 0 and target->state == SRP_TARGET_REMOVED if asynchronous target port
3294bc44bd1dSBart Van Assche  *    removal has been scheduled.
3295bc44bd1dSBart Van Assche  * 0 and target->state != SRP_TARGET_REMOVED upon success.
3296bc44bd1dSBart Van Assche  */
3297aef9ec39SRoland Dreier static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
3298aef9ec39SRoland Dreier {
32993236822bSFUJITA Tomonori 	struct srp_rport_identifiers ids;
33003236822bSFUJITA Tomonori 	struct srp_rport *rport;
33013236822bSFUJITA Tomonori 
330234aa654eSBart Van Assche 	target->state = SRP_TARGET_SCANNING;
3303aef9ec39SRoland Dreier 	sprintf(target->target_name, "SRP.T10:%016llX",
330445c37cadSBart Van Assche 		be64_to_cpu(target->id_ext));
3305aef9ec39SRoland Dreier 
3306dee2b82aSBart Van Assche 	if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dev.parent))
3307aef9ec39SRoland Dreier 		return -ENODEV;
3308aef9ec39SRoland Dreier 
33093236822bSFUJITA Tomonori 	memcpy(ids.port_id, &target->id_ext, 8);
33103236822bSFUJITA Tomonori 	memcpy(ids.port_id + 8, &target->ioc_guid, 8);
3311aebd5e47SFUJITA Tomonori 	ids.roles = SRP_RPORT_ROLE_TARGET;
33123236822bSFUJITA Tomonori 	rport = srp_rport_add(target->scsi_host, &ids);
33133236822bSFUJITA Tomonori 	if (IS_ERR(rport)) {
33143236822bSFUJITA Tomonori 		scsi_remove_host(target->scsi_host);
33153236822bSFUJITA Tomonori 		return PTR_ERR(rport);
33163236822bSFUJITA Tomonori 	}
33173236822bSFUJITA Tomonori 
3318dc1bdbd9SBart Van Assche 	rport->lld_data = target;
33199dd69a60SBart Van Assche 	target->rport = rport;
3320dc1bdbd9SBart Van Assche 
3321b3589fd4SMatthew Wilcox 	spin_lock(&host->target_lock);
3322aef9ec39SRoland Dreier 	list_add_tail(&target->list, &host->target_list);
3323b3589fd4SMatthew Wilcox 	spin_unlock(&host->target_lock);
3324aef9ec39SRoland Dreier 
3325aef9ec39SRoland Dreier 	scsi_scan_target(&target->scsi_host->shost_gendev,
33261d645088SHannes Reinecke 			 0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
3327aef9ec39SRoland Dreier 
3328c014c8cdSBart Van Assche 	if (srp_connected_ch(target) < target->ch_count ||
3329c014c8cdSBart Van Assche 	    target->qp_in_error) {
333034aa654eSBart Van Assche 		shost_printk(KERN_INFO, target->scsi_host,
333134aa654eSBart Van Assche 			     PFX "SCSI scan failed - removing SCSI host\n");
333234aa654eSBart Van Assche 		srp_queue_remove_work(target);
333334aa654eSBart Van Assche 		goto out;
333434aa654eSBart Van Assche 	}
333534aa654eSBart Van Assche 
3336cf1acab7SBart Van Assche 	pr_debug("%s: SCSI scan succeeded - detected %d LUNs\n",
333734aa654eSBart Van Assche 		 dev_name(&target->scsi_host->shost_gendev),
333834aa654eSBart Van Assche 		 srp_sdev_count(target->scsi_host));
333934aa654eSBart Van Assche 
334034aa654eSBart Van Assche 	spin_lock_irq(&target->lock);
334134aa654eSBart Van Assche 	if (target->state == SRP_TARGET_SCANNING)
334234aa654eSBart Van Assche 		target->state = SRP_TARGET_LIVE;
334334aa654eSBart Van Assche 	spin_unlock_irq(&target->lock);
334434aa654eSBart Van Assche 
334534aa654eSBart Van Assche out:
3346aef9ec39SRoland Dreier 	return 0;
3347aef9ec39SRoland Dreier }
3348aef9ec39SRoland Dreier 
3349ee959b00STony Jones static void srp_release_dev(struct device *dev)
3350aef9ec39SRoland Dreier {
3351aef9ec39SRoland Dreier 	struct srp_host *host =
3352ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3353aef9ec39SRoland Dreier 
3354aef9ec39SRoland Dreier 	complete(&host->released);
3355aef9ec39SRoland Dreier }
3356aef9ec39SRoland Dreier 
3357aef9ec39SRoland Dreier static struct class srp_class = {
3358aef9ec39SRoland Dreier 	.name    = "infiniband_srp",
3359ee959b00STony Jones 	.dev_release = srp_release_dev
3360aef9ec39SRoland Dreier };
3361aef9ec39SRoland Dreier 
336296fc248aSBart Van Assche /**
336396fc248aSBart Van Assche  * srp_conn_unique() - check whether the connection to a target is unique
3364af24663bSBart Van Assche  * @host:   SRP host.
3365af24663bSBart Van Assche  * @target: SRP target port.
336696fc248aSBart Van Assche  */
336796fc248aSBart Van Assche static bool srp_conn_unique(struct srp_host *host,
336896fc248aSBart Van Assche 			    struct srp_target_port *target)
336996fc248aSBart Van Assche {
337096fc248aSBart Van Assche 	struct srp_target_port *t;
337196fc248aSBart Van Assche 	bool ret = false;
337296fc248aSBart Van Assche 
337396fc248aSBart Van Assche 	if (target->state == SRP_TARGET_REMOVED)
337496fc248aSBart Van Assche 		goto out;
337596fc248aSBart Van Assche 
337696fc248aSBart Van Assche 	ret = true;
337796fc248aSBart Van Assche 
337896fc248aSBart Van Assche 	spin_lock(&host->target_lock);
337996fc248aSBart Van Assche 	list_for_each_entry(t, &host->target_list, list) {
338096fc248aSBart Van Assche 		if (t != target &&
338196fc248aSBart Van Assche 		    target->id_ext == t->id_ext &&
338296fc248aSBart Van Assche 		    target->ioc_guid == t->ioc_guid &&
338396fc248aSBart Van Assche 		    target->initiator_ext == t->initiator_ext) {
338496fc248aSBart Van Assche 			ret = false;
338596fc248aSBart Van Assche 			break;
338696fc248aSBart Van Assche 		}
338796fc248aSBart Van Assche 	}
338896fc248aSBart Van Assche 	spin_unlock(&host->target_lock);
338996fc248aSBart Van Assche 
339096fc248aSBart Van Assche out:
339196fc248aSBart Van Assche 	return ret;
339296fc248aSBart Van Assche }
339396fc248aSBart Van Assche 
3394aef9ec39SRoland Dreier /*
3395aef9ec39SRoland Dreier  * Target ports are added by writing
3396aef9ec39SRoland Dreier  *
3397aef9ec39SRoland Dreier  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>,
3398aef9ec39SRoland Dreier  *     pkey=<P_Key>,service_id=<service ID>
339919f31343SBart Van Assche  * or
340019f31343SBart Van Assche  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,
340119f31343SBart Van Assche  *     [src=<IPv4 address>,]dest=<IPv4 address>:<port number>
3402aef9ec39SRoland Dreier  *
3403aef9ec39SRoland Dreier  * to the add_target sysfs attribute.
3404aef9ec39SRoland Dreier  */
3405aef9ec39SRoland Dreier enum {
3406aef9ec39SRoland Dreier 	SRP_OPT_ERR		= 0,
3407aef9ec39SRoland Dreier 	SRP_OPT_ID_EXT		= 1 << 0,
3408aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	= 1 << 1,
3409aef9ec39SRoland Dreier 	SRP_OPT_DGID		= 1 << 2,
3410aef9ec39SRoland Dreier 	SRP_OPT_PKEY		= 1 << 3,
3411aef9ec39SRoland Dreier 	SRP_OPT_SERVICE_ID	= 1 << 4,
3412aef9ec39SRoland Dreier 	SRP_OPT_MAX_SECT	= 1 << 5,
341352fb2b50SVu Pham 	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
34140c0450dbSRamachandra K 	SRP_OPT_IO_CLASS	= 1 << 7,
341501cb9bcbSIshai Rabinovitz 	SRP_OPT_INITIATOR_EXT	= 1 << 8,
341649248644SDavid Dillow 	SRP_OPT_CMD_SG_ENTRIES	= 1 << 9,
3417c07d424dSDavid Dillow 	SRP_OPT_ALLOW_EXT_SG	= 1 << 10,
3418c07d424dSDavid Dillow 	SRP_OPT_SG_TABLESIZE	= 1 << 11,
34194b5e5f41SBart Van Assche 	SRP_OPT_COMP_VECTOR	= 1 << 12,
34207bb312e4SVu Pham 	SRP_OPT_TL_RETRY_COUNT	= 1 << 13,
34214d73f95fSBart Van Assche 	SRP_OPT_QUEUE_SIZE	= 1 << 14,
342219f31343SBart Van Assche 	SRP_OPT_IP_SRC		= 1 << 15,
342319f31343SBart Van Assche 	SRP_OPT_IP_DEST		= 1 << 16,
3424b0780ee5SBart Van Assche 	SRP_OPT_TARGET_CAN_QUEUE= 1 << 17,
3425547ed331SHonggang Li 	SRP_OPT_MAX_IT_IU_SIZE  = 1 << 18,
342619f31343SBart Van Assche };
342719f31343SBart Van Assche 
342819f31343SBart Van Assche static unsigned int srp_opt_mandatory[] = {
342919f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
3430aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	|
3431aef9ec39SRoland Dreier 	SRP_OPT_DGID		|
3432aef9ec39SRoland Dreier 	SRP_OPT_PKEY		|
343319f31343SBart Van Assche 	SRP_OPT_SERVICE_ID,
343419f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
343519f31343SBart Van Assche 	SRP_OPT_IOC_GUID	|
343619f31343SBart Van Assche 	SRP_OPT_IP_DEST,
3437aef9ec39SRoland Dreier };
3438aef9ec39SRoland Dreier 
3439a447c093SSteven Whitehouse static const match_table_t srp_opt_tokens = {
3440aef9ec39SRoland Dreier 	{ SRP_OPT_ID_EXT,		"id_ext=%s" 		},
3441aef9ec39SRoland Dreier 	{ SRP_OPT_IOC_GUID,		"ioc_guid=%s" 		},
3442aef9ec39SRoland Dreier 	{ SRP_OPT_DGID,			"dgid=%s" 		},
3443aef9ec39SRoland Dreier 	{ SRP_OPT_PKEY,			"pkey=%x" 		},
3444aef9ec39SRoland Dreier 	{ SRP_OPT_SERVICE_ID,		"service_id=%s"		},
3445aef9ec39SRoland Dreier 	{ SRP_OPT_MAX_SECT,		"max_sect=%d" 		},
344652fb2b50SVu Pham 	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
3447b0780ee5SBart Van Assche 	{ SRP_OPT_TARGET_CAN_QUEUE,	"target_can_queue=%d"	},
34480c0450dbSRamachandra K 	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
344901cb9bcbSIshai Rabinovitz 	{ SRP_OPT_INITIATOR_EXT,	"initiator_ext=%s"	},
345049248644SDavid Dillow 	{ SRP_OPT_CMD_SG_ENTRIES,	"cmd_sg_entries=%u"	},
3451c07d424dSDavid Dillow 	{ SRP_OPT_ALLOW_EXT_SG,		"allow_ext_sg=%u"	},
3452c07d424dSDavid Dillow 	{ SRP_OPT_SG_TABLESIZE,		"sg_tablesize=%u"	},
34534b5e5f41SBart Van Assche 	{ SRP_OPT_COMP_VECTOR,		"comp_vector=%u"	},
34547bb312e4SVu Pham 	{ SRP_OPT_TL_RETRY_COUNT,	"tl_retry_count=%u"	},
34554d73f95fSBart Van Assche 	{ SRP_OPT_QUEUE_SIZE,		"queue_size=%d"		},
345619f31343SBart Van Assche 	{ SRP_OPT_IP_SRC,		"src=%s"		},
345719f31343SBart Van Assche 	{ SRP_OPT_IP_DEST,		"dest=%s"		},
3458547ed331SHonggang Li 	{ SRP_OPT_MAX_IT_IU_SIZE,	"max_it_iu_size=%d"	},
3459aef9ec39SRoland Dreier 	{ SRP_OPT_ERR,			NULL 			}
3460aef9ec39SRoland Dreier };
3461aef9ec39SRoland Dreier 
3462c62adb7dSBart Van Assche /**
3463c62adb7dSBart Van Assche  * srp_parse_in - parse an IP address and port number combination
3464e37df2d5SBart Van Assche  * @net:	   [in]  Network namespace.
3465e37df2d5SBart Van Assche  * @sa:		   [out] Address family, IP address and port number.
3466e37df2d5SBart Van Assche  * @addr_port_str: [in]  IP address and port number.
3467bcef5b72SBart Van Assche  * @has_port:	   [out] Whether or not @addr_port_str includes a port number.
3468c62adb7dSBart Van Assche  *
3469c62adb7dSBart Van Assche  * Parse the following address formats:
3470c62adb7dSBart Van Assche  * - IPv4: <ip_address>:<port>, e.g. 1.2.3.4:5.
3471c62adb7dSBart Van Assche  * - IPv6: \[<ipv6_address>\]:<port>, e.g. [1::2:3%4]:5.
3472c62adb7dSBart Van Assche  */
347319f31343SBart Van Assche static int srp_parse_in(struct net *net, struct sockaddr_storage *sa,
3474bcef5b72SBart Van Assche 			const char *addr_port_str, bool *has_port)
347519f31343SBart Van Assche {
3476c62adb7dSBart Van Assche 	char *addr_end, *addr = kstrdup(addr_port_str, GFP_KERNEL);
3477c62adb7dSBart Van Assche 	char *port_str;
347819f31343SBart Van Assche 	int ret;
347919f31343SBart Van Assche 
348019f31343SBart Van Assche 	if (!addr)
348119f31343SBart Van Assche 		return -ENOMEM;
3482c62adb7dSBart Van Assche 	port_str = strrchr(addr, ':');
3483bcef5b72SBart Van Assche 	if (port_str && strchr(port_str, ']'))
3484bcef5b72SBart Van Assche 		port_str = NULL;
3485bcef5b72SBart Van Assche 	if (port_str)
3486c62adb7dSBart Van Assche 		*port_str++ = '\0';
3487bcef5b72SBart Van Assche 	if (has_port)
3488bcef5b72SBart Van Assche 		*has_port = port_str != NULL;
3489c62adb7dSBart Van Assche 	ret = inet_pton_with_scope(net, AF_INET, addr, port_str, sa);
3490c62adb7dSBart Van Assche 	if (ret && addr[0]) {
3491c62adb7dSBart Van Assche 		addr_end = addr + strlen(addr) - 1;
3492c62adb7dSBart Van Assche 		if (addr[0] == '[' && *addr_end == ']') {
3493c62adb7dSBart Van Assche 			*addr_end = '\0';
3494c62adb7dSBart Van Assche 			ret = inet_pton_with_scope(net, AF_INET6, addr + 1,
3495c62adb7dSBart Van Assche 						   port_str, sa);
3496c62adb7dSBart Van Assche 		}
3497c62adb7dSBart Van Assche 	}
349819f31343SBart Van Assche 	kfree(addr);
3499c62adb7dSBart Van Assche 	pr_debug("%s -> %pISpfsc\n", addr_port_str, sa);
350019f31343SBart Van Assche 	return ret;
350119f31343SBart Van Assche }
350219f31343SBart Van Assche 
350319f31343SBart Van Assche static int srp_parse_options(struct net *net, const char *buf,
350419f31343SBart Van Assche 			     struct srp_target_port *target)
3505aef9ec39SRoland Dreier {
3506aef9ec39SRoland Dreier 	char *options, *sep_opt;
3507aef9ec39SRoland Dreier 	char *p;
3508aef9ec39SRoland Dreier 	substring_t args[MAX_OPT_ARGS];
35092a174df0SBart Van Assche 	unsigned long long ull;
3510bcef5b72SBart Van Assche 	bool has_port;
3511aef9ec39SRoland Dreier 	int opt_mask = 0;
3512aef9ec39SRoland Dreier 	int token;
3513aef9ec39SRoland Dreier 	int ret = -EINVAL;
3514aef9ec39SRoland Dreier 	int i;
3515aef9ec39SRoland Dreier 
3516aef9ec39SRoland Dreier 	options = kstrdup(buf, GFP_KERNEL);
3517aef9ec39SRoland Dreier 	if (!options)
3518aef9ec39SRoland Dreier 		return -ENOMEM;
3519aef9ec39SRoland Dreier 
3520aef9ec39SRoland Dreier 	sep_opt = options;
35217dcf9c19SSagi Grimberg 	while ((p = strsep(&sep_opt, ",\n")) != NULL) {
3522aef9ec39SRoland Dreier 		if (!*p)
3523aef9ec39SRoland Dreier 			continue;
3524aef9ec39SRoland Dreier 
3525aef9ec39SRoland Dreier 		token = match_token(p, srp_opt_tokens, args);
3526aef9ec39SRoland Dreier 		opt_mask |= token;
3527aef9ec39SRoland Dreier 
3528aef9ec39SRoland Dreier 		switch (token) {
3529aef9ec39SRoland Dreier 		case SRP_OPT_ID_EXT:
3530aef9ec39SRoland Dreier 			p = match_strdup(args);
3531a20f3a6dSIshai Rabinovitz 			if (!p) {
3532a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3533a20f3a6dSIshai Rabinovitz 				goto out;
3534a20f3a6dSIshai Rabinovitz 			}
35352a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35362a174df0SBart Van Assche 			if (ret) {
35372a174df0SBart Van Assche 				pr_warn("invalid id_ext parameter '%s'\n", p);
35382a174df0SBart Van Assche 				kfree(p);
35392a174df0SBart Van Assche 				goto out;
35402a174df0SBart Van Assche 			}
35412a174df0SBart Van Assche 			target->id_ext = cpu_to_be64(ull);
3542aef9ec39SRoland Dreier 			kfree(p);
3543aef9ec39SRoland Dreier 			break;
3544aef9ec39SRoland Dreier 
3545aef9ec39SRoland Dreier 		case SRP_OPT_IOC_GUID:
3546aef9ec39SRoland Dreier 			p = match_strdup(args);
3547a20f3a6dSIshai Rabinovitz 			if (!p) {
3548a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3549a20f3a6dSIshai Rabinovitz 				goto out;
3550a20f3a6dSIshai Rabinovitz 			}
35512a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35522a174df0SBart Van Assche 			if (ret) {
35532a174df0SBart Van Assche 				pr_warn("invalid ioc_guid parameter '%s'\n", p);
35542a174df0SBart Van Assche 				kfree(p);
35552a174df0SBart Van Assche 				goto out;
35562a174df0SBart Van Assche 			}
35572a174df0SBart Van Assche 			target->ioc_guid = cpu_to_be64(ull);
3558aef9ec39SRoland Dreier 			kfree(p);
3559aef9ec39SRoland Dreier 			break;
3560aef9ec39SRoland Dreier 
3561aef9ec39SRoland Dreier 		case SRP_OPT_DGID:
3562aef9ec39SRoland Dreier 			p = match_strdup(args);
3563a20f3a6dSIshai Rabinovitz 			if (!p) {
3564a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3565a20f3a6dSIshai Rabinovitz 				goto out;
3566a20f3a6dSIshai Rabinovitz 			}
3567aef9ec39SRoland Dreier 			if (strlen(p) != 32) {
3568e0bda7d8SBart Van Assche 				pr_warn("bad dest GID parameter '%s'\n", p);
3569ce1823f0SRoland Dreier 				kfree(p);
3570aef9ec39SRoland Dreier 				goto out;
3571aef9ec39SRoland Dreier 			}
3572aef9ec39SRoland Dreier 
357319f31343SBart Van Assche 			ret = hex2bin(target->ib_cm.orig_dgid.raw, p, 16);
3574747fe000SBart Van Assche 			kfree(p);
3575e711f968SAndy Shevchenko 			if (ret < 0)
3576747fe000SBart Van Assche 				goto out;
3577aef9ec39SRoland Dreier 			break;
3578aef9ec39SRoland Dreier 
3579aef9ec39SRoland Dreier 		case SRP_OPT_PKEY:
3580aef9ec39SRoland Dreier 			if (match_hex(args, &token)) {
3581e0bda7d8SBart Van Assche 				pr_warn("bad P_Key parameter '%s'\n", p);
3582aef9ec39SRoland Dreier 				goto out;
3583aef9ec39SRoland Dreier 			}
358419f31343SBart Van Assche 			target->ib_cm.pkey = cpu_to_be16(token);
3585aef9ec39SRoland Dreier 			break;
3586aef9ec39SRoland Dreier 
3587aef9ec39SRoland Dreier 		case SRP_OPT_SERVICE_ID:
3588aef9ec39SRoland Dreier 			p = match_strdup(args);
3589a20f3a6dSIshai Rabinovitz 			if (!p) {
3590a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3591a20f3a6dSIshai Rabinovitz 				goto out;
3592a20f3a6dSIshai Rabinovitz 			}
35932a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35942a174df0SBart Van Assche 			if (ret) {
35952a174df0SBart Van Assche 				pr_warn("bad service_id parameter '%s'\n", p);
35962a174df0SBart Van Assche 				kfree(p);
35972a174df0SBart Van Assche 				goto out;
35982a174df0SBart Van Assche 			}
359919f31343SBart Van Assche 			target->ib_cm.service_id = cpu_to_be64(ull);
360019f31343SBart Van Assche 			kfree(p);
360119f31343SBart Van Assche 			break;
360219f31343SBart Van Assche 
360319f31343SBart Van Assche 		case SRP_OPT_IP_SRC:
360419f31343SBart Van Assche 			p = match_strdup(args);
360519f31343SBart Van Assche 			if (!p) {
360619f31343SBart Van Assche 				ret = -ENOMEM;
360719f31343SBart Van Assche 				goto out;
360819f31343SBart Van Assche 			}
3609bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.src.ss, p,
3610bcef5b72SBart Van Assche 					   NULL);
361119f31343SBart Van Assche 			if (ret < 0) {
361219f31343SBart Van Assche 				pr_warn("bad source parameter '%s'\n", p);
361319f31343SBart Van Assche 				kfree(p);
361419f31343SBart Van Assche 				goto out;
361519f31343SBart Van Assche 			}
361619f31343SBart Van Assche 			target->rdma_cm.src_specified = true;
361719f31343SBart Van Assche 			kfree(p);
361819f31343SBart Van Assche 			break;
361919f31343SBart Van Assche 
362019f31343SBart Van Assche 		case SRP_OPT_IP_DEST:
362119f31343SBart Van Assche 			p = match_strdup(args);
362219f31343SBart Van Assche 			if (!p) {
362319f31343SBart Van Assche 				ret = -ENOMEM;
362419f31343SBart Van Assche 				goto out;
362519f31343SBart Van Assche 			}
3626bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.dst.ss, p,
3627bcef5b72SBart Van Assche 					   &has_port);
3628bcef5b72SBart Van Assche 			if (!has_port)
3629bcef5b72SBart Van Assche 				ret = -EINVAL;
363019f31343SBart Van Assche 			if (ret < 0) {
363119f31343SBart Van Assche 				pr_warn("bad dest parameter '%s'\n", p);
363219f31343SBart Van Assche 				kfree(p);
363319f31343SBart Van Assche 				goto out;
363419f31343SBart Van Assche 			}
363519f31343SBart Van Assche 			target->using_rdma_cm = true;
3636aef9ec39SRoland Dreier 			kfree(p);
3637aef9ec39SRoland Dreier 			break;
3638aef9ec39SRoland Dreier 
3639aef9ec39SRoland Dreier 		case SRP_OPT_MAX_SECT:
3640aef9ec39SRoland Dreier 			if (match_int(args, &token)) {
3641e0bda7d8SBart Van Assche 				pr_warn("bad max sect parameter '%s'\n", p);
3642aef9ec39SRoland Dreier 				goto out;
3643aef9ec39SRoland Dreier 			}
3644aef9ec39SRoland Dreier 			target->scsi_host->max_sectors = token;
3645aef9ec39SRoland Dreier 			break;
3646aef9ec39SRoland Dreier 
36474d73f95fSBart Van Assche 		case SRP_OPT_QUEUE_SIZE:
36484d73f95fSBart Van Assche 			if (match_int(args, &token) || token < 1) {
36494d73f95fSBart Van Assche 				pr_warn("bad queue_size parameter '%s'\n", p);
36504d73f95fSBart Van Assche 				goto out;
36514d73f95fSBart Van Assche 			}
36524d73f95fSBart Van Assche 			target->scsi_host->can_queue = token;
36534d73f95fSBart Van Assche 			target->queue_size = token + SRP_RSP_SQ_SIZE +
36544d73f95fSBart Van Assche 					     SRP_TSK_MGMT_SQ_SIZE;
36554d73f95fSBart Van Assche 			if (!(opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
36564d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun = token;
36574d73f95fSBart Van Assche 			break;
36584d73f95fSBart Van Assche 
365952fb2b50SVu Pham 		case SRP_OPT_MAX_CMD_PER_LUN:
36604d73f95fSBart Van Assche 			if (match_int(args, &token) || token < 1) {
3661e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_per_lun parameter '%s'\n",
3662e0bda7d8SBart Van Assche 					p);
366352fb2b50SVu Pham 				goto out;
366452fb2b50SVu Pham 			}
36654d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun = token;
366652fb2b50SVu Pham 			break;
366752fb2b50SVu Pham 
3668b0780ee5SBart Van Assche 		case SRP_OPT_TARGET_CAN_QUEUE:
3669b0780ee5SBart Van Assche 			if (match_int(args, &token) || token < 1) {
3670b0780ee5SBart Van Assche 				pr_warn("bad max target_can_queue parameter '%s'\n",
3671b0780ee5SBart Van Assche 					p);
3672b0780ee5SBart Van Assche 				goto out;
3673b0780ee5SBart Van Assche 			}
3674b0780ee5SBart Van Assche 			target->target_can_queue = token;
3675b0780ee5SBart Van Assche 			break;
3676b0780ee5SBart Van Assche 
36770c0450dbSRamachandra K 		case SRP_OPT_IO_CLASS:
36780c0450dbSRamachandra K 			if (match_hex(args, &token)) {
3679e0bda7d8SBart Van Assche 				pr_warn("bad IO class parameter '%s'\n", p);
36800c0450dbSRamachandra K 				goto out;
36810c0450dbSRamachandra K 			}
36820c0450dbSRamachandra K 			if (token != SRP_REV10_IB_IO_CLASS &&
36830c0450dbSRamachandra K 			    token != SRP_REV16A_IB_IO_CLASS) {
3684e0bda7d8SBart Van Assche 				pr_warn("unknown IO class parameter value %x specified (use %x or %x).\n",
3685e0bda7d8SBart Van Assche 					token, SRP_REV10_IB_IO_CLASS,
3686e0bda7d8SBart Van Assche 					SRP_REV16A_IB_IO_CLASS);
36870c0450dbSRamachandra K 				goto out;
36880c0450dbSRamachandra K 			}
36890c0450dbSRamachandra K 			target->io_class = token;
36900c0450dbSRamachandra K 			break;
36910c0450dbSRamachandra K 
369201cb9bcbSIshai Rabinovitz 		case SRP_OPT_INITIATOR_EXT:
369301cb9bcbSIshai Rabinovitz 			p = match_strdup(args);
3694a20f3a6dSIshai Rabinovitz 			if (!p) {
3695a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3696a20f3a6dSIshai Rabinovitz 				goto out;
3697a20f3a6dSIshai Rabinovitz 			}
36982a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
36992a174df0SBart Van Assche 			if (ret) {
37002a174df0SBart Van Assche 				pr_warn("bad initiator_ext value '%s'\n", p);
37012a174df0SBart Van Assche 				kfree(p);
37022a174df0SBart Van Assche 				goto out;
37032a174df0SBart Van Assche 			}
37042a174df0SBart Van Assche 			target->initiator_ext = cpu_to_be64(ull);
370501cb9bcbSIshai Rabinovitz 			kfree(p);
370601cb9bcbSIshai Rabinovitz 			break;
370701cb9bcbSIshai Rabinovitz 
370849248644SDavid Dillow 		case SRP_OPT_CMD_SG_ENTRIES:
370949248644SDavid Dillow 			if (match_int(args, &token) || token < 1 || token > 255) {
3710e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_sg_entries parameter '%s'\n",
3711e0bda7d8SBart Van Assche 					p);
371249248644SDavid Dillow 				goto out;
371349248644SDavid Dillow 			}
371449248644SDavid Dillow 			target->cmd_sg_cnt = token;
371549248644SDavid Dillow 			break;
371649248644SDavid Dillow 
3717c07d424dSDavid Dillow 		case SRP_OPT_ALLOW_EXT_SG:
3718c07d424dSDavid Dillow 			if (match_int(args, &token)) {
3719e0bda7d8SBart Van Assche 				pr_warn("bad allow_ext_sg parameter '%s'\n", p);
3720c07d424dSDavid Dillow 				goto out;
3721c07d424dSDavid Dillow 			}
3722c07d424dSDavid Dillow 			target->allow_ext_sg = !!token;
3723c07d424dSDavid Dillow 			break;
3724c07d424dSDavid Dillow 
3725c07d424dSDavid Dillow 		case SRP_OPT_SG_TABLESIZE:
3726c07d424dSDavid Dillow 			if (match_int(args, &token) || token < 1 ||
372765e8617fSMing Lin 					token > SG_MAX_SEGMENTS) {
3728e0bda7d8SBart Van Assche 				pr_warn("bad max sg_tablesize parameter '%s'\n",
3729e0bda7d8SBart Van Assche 					p);
3730c07d424dSDavid Dillow 				goto out;
3731c07d424dSDavid Dillow 			}
3732c07d424dSDavid Dillow 			target->sg_tablesize = token;
3733c07d424dSDavid Dillow 			break;
3734c07d424dSDavid Dillow 
37354b5e5f41SBart Van Assche 		case SRP_OPT_COMP_VECTOR:
37364b5e5f41SBart Van Assche 			if (match_int(args, &token) || token < 0) {
37374b5e5f41SBart Van Assche 				pr_warn("bad comp_vector parameter '%s'\n", p);
37384b5e5f41SBart Van Assche 				goto out;
37394b5e5f41SBart Van Assche 			}
37404b5e5f41SBart Van Assche 			target->comp_vector = token;
37414b5e5f41SBart Van Assche 			break;
37424b5e5f41SBart Van Assche 
37437bb312e4SVu Pham 		case SRP_OPT_TL_RETRY_COUNT:
37447bb312e4SVu Pham 			if (match_int(args, &token) || token < 2 || token > 7) {
37457bb312e4SVu Pham 				pr_warn("bad tl_retry_count parameter '%s' (must be a number between 2 and 7)\n",
37467bb312e4SVu Pham 					p);
37477bb312e4SVu Pham 				goto out;
37487bb312e4SVu Pham 			}
37497bb312e4SVu Pham 			target->tl_retry_count = token;
37507bb312e4SVu Pham 			break;
37517bb312e4SVu Pham 
3752547ed331SHonggang Li 		case SRP_OPT_MAX_IT_IU_SIZE:
3753547ed331SHonggang Li 			if (match_int(args, &token) || token < 0) {
3754547ed331SHonggang Li 				pr_warn("bad maximum initiator to target IU size '%s'\n", p);
3755547ed331SHonggang Li 				goto out;
3756547ed331SHonggang Li 			}
3757547ed331SHonggang Li 			target->max_it_iu_size = token;
3758547ed331SHonggang Li 			break;
3759547ed331SHonggang Li 
3760aef9ec39SRoland Dreier 		default:
3761e0bda7d8SBart Van Assche 			pr_warn("unknown parameter or missing value '%s' in target creation request\n",
3762e0bda7d8SBart Van Assche 				p);
3763aef9ec39SRoland Dreier 			goto out;
3764aef9ec39SRoland Dreier 		}
3765aef9ec39SRoland Dreier 	}
3766aef9ec39SRoland Dreier 
376719f31343SBart Van Assche 	for (i = 0; i < ARRAY_SIZE(srp_opt_mandatory); i++) {
376819f31343SBart Van Assche 		if ((opt_mask & srp_opt_mandatory[i]) == srp_opt_mandatory[i]) {
3769aef9ec39SRoland Dreier 			ret = 0;
377019f31343SBart Van Assche 			break;
377119f31343SBart Van Assche 		}
377219f31343SBart Van Assche 	}
377319f31343SBart Van Assche 	if (ret)
377419f31343SBart Van Assche 		pr_warn("target creation request is missing one or more parameters\n");
3775aef9ec39SRoland Dreier 
37764d73f95fSBart Van Assche 	if (target->scsi_host->cmd_per_lun > target->scsi_host->can_queue
37774d73f95fSBart Van Assche 	    && (opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
37784d73f95fSBart Van Assche 		pr_warn("cmd_per_lun = %d > queue_size = %d\n",
37794d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun,
37804d73f95fSBart Van Assche 			target->scsi_host->can_queue);
37814d73f95fSBart Van Assche 
3782aef9ec39SRoland Dreier out:
3783aef9ec39SRoland Dreier 	kfree(options);
3784aef9ec39SRoland Dreier 	return ret;
3785aef9ec39SRoland Dreier }
3786aef9ec39SRoland Dreier 
3787ee959b00STony Jones static ssize_t srp_create_target(struct device *dev,
3788ee959b00STony Jones 				 struct device_attribute *attr,
3789aef9ec39SRoland Dreier 				 const char *buf, size_t count)
3790aef9ec39SRoland Dreier {
3791aef9ec39SRoland Dreier 	struct srp_host *host =
3792ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3793aef9ec39SRoland Dreier 	struct Scsi_Host *target_host;
3794aef9ec39SRoland Dreier 	struct srp_target_port *target;
3795509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
3796d1b4289eSBart Van Assche 	struct srp_device *srp_dev = host->srp_dev;
3797d1b4289eSBart Van Assche 	struct ib_device *ibdev = srp_dev->dev;
3798d92c0da7SBart Van Assche 	int ret, node_idx, node, cpu, i;
3799509c5f33SBart Van Assche 	unsigned int max_sectors_per_mr, mr_per_cmd = 0;
3800d92c0da7SBart Van Assche 	bool multich = false;
3801513d5647SBart Van Assche 	uint32_t max_iu_len;
3802aef9ec39SRoland Dreier 
3803aef9ec39SRoland Dreier 	target_host = scsi_host_alloc(&srp_template,
3804aef9ec39SRoland Dreier 				      sizeof (struct srp_target_port));
3805aef9ec39SRoland Dreier 	if (!target_host)
3806aef9ec39SRoland Dreier 		return -ENOMEM;
3807aef9ec39SRoland Dreier 
38083236822bSFUJITA Tomonori 	target_host->transportt  = ib_srp_transport_template;
3809fd1b6c4aSBart Van Assche 	target_host->max_channel = 0;
3810fd1b6c4aSBart Van Assche 	target_host->max_id      = 1;
3811985aa495SBart Van Assche 	target_host->max_lun     = -1LL;
38123c8edf0eSArne Redlich 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
38130b5cb330SBart Van Assche 	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
38145f068992SRoland Dreier 
38158c175d31SChristoph Hellwig 	if (!(ibdev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG))
38168c175d31SChristoph Hellwig 		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
38178c175d31SChristoph Hellwig 
3818aef9ec39SRoland Dreier 	target = host_to_target(target_host);
3819aef9ec39SRoland Dreier 
382019f31343SBart Van Assche 	target->net		= kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
38210c0450dbSRamachandra K 	target->io_class	= SRP_REV16A_IB_IO_CLASS;
3822aef9ec39SRoland Dreier 	target->scsi_host	= target_host;
3823aef9ec39SRoland Dreier 	target->srp_host	= host;
3824e6bf5f48SJason Gunthorpe 	target->lkey		= host->srp_dev->pd->local_dma_lkey;
3825cee687b6SBart Van Assche 	target->global_rkey	= host->srp_dev->global_rkey;
382649248644SDavid Dillow 	target->cmd_sg_cnt	= cmd_sg_entries;
3827c07d424dSDavid Dillow 	target->sg_tablesize	= indirect_sg_entries ? : cmd_sg_entries;
3828c07d424dSDavid Dillow 	target->allow_ext_sg	= allow_ext_sg;
38297bb312e4SVu Pham 	target->tl_retry_count	= 7;
38304d73f95fSBart Van Assche 	target->queue_size	= SRP_DEFAULT_QUEUE_SIZE;
3831aef9ec39SRoland Dreier 
383234aa654eSBart Van Assche 	/*
383334aa654eSBart Van Assche 	 * Avoid that the SCSI host can be removed by srp_remove_target()
383434aa654eSBart Van Assche 	 * before this function returns.
383534aa654eSBart Van Assche 	 */
383634aa654eSBart Van Assche 	scsi_host_get(target->scsi_host);
383734aa654eSBart Van Assche 
38384fa354c9SBart Van Assche 	ret = mutex_lock_interruptible(&host->add_target_mutex);
38394fa354c9SBart Van Assche 	if (ret < 0)
38404fa354c9SBart Van Assche 		goto put;
38412d7091bcSBart Van Assche 
384219f31343SBart Van Assche 	ret = srp_parse_options(target->net, buf, target);
3843aef9ec39SRoland Dreier 	if (ret)
3844fb49c8bbSBart Van Assche 		goto out;
3845aef9ec39SRoland Dreier 
38464d73f95fSBart Van Assche 	target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
38474d73f95fSBart Van Assche 
384896fc248aSBart Van Assche 	if (!srp_conn_unique(target->srp_host, target)) {
384919f31343SBart Van Assche 		if (target->using_rdma_cm) {
385019f31343SBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
38517da09af9SBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;dest=%pIS\n",
385219f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
385319f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
38547da09af9SBart Van Assche 				     &target->rdma_cm.dst);
385519f31343SBart Van Assche 		} else {
385696fc248aSBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
385796fc248aSBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n",
385896fc248aSBart Van Assche 				     be64_to_cpu(target->id_ext),
385996fc248aSBart Van Assche 				     be64_to_cpu(target->ioc_guid),
386096fc248aSBart Van Assche 				     be64_to_cpu(target->initiator_ext));
386119f31343SBart Van Assche 		}
386296fc248aSBart Van Assche 		ret = -EEXIST;
3863fb49c8bbSBart Van Assche 		goto out;
386496fc248aSBart Van Assche 	}
386596fc248aSBart Van Assche 
38665cfb1782SBart Van Assche 	if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg &&
3867c07d424dSDavid Dillow 	    target->cmd_sg_cnt < target->sg_tablesize) {
38685cfb1782SBart Van Assche 		pr_warn("No MR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
3869c07d424dSDavid Dillow 		target->sg_tablesize = target->cmd_sg_cnt;
3870c07d424dSDavid Dillow 	}
3871c07d424dSDavid Dillow 
3872509c5f33SBart Van Assche 	if (srp_dev->use_fast_reg || srp_dev->use_fmr) {
3873fbd36818SSergey Gorenko 		bool gaps_reg = (ibdev->attrs.device_cap_flags &
3874fbd36818SSergey Gorenko 				 IB_DEVICE_SG_GAPS_REG);
3875fbd36818SSergey Gorenko 
3876509c5f33SBart Van Assche 		max_sectors_per_mr = srp_dev->max_pages_per_mr <<
3877509c5f33SBart Van Assche 				  (ilog2(srp_dev->mr_page_size) - 9);
3878fbd36818SSergey Gorenko 		if (!gaps_reg) {
3879fbd36818SSergey Gorenko 			/*
3880fbd36818SSergey Gorenko 			 * FR and FMR can only map one HCA page per entry. If
3881fbd36818SSergey Gorenko 			 * the start address is not aligned on a HCA page
3882fbd36818SSergey Gorenko 			 * boundary two entries will be used for the head and
3883fbd36818SSergey Gorenko 			 * the tail although these two entries combined
3884fbd36818SSergey Gorenko 			 * contain at most one HCA page of data. Hence the "+
3885fbd36818SSergey Gorenko 			 * 1" in the calculation below.
3886fbd36818SSergey Gorenko 			 *
3887fbd36818SSergey Gorenko 			 * The indirect data buffer descriptor is contiguous
3888fbd36818SSergey Gorenko 			 * so the memory for that buffer will only be
3889fbd36818SSergey Gorenko 			 * registered if register_always is true. Hence add
3890fbd36818SSergey Gorenko 			 * one to mr_per_cmd if register_always has been set.
3891fbd36818SSergey Gorenko 			 */
3892509c5f33SBart Van Assche 			mr_per_cmd = register_always +
3893509c5f33SBart Van Assche 				(target->scsi_host->max_sectors + 1 +
3894509c5f33SBart Van Assche 				 max_sectors_per_mr - 1) / max_sectors_per_mr;
3895fbd36818SSergey Gorenko 		} else {
3896fbd36818SSergey Gorenko 			mr_per_cmd = register_always +
3897fbd36818SSergey Gorenko 				(target->sg_tablesize +
3898fbd36818SSergey Gorenko 				 srp_dev->max_pages_per_mr - 1) /
3899fbd36818SSergey Gorenko 				srp_dev->max_pages_per_mr;
3900fbd36818SSergey Gorenko 		}
3901509c5f33SBart 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",
3902fbd36818SSergey Gorenko 			 target->scsi_host->max_sectors, srp_dev->max_pages_per_mr, srp_dev->mr_page_size,
3903509c5f33SBart Van Assche 			 max_sectors_per_mr, mr_per_cmd);
3904509c5f33SBart Van Assche 	}
3905509c5f33SBart Van Assche 
3906c07d424dSDavid Dillow 	target_host->sg_tablesize = target->sg_tablesize;
3907509c5f33SBart Van Assche 	target->mr_pool_size = target->scsi_host->can_queue * mr_per_cmd;
3908509c5f33SBart Van Assche 	target->mr_per_cmd = mr_per_cmd;
3909c07d424dSDavid Dillow 	target->indirect_size = target->sg_tablesize *
3910c07d424dSDavid Dillow 				sizeof (struct srp_direct_buf);
3911*b2e872f4SHonggang Li 	max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
3912*b2e872f4SHonggang Li 				       srp_use_imm_data,
3913*b2e872f4SHonggang Li 				       target->max_it_iu_size);
391449248644SDavid Dillow 
3915c1120f89SBart Van Assche 	INIT_WORK(&target->tl_err_work, srp_tl_err_work);
3916ef6c49d8SBart Van Assche 	INIT_WORK(&target->remove_work, srp_remove_work);
39178f26c9ffSDavid Dillow 	spin_lock_init(&target->lock);
39181dfce294SParav Pandit 	ret = rdma_query_gid(ibdev, host->port, 0, &target->sgid);
39192088ca66SSagi Grimberg 	if (ret)
3920fb49c8bbSBart Van Assche 		goto out;
3921d92c0da7SBart Van Assche 
3922d92c0da7SBart Van Assche 	ret = -ENOMEM;
3923d92c0da7SBart Van Assche 	target->ch_count = max_t(unsigned, num_online_nodes(),
3924d92c0da7SBart Van Assche 				 min(ch_count ? :
3925d92c0da7SBart Van Assche 				     min(4 * num_online_nodes(),
3926d92c0da7SBart Van Assche 					 ibdev->num_comp_vectors),
3927d92c0da7SBart Van Assche 				     num_online_cpus()));
3928d92c0da7SBart Van Assche 	target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
3929d92c0da7SBart Van Assche 			     GFP_KERNEL);
3930d92c0da7SBart Van Assche 	if (!target->ch)
3931fb49c8bbSBart Van Assche 		goto out;
3932d92c0da7SBart Van Assche 
3933d92c0da7SBart Van Assche 	node_idx = 0;
3934d92c0da7SBart Van Assche 	for_each_online_node(node) {
3935d92c0da7SBart Van Assche 		const int ch_start = (node_idx * target->ch_count /
3936d92c0da7SBart Van Assche 				      num_online_nodes());
3937d92c0da7SBart Van Assche 		const int ch_end = ((node_idx + 1) * target->ch_count /
3938d92c0da7SBart Van Assche 				    num_online_nodes());
39393a148896SBart Van Assche 		const int cv_start = node_idx * ibdev->num_comp_vectors /
39403a148896SBart Van Assche 				     num_online_nodes();
39413a148896SBart Van Assche 		const int cv_end = (node_idx + 1) * ibdev->num_comp_vectors /
39423a148896SBart Van Assche 				   num_online_nodes();
3943d92c0da7SBart Van Assche 		int cpu_idx = 0;
3944d92c0da7SBart Van Assche 
3945d92c0da7SBart Van Assche 		for_each_online_cpu(cpu) {
3946d92c0da7SBart Van Assche 			if (cpu_to_node(cpu) != node)
3947d92c0da7SBart Van Assche 				continue;
3948d92c0da7SBart Van Assche 			if (ch_start + cpu_idx >= ch_end)
3949d92c0da7SBart Van Assche 				continue;
3950d92c0da7SBart Van Assche 			ch = &target->ch[ch_start + cpu_idx];
3951d92c0da7SBart Van Assche 			ch->target = target;
3952d92c0da7SBart Van Assche 			ch->comp_vector = cv_start == cv_end ? cv_start :
3953d92c0da7SBart Van Assche 				cv_start + cpu_idx % (cv_end - cv_start);
3954d92c0da7SBart Van Assche 			spin_lock_init(&ch->lock);
3955d92c0da7SBart Van Assche 			INIT_LIST_HEAD(&ch->free_tx);
3956d92c0da7SBart Van Assche 			ret = srp_new_cm_id(ch);
3957d92c0da7SBart Van Assche 			if (ret)
3958d92c0da7SBart Van Assche 				goto err_disconnect;
3959aef9ec39SRoland Dreier 
3960509c07bcSBart Van Assche 			ret = srp_create_ch_ib(ch);
3961aef9ec39SRoland Dreier 			if (ret)
3962d92c0da7SBart Van Assche 				goto err_disconnect;
3963aef9ec39SRoland Dreier 
3964d92c0da7SBart Van Assche 			ret = srp_alloc_req_data(ch);
39659fe4bcf4SDavid Dillow 			if (ret)
3966d92c0da7SBart Van Assche 				goto err_disconnect;
3967aef9ec39SRoland Dreier 
3968513d5647SBart Van Assche 			ret = srp_connect_ch(ch, max_iu_len, multich);
3969aef9ec39SRoland Dreier 			if (ret) {
397019f31343SBart Van Assche 				char dst[64];
397119f31343SBart Van Assche 
397219f31343SBart Van Assche 				if (target->using_rdma_cm)
39737da09af9SBart Van Assche 					snprintf(dst, sizeof(dst), "%pIS",
39747da09af9SBart Van Assche 						 &target->rdma_cm.dst);
397519f31343SBart Van Assche 				else
397619f31343SBart Van Assche 					snprintf(dst, sizeof(dst), "%pI6",
397719f31343SBart Van Assche 						 target->ib_cm.orig_dgid.raw);
39787aa54bd7SDavid Dillow 				shost_printk(KERN_ERR, target->scsi_host,
397919f31343SBart Van Assche 					     PFX "Connection %d/%d to %s failed\n",
3980d92c0da7SBart Van Assche 					     ch_start + cpu_idx,
398119f31343SBart Van Assche 					     target->ch_count, dst);
3982d92c0da7SBart Van Assche 				if (node_idx == 0 && cpu_idx == 0) {
3983b02c1536SBart Van Assche 					goto free_ch;
3984d92c0da7SBart Van Assche 				} else {
3985d92c0da7SBart Van Assche 					srp_free_ch_ib(target, ch);
3986d92c0da7SBart Van Assche 					srp_free_req_data(target, ch);
3987d92c0da7SBart Van Assche 					target->ch_count = ch - target->ch;
3988c257ea6fSBart Van Assche 					goto connected;
3989aef9ec39SRoland Dreier 				}
3990d92c0da7SBart Van Assche 			}
3991d92c0da7SBart Van Assche 
3992d92c0da7SBart Van Assche 			multich = true;
3993d92c0da7SBart Van Assche 			cpu_idx++;
3994d92c0da7SBart Van Assche 		}
3995d92c0da7SBart Van Assche 		node_idx++;
3996d92c0da7SBart Van Assche 	}
3997d92c0da7SBart Van Assche 
3998c257ea6fSBart Van Assche connected:
3999d92c0da7SBart Van Assche 	target->scsi_host->nr_hw_queues = target->ch_count;
4000aef9ec39SRoland Dreier 
4001aef9ec39SRoland Dreier 	ret = srp_add_target(host, target);
4002aef9ec39SRoland Dreier 	if (ret)
4003aef9ec39SRoland Dreier 		goto err_disconnect;
4004aef9ec39SRoland Dreier 
400534aa654eSBart Van Assche 	if (target->state != SRP_TARGET_REMOVED) {
400619f31343SBart Van Assche 		if (target->using_rdma_cm) {
400719f31343SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
40087da09af9SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx sgid %pI6 dest %pIS\n",
400919f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
401019f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
40117da09af9SBart Van Assche 				     target->sgid.raw, &target->rdma_cm.dst);
401219f31343SBart Van Assche 		} else {
4013e7ffde01SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
4014e7ffde01SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
4015e7ffde01SBart Van Assche 				     be64_to_cpu(target->id_ext),
4016e7ffde01SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
401719f31343SBart Van Assche 				     be16_to_cpu(target->ib_cm.pkey),
401819f31343SBart Van Assche 				     be64_to_cpu(target->ib_cm.service_id),
401919f31343SBart Van Assche 				     target->sgid.raw,
402019f31343SBart Van Assche 				     target->ib_cm.orig_dgid.raw);
402119f31343SBart Van Assche 		}
402234aa654eSBart Van Assche 	}
4023e7ffde01SBart Van Assche 
40242d7091bcSBart Van Assche 	ret = count;
40252d7091bcSBart Van Assche 
40262d7091bcSBart Van Assche out:
40272d7091bcSBart Van Assche 	mutex_unlock(&host->add_target_mutex);
402834aa654eSBart Van Assche 
40294fa354c9SBart Van Assche put:
403034aa654eSBart Van Assche 	scsi_host_put(target->scsi_host);
403119f31343SBart Van Assche 	if (ret < 0) {
403219f31343SBart Van Assche 		/*
403319f31343SBart Van Assche 		 * If a call to srp_remove_target() has not been scheduled,
403419f31343SBart Van Assche 		 * drop the network namespace reference now that was obtained
403519f31343SBart Van Assche 		 * earlier in this function.
403619f31343SBart Van Assche 		 */
403719f31343SBart Van Assche 		if (target->state != SRP_TARGET_REMOVED)
403819f31343SBart Van Assche 			kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
4039bc44bd1dSBart Van Assche 		scsi_host_put(target->scsi_host);
404019f31343SBart Van Assche 	}
404134aa654eSBart Van Assche 
40422d7091bcSBart Van Assche 	return ret;
4043aef9ec39SRoland Dreier 
4044aef9ec39SRoland Dreier err_disconnect:
4045aef9ec39SRoland Dreier 	srp_disconnect_target(target);
4046aef9ec39SRoland Dreier 
4047b02c1536SBart Van Assche free_ch:
4048d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
4049d92c0da7SBart Van Assche 		ch = &target->ch[i];
4050509c07bcSBart Van Assche 		srp_free_ch_ib(target, ch);
4051509c07bcSBart Van Assche 		srp_free_req_data(target, ch);
4052d92c0da7SBart Van Assche 	}
4053d92c0da7SBart Van Assche 
4054d92c0da7SBart Van Assche 	kfree(target->ch);
40552d7091bcSBart Van Assche 	goto out;
4056aef9ec39SRoland Dreier }
4057aef9ec39SRoland Dreier 
4058ee959b00STony Jones static DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
4059aef9ec39SRoland Dreier 
4060ee959b00STony Jones static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
4061ee959b00STony Jones 			  char *buf)
4062aef9ec39SRoland Dreier {
4063ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
4064aef9ec39SRoland Dreier 
40656c854111SJason Gunthorpe 	return sprintf(buf, "%s\n", dev_name(&host->srp_dev->dev->dev));
4066aef9ec39SRoland Dreier }
4067aef9ec39SRoland Dreier 
4068ee959b00STony Jones static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
4069aef9ec39SRoland Dreier 
4070ee959b00STony Jones static ssize_t show_port(struct device *dev, struct device_attribute *attr,
4071ee959b00STony Jones 			 char *buf)
4072aef9ec39SRoland Dreier {
4073ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
4074aef9ec39SRoland Dreier 
4075aef9ec39SRoland Dreier 	return sprintf(buf, "%d\n", host->port);
4076aef9ec39SRoland Dreier }
4077aef9ec39SRoland Dreier 
4078ee959b00STony Jones static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
4079aef9ec39SRoland Dreier 
4080f5358a17SRoland Dreier static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
4081aef9ec39SRoland Dreier {
4082aef9ec39SRoland Dreier 	struct srp_host *host;
4083aef9ec39SRoland Dreier 
4084aef9ec39SRoland Dreier 	host = kzalloc(sizeof *host, GFP_KERNEL);
4085aef9ec39SRoland Dreier 	if (!host)
4086aef9ec39SRoland Dreier 		return NULL;
4087aef9ec39SRoland Dreier 
4088aef9ec39SRoland Dreier 	INIT_LIST_HEAD(&host->target_list);
4089b3589fd4SMatthew Wilcox 	spin_lock_init(&host->target_lock);
4090aef9ec39SRoland Dreier 	init_completion(&host->released);
40912d7091bcSBart Van Assche 	mutex_init(&host->add_target_mutex);
409205321937SGreg Kroah-Hartman 	host->srp_dev = device;
4093aef9ec39SRoland Dreier 	host->port = port;
4094aef9ec39SRoland Dreier 
4095ee959b00STony Jones 	host->dev.class = &srp_class;
4096dee2b82aSBart Van Assche 	host->dev.parent = device->dev->dev.parent;
40976c854111SJason Gunthorpe 	dev_set_name(&host->dev, "srp-%s-%d", dev_name(&device->dev->dev),
40986c854111SJason Gunthorpe 		     port);
4099aef9ec39SRoland Dreier 
4100ee959b00STony Jones 	if (device_register(&host->dev))
4101f5358a17SRoland Dreier 		goto free_host;
4102ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_add_target))
4103aef9ec39SRoland Dreier 		goto err_class;
4104ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_ibdev))
4105aef9ec39SRoland Dreier 		goto err_class;
4106ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_port))
4107aef9ec39SRoland Dreier 		goto err_class;
4108aef9ec39SRoland Dreier 
4109aef9ec39SRoland Dreier 	return host;
4110aef9ec39SRoland Dreier 
4111aef9ec39SRoland Dreier err_class:
4112ee959b00STony Jones 	device_unregister(&host->dev);
4113aef9ec39SRoland Dreier 
4114f5358a17SRoland Dreier free_host:
4115aef9ec39SRoland Dreier 	kfree(host);
4116aef9ec39SRoland Dreier 
4117aef9ec39SRoland Dreier 	return NULL;
4118aef9ec39SRoland Dreier }
4119aef9ec39SRoland Dreier 
4120dc1435c0SLeon Romanovsky static void srp_rename_dev(struct ib_device *device, void *client_data)
4121dc1435c0SLeon Romanovsky {
4122dc1435c0SLeon Romanovsky 	struct srp_device *srp_dev = client_data;
4123dc1435c0SLeon Romanovsky 	struct srp_host *host, *tmp_host;
4124dc1435c0SLeon Romanovsky 
4125dc1435c0SLeon Romanovsky 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
4126dc1435c0SLeon Romanovsky 		char name[IB_DEVICE_NAME_MAX + 8];
4127dc1435c0SLeon Romanovsky 
4128dc1435c0SLeon Romanovsky 		snprintf(name, sizeof(name), "srp-%s-%d",
4129dc1435c0SLeon Romanovsky 			 dev_name(&device->dev), host->port);
4130dc1435c0SLeon Romanovsky 		device_rename(&host->dev, name);
4131dc1435c0SLeon Romanovsky 	}
4132dc1435c0SLeon Romanovsky }
4133dc1435c0SLeon Romanovsky 
4134aef9ec39SRoland Dreier static void srp_add_one(struct ib_device *device)
4135aef9ec39SRoland Dreier {
4136f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4137042dd765SBart Van Assche 	struct ib_device_attr *attr = &device->attrs;
4138aef9ec39SRoland Dreier 	struct srp_host *host;
4139ea1075edSJason Gunthorpe 	int mr_page_shift;
4140ea1075edSJason Gunthorpe 	unsigned int p;
414152ede08fSBart Van Assche 	u64 max_pages_per_mr;
41425f071777SChristoph Hellwig 	unsigned int flags = 0;
4143aef9ec39SRoland Dreier 
4144249f0656SBart Van Assche 	srp_dev = kzalloc(sizeof(*srp_dev), GFP_KERNEL);
4145f5358a17SRoland Dreier 	if (!srp_dev)
41464a061b28SOr Gerlitz 		return;
4147f5358a17SRoland Dreier 
4148f5358a17SRoland Dreier 	/*
4149f5358a17SRoland Dreier 	 * Use the smallest page size supported by the HCA, down to a
41508f26c9ffSDavid Dillow 	 * minimum of 4096 bytes. We're unlikely to build large sglists
41518f26c9ffSDavid Dillow 	 * out of smaller entries.
4152f5358a17SRoland Dreier 	 */
4153042dd765SBart Van Assche 	mr_page_shift		= max(12, ffs(attr->page_size_cap) - 1);
415452ede08fSBart Van Assche 	srp_dev->mr_page_size	= 1 << mr_page_shift;
415552ede08fSBart Van Assche 	srp_dev->mr_page_mask	= ~((u64) srp_dev->mr_page_size - 1);
4156042dd765SBart Van Assche 	max_pages_per_mr	= attr->max_mr_size;
415752ede08fSBart Van Assche 	do_div(max_pages_per_mr, srp_dev->mr_page_size);
4158509c5f33SBart Van Assche 	pr_debug("%s: %llu / %u = %llu <> %u\n", __func__,
4159042dd765SBart Van Assche 		 attr->max_mr_size, srp_dev->mr_page_size,
4160509c5f33SBart Van Assche 		 max_pages_per_mr, SRP_MAX_PAGES_PER_MR);
416152ede08fSBart Van Assche 	srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR,
416252ede08fSBart Van Assche 					  max_pages_per_mr);
4163835ee624SBart Van Assche 
41643023a1e9SKamal Heib 	srp_dev->has_fmr = (device->ops.alloc_fmr &&
41653023a1e9SKamal Heib 			    device->ops.dealloc_fmr &&
41663023a1e9SKamal Heib 			    device->ops.map_phys_fmr &&
41673023a1e9SKamal Heib 			    device->ops.unmap_fmr);
4168042dd765SBart Van Assche 	srp_dev->has_fr = (attr->device_cap_flags &
4169835ee624SBart Van Assche 			   IB_DEVICE_MEM_MGT_EXTENSIONS);
4170c222a39fSBart Van Assche 	if (!never_register && !srp_dev->has_fmr && !srp_dev->has_fr) {
4171835ee624SBart Van Assche 		dev_warn(&device->dev, "neither FMR nor FR is supported\n");
4172c222a39fSBart Van Assche 	} else if (!never_register &&
4173042dd765SBart Van Assche 		   attr->max_mr_size >= 2 * srp_dev->mr_page_size) {
4174835ee624SBart Van Assche 		srp_dev->use_fast_reg = (srp_dev->has_fr &&
4175835ee624SBart Van Assche 					 (!srp_dev->has_fmr || prefer_fr));
4176835ee624SBart Van Assche 		srp_dev->use_fmr = !srp_dev->use_fast_reg && srp_dev->has_fmr;
4177509c5f33SBart Van Assche 	}
4178835ee624SBart Van Assche 
41795f071777SChristoph Hellwig 	if (never_register || !register_always ||
41805f071777SChristoph Hellwig 	    (!srp_dev->has_fmr && !srp_dev->has_fr))
41815f071777SChristoph Hellwig 		flags |= IB_PD_UNSAFE_GLOBAL_RKEY;
41825f071777SChristoph Hellwig 
41835cfb1782SBart Van Assche 	if (srp_dev->use_fast_reg) {
41845cfb1782SBart Van Assche 		srp_dev->max_pages_per_mr =
41855cfb1782SBart Van Assche 			min_t(u32, srp_dev->max_pages_per_mr,
4186042dd765SBart Van Assche 			      attr->max_fast_reg_page_list_len);
41875cfb1782SBart Van Assche 	}
418852ede08fSBart Van Assche 	srp_dev->mr_max_size	= srp_dev->mr_page_size *
418952ede08fSBart Van Assche 				   srp_dev->max_pages_per_mr;
41904a061b28SOr 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",
41916c854111SJason Gunthorpe 		 dev_name(&device->dev), mr_page_shift, attr->max_mr_size,
4192042dd765SBart Van Assche 		 attr->max_fast_reg_page_list_len,
419352ede08fSBart Van Assche 		 srp_dev->max_pages_per_mr, srp_dev->mr_max_size);
4194f5358a17SRoland Dreier 
4195f5358a17SRoland Dreier 	INIT_LIST_HEAD(&srp_dev->dev_list);
4196f5358a17SRoland Dreier 
4197f5358a17SRoland Dreier 	srp_dev->dev = device;
41985f071777SChristoph Hellwig 	srp_dev->pd  = ib_alloc_pd(device, flags);
4199f5358a17SRoland Dreier 	if (IS_ERR(srp_dev->pd))
4200f5358a17SRoland Dreier 		goto free_dev;
4201f5358a17SRoland Dreier 
4202cee687b6SBart Van Assche 	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
4203cee687b6SBart Van Assche 		srp_dev->global_rkey = srp_dev->pd->unsafe_global_rkey;
4204cee687b6SBart Van Assche 		WARN_ON_ONCE(srp_dev->global_rkey == 0);
4205cee687b6SBart Van Assche 	}
4206f5358a17SRoland Dreier 
4207ea1075edSJason Gunthorpe 	rdma_for_each_port (device, p) {
4208f5358a17SRoland Dreier 		host = srp_add_port(srp_dev, p);
4209aef9ec39SRoland Dreier 		if (host)
4210f5358a17SRoland Dreier 			list_add_tail(&host->list, &srp_dev->dev_list);
4211aef9ec39SRoland Dreier 	}
4212aef9ec39SRoland Dreier 
4213f5358a17SRoland Dreier 	ib_set_client_data(device, &srp_client, srp_dev);
42144a061b28SOr Gerlitz 	return;
4215f5358a17SRoland Dreier 
4216f5358a17SRoland Dreier free_dev:
4217f5358a17SRoland Dreier 	kfree(srp_dev);
4218aef9ec39SRoland Dreier }
4219aef9ec39SRoland Dreier 
42207c1eb45aSHaggai Eran static void srp_remove_one(struct ib_device *device, void *client_data)
4221aef9ec39SRoland Dreier {
4222f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4223aef9ec39SRoland Dreier 	struct srp_host *host, *tmp_host;
4224ef6c49d8SBart Van Assche 	struct srp_target_port *target;
4225aef9ec39SRoland Dreier 
42267c1eb45aSHaggai Eran 	srp_dev = client_data;
42271fe0cb84SDotan Barak 	if (!srp_dev)
42281fe0cb84SDotan Barak 		return;
4229aef9ec39SRoland Dreier 
4230f5358a17SRoland Dreier 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
4231ee959b00STony Jones 		device_unregister(&host->dev);
4232aef9ec39SRoland Dreier 		/*
4233aef9ec39SRoland Dreier 		 * Wait for the sysfs entry to go away, so that no new
4234aef9ec39SRoland Dreier 		 * target ports can be created.
4235aef9ec39SRoland Dreier 		 */
4236aef9ec39SRoland Dreier 		wait_for_completion(&host->released);
4237aef9ec39SRoland Dreier 
4238aef9ec39SRoland Dreier 		/*
4239ef6c49d8SBart Van Assche 		 * Remove all target ports.
4240aef9ec39SRoland Dreier 		 */
4241b3589fd4SMatthew Wilcox 		spin_lock(&host->target_lock);
4242ef6c49d8SBart Van Assche 		list_for_each_entry(target, &host->target_list, list)
4243ef6c49d8SBart Van Assche 			srp_queue_remove_work(target);
4244b3589fd4SMatthew Wilcox 		spin_unlock(&host->target_lock);
4245aef9ec39SRoland Dreier 
4246aef9ec39SRoland Dreier 		/*
4247bcc05910SBart Van Assche 		 * Wait for tl_err and target port removal tasks.
4248aef9ec39SRoland Dreier 		 */
4249ef6c49d8SBart Van Assche 		flush_workqueue(system_long_wq);
4250bcc05910SBart Van Assche 		flush_workqueue(srp_remove_wq);
4251aef9ec39SRoland Dreier 
4252aef9ec39SRoland Dreier 		kfree(host);
4253aef9ec39SRoland Dreier 	}
4254aef9ec39SRoland Dreier 
4255f5358a17SRoland Dreier 	ib_dealloc_pd(srp_dev->pd);
4256f5358a17SRoland Dreier 
4257f5358a17SRoland Dreier 	kfree(srp_dev);
4258aef9ec39SRoland Dreier }
4259aef9ec39SRoland Dreier 
42603236822bSFUJITA Tomonori static struct srp_function_template ib_srp_transport_functions = {
4261ed9b2264SBart Van Assche 	.has_rport_state	 = true,
4262ed9b2264SBart Van Assche 	.reset_timer_if_blocked	 = true,
4263a95cadb9SBart Van Assche 	.reconnect_delay	 = &srp_reconnect_delay,
4264ed9b2264SBart Van Assche 	.fast_io_fail_tmo	 = &srp_fast_io_fail_tmo,
4265ed9b2264SBart Van Assche 	.dev_loss_tmo		 = &srp_dev_loss_tmo,
4266ed9b2264SBart Van Assche 	.reconnect		 = srp_rport_reconnect,
4267dc1bdbd9SBart Van Assche 	.rport_delete		 = srp_rport_delete,
4268ed9b2264SBart Van Assche 	.terminate_rport_io	 = srp_terminate_io,
42693236822bSFUJITA Tomonori };
42703236822bSFUJITA Tomonori 
4271aef9ec39SRoland Dreier static int __init srp_init_module(void)
4272aef9ec39SRoland Dreier {
4273aef9ec39SRoland Dreier 	int ret;
4274aef9ec39SRoland Dreier 
427516d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_imm_buf) != 4);
427616d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req) != 64);
427716d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req_rdma) != 56);
427816d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_cmd) != 48);
427916d14e01SBart Van Assche 
428049248644SDavid Dillow 	if (srp_sg_tablesize) {
4281e0bda7d8SBart Van Assche 		pr_warn("srp_sg_tablesize is deprecated, please use cmd_sg_entries\n");
428249248644SDavid Dillow 		if (!cmd_sg_entries)
428349248644SDavid Dillow 			cmd_sg_entries = srp_sg_tablesize;
428449248644SDavid Dillow 	}
428549248644SDavid Dillow 
428649248644SDavid Dillow 	if (!cmd_sg_entries)
428749248644SDavid Dillow 		cmd_sg_entries = SRP_DEF_SG_TABLESIZE;
428849248644SDavid Dillow 
428949248644SDavid Dillow 	if (cmd_sg_entries > 255) {
4290e0bda7d8SBart Van Assche 		pr_warn("Clamping cmd_sg_entries to 255\n");
429149248644SDavid Dillow 		cmd_sg_entries = 255;
42921e89a194SDavid Dillow 	}
42931e89a194SDavid Dillow 
4294c07d424dSDavid Dillow 	if (!indirect_sg_entries)
4295c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4296c07d424dSDavid Dillow 	else if (indirect_sg_entries < cmd_sg_entries) {
4297e0bda7d8SBart Van Assche 		pr_warn("Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n",
4298e0bda7d8SBart Van Assche 			cmd_sg_entries);
4299c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4300c07d424dSDavid Dillow 	}
4301c07d424dSDavid Dillow 
43020a475ef4SIsrael Rukshin 	if (indirect_sg_entries > SG_MAX_SEGMENTS) {
43030a475ef4SIsrael Rukshin 		pr_warn("Clamping indirect_sg_entries to %u\n",
43040a475ef4SIsrael Rukshin 			SG_MAX_SEGMENTS);
43050a475ef4SIsrael Rukshin 		indirect_sg_entries = SG_MAX_SEGMENTS;
43060a475ef4SIsrael Rukshin 	}
43070a475ef4SIsrael Rukshin 
4308bcc05910SBart Van Assche 	srp_remove_wq = create_workqueue("srp_remove");
4309da05be29SWei Yongjun 	if (!srp_remove_wq) {
4310da05be29SWei Yongjun 		ret = -ENOMEM;
4311bcc05910SBart Van Assche 		goto out;
4312bcc05910SBart Van Assche 	}
4313bcc05910SBart Van Assche 
4314bcc05910SBart Van Assche 	ret = -ENOMEM;
43153236822bSFUJITA Tomonori 	ib_srp_transport_template =
43163236822bSFUJITA Tomonori 		srp_attach_transport(&ib_srp_transport_functions);
43173236822bSFUJITA Tomonori 	if (!ib_srp_transport_template)
4318bcc05910SBart Van Assche 		goto destroy_wq;
43193236822bSFUJITA Tomonori 
4320aef9ec39SRoland Dreier 	ret = class_register(&srp_class);
4321aef9ec39SRoland Dreier 	if (ret) {
4322e0bda7d8SBart Van Assche 		pr_err("couldn't register class infiniband_srp\n");
4323bcc05910SBart Van Assche 		goto release_tr;
4324aef9ec39SRoland Dreier 	}
4325aef9ec39SRoland Dreier 
4326c1a0b23bSMichael S. Tsirkin 	ib_sa_register_client(&srp_sa_client);
4327c1a0b23bSMichael S. Tsirkin 
4328aef9ec39SRoland Dreier 	ret = ib_register_client(&srp_client);
4329aef9ec39SRoland Dreier 	if (ret) {
4330e0bda7d8SBart Van Assche 		pr_err("couldn't register IB client\n");
4331bcc05910SBart Van Assche 		goto unreg_sa;
4332aef9ec39SRoland Dreier 	}
4333aef9ec39SRoland Dreier 
4334bcc05910SBart Van Assche out:
4335bcc05910SBart Van Assche 	return ret;
4336bcc05910SBart Van Assche 
4337bcc05910SBart Van Assche unreg_sa:
4338bcc05910SBart Van Assche 	ib_sa_unregister_client(&srp_sa_client);
4339bcc05910SBart Van Assche 	class_unregister(&srp_class);
4340bcc05910SBart Van Assche 
4341bcc05910SBart Van Assche release_tr:
4342bcc05910SBart Van Assche 	srp_release_transport(ib_srp_transport_template);
4343bcc05910SBart Van Assche 
4344bcc05910SBart Van Assche destroy_wq:
4345bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4346bcc05910SBart Van Assche 	goto out;
4347aef9ec39SRoland Dreier }
4348aef9ec39SRoland Dreier 
4349aef9ec39SRoland Dreier static void __exit srp_cleanup_module(void)
4350aef9ec39SRoland Dreier {
4351aef9ec39SRoland Dreier 	ib_unregister_client(&srp_client);
4352c1a0b23bSMichael S. Tsirkin 	ib_sa_unregister_client(&srp_sa_client);
4353aef9ec39SRoland Dreier 	class_unregister(&srp_class);
43543236822bSFUJITA Tomonori 	srp_release_transport(ib_srp_transport_template);
4355bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4356aef9ec39SRoland Dreier }
4357aef9ec39SRoland Dreier 
4358aef9ec39SRoland Dreier module_init(srp_init_module);
4359aef9ec39SRoland Dreier module_exit(srp_cleanup_module);
4360