xref: /linux/drivers/infiniband/ulp/srp/ib_srp.c (revision bcef5b7215681250c4bf8961dfe15e9e4fef97d0)
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);
1511dc7b1f1SChristoph Hellwig static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc);
1521dc7b1f1SChristoph Hellwig static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
1531dc7b1f1SChristoph Hellwig 		const char *opname);
154e7ff98aeSParav Pandit static int srp_ib_cm_handler(struct ib_cm_id *cm_id,
155e7ff98aeSParav Pandit 			     const struct ib_cm_event *event);
15619f31343SBart Van Assche static int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
15719f31343SBart Van Assche 			       struct rdma_cm_event *event);
158aef9ec39SRoland Dreier 
1593236822bSFUJITA Tomonori static struct scsi_transport_template *ib_srp_transport_template;
160bcc05910SBart Van Assche static struct workqueue_struct *srp_remove_wq;
1613236822bSFUJITA Tomonori 
162aef9ec39SRoland Dreier static struct ib_client srp_client = {
163aef9ec39SRoland Dreier 	.name   = "srp",
164aef9ec39SRoland Dreier 	.add    = srp_add_one,
165aef9ec39SRoland Dreier 	.remove = srp_remove_one
166aef9ec39SRoland Dreier };
167aef9ec39SRoland Dreier 
168c1a0b23bSMichael S. Tsirkin static struct ib_sa_client srp_sa_client;
169c1a0b23bSMichael S. Tsirkin 
170ed9b2264SBart Van Assche static int srp_tmo_get(char *buffer, const struct kernel_param *kp)
171ed9b2264SBart Van Assche {
172ed9b2264SBart Van Assche 	int tmo = *(int *)kp->arg;
173ed9b2264SBart Van Assche 
174ed9b2264SBart Van Assche 	if (tmo >= 0)
175ed9b2264SBart Van Assche 		return sprintf(buffer, "%d", tmo);
176ed9b2264SBart Van Assche 	else
177ed9b2264SBart Van Assche 		return sprintf(buffer, "off");
178ed9b2264SBart Van Assche }
179ed9b2264SBart Van Assche 
180ed9b2264SBart Van Assche static int srp_tmo_set(const char *val, const struct kernel_param *kp)
181ed9b2264SBart Van Assche {
182ed9b2264SBart Van Assche 	int tmo, res;
183ed9b2264SBart Van Assche 
1843fdf70acSSagi Grimberg 	res = srp_parse_tmo(&tmo, val);
185ed9b2264SBart Van Assche 	if (res)
186ed9b2264SBart Van Assche 		goto out;
1873fdf70acSSagi Grimberg 
188a95cadb9SBart Van Assche 	if (kp->arg == &srp_reconnect_delay)
189a95cadb9SBart Van Assche 		res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo,
190a95cadb9SBart Van Assche 				    srp_dev_loss_tmo);
191a95cadb9SBart Van Assche 	else if (kp->arg == &srp_fast_io_fail_tmo)
192a95cadb9SBart Van Assche 		res = srp_tmo_valid(srp_reconnect_delay, tmo, srp_dev_loss_tmo);
193ed9b2264SBart Van Assche 	else
194a95cadb9SBart Van Assche 		res = srp_tmo_valid(srp_reconnect_delay, srp_fast_io_fail_tmo,
195a95cadb9SBart Van Assche 				    tmo);
196ed9b2264SBart Van Assche 	if (res)
197ed9b2264SBart Van Assche 		goto out;
198ed9b2264SBart Van Assche 	*(int *)kp->arg = tmo;
199ed9b2264SBart Van Assche 
200ed9b2264SBart Van Assche out:
201ed9b2264SBart Van Assche 	return res;
202ed9b2264SBart Van Assche }
203ed9b2264SBart Van Assche 
2049c27847dSLuis R. Rodriguez static const struct kernel_param_ops srp_tmo_ops = {
205ed9b2264SBart Van Assche 	.get = srp_tmo_get,
206ed9b2264SBart Van Assche 	.set = srp_tmo_set,
207ed9b2264SBart Van Assche };
208ed9b2264SBart Van Assche 
209aef9ec39SRoland Dreier static inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
210aef9ec39SRoland Dreier {
211aef9ec39SRoland Dreier 	return (struct srp_target_port *) host->hostdata;
212aef9ec39SRoland Dreier }
213aef9ec39SRoland Dreier 
214aef9ec39SRoland Dreier static const char *srp_target_info(struct Scsi_Host *host)
215aef9ec39SRoland Dreier {
216aef9ec39SRoland Dreier 	return host_to_target(host)->target_name;
217aef9ec39SRoland Dreier }
218aef9ec39SRoland Dreier 
2195d7cbfd6SRoland Dreier static int srp_target_is_topspin(struct srp_target_port *target)
2205d7cbfd6SRoland Dreier {
2215d7cbfd6SRoland Dreier 	static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
2223d1ff48dSRaghava Kondapalli 	static const u8 cisco_oui[3]   = { 0x00, 0x1b, 0x0d };
2235d7cbfd6SRoland Dreier 
2245d7cbfd6SRoland Dreier 	return topspin_workarounds &&
2253d1ff48dSRaghava Kondapalli 		(!memcmp(&target->ioc_guid, topspin_oui, sizeof topspin_oui) ||
2263d1ff48dSRaghava Kondapalli 		 !memcmp(&target->ioc_guid, cisco_oui, sizeof cisco_oui));
2275d7cbfd6SRoland Dreier }
2285d7cbfd6SRoland Dreier 
229aef9ec39SRoland Dreier static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
230aef9ec39SRoland Dreier 				   gfp_t gfp_mask,
231aef9ec39SRoland Dreier 				   enum dma_data_direction direction)
232aef9ec39SRoland Dreier {
233aef9ec39SRoland Dreier 	struct srp_iu *iu;
234aef9ec39SRoland Dreier 
235aef9ec39SRoland Dreier 	iu = kmalloc(sizeof *iu, gfp_mask);
236aef9ec39SRoland Dreier 	if (!iu)
237aef9ec39SRoland Dreier 		goto out;
238aef9ec39SRoland Dreier 
239aef9ec39SRoland Dreier 	iu->buf = kzalloc(size, gfp_mask);
240aef9ec39SRoland Dreier 	if (!iu->buf)
241aef9ec39SRoland Dreier 		goto out_free_iu;
242aef9ec39SRoland Dreier 
24305321937SGreg Kroah-Hartman 	iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size,
24405321937SGreg Kroah-Hartman 				    direction);
24505321937SGreg Kroah-Hartman 	if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma))
246aef9ec39SRoland Dreier 		goto out_free_buf;
247aef9ec39SRoland Dreier 
248aef9ec39SRoland Dreier 	iu->size      = size;
249aef9ec39SRoland Dreier 	iu->direction = direction;
250aef9ec39SRoland Dreier 
251aef9ec39SRoland Dreier 	return iu;
252aef9ec39SRoland Dreier 
253aef9ec39SRoland Dreier out_free_buf:
254aef9ec39SRoland Dreier 	kfree(iu->buf);
255aef9ec39SRoland Dreier out_free_iu:
256aef9ec39SRoland Dreier 	kfree(iu);
257aef9ec39SRoland Dreier out:
258aef9ec39SRoland Dreier 	return NULL;
259aef9ec39SRoland Dreier }
260aef9ec39SRoland Dreier 
261aef9ec39SRoland Dreier static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
262aef9ec39SRoland Dreier {
263aef9ec39SRoland Dreier 	if (!iu)
264aef9ec39SRoland Dreier 		return;
265aef9ec39SRoland Dreier 
26605321937SGreg Kroah-Hartman 	ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size,
26705321937SGreg Kroah-Hartman 			    iu->direction);
268aef9ec39SRoland Dreier 	kfree(iu->buf);
269aef9ec39SRoland Dreier 	kfree(iu);
270aef9ec39SRoland Dreier }
271aef9ec39SRoland Dreier 
272aef9ec39SRoland Dreier static void srp_qp_event(struct ib_event *event, void *context)
273aef9ec39SRoland Dreier {
27457363d98SSagi Grimberg 	pr_debug("QP event %s (%d)\n",
27557363d98SSagi Grimberg 		 ib_event_msg(event->event), event->event);
276aef9ec39SRoland Dreier }
277aef9ec39SRoland Dreier 
27819f31343SBart Van Assche static int srp_init_ib_qp(struct srp_target_port *target,
279aef9ec39SRoland Dreier 			  struct ib_qp *qp)
280aef9ec39SRoland Dreier {
281aef9ec39SRoland Dreier 	struct ib_qp_attr *attr;
282aef9ec39SRoland Dreier 	int ret;
283aef9ec39SRoland Dreier 
284aef9ec39SRoland Dreier 	attr = kmalloc(sizeof *attr, GFP_KERNEL);
285aef9ec39SRoland Dreier 	if (!attr)
286aef9ec39SRoland Dreier 		return -ENOMEM;
287aef9ec39SRoland Dreier 
28856b5390cSBart Van Assche 	ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev,
289aef9ec39SRoland Dreier 				  target->srp_host->port,
29019f31343SBart Van Assche 				  be16_to_cpu(target->ib_cm.pkey),
291aef9ec39SRoland Dreier 				  &attr->pkey_index);
292aef9ec39SRoland Dreier 	if (ret)
293aef9ec39SRoland Dreier 		goto out;
294aef9ec39SRoland Dreier 
295aef9ec39SRoland Dreier 	attr->qp_state        = IB_QPS_INIT;
296aef9ec39SRoland Dreier 	attr->qp_access_flags = (IB_ACCESS_REMOTE_READ |
297aef9ec39SRoland Dreier 				    IB_ACCESS_REMOTE_WRITE);
298aef9ec39SRoland Dreier 	attr->port_num        = target->srp_host->port;
299aef9ec39SRoland Dreier 
300aef9ec39SRoland Dreier 	ret = ib_modify_qp(qp, attr,
301aef9ec39SRoland Dreier 			   IB_QP_STATE		|
302aef9ec39SRoland Dreier 			   IB_QP_PKEY_INDEX	|
303aef9ec39SRoland Dreier 			   IB_QP_ACCESS_FLAGS	|
304aef9ec39SRoland Dreier 			   IB_QP_PORT);
305aef9ec39SRoland Dreier 
306aef9ec39SRoland Dreier out:
307aef9ec39SRoland Dreier 	kfree(attr);
308aef9ec39SRoland Dreier 	return ret;
309aef9ec39SRoland Dreier }
310aef9ec39SRoland Dreier 
31119f31343SBart Van Assche static int srp_new_ib_cm_id(struct srp_rdma_ch *ch)
3129fe4bcf4SDavid Dillow {
313509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
3149fe4bcf4SDavid Dillow 	struct ib_cm_id *new_cm_id;
3159fe4bcf4SDavid Dillow 
31605321937SGreg Kroah-Hartman 	new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
31719f31343SBart Van Assche 				    srp_ib_cm_handler, ch);
3189fe4bcf4SDavid Dillow 	if (IS_ERR(new_cm_id))
3199fe4bcf4SDavid Dillow 		return PTR_ERR(new_cm_id);
3209fe4bcf4SDavid Dillow 
32119f31343SBart Van Assche 	if (ch->ib_cm.cm_id)
32219f31343SBart Van Assche 		ib_destroy_cm_id(ch->ib_cm.cm_id);
32319f31343SBart Van Assche 	ch->ib_cm.cm_id = new_cm_id;
3244c33bd19SDasaratharaman Chandramouli 	if (rdma_cap_opa_ah(target->srp_host->srp_dev->dev,
3254c33bd19SDasaratharaman Chandramouli 			    target->srp_host->port))
32619f31343SBart Van Assche 		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_OPA;
3274c33bd19SDasaratharaman Chandramouli 	else
32819f31343SBart Van Assche 		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_IB;
32919f31343SBart Van Assche 	ch->ib_cm.path.sgid = target->sgid;
33019f31343SBart Van Assche 	ch->ib_cm.path.dgid = target->ib_cm.orig_dgid;
33119f31343SBart Van Assche 	ch->ib_cm.path.pkey = target->ib_cm.pkey;
33219f31343SBart Van Assche 	ch->ib_cm.path.service_id = target->ib_cm.service_id;
3339fe4bcf4SDavid Dillow 
3349fe4bcf4SDavid Dillow 	return 0;
3359fe4bcf4SDavid Dillow }
3369fe4bcf4SDavid Dillow 
33719f31343SBart Van Assche static int srp_new_rdma_cm_id(struct srp_rdma_ch *ch)
33819f31343SBart Van Assche {
33919f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
34019f31343SBart Van Assche 	struct rdma_cm_id *new_cm_id;
34119f31343SBart Van Assche 	int ret;
34219f31343SBart Van Assche 
34319f31343SBart Van Assche 	new_cm_id = rdma_create_id(target->net, srp_rdma_cm_handler, ch,
34419f31343SBart Van Assche 				   RDMA_PS_TCP, IB_QPT_RC);
34519f31343SBart Van Assche 	if (IS_ERR(new_cm_id)) {
34619f31343SBart Van Assche 		ret = PTR_ERR(new_cm_id);
34719f31343SBart Van Assche 		new_cm_id = NULL;
34819f31343SBart Van Assche 		goto out;
34919f31343SBart Van Assche 	}
35019f31343SBart Van Assche 
35119f31343SBart Van Assche 	init_completion(&ch->done);
35219f31343SBart Van Assche 	ret = rdma_resolve_addr(new_cm_id, target->rdma_cm.src_specified ?
35319f31343SBart Van Assche 				(struct sockaddr *)&target->rdma_cm.src : NULL,
35419f31343SBart Van Assche 				(struct sockaddr *)&target->rdma_cm.dst,
35519f31343SBart Van Assche 				SRP_PATH_REC_TIMEOUT_MS);
35619f31343SBart Van Assche 	if (ret) {
3577da09af9SBart Van Assche 		pr_err("No route available from %pIS to %pIS (%d)\n",
3587da09af9SBart Van Assche 		       &target->rdma_cm.src, &target->rdma_cm.dst, ret);
35919f31343SBart Van Assche 		goto out;
36019f31343SBart Van Assche 	}
36119f31343SBart Van Assche 	ret = wait_for_completion_interruptible(&ch->done);
36219f31343SBart Van Assche 	if (ret < 0)
36319f31343SBart Van Assche 		goto out;
36419f31343SBart Van Assche 
36519f31343SBart Van Assche 	ret = ch->status;
36619f31343SBart Van Assche 	if (ret) {
3677da09af9SBart Van Assche 		pr_err("Resolving address %pIS failed (%d)\n",
3687da09af9SBart Van Assche 		       &target->rdma_cm.dst, ret);
36919f31343SBart Van Assche 		goto out;
37019f31343SBart Van Assche 	}
37119f31343SBart Van Assche 
37219f31343SBart Van Assche 	swap(ch->rdma_cm.cm_id, new_cm_id);
37319f31343SBart Van Assche 
37419f31343SBart Van Assche out:
37519f31343SBart Van Assche 	if (new_cm_id)
37619f31343SBart Van Assche 		rdma_destroy_id(new_cm_id);
37719f31343SBart Van Assche 
37819f31343SBart Van Assche 	return ret;
37919f31343SBart Van Assche }
38019f31343SBart Van Assche 
38119f31343SBart Van Assche static int srp_new_cm_id(struct srp_rdma_ch *ch)
38219f31343SBart Van Assche {
38319f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
38419f31343SBart Van Assche 
38519f31343SBart Van Assche 	return target->using_rdma_cm ? srp_new_rdma_cm_id(ch) :
38619f31343SBart Van Assche 		srp_new_ib_cm_id(ch);
38719f31343SBart Van Assche }
38819f31343SBart Van Assche 
389d1b4289eSBart Van Assche static struct ib_fmr_pool *srp_alloc_fmr_pool(struct srp_target_port *target)
390d1b4289eSBart Van Assche {
391d1b4289eSBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
392d1b4289eSBart Van Assche 	struct ib_fmr_pool_param fmr_param;
393d1b4289eSBart Van Assche 
394d1b4289eSBart Van Assche 	memset(&fmr_param, 0, sizeof(fmr_param));
395fa9863f8SBart Van Assche 	fmr_param.pool_size	    = target->mr_pool_size;
396d1b4289eSBart Van Assche 	fmr_param.dirty_watermark   = fmr_param.pool_size / 4;
397d1b4289eSBart Van Assche 	fmr_param.cache		    = 1;
39852ede08fSBart Van Assche 	fmr_param.max_pages_per_fmr = dev->max_pages_per_mr;
39952ede08fSBart Van Assche 	fmr_param.page_shift	    = ilog2(dev->mr_page_size);
400d1b4289eSBart Van Assche 	fmr_param.access	    = (IB_ACCESS_LOCAL_WRITE |
401d1b4289eSBart Van Assche 				       IB_ACCESS_REMOTE_WRITE |
402d1b4289eSBart Van Assche 				       IB_ACCESS_REMOTE_READ);
403d1b4289eSBart Van Assche 
404d1b4289eSBart Van Assche 	return ib_create_fmr_pool(dev->pd, &fmr_param);
405d1b4289eSBart Van Assche }
406d1b4289eSBart Van Assche 
4075cfb1782SBart Van Assche /**
4085cfb1782SBart Van Assche  * srp_destroy_fr_pool() - free the resources owned by a pool
4095cfb1782SBart Van Assche  * @pool: Fast registration pool to be destroyed.
4105cfb1782SBart Van Assche  */
4115cfb1782SBart Van Assche static void srp_destroy_fr_pool(struct srp_fr_pool *pool)
4125cfb1782SBart Van Assche {
4135cfb1782SBart Van Assche 	int i;
4145cfb1782SBart Van Assche 	struct srp_fr_desc *d;
4155cfb1782SBart Van Assche 
4165cfb1782SBart Van Assche 	if (!pool)
4175cfb1782SBart Van Assche 		return;
4185cfb1782SBart Van Assche 
4195cfb1782SBart Van Assche 	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
4205cfb1782SBart Van Assche 		if (d->mr)
4215cfb1782SBart Van Assche 			ib_dereg_mr(d->mr);
4225cfb1782SBart Van Assche 	}
4235cfb1782SBart Van Assche 	kfree(pool);
4245cfb1782SBart Van Assche }
4255cfb1782SBart Van Assche 
4265cfb1782SBart Van Assche /**
4275cfb1782SBart Van Assche  * srp_create_fr_pool() - allocate and initialize a pool for fast registration
4285cfb1782SBart Van Assche  * @device:            IB device to allocate fast registration descriptors for.
4295cfb1782SBart Van Assche  * @pd:                Protection domain associated with the FR descriptors.
4305cfb1782SBart Van Assche  * @pool_size:         Number of descriptors to allocate.
4315cfb1782SBart Van Assche  * @max_page_list_len: Maximum fast registration work request page list length.
4325cfb1782SBart Van Assche  */
4335cfb1782SBart Van Assche static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
4345cfb1782SBart Van Assche 					      struct ib_pd *pd, int pool_size,
4355cfb1782SBart Van Assche 					      int max_page_list_len)
4365cfb1782SBart Van Assche {
4375cfb1782SBart Van Assche 	struct srp_fr_pool *pool;
4385cfb1782SBart Van Assche 	struct srp_fr_desc *d;
4395cfb1782SBart Van Assche 	struct ib_mr *mr;
4405cfb1782SBart Van Assche 	int i, ret = -EINVAL;
441fbd36818SSergey Gorenko 	enum ib_mr_type mr_type;
4425cfb1782SBart Van Assche 
4435cfb1782SBart Van Assche 	if (pool_size <= 0)
4445cfb1782SBart Van Assche 		goto err;
4455cfb1782SBart Van Assche 	ret = -ENOMEM;
4467a7b0feaSGustavo A. R. Silva 	pool = kzalloc(struct_size(pool, desc, pool_size), GFP_KERNEL);
4475cfb1782SBart Van Assche 	if (!pool)
4485cfb1782SBart Van Assche 		goto err;
4495cfb1782SBart Van Assche 	pool->size = pool_size;
4505cfb1782SBart Van Assche 	pool->max_page_list_len = max_page_list_len;
4515cfb1782SBart Van Assche 	spin_lock_init(&pool->lock);
4525cfb1782SBart Van Assche 	INIT_LIST_HEAD(&pool->free_list);
4535cfb1782SBart Van Assche 
454fbd36818SSergey Gorenko 	if (device->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)
455fbd36818SSergey Gorenko 		mr_type = IB_MR_TYPE_SG_GAPS;
456fbd36818SSergey Gorenko 	else
457fbd36818SSergey Gorenko 		mr_type = IB_MR_TYPE_MEM_REG;
458fbd36818SSergey Gorenko 
4595cfb1782SBart Van Assche 	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
460fbd36818SSergey Gorenko 		mr = ib_alloc_mr(pd, mr_type, max_page_list_len);
4615cfb1782SBart Van Assche 		if (IS_ERR(mr)) {
4625cfb1782SBart Van Assche 			ret = PTR_ERR(mr);
4633787d990SBart Van Assche 			if (ret == -ENOMEM)
4643787d990SBart Van Assche 				pr_info("%s: ib_alloc_mr() failed. Try to reduce max_cmd_per_lun, max_sect or ch_count\n",
4653787d990SBart Van Assche 					dev_name(&device->dev));
4665cfb1782SBart Van Assche 			goto destroy_pool;
4675cfb1782SBart Van Assche 		}
4685cfb1782SBart Van Assche 		d->mr = mr;
4695cfb1782SBart Van Assche 		list_add_tail(&d->entry, &pool->free_list);
4705cfb1782SBart Van Assche 	}
4715cfb1782SBart Van Assche 
4725cfb1782SBart Van Assche out:
4735cfb1782SBart Van Assche 	return pool;
4745cfb1782SBart Van Assche 
4755cfb1782SBart Van Assche destroy_pool:
4765cfb1782SBart Van Assche 	srp_destroy_fr_pool(pool);
4775cfb1782SBart Van Assche 
4785cfb1782SBart Van Assche err:
4795cfb1782SBart Van Assche 	pool = ERR_PTR(ret);
4805cfb1782SBart Van Assche 	goto out;
4815cfb1782SBart Van Assche }
4825cfb1782SBart Van Assche 
4835cfb1782SBart Van Assche /**
4845cfb1782SBart Van Assche  * srp_fr_pool_get() - obtain a descriptor suitable for fast registration
4855cfb1782SBart Van Assche  * @pool: Pool to obtain descriptor from.
4865cfb1782SBart Van Assche  */
4875cfb1782SBart Van Assche static struct srp_fr_desc *srp_fr_pool_get(struct srp_fr_pool *pool)
4885cfb1782SBart Van Assche {
4895cfb1782SBart Van Assche 	struct srp_fr_desc *d = NULL;
4905cfb1782SBart Van Assche 	unsigned long flags;
4915cfb1782SBart Van Assche 
4925cfb1782SBart Van Assche 	spin_lock_irqsave(&pool->lock, flags);
4935cfb1782SBart Van Assche 	if (!list_empty(&pool->free_list)) {
4945cfb1782SBart Van Assche 		d = list_first_entry(&pool->free_list, typeof(*d), entry);
4955cfb1782SBart Van Assche 		list_del(&d->entry);
4965cfb1782SBart Van Assche 	}
4975cfb1782SBart Van Assche 	spin_unlock_irqrestore(&pool->lock, flags);
4985cfb1782SBart Van Assche 
4995cfb1782SBart Van Assche 	return d;
5005cfb1782SBart Van Assche }
5015cfb1782SBart Van Assche 
5025cfb1782SBart Van Assche /**
5035cfb1782SBart Van Assche  * srp_fr_pool_put() - put an FR descriptor back in the free list
5045cfb1782SBart Van Assche  * @pool: Pool the descriptor was allocated from.
5055cfb1782SBart Van Assche  * @desc: Pointer to an array of fast registration descriptor pointers.
5065cfb1782SBart Van Assche  * @n:    Number of descriptors to put back.
5075cfb1782SBart Van Assche  *
5085cfb1782SBart Van Assche  * Note: The caller must already have queued an invalidation request for
5095cfb1782SBart Van Assche  * desc->mr->rkey before calling this function.
5105cfb1782SBart Van Assche  */
5115cfb1782SBart Van Assche static void srp_fr_pool_put(struct srp_fr_pool *pool, struct srp_fr_desc **desc,
5125cfb1782SBart Van Assche 			    int n)
5135cfb1782SBart Van Assche {
5145cfb1782SBart Van Assche 	unsigned long flags;
5155cfb1782SBart Van Assche 	int i;
5165cfb1782SBart Van Assche 
5175cfb1782SBart Van Assche 	spin_lock_irqsave(&pool->lock, flags);
5185cfb1782SBart Van Assche 	for (i = 0; i < n; i++)
5195cfb1782SBart Van Assche 		list_add(&desc[i]->entry, &pool->free_list);
5205cfb1782SBart Van Assche 	spin_unlock_irqrestore(&pool->lock, flags);
5215cfb1782SBart Van Assche }
5225cfb1782SBart Van Assche 
5235cfb1782SBart Van Assche static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
5245cfb1782SBart Van Assche {
5255cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
5265cfb1782SBart Van Assche 
527fa9863f8SBart Van Assche 	return srp_create_fr_pool(dev->dev, dev->pd, target->mr_pool_size,
5285cfb1782SBart Van Assche 				  dev->max_pages_per_mr);
5295cfb1782SBart Van Assche }
5305cfb1782SBart Van Assche 
5317dad6b2eSBart Van Assche /**
5327dad6b2eSBart Van Assche  * srp_destroy_qp() - destroy an RDMA queue pair
5339566b054SBart Van Assche  * @ch: SRP RDMA channel.
5347dad6b2eSBart Van Assche  *
535561392d4SSteve Wise  * Drain the qp before destroying it.  This avoids that the receive
536561392d4SSteve Wise  * completion handler can access the queue pair while it is
5377dad6b2eSBart Van Assche  * being destroyed.
5387dad6b2eSBart Van Assche  */
5399566b054SBart Van Assche static void srp_destroy_qp(struct srp_rdma_ch *ch)
5407dad6b2eSBart Van Assche {
5419294000dSBart Van Assche 	spin_lock_irq(&ch->lock);
5429294000dSBart Van Assche 	ib_process_cq_direct(ch->send_cq, -1);
5439294000dSBart Van Assche 	spin_unlock_irq(&ch->lock);
5449294000dSBart Van Assche 
5459566b054SBart Van Assche 	ib_drain_qp(ch->qp);
5469566b054SBart Van Assche 	ib_destroy_qp(ch->qp);
5477dad6b2eSBart Van Assche }
5487dad6b2eSBart Van Assche 
549509c07bcSBart Van Assche static int srp_create_ch_ib(struct srp_rdma_ch *ch)
550aef9ec39SRoland Dreier {
551509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
55262154b2eSBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
553aef9ec39SRoland Dreier 	struct ib_qp_init_attr *init_attr;
55473aa89edSIshai Rabinovitz 	struct ib_cq *recv_cq, *send_cq;
55573aa89edSIshai Rabinovitz 	struct ib_qp *qp;
556d1b4289eSBart Van Assche 	struct ib_fmr_pool *fmr_pool = NULL;
5575cfb1782SBart Van Assche 	struct srp_fr_pool *fr_pool = NULL;
558509c5f33SBart Van Assche 	const int m = 1 + dev->use_fast_reg * target->mr_per_cmd * 2;
559aef9ec39SRoland Dreier 	int ret;
560aef9ec39SRoland Dreier 
561aef9ec39SRoland Dreier 	init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
562aef9ec39SRoland Dreier 	if (!init_attr)
563aef9ec39SRoland Dreier 		return -ENOMEM;
564aef9ec39SRoland Dreier 
565561392d4SSteve Wise 	/* queue_size + 1 for ib_drain_rq() */
5661dc7b1f1SChristoph Hellwig 	recv_cq = ib_alloc_cq(dev->dev, ch, target->queue_size + 1,
5671dc7b1f1SChristoph Hellwig 				ch->comp_vector, IB_POLL_SOFTIRQ);
56873aa89edSIshai Rabinovitz 	if (IS_ERR(recv_cq)) {
56973aa89edSIshai Rabinovitz 		ret = PTR_ERR(recv_cq);
570da9d2f07SRoland Dreier 		goto err;
571aef9ec39SRoland Dreier 	}
572aef9ec39SRoland Dreier 
5731dc7b1f1SChristoph Hellwig 	send_cq = ib_alloc_cq(dev->dev, ch, m * target->queue_size,
5741dc7b1f1SChristoph Hellwig 				ch->comp_vector, IB_POLL_DIRECT);
57573aa89edSIshai Rabinovitz 	if (IS_ERR(send_cq)) {
57673aa89edSIshai Rabinovitz 		ret = PTR_ERR(send_cq);
577da9d2f07SRoland Dreier 		goto err_recv_cq;
5789c03dc9fSBart Van Assche 	}
5799c03dc9fSBart Van Assche 
580aef9ec39SRoland Dreier 	init_attr->event_handler       = srp_qp_event;
5815cfb1782SBart Van Assche 	init_attr->cap.max_send_wr     = m * target->queue_size;
5827dad6b2eSBart Van Assche 	init_attr->cap.max_recv_wr     = target->queue_size + 1;
583aef9ec39SRoland Dreier 	init_attr->cap.max_recv_sge    = 1;
584882981f4SBart Van Assche 	init_attr->cap.max_send_sge    = SRP_MAX_SGE;
5855cfb1782SBart Van Assche 	init_attr->sq_sig_type         = IB_SIGNAL_REQ_WR;
586aef9ec39SRoland Dreier 	init_attr->qp_type             = IB_QPT_RC;
58773aa89edSIshai Rabinovitz 	init_attr->send_cq             = send_cq;
58873aa89edSIshai Rabinovitz 	init_attr->recv_cq             = recv_cq;
589aef9ec39SRoland Dreier 
59019f31343SBart Van Assche 	if (target->using_rdma_cm) {
59119f31343SBart Van Assche 		ret = rdma_create_qp(ch->rdma_cm.cm_id, dev->pd, init_attr);
59219f31343SBart Van Assche 		qp = ch->rdma_cm.cm_id->qp;
59319f31343SBart Van Assche 	} else {
59462154b2eSBart Van Assche 		qp = ib_create_qp(dev->pd, init_attr);
59519f31343SBart Van Assche 		if (!IS_ERR(qp)) {
59619f31343SBart Van Assche 			ret = srp_init_ib_qp(target, qp);
59719f31343SBart Van Assche 			if (ret)
59819f31343SBart Van Assche 				ib_destroy_qp(qp);
59919f31343SBart Van Assche 		} else {
60073aa89edSIshai Rabinovitz 			ret = PTR_ERR(qp);
60119f31343SBart Van Assche 		}
60219f31343SBart Van Assche 	}
60319f31343SBart Van Assche 	if (ret) {
60419f31343SBart Van Assche 		pr_err("QP creation failed for dev %s: %d\n",
60519f31343SBart Van Assche 		       dev_name(&dev->dev->dev), ret);
606da9d2f07SRoland Dreier 		goto err_send_cq;
607aef9ec39SRoland Dreier 	}
608aef9ec39SRoland Dreier 
609002f1567SBart Van Assche 	if (dev->use_fast_reg) {
6105cfb1782SBart Van Assche 		fr_pool = srp_alloc_fr_pool(target);
6115cfb1782SBart Van Assche 		if (IS_ERR(fr_pool)) {
6125cfb1782SBart Van Assche 			ret = PTR_ERR(fr_pool);
6135cfb1782SBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host, PFX
6145cfb1782SBart Van Assche 				     "FR pool allocation failed (%d)\n", ret);
6155cfb1782SBart Van Assche 			goto err_qp;
6165cfb1782SBart Van Assche 		}
617002f1567SBart Van Assche 	} else if (dev->use_fmr) {
618d1b4289eSBart Van Assche 		fmr_pool = srp_alloc_fmr_pool(target);
619d1b4289eSBart Van Assche 		if (IS_ERR(fmr_pool)) {
620d1b4289eSBart Van Assche 			ret = PTR_ERR(fmr_pool);
621d1b4289eSBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host, PFX
622d1b4289eSBart Van Assche 				     "FMR pool allocation failed (%d)\n", ret);
623d1b4289eSBart Van Assche 			goto err_qp;
624d1b4289eSBart Van Assche 		}
625d1b4289eSBart Van Assche 	}
626d1b4289eSBart Van Assche 
627509c07bcSBart Van Assche 	if (ch->qp)
6289566b054SBart Van Assche 		srp_destroy_qp(ch);
629509c07bcSBart Van Assche 	if (ch->recv_cq)
6301dc7b1f1SChristoph Hellwig 		ib_free_cq(ch->recv_cq);
631509c07bcSBart Van Assche 	if (ch->send_cq)
6321dc7b1f1SChristoph Hellwig 		ib_free_cq(ch->send_cq);
63373aa89edSIshai Rabinovitz 
634509c07bcSBart Van Assche 	ch->qp = qp;
635509c07bcSBart Van Assche 	ch->recv_cq = recv_cq;
636509c07bcSBart Van Assche 	ch->send_cq = send_cq;
63773aa89edSIshai Rabinovitz 
6387fbc67dfSSagi Grimberg 	if (dev->use_fast_reg) {
6397fbc67dfSSagi Grimberg 		if (ch->fr_pool)
6407fbc67dfSSagi Grimberg 			srp_destroy_fr_pool(ch->fr_pool);
6417fbc67dfSSagi Grimberg 		ch->fr_pool = fr_pool;
6427fbc67dfSSagi Grimberg 	} else if (dev->use_fmr) {
6437fbc67dfSSagi Grimberg 		if (ch->fmr_pool)
6447fbc67dfSSagi Grimberg 			ib_destroy_fmr_pool(ch->fmr_pool);
6457fbc67dfSSagi Grimberg 		ch->fmr_pool = fmr_pool;
6467fbc67dfSSagi Grimberg 	}
6477fbc67dfSSagi Grimberg 
648da9d2f07SRoland Dreier 	kfree(init_attr);
649da9d2f07SRoland Dreier 	return 0;
650da9d2f07SRoland Dreier 
651da9d2f07SRoland Dreier err_qp:
65219f31343SBart Van Assche 	if (target->using_rdma_cm)
65319f31343SBart Van Assche 		rdma_destroy_qp(ch->rdma_cm.cm_id);
65419f31343SBart Van Assche 	else
65595c2ef50SIsrael Rukshin 		ib_destroy_qp(qp);
656da9d2f07SRoland Dreier 
657da9d2f07SRoland Dreier err_send_cq:
6581dc7b1f1SChristoph Hellwig 	ib_free_cq(send_cq);
659da9d2f07SRoland Dreier 
660da9d2f07SRoland Dreier err_recv_cq:
6611dc7b1f1SChristoph Hellwig 	ib_free_cq(recv_cq);
662da9d2f07SRoland Dreier 
663da9d2f07SRoland Dreier err:
664aef9ec39SRoland Dreier 	kfree(init_attr);
665aef9ec39SRoland Dreier 	return ret;
666aef9ec39SRoland Dreier }
667aef9ec39SRoland Dreier 
6684d73f95fSBart Van Assche /*
6694d73f95fSBart Van Assche  * Note: this function may be called without srp_alloc_iu_bufs() having been
670509c07bcSBart Van Assche  * invoked. Hence the ch->[rt]x_ring checks.
6714d73f95fSBart Van Assche  */
672509c07bcSBart Van Assche static void srp_free_ch_ib(struct srp_target_port *target,
673509c07bcSBart Van Assche 			   struct srp_rdma_ch *ch)
674aef9ec39SRoland Dreier {
6755cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
676aef9ec39SRoland Dreier 	int i;
677aef9ec39SRoland Dreier 
678d92c0da7SBart Van Assche 	if (!ch->target)
679d92c0da7SBart Van Assche 		return;
680d92c0da7SBart Van Assche 
68119f31343SBart Van Assche 	if (target->using_rdma_cm) {
68219f31343SBart Van Assche 		if (ch->rdma_cm.cm_id) {
68319f31343SBart Van Assche 			rdma_destroy_id(ch->rdma_cm.cm_id);
68419f31343SBart Van Assche 			ch->rdma_cm.cm_id = NULL;
68519f31343SBart Van Assche 		}
68619f31343SBart Van Assche 	} else {
68719f31343SBart Van Assche 		if (ch->ib_cm.cm_id) {
68819f31343SBart Van Assche 			ib_destroy_cm_id(ch->ib_cm.cm_id);
68919f31343SBart Van Assche 			ch->ib_cm.cm_id = NULL;
69019f31343SBart Van Assche 		}
691394c595eSBart Van Assche 	}
692394c595eSBart Van Assche 
693d92c0da7SBart Van Assche 	/* If srp_new_cm_id() succeeded but srp_create_ch_ib() not, return. */
694d92c0da7SBart Van Assche 	if (!ch->qp)
695d92c0da7SBart Van Assche 		return;
696d92c0da7SBart Van Assche 
6975cfb1782SBart Van Assche 	if (dev->use_fast_reg) {
698509c07bcSBart Van Assche 		if (ch->fr_pool)
699509c07bcSBart Van Assche 			srp_destroy_fr_pool(ch->fr_pool);
700002f1567SBart Van Assche 	} else if (dev->use_fmr) {
701509c07bcSBart Van Assche 		if (ch->fmr_pool)
702509c07bcSBart Van Assche 			ib_destroy_fmr_pool(ch->fmr_pool);
7035cfb1782SBart Van Assche 	}
7041dc7b1f1SChristoph Hellwig 
7059566b054SBart Van Assche 	srp_destroy_qp(ch);
7061dc7b1f1SChristoph Hellwig 	ib_free_cq(ch->send_cq);
7071dc7b1f1SChristoph Hellwig 	ib_free_cq(ch->recv_cq);
708aef9ec39SRoland Dreier 
709d92c0da7SBart Van Assche 	/*
710d92c0da7SBart Van Assche 	 * Avoid that the SCSI error handler tries to use this channel after
711d92c0da7SBart Van Assche 	 * it has been freed. The SCSI error handler can namely continue
712d92c0da7SBart Van Assche 	 * trying to perform recovery actions after scsi_remove_host()
713d92c0da7SBart Van Assche 	 * returned.
714d92c0da7SBart Van Assche 	 */
715d92c0da7SBart Van Assche 	ch->target = NULL;
716d92c0da7SBart Van Assche 
717509c07bcSBart Van Assche 	ch->qp = NULL;
718509c07bcSBart Van Assche 	ch->send_cq = ch->recv_cq = NULL;
71973aa89edSIshai Rabinovitz 
720509c07bcSBart Van Assche 	if (ch->rx_ring) {
7214d73f95fSBart Van Assche 		for (i = 0; i < target->queue_size; ++i)
722509c07bcSBart Van Assche 			srp_free_iu(target->srp_host, ch->rx_ring[i]);
723509c07bcSBart Van Assche 		kfree(ch->rx_ring);
724509c07bcSBart Van Assche 		ch->rx_ring = NULL;
7254d73f95fSBart Van Assche 	}
726509c07bcSBart Van Assche 	if (ch->tx_ring) {
7274d73f95fSBart Van Assche 		for (i = 0; i < target->queue_size; ++i)
728509c07bcSBart Van Assche 			srp_free_iu(target->srp_host, ch->tx_ring[i]);
729509c07bcSBart Van Assche 		kfree(ch->tx_ring);
730509c07bcSBart Van Assche 		ch->tx_ring = NULL;
7314d73f95fSBart Van Assche 	}
732aef9ec39SRoland Dreier }
733aef9ec39SRoland Dreier 
734aef9ec39SRoland Dreier static void srp_path_rec_completion(int status,
735c2f8fc4eSDasaratharaman Chandramouli 				    struct sa_path_rec *pathrec,
736509c07bcSBart Van Assche 				    void *ch_ptr)
737aef9ec39SRoland Dreier {
738509c07bcSBart Van Assche 	struct srp_rdma_ch *ch = ch_ptr;
739509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
740aef9ec39SRoland Dreier 
741509c07bcSBart Van Assche 	ch->status = status;
742aef9ec39SRoland Dreier 	if (status)
7437aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
7447aa54bd7SDavid Dillow 			     PFX "Got failed path rec status %d\n", status);
745aef9ec39SRoland Dreier 	else
74619f31343SBart Van Assche 		ch->ib_cm.path = *pathrec;
747509c07bcSBart Van Assche 	complete(&ch->done);
748aef9ec39SRoland Dreier }
749aef9ec39SRoland Dreier 
75019f31343SBart Van Assche static int srp_ib_lookup_path(struct srp_rdma_ch *ch)
751aef9ec39SRoland Dreier {
752509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
753c74ff750SBart Van Assche 	int ret;
754a702adceSBart Van Assche 
75519f31343SBart Van Assche 	ch->ib_cm.path.numb_path = 1;
756aef9ec39SRoland Dreier 
757509c07bcSBart Van Assche 	init_completion(&ch->done);
758aef9ec39SRoland Dreier 
75919f31343SBart Van Assche 	ch->ib_cm.path_query_id = ib_sa_path_rec_get(&srp_sa_client,
76005321937SGreg Kroah-Hartman 					       target->srp_host->srp_dev->dev,
761aef9ec39SRoland Dreier 					       target->srp_host->port,
76219f31343SBart Van Assche 					       &ch->ib_cm.path,
763247e020eSSean Hefty 					       IB_SA_PATH_REC_SERVICE_ID |
764aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_DGID	 |
765aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_SGID	 |
766aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_NUMB_PATH	 |
767aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_PKEY,
768aef9ec39SRoland Dreier 					       SRP_PATH_REC_TIMEOUT_MS,
769aef9ec39SRoland Dreier 					       GFP_KERNEL,
770aef9ec39SRoland Dreier 					       srp_path_rec_completion,
77119f31343SBart Van Assche 					       ch, &ch->ib_cm.path_query);
772c74ff750SBart Van Assche 	if (ch->ib_cm.path_query_id < 0)
773c74ff750SBart Van Assche 		return ch->ib_cm.path_query_id;
774aef9ec39SRoland Dreier 
775509c07bcSBart Van Assche 	ret = wait_for_completion_interruptible(&ch->done);
776a702adceSBart Van Assche 	if (ret < 0)
777c74ff750SBart Van Assche 		return ret;
778aef9ec39SRoland Dreier 
779c74ff750SBart Van Assche 	if (ch->status < 0)
7807aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
78185769c6fSBart Van Assche 			     PFX "Path record query failed: sgid %pI6, dgid %pI6, pkey %#04x, service_id %#16llx\n",
78219f31343SBart Van Assche 			     ch->ib_cm.path.sgid.raw, ch->ib_cm.path.dgid.raw,
78319f31343SBart Van Assche 			     be16_to_cpu(target->ib_cm.pkey),
78419f31343SBart Van Assche 			     be64_to_cpu(target->ib_cm.service_id));
785aef9ec39SRoland Dreier 
786c74ff750SBart Van Assche 	return ch->status;
787aef9ec39SRoland Dreier }
788aef9ec39SRoland Dreier 
78919f31343SBart Van Assche static int srp_rdma_lookup_path(struct srp_rdma_ch *ch)
79019f31343SBart Van Assche {
79119f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
79219f31343SBart Van Assche 	int ret;
79319f31343SBart Van Assche 
79419f31343SBart Van Assche 	init_completion(&ch->done);
79519f31343SBart Van Assche 
79619f31343SBart Van Assche 	ret = rdma_resolve_route(ch->rdma_cm.cm_id, SRP_PATH_REC_TIMEOUT_MS);
79719f31343SBart Van Assche 	if (ret)
79819f31343SBart Van Assche 		return ret;
79919f31343SBart Van Assche 
80019f31343SBart Van Assche 	wait_for_completion_interruptible(&ch->done);
80119f31343SBart Van Assche 
80219f31343SBart Van Assche 	if (ch->status != 0)
80319f31343SBart Van Assche 		shost_printk(KERN_WARNING, target->scsi_host,
80419f31343SBart Van Assche 			     PFX "Path resolution failed\n");
80519f31343SBart Van Assche 
80619f31343SBart Van Assche 	return ch->status;
80719f31343SBart Van Assche }
80819f31343SBart Van Assche 
80919f31343SBart Van Assche static int srp_lookup_path(struct srp_rdma_ch *ch)
81019f31343SBart Van Assche {
81119f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
81219f31343SBart Van Assche 
81319f31343SBart Van Assche 	return target->using_rdma_cm ? srp_rdma_lookup_path(ch) :
81419f31343SBart Van Assche 		srp_ib_lookup_path(ch);
81519f31343SBart Van Assche }
81619f31343SBart Van Assche 
8174c532d6cSBart Van Assche static u8 srp_get_subnet_timeout(struct srp_host *host)
8184c532d6cSBart Van Assche {
8194c532d6cSBart Van Assche 	struct ib_port_attr attr;
8204c532d6cSBart Van Assche 	int ret;
8214c532d6cSBart Van Assche 	u8 subnet_timeout = 18;
8224c532d6cSBart Van Assche 
8234c532d6cSBart Van Assche 	ret = ib_query_port(host->srp_dev->dev, host->port, &attr);
8244c532d6cSBart Van Assche 	if (ret == 0)
8254c532d6cSBart Van Assche 		subnet_timeout = attr.subnet_timeout;
8264c532d6cSBart Van Assche 
8274c532d6cSBart Van Assche 	if (unlikely(subnet_timeout < 15))
8284c532d6cSBart Van Assche 		pr_warn("%s: subnet timeout %d may cause SRP login to fail.\n",
8294c532d6cSBart Van Assche 			dev_name(&host->srp_dev->dev->dev), subnet_timeout);
8304c532d6cSBart Van Assche 
8314c532d6cSBart Van Assche 	return subnet_timeout;
8324c532d6cSBart Van Assche }
8334c532d6cSBart Van Assche 
834513d5647SBart Van Assche static int srp_send_req(struct srp_rdma_ch *ch, uint32_t max_iu_len,
835513d5647SBart Van Assche 			bool multich)
836aef9ec39SRoland Dreier {
837509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
838aef9ec39SRoland Dreier 	struct {
83919f31343SBart Van Assche 		struct rdma_conn_param	  rdma_param;
84019f31343SBart Van Assche 		struct srp_login_req_rdma rdma_req;
84119f31343SBart Van Assche 		struct ib_cm_req_param	  ib_param;
84219f31343SBart Van Assche 		struct srp_login_req	  ib_req;
843aef9ec39SRoland Dreier 	} *req = NULL;
84448900a28SBart Van Assche 	char *ipi, *tpi;
845aef9ec39SRoland Dreier 	int status;
846aef9ec39SRoland Dreier 
847aef9ec39SRoland Dreier 	req = kzalloc(sizeof *req, GFP_KERNEL);
848aef9ec39SRoland Dreier 	if (!req)
849aef9ec39SRoland Dreier 		return -ENOMEM;
850aef9ec39SRoland Dreier 
85119f31343SBart Van Assche 	req->ib_param.flow_control = 1;
85219f31343SBart Van Assche 	req->ib_param.retry_count = target->tl_retry_count;
853aef9ec39SRoland Dreier 
854aef9ec39SRoland Dreier 	/*
855aef9ec39SRoland Dreier 	 * Pick some arbitrary defaults here; we could make these
856aef9ec39SRoland Dreier 	 * module parameters if anyone cared about setting them.
857aef9ec39SRoland Dreier 	 */
85819f31343SBart Van Assche 	req->ib_param.responder_resources = 4;
85919f31343SBart Van Assche 	req->ib_param.rnr_retry_count = 7;
86019f31343SBart Van Assche 	req->ib_param.max_cm_retries = 15;
861aef9ec39SRoland Dreier 
86219f31343SBart Van Assche 	req->ib_req.opcode = SRP_LOGIN_REQ;
86319f31343SBart Van Assche 	req->ib_req.tag = 0;
864513d5647SBart Van Assche 	req->ib_req.req_it_iu_len = cpu_to_be32(max_iu_len);
86519f31343SBart Van Assche 	req->ib_req.req_buf_fmt	= cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
866aef9ec39SRoland Dreier 					      SRP_BUF_FORMAT_INDIRECT);
86719f31343SBart Van Assche 	req->ib_req.req_flags = (multich ? SRP_MULTICHAN_MULTI :
868d92c0da7SBart Van Assche 				 SRP_MULTICHAN_SINGLE);
869882981f4SBart Van Assche 	if (srp_use_imm_data) {
870882981f4SBart Van Assche 		req->ib_req.req_flags |= SRP_IMMED_REQUESTED;
871882981f4SBart Van Assche 		req->ib_req.imm_data_offset = cpu_to_be16(SRP_IMM_DATA_OFFSET);
872882981f4SBart Van Assche 	}
87348900a28SBart Van Assche 
87419f31343SBart Van Assche 	if (target->using_rdma_cm) {
87519f31343SBart Van Assche 		req->rdma_param.flow_control = req->ib_param.flow_control;
87619f31343SBart Van Assche 		req->rdma_param.responder_resources =
87719f31343SBart Van Assche 			req->ib_param.responder_resources;
87819f31343SBart Van Assche 		req->rdma_param.initiator_depth = req->ib_param.initiator_depth;
87919f31343SBart Van Assche 		req->rdma_param.retry_count = req->ib_param.retry_count;
88019f31343SBart Van Assche 		req->rdma_param.rnr_retry_count = req->ib_param.rnr_retry_count;
88119f31343SBart Van Assche 		req->rdma_param.private_data = &req->rdma_req;
88219f31343SBart Van Assche 		req->rdma_param.private_data_len = sizeof(req->rdma_req);
88319f31343SBart Van Assche 
88419f31343SBart Van Assche 		req->rdma_req.opcode = req->ib_req.opcode;
88519f31343SBart Van Assche 		req->rdma_req.tag = req->ib_req.tag;
88619f31343SBart Van Assche 		req->rdma_req.req_it_iu_len = req->ib_req.req_it_iu_len;
88719f31343SBart Van Assche 		req->rdma_req.req_buf_fmt = req->ib_req.req_buf_fmt;
88819f31343SBart Van Assche 		req->rdma_req.req_flags	= req->ib_req.req_flags;
889882981f4SBart Van Assche 		req->rdma_req.imm_data_offset = req->ib_req.imm_data_offset;
89019f31343SBart Van Assche 
89119f31343SBart Van Assche 		ipi = req->rdma_req.initiator_port_id;
89219f31343SBart Van Assche 		tpi = req->rdma_req.target_port_id;
89319f31343SBart Van Assche 	} else {
89448900a28SBart Van Assche 		u8 subnet_timeout;
89548900a28SBart Van Assche 
89648900a28SBart Van Assche 		subnet_timeout = srp_get_subnet_timeout(target->srp_host);
89748900a28SBart Van Assche 
89819f31343SBart Van Assche 		req->ib_param.primary_path = &ch->ib_cm.path;
89919f31343SBart Van Assche 		req->ib_param.alternate_path = NULL;
90019f31343SBart Van Assche 		req->ib_param.service_id = target->ib_cm.service_id;
90119f31343SBart Van Assche 		get_random_bytes(&req->ib_param.starting_psn, 4);
90219f31343SBart Van Assche 		req->ib_param.starting_psn &= 0xffffff;
90319f31343SBart Van Assche 		req->ib_param.qp_num = ch->qp->qp_num;
90419f31343SBart Van Assche 		req->ib_param.qp_type = ch->qp->qp_type;
90519f31343SBart Van Assche 		req->ib_param.local_cm_response_timeout = subnet_timeout + 2;
90619f31343SBart Van Assche 		req->ib_param.remote_cm_response_timeout = subnet_timeout + 2;
90719f31343SBart Van Assche 		req->ib_param.private_data = &req->ib_req;
90819f31343SBart Van Assche 		req->ib_param.private_data_len = sizeof(req->ib_req);
90948900a28SBart Van Assche 
91019f31343SBart Van Assche 		ipi = req->ib_req.initiator_port_id;
91119f31343SBart Van Assche 		tpi = req->ib_req.target_port_id;
91248900a28SBart Van Assche 	}
91348900a28SBart Van Assche 
9140c0450dbSRamachandra K 	/*
9150c0450dbSRamachandra K 	 * In the published SRP specification (draft rev. 16a), the
9160c0450dbSRamachandra K 	 * port identifier format is 8 bytes of ID extension followed
9170c0450dbSRamachandra K 	 * by 8 bytes of GUID.  Older drafts put the two halves in the
9180c0450dbSRamachandra K 	 * opposite order, so that the GUID comes first.
9190c0450dbSRamachandra K 	 *
9200c0450dbSRamachandra K 	 * Targets conforming to these obsolete drafts can be
9210c0450dbSRamachandra K 	 * recognized by the I/O Class they report.
9220c0450dbSRamachandra K 	 */
9230c0450dbSRamachandra K 	if (target->io_class == SRP_REV10_IB_IO_CLASS) {
92448900a28SBart Van Assche 		memcpy(ipi,     &target->sgid.global.interface_id, 8);
92548900a28SBart Van Assche 		memcpy(ipi + 8, &target->initiator_ext, 8);
92648900a28SBart Van Assche 		memcpy(tpi,     &target->ioc_guid, 8);
92748900a28SBart Van Assche 		memcpy(tpi + 8, &target->id_ext, 8);
9280c0450dbSRamachandra K 	} else {
92948900a28SBart Van Assche 		memcpy(ipi,     &target->initiator_ext, 8);
93048900a28SBart Van Assche 		memcpy(ipi + 8, &target->sgid.global.interface_id, 8);
93148900a28SBart Van Assche 		memcpy(tpi,     &target->id_ext, 8);
93248900a28SBart Van Assche 		memcpy(tpi + 8, &target->ioc_guid, 8);
9330c0450dbSRamachandra K 	}
9340c0450dbSRamachandra K 
935aef9ec39SRoland Dreier 	/*
936aef9ec39SRoland Dreier 	 * Topspin/Cisco SRP targets will reject our login unless we
93701cb9bcbSIshai Rabinovitz 	 * zero out the first 8 bytes of our initiator port ID and set
93801cb9bcbSIshai Rabinovitz 	 * the second 8 bytes to the local node GUID.
939aef9ec39SRoland Dreier 	 */
9405d7cbfd6SRoland Dreier 	if (srp_target_is_topspin(target)) {
9417aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host,
9427aa54bd7SDavid Dillow 			     PFX "Topspin/Cisco initiator port ID workaround "
943aef9ec39SRoland Dreier 			     "activated for target GUID %016llx\n",
94445c37cadSBart Van Assche 			     be64_to_cpu(target->ioc_guid));
94548900a28SBart Van Assche 		memset(ipi, 0, 8);
94648900a28SBart Van Assche 		memcpy(ipi + 8, &target->srp_host->srp_dev->dev->node_guid, 8);
947aef9ec39SRoland Dreier 	}
948aef9ec39SRoland Dreier 
94919f31343SBart Van Assche 	if (target->using_rdma_cm)
95019f31343SBart Van Assche 		status = rdma_connect(ch->rdma_cm.cm_id, &req->rdma_param);
95119f31343SBart Van Assche 	else
95219f31343SBart Van Assche 		status = ib_send_cm_req(ch->ib_cm.cm_id, &req->ib_param);
953aef9ec39SRoland Dreier 
954aef9ec39SRoland Dreier 	kfree(req);
955aef9ec39SRoland Dreier 
956aef9ec39SRoland Dreier 	return status;
957aef9ec39SRoland Dreier }
958aef9ec39SRoland Dreier 
959ef6c49d8SBart Van Assche static bool srp_queue_remove_work(struct srp_target_port *target)
960ef6c49d8SBart Van Assche {
961ef6c49d8SBart Van Assche 	bool changed = false;
962ef6c49d8SBart Van Assche 
963ef6c49d8SBart Van Assche 	spin_lock_irq(&target->lock);
964ef6c49d8SBart Van Assche 	if (target->state != SRP_TARGET_REMOVED) {
965ef6c49d8SBart Van Assche 		target->state = SRP_TARGET_REMOVED;
966ef6c49d8SBart Van Assche 		changed = true;
967ef6c49d8SBart Van Assche 	}
968ef6c49d8SBart Van Assche 	spin_unlock_irq(&target->lock);
969ef6c49d8SBart Van Assche 
970ef6c49d8SBart Van Assche 	if (changed)
971bcc05910SBart Van Assche 		queue_work(srp_remove_wq, &target->remove_work);
972ef6c49d8SBart Van Assche 
973ef6c49d8SBart Van Assche 	return changed;
974ef6c49d8SBart Van Assche }
975ef6c49d8SBart Van Assche 
976aef9ec39SRoland Dreier static void srp_disconnect_target(struct srp_target_port *target)
977aef9ec39SRoland Dreier {
978d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
97919f31343SBart Van Assche 	int i, ret;
980509c07bcSBart Van Assche 
981aef9ec39SRoland Dreier 	/* XXX should send SRP_I_LOGOUT request */
982aef9ec39SRoland Dreier 
983d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
984d92c0da7SBart Van Assche 		ch = &target->ch[i];
985c014c8cdSBart Van Assche 		ch->connected = false;
98619f31343SBart Van Assche 		ret = 0;
98719f31343SBart Van Assche 		if (target->using_rdma_cm) {
98819f31343SBart Van Assche 			if (ch->rdma_cm.cm_id)
98919f31343SBart Van Assche 				rdma_disconnect(ch->rdma_cm.cm_id);
99019f31343SBart Van Assche 		} else {
99119f31343SBart Van Assche 			if (ch->ib_cm.cm_id)
99219f31343SBart Van Assche 				ret = ib_send_cm_dreq(ch->ib_cm.cm_id,
99319f31343SBart Van Assche 						      NULL, 0);
99419f31343SBart Van Assche 		}
99519f31343SBart Van Assche 		if (ret < 0) {
9967aa54bd7SDavid Dillow 			shost_printk(KERN_DEBUG, target->scsi_host,
9977aa54bd7SDavid Dillow 				     PFX "Sending CM DREQ failed\n");
998aef9ec39SRoland Dreier 		}
999294c875aSBart Van Assche 	}
1000294c875aSBart Van Assche }
1001aef9ec39SRoland Dreier 
1002509c07bcSBart Van Assche static void srp_free_req_data(struct srp_target_port *target,
1003509c07bcSBart Van Assche 			      struct srp_rdma_ch *ch)
10048f26c9ffSDavid Dillow {
10055cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
10065cfb1782SBart Van Assche 	struct ib_device *ibdev = dev->dev;
10078f26c9ffSDavid Dillow 	struct srp_request *req;
10088f26c9ffSDavid Dillow 	int i;
10098f26c9ffSDavid Dillow 
101047513cf4SBart Van Assche 	if (!ch->req_ring)
10114d73f95fSBart Van Assche 		return;
10124d73f95fSBart Van Assche 
10134d73f95fSBart Van Assche 	for (i = 0; i < target->req_ring_size; ++i) {
1014509c07bcSBart Van Assche 		req = &ch->req_ring[i];
10159a21be53SSagi Grimberg 		if (dev->use_fast_reg) {
10165cfb1782SBart Van Assche 			kfree(req->fr_list);
10179a21be53SSagi Grimberg 		} else {
10188f26c9ffSDavid Dillow 			kfree(req->fmr_list);
10198f26c9ffSDavid Dillow 			kfree(req->map_page);
10209a21be53SSagi Grimberg 		}
1021c07d424dSDavid Dillow 		if (req->indirect_dma_addr) {
1022c07d424dSDavid Dillow 			ib_dma_unmap_single(ibdev, req->indirect_dma_addr,
1023c07d424dSDavid Dillow 					    target->indirect_size,
1024c07d424dSDavid Dillow 					    DMA_TO_DEVICE);
1025c07d424dSDavid Dillow 		}
1026c07d424dSDavid Dillow 		kfree(req->indirect_desc);
10278f26c9ffSDavid Dillow 	}
10284d73f95fSBart Van Assche 
1029509c07bcSBart Van Assche 	kfree(ch->req_ring);
1030509c07bcSBart Van Assche 	ch->req_ring = NULL;
10318f26c9ffSDavid Dillow }
10328f26c9ffSDavid Dillow 
1033509c07bcSBart Van Assche static int srp_alloc_req_data(struct srp_rdma_ch *ch)
1034b81d00bdSBart Van Assche {
1035509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1036b81d00bdSBart Van Assche 	struct srp_device *srp_dev = target->srp_host->srp_dev;
1037b81d00bdSBart Van Assche 	struct ib_device *ibdev = srp_dev->dev;
1038b81d00bdSBart Van Assche 	struct srp_request *req;
10395cfb1782SBart Van Assche 	void *mr_list;
1040b81d00bdSBart Van Assche 	dma_addr_t dma_addr;
1041b81d00bdSBart Van Assche 	int i, ret = -ENOMEM;
1042b81d00bdSBart Van Assche 
1043509c07bcSBart Van Assche 	ch->req_ring = kcalloc(target->req_ring_size, sizeof(*ch->req_ring),
1044509c07bcSBart Van Assche 			       GFP_KERNEL);
1045509c07bcSBart Van Assche 	if (!ch->req_ring)
10464d73f95fSBart Van Assche 		goto out;
10474d73f95fSBart Van Assche 
10484d73f95fSBart Van Assche 	for (i = 0; i < target->req_ring_size; ++i) {
1049509c07bcSBart Van Assche 		req = &ch->req_ring[i];
10506da2ec56SKees Cook 		mr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *),
1051b81d00bdSBart Van Assche 					GFP_KERNEL);
10525cfb1782SBart Van Assche 		if (!mr_list)
10535cfb1782SBart Van Assche 			goto out;
10549a21be53SSagi Grimberg 		if (srp_dev->use_fast_reg) {
10555cfb1782SBart Van Assche 			req->fr_list = mr_list;
10569a21be53SSagi Grimberg 		} else {
10575cfb1782SBart Van Assche 			req->fmr_list = mr_list;
10586da2ec56SKees Cook 			req->map_page = kmalloc_array(srp_dev->max_pages_per_mr,
10596da2ec56SKees Cook 						      sizeof(void *),
10606da2ec56SKees Cook 						      GFP_KERNEL);
10615cfb1782SBart Van Assche 			if (!req->map_page)
10625cfb1782SBart Van Assche 				goto out;
10639a21be53SSagi Grimberg 		}
1064b81d00bdSBart Van Assche 		req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
10655cfb1782SBart Van Assche 		if (!req->indirect_desc)
1066b81d00bdSBart Van Assche 			goto out;
1067b81d00bdSBart Van Assche 
1068b81d00bdSBart Van Assche 		dma_addr = ib_dma_map_single(ibdev, req->indirect_desc,
1069b81d00bdSBart Van Assche 					     target->indirect_size,
1070b81d00bdSBart Van Assche 					     DMA_TO_DEVICE);
1071b81d00bdSBart Van Assche 		if (ib_dma_mapping_error(ibdev, dma_addr))
1072b81d00bdSBart Van Assche 			goto out;
1073b81d00bdSBart Van Assche 
1074b81d00bdSBart Van Assche 		req->indirect_dma_addr = dma_addr;
1075b81d00bdSBart Van Assche 	}
1076b81d00bdSBart Van Assche 	ret = 0;
1077b81d00bdSBart Van Assche 
1078b81d00bdSBart Van Assche out:
1079b81d00bdSBart Van Assche 	return ret;
1080b81d00bdSBart Van Assche }
1081b81d00bdSBart Van Assche 
1082683b159aSBart Van Assche /**
1083683b159aSBart Van Assche  * srp_del_scsi_host_attr() - Remove attributes defined in the host template.
1084683b159aSBart Van Assche  * @shost: SCSI host whose attributes to remove from sysfs.
1085683b159aSBart Van Assche  *
1086683b159aSBart Van Assche  * Note: Any attributes defined in the host template and that did not exist
1087683b159aSBart Van Assche  * before invocation of this function will be ignored.
1088683b159aSBart Van Assche  */
1089683b159aSBart Van Assche static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
1090683b159aSBart Van Assche {
1091683b159aSBart Van Assche 	struct device_attribute **attr;
1092683b159aSBart Van Assche 
1093683b159aSBart Van Assche 	for (attr = shost->hostt->shost_attrs; attr && *attr; ++attr)
1094683b159aSBart Van Assche 		device_remove_file(&shost->shost_dev, *attr);
1095683b159aSBart Van Assche }
1096683b159aSBart Van Assche 
1097ee12d6a8SBart Van Assche static void srp_remove_target(struct srp_target_port *target)
1098ee12d6a8SBart Van Assche {
1099d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1100d92c0da7SBart Van Assche 	int i;
1101509c07bcSBart Van Assche 
1102ef6c49d8SBart Van Assche 	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
1103ef6c49d8SBart Van Assche 
1104ee12d6a8SBart Van Assche 	srp_del_scsi_host_attr(target->scsi_host);
11059dd69a60SBart Van Assche 	srp_rport_get(target->rport);
1106ee12d6a8SBart Van Assche 	srp_remove_host(target->scsi_host);
1107ee12d6a8SBart Van Assche 	scsi_remove_host(target->scsi_host);
110893079162SBart Van Assche 	srp_stop_rport_timers(target->rport);
1109ef6c49d8SBart Van Assche 	srp_disconnect_target(target);
111019f31343SBart Van Assche 	kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
1111d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1112d92c0da7SBart Van Assche 		ch = &target->ch[i];
1113509c07bcSBart Van Assche 		srp_free_ch_ib(target, ch);
1114d92c0da7SBart Van Assche 	}
1115c1120f89SBart Van Assche 	cancel_work_sync(&target->tl_err_work);
11169dd69a60SBart Van Assche 	srp_rport_put(target->rport);
1117d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1118d92c0da7SBart Van Assche 		ch = &target->ch[i];
1119509c07bcSBart Van Assche 		srp_free_req_data(target, ch);
1120d92c0da7SBart Van Assche 	}
1121d92c0da7SBart Van Assche 	kfree(target->ch);
1122d92c0da7SBart Van Assche 	target->ch = NULL;
112365d7dd2fSVu Pham 
112465d7dd2fSVu Pham 	spin_lock(&target->srp_host->target_lock);
112565d7dd2fSVu Pham 	list_del(&target->list);
112665d7dd2fSVu Pham 	spin_unlock(&target->srp_host->target_lock);
112765d7dd2fSVu Pham 
1128ee12d6a8SBart Van Assche 	scsi_host_put(target->scsi_host);
1129ee12d6a8SBart Van Assche }
1130ee12d6a8SBart Van Assche 
1131c4028958SDavid Howells static void srp_remove_work(struct work_struct *work)
1132aef9ec39SRoland Dreier {
1133c4028958SDavid Howells 	struct srp_target_port *target =
1134ef6c49d8SBart Van Assche 		container_of(work, struct srp_target_port, remove_work);
1135aef9ec39SRoland Dreier 
1136ef6c49d8SBart Van Assche 	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
1137aef9ec39SRoland Dreier 
113896fc248aSBart Van Assche 	srp_remove_target(target);
1139aef9ec39SRoland Dreier }
1140aef9ec39SRoland Dreier 
1141dc1bdbd9SBart Van Assche static void srp_rport_delete(struct srp_rport *rport)
1142dc1bdbd9SBart Van Assche {
1143dc1bdbd9SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1144dc1bdbd9SBart Van Assche 
1145dc1bdbd9SBart Van Assche 	srp_queue_remove_work(target);
1146dc1bdbd9SBart Van Assche }
1147dc1bdbd9SBart Van Assche 
1148c014c8cdSBart Van Assche /**
1149c014c8cdSBart Van Assche  * srp_connected_ch() - number of connected channels
1150c014c8cdSBart Van Assche  * @target: SRP target port.
1151c014c8cdSBart Van Assche  */
1152c014c8cdSBart Van Assche static int srp_connected_ch(struct srp_target_port *target)
1153c014c8cdSBart Van Assche {
1154c014c8cdSBart Van Assche 	int i, c = 0;
1155c014c8cdSBart Van Assche 
1156c014c8cdSBart Van Assche 	for (i = 0; i < target->ch_count; i++)
1157c014c8cdSBart Van Assche 		c += target->ch[i].connected;
1158c014c8cdSBart Van Assche 
1159c014c8cdSBart Van Assche 	return c;
1160c014c8cdSBart Van Assche }
1161c014c8cdSBart Van Assche 
1162513d5647SBart Van Assche static int srp_connect_ch(struct srp_rdma_ch *ch, uint32_t max_iu_len,
1163513d5647SBart Van Assche 			  bool multich)
1164aef9ec39SRoland Dreier {
1165509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1166aef9ec39SRoland Dreier 	int ret;
1167aef9ec39SRoland Dreier 
1168c014c8cdSBart Van Assche 	WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0);
1169294c875aSBart Van Assche 
1170509c07bcSBart Van Assche 	ret = srp_lookup_path(ch);
1171aef9ec39SRoland Dreier 	if (ret)
11724d59ad29SBart Van Assche 		goto out;
1173aef9ec39SRoland Dreier 
1174aef9ec39SRoland Dreier 	while (1) {
1175509c07bcSBart Van Assche 		init_completion(&ch->done);
1176513d5647SBart Van Assche 		ret = srp_send_req(ch, max_iu_len, multich);
1177aef9ec39SRoland Dreier 		if (ret)
11784d59ad29SBart Van Assche 			goto out;
1179509c07bcSBart Van Assche 		ret = wait_for_completion_interruptible(&ch->done);
1180a702adceSBart Van Assche 		if (ret < 0)
11814d59ad29SBart Van Assche 			goto out;
1182aef9ec39SRoland Dreier 
1183aef9ec39SRoland Dreier 		/*
1184aef9ec39SRoland Dreier 		 * The CM event handling code will set status to
1185aef9ec39SRoland Dreier 		 * SRP_PORT_REDIRECT if we get a port redirect REJ
1186aef9ec39SRoland Dreier 		 * back, or SRP_DLID_REDIRECT if we get a lid/qp
1187aef9ec39SRoland Dreier 		 * redirect REJ back.
1188aef9ec39SRoland Dreier 		 */
11894d59ad29SBart Van Assche 		ret = ch->status;
11904d59ad29SBart Van Assche 		switch (ret) {
1191aef9ec39SRoland Dreier 		case 0:
1192c014c8cdSBart Van Assche 			ch->connected = true;
11934d59ad29SBart Van Assche 			goto out;
1194aef9ec39SRoland Dreier 
1195aef9ec39SRoland Dreier 		case SRP_PORT_REDIRECT:
1196509c07bcSBart Van Assche 			ret = srp_lookup_path(ch);
1197aef9ec39SRoland Dreier 			if (ret)
11984d59ad29SBart Van Assche 				goto out;
1199aef9ec39SRoland Dreier 			break;
1200aef9ec39SRoland Dreier 
1201aef9ec39SRoland Dreier 		case SRP_DLID_REDIRECT:
1202aef9ec39SRoland Dreier 			break;
1203aef9ec39SRoland Dreier 
12049fe4bcf4SDavid Dillow 		case SRP_STALE_CONN:
12059fe4bcf4SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host, PFX
12069fe4bcf4SDavid Dillow 				     "giving up on stale connection\n");
12074d59ad29SBart Van Assche 			ret = -ECONNRESET;
12084d59ad29SBart Van Assche 			goto out;
12099fe4bcf4SDavid Dillow 
1210aef9ec39SRoland Dreier 		default:
12114d59ad29SBart Van Assche 			goto out;
1212aef9ec39SRoland Dreier 		}
1213aef9ec39SRoland Dreier 	}
12144d59ad29SBart Van Assche 
12154d59ad29SBart Van Assche out:
12164d59ad29SBart Van Assche 	return ret <= 0 ? ret : -ENODEV;
1217aef9ec39SRoland Dreier }
1218aef9ec39SRoland Dreier 
12191dc7b1f1SChristoph Hellwig static void srp_inv_rkey_err_done(struct ib_cq *cq, struct ib_wc *wc)
12201dc7b1f1SChristoph Hellwig {
12211dc7b1f1SChristoph Hellwig 	srp_handle_qp_err(cq, wc, "INV RKEY");
12221dc7b1f1SChristoph Hellwig }
12231dc7b1f1SChristoph Hellwig 
12241dc7b1f1SChristoph Hellwig static int srp_inv_rkey(struct srp_request *req, struct srp_rdma_ch *ch,
12251dc7b1f1SChristoph Hellwig 		u32 rkey)
12265cfb1782SBart Van Assche {
12275cfb1782SBart Van Assche 	struct ib_send_wr wr = {
12285cfb1782SBart Van Assche 		.opcode		    = IB_WR_LOCAL_INV,
12295cfb1782SBart Van Assche 		.next		    = NULL,
12305cfb1782SBart Van Assche 		.num_sge	    = 0,
12315cfb1782SBart Van Assche 		.send_flags	    = 0,
12325cfb1782SBart Van Assche 		.ex.invalidate_rkey = rkey,
12335cfb1782SBart Van Assche 	};
12345cfb1782SBart Van Assche 
12351dc7b1f1SChristoph Hellwig 	wr.wr_cqe = &req->reg_cqe;
12361dc7b1f1SChristoph Hellwig 	req->reg_cqe.done = srp_inv_rkey_err_done;
123771347b0cSBart Van Assche 	return ib_post_send(ch->qp, &wr, NULL);
12385cfb1782SBart Van Assche }
12395cfb1782SBart Van Assche 
1240d945e1dfSRoland Dreier static void srp_unmap_data(struct scsi_cmnd *scmnd,
1241509c07bcSBart Van Assche 			   struct srp_rdma_ch *ch,
1242d945e1dfSRoland Dreier 			   struct srp_request *req)
1243d945e1dfSRoland Dreier {
1244509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
12455cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
12465cfb1782SBart Van Assche 	struct ib_device *ibdev = dev->dev;
12475cfb1782SBart Van Assche 	int i, res;
12488f26c9ffSDavid Dillow 
1249bb350d1dSFUJITA Tomonori 	if (!scsi_sglist(scmnd) ||
1250d945e1dfSRoland Dreier 	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
1251d945e1dfSRoland Dreier 	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
1252d945e1dfSRoland Dreier 		return;
1253d945e1dfSRoland Dreier 
12545cfb1782SBart Van Assche 	if (dev->use_fast_reg) {
12555cfb1782SBart Van Assche 		struct srp_fr_desc **pfr;
12565cfb1782SBart Van Assche 
12575cfb1782SBart Van Assche 		for (i = req->nmdesc, pfr = req->fr_list; i > 0; i--, pfr++) {
12581dc7b1f1SChristoph Hellwig 			res = srp_inv_rkey(req, ch, (*pfr)->mr->rkey);
12595cfb1782SBart Van Assche 			if (res < 0) {
12605cfb1782SBart Van Assche 				shost_printk(KERN_ERR, target->scsi_host, PFX
12615cfb1782SBart Van Assche 				  "Queueing INV WR for rkey %#x failed (%d)\n",
12625cfb1782SBart Van Assche 				  (*pfr)->mr->rkey, res);
12635cfb1782SBart Van Assche 				queue_work(system_long_wq,
12645cfb1782SBart Van Assche 					   &target->tl_err_work);
12655cfb1782SBart Van Assche 			}
12665cfb1782SBart Van Assche 		}
12675cfb1782SBart Van Assche 		if (req->nmdesc)
1268509c07bcSBart Van Assche 			srp_fr_pool_put(ch->fr_pool, req->fr_list,
12695cfb1782SBart Van Assche 					req->nmdesc);
1270002f1567SBart Van Assche 	} else if (dev->use_fmr) {
12715cfb1782SBart Van Assche 		struct ib_pool_fmr **pfmr;
12725cfb1782SBart Van Assche 
12735cfb1782SBart Van Assche 		for (i = req->nmdesc, pfmr = req->fmr_list; i > 0; i--, pfmr++)
12745cfb1782SBart Van Assche 			ib_fmr_pool_unmap(*pfmr);
12755cfb1782SBart Van Assche 	}
1276f5358a17SRoland Dreier 
12778f26c9ffSDavid Dillow 	ib_dma_unmap_sg(ibdev, scsi_sglist(scmnd), scsi_sg_count(scmnd),
12788f26c9ffSDavid Dillow 			scmnd->sc_data_direction);
1279d945e1dfSRoland Dreier }
1280d945e1dfSRoland Dreier 
128122032991SBart Van Assche /**
128222032991SBart Van Assche  * srp_claim_req - Take ownership of the scmnd associated with a request.
1283509c07bcSBart Van Assche  * @ch: SRP RDMA channel.
128422032991SBart Van Assche  * @req: SRP request.
1285b3fe628dSBart Van Assche  * @sdev: If not NULL, only take ownership for this SCSI device.
128622032991SBart Van Assche  * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
128722032991SBart Van Assche  *         ownership of @req->scmnd if it equals @scmnd.
128822032991SBart Van Assche  *
128922032991SBart Van Assche  * Return value:
129022032991SBart Van Assche  * Either NULL or a pointer to the SCSI command the caller became owner of.
129122032991SBart Van Assche  */
1292509c07bcSBart Van Assche static struct scsi_cmnd *srp_claim_req(struct srp_rdma_ch *ch,
129322032991SBart Van Assche 				       struct srp_request *req,
1294b3fe628dSBart Van Assche 				       struct scsi_device *sdev,
129522032991SBart Van Assche 				       struct scsi_cmnd *scmnd)
1296526b4caaSIshai Rabinovitz {
129794a9174cSBart Van Assche 	unsigned long flags;
129894a9174cSBart Van Assche 
1299509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1300b3fe628dSBart Van Assche 	if (req->scmnd &&
1301b3fe628dSBart Van Assche 	    (!sdev || req->scmnd->device == sdev) &&
1302b3fe628dSBart Van Assche 	    (!scmnd || req->scmnd == scmnd)) {
130322032991SBart Van Assche 		scmnd = req->scmnd;
130422032991SBart Van Assche 		req->scmnd = NULL;
130522032991SBart Van Assche 	} else {
130622032991SBart Van Assche 		scmnd = NULL;
130722032991SBart Van Assche 	}
1308509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
130922032991SBart Van Assche 
131022032991SBart Van Assche 	return scmnd;
131122032991SBart Van Assche }
131222032991SBart Van Assche 
131322032991SBart Van Assche /**
13146ec2ba02SBart Van Assche  * srp_free_req() - Unmap data and adjust ch->req_lim.
1315509c07bcSBart Van Assche  * @ch:     SRP RDMA channel.
1316af24663bSBart Van Assche  * @req:    Request to be freed.
1317af24663bSBart Van Assche  * @scmnd:  SCSI command associated with @req.
1318af24663bSBart Van Assche  * @req_lim_delta: Amount to be added to @target->req_lim.
131922032991SBart Van Assche  */
1320509c07bcSBart Van Assche static void srp_free_req(struct srp_rdma_ch *ch, struct srp_request *req,
1321509c07bcSBart Van Assche 			 struct scsi_cmnd *scmnd, s32 req_lim_delta)
132222032991SBart Van Assche {
132322032991SBart Van Assche 	unsigned long flags;
132422032991SBart Van Assche 
1325509c07bcSBart Van Assche 	srp_unmap_data(scmnd, ch, req);
132622032991SBart Van Assche 
1327509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1328509c07bcSBart Van Assche 	ch->req_lim += req_lim_delta;
1329509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
1330526b4caaSIshai Rabinovitz }
1331526b4caaSIshai Rabinovitz 
1332509c07bcSBart Van Assche static void srp_finish_req(struct srp_rdma_ch *ch, struct srp_request *req,
1333509c07bcSBart Van Assche 			   struct scsi_device *sdev, int result)
1334526b4caaSIshai Rabinovitz {
1335509c07bcSBart Van Assche 	struct scsi_cmnd *scmnd = srp_claim_req(ch, req, sdev, NULL);
133622032991SBart Van Assche 
133722032991SBart Van Assche 	if (scmnd) {
1338509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd, 0);
1339ed9b2264SBart Van Assche 		scmnd->result = result;
134022032991SBart Van Assche 		scmnd->scsi_done(scmnd);
134122032991SBart Van Assche 	}
1342526b4caaSIshai Rabinovitz }
1343526b4caaSIshai Rabinovitz 
1344ed9b2264SBart Van Assche static void srp_terminate_io(struct srp_rport *rport)
1345aef9ec39SRoland Dreier {
1346ed9b2264SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1347d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1348d92c0da7SBart Van Assche 	int i, j;
1349aef9ec39SRoland Dreier 
1350d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1351d92c0da7SBart Van Assche 		ch = &target->ch[i];
1352509c07bcSBart Van Assche 
1353d92c0da7SBart Van Assche 		for (j = 0; j < target->req_ring_size; ++j) {
1354d92c0da7SBart Van Assche 			struct srp_request *req = &ch->req_ring[j];
1355d92c0da7SBart Van Assche 
1356d92c0da7SBart Van Assche 			srp_finish_req(ch, req, NULL,
1357d92c0da7SBart Van Assche 				       DID_TRANSPORT_FAILFAST << 16);
1358d92c0da7SBart Van Assche 		}
1359ed9b2264SBart Van Assche 	}
1360ed9b2264SBart Van Assche }
1361ed9b2264SBart Van Assche 
1362513d5647SBart Van Assche /* Calculate maximum initiator to target information unit length. */
1363882981f4SBart Van Assche static uint32_t srp_max_it_iu_len(int cmd_sg_cnt, bool use_imm_data)
1364513d5647SBart Van Assche {
1365513d5647SBart Van Assche 	uint32_t max_iu_len = sizeof(struct srp_cmd) + SRP_MAX_ADD_CDB_LEN +
1366513d5647SBart Van Assche 		sizeof(struct srp_indirect_buf) +
1367513d5647SBart Van Assche 		cmd_sg_cnt * sizeof(struct srp_direct_buf);
1368513d5647SBart Van Assche 
1369882981f4SBart Van Assche 	if (use_imm_data)
1370882981f4SBart Van Assche 		max_iu_len = max(max_iu_len, SRP_IMM_DATA_OFFSET +
1371882981f4SBart Van Assche 				 srp_max_imm_data);
1372882981f4SBart Van Assche 
1373513d5647SBart Van Assche 	return max_iu_len;
1374513d5647SBart Van Assche }
1375513d5647SBart Van Assche 
1376ed9b2264SBart Van Assche /*
1377ed9b2264SBart Van Assche  * It is up to the caller to ensure that srp_rport_reconnect() calls are
1378ed9b2264SBart Van Assche  * serialized and that no concurrent srp_queuecommand(), srp_abort(),
1379ed9b2264SBart Van Assche  * srp_reset_device() or srp_reset_host() calls will occur while this function
1380ed9b2264SBart Van Assche  * is in progress. One way to realize that is not to call this function
1381ed9b2264SBart Van Assche  * directly but to call srp_reconnect_rport() instead since that last function
1382ed9b2264SBart Van Assche  * serializes calls of this function via rport->mutex and also blocks
1383ed9b2264SBart Van Assche  * srp_queuecommand() calls before invoking this function.
1384ed9b2264SBart Van Assche  */
1385ed9b2264SBart Van Assche static int srp_rport_reconnect(struct srp_rport *rport)
1386ed9b2264SBart Van Assche {
1387ed9b2264SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1388d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1389882981f4SBart Van Assche 	uint32_t max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
1390882981f4SBart Van Assche 						srp_use_imm_data);
1391d92c0da7SBart Van Assche 	int i, j, ret = 0;
1392d92c0da7SBart Van Assche 	bool multich = false;
139309be70a2SBart Van Assche 
1394aef9ec39SRoland Dreier 	srp_disconnect_target(target);
139534aa654eSBart Van Assche 
139634aa654eSBart Van Assche 	if (target->state == SRP_TARGET_SCANNING)
139734aa654eSBart Van Assche 		return -ENODEV;
139834aa654eSBart Van Assche 
1399aef9ec39SRoland Dreier 	/*
1400c7c4e7ffSBart Van Assche 	 * Now get a new local CM ID so that we avoid confusing the target in
1401c7c4e7ffSBart Van Assche 	 * case things are really fouled up. Doing so also ensures that all CM
1402c7c4e7ffSBart Van Assche 	 * callbacks will have finished before a new QP is allocated.
1403aef9ec39SRoland Dreier 	 */
1404d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1405d92c0da7SBart Van Assche 		ch = &target->ch[i];
1406d92c0da7SBart Van Assche 		ret += srp_new_cm_id(ch);
1407d92c0da7SBart Van Assche 	}
1408d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1409d92c0da7SBart Van Assche 		ch = &target->ch[i];
1410d92c0da7SBart Van Assche 		for (j = 0; j < target->req_ring_size; ++j) {
1411d92c0da7SBart Van Assche 			struct srp_request *req = &ch->req_ring[j];
1412509c07bcSBart Van Assche 
1413509c07bcSBart Van Assche 			srp_finish_req(ch, req, NULL, DID_RESET << 16);
1414536ae14eSBart Van Assche 		}
1415d92c0da7SBart Van Assche 	}
1416d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1417d92c0da7SBart Van Assche 		ch = &target->ch[i];
14185cfb1782SBart Van Assche 		/*
14195cfb1782SBart Van Assche 		 * Whether or not creating a new CM ID succeeded, create a new
1420d92c0da7SBart Van Assche 		 * QP. This guarantees that all completion callback function
1421d92c0da7SBart Van Assche 		 * invocations have finished before request resetting starts.
14225cfb1782SBart Van Assche 		 */
1423509c07bcSBart Van Assche 		ret += srp_create_ch_ib(ch);
14245cfb1782SBart Van Assche 
1425509c07bcSBart Van Assche 		INIT_LIST_HEAD(&ch->free_tx);
1426d92c0da7SBart Van Assche 		for (j = 0; j < target->queue_size; ++j)
1427d92c0da7SBart Van Assche 			list_add(&ch->tx_ring[j]->list, &ch->free_tx);
1428d92c0da7SBart Van Assche 	}
14298de9fe3aSBart Van Assche 
14308de9fe3aSBart Van Assche 	target->qp_in_error = false;
14318de9fe3aSBart Van Assche 
1432d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1433d92c0da7SBart Van Assche 		ch = &target->ch[i];
1434bbac5ccfSBart Van Assche 		if (ret)
1435d92c0da7SBart Van Assche 			break;
1436513d5647SBart Van Assche 		ret = srp_connect_ch(ch, max_iu_len, multich);
1437d92c0da7SBart Van Assche 		multich = true;
1438d92c0da7SBart Van Assche 	}
143909be70a2SBart Van Assche 
1440ed9b2264SBart Van Assche 	if (ret == 0)
1441ed9b2264SBart Van Assche 		shost_printk(KERN_INFO, target->scsi_host,
1442ed9b2264SBart Van Assche 			     PFX "reconnect succeeded\n");
1443aef9ec39SRoland Dreier 
1444aef9ec39SRoland Dreier 	return ret;
1445aef9ec39SRoland Dreier }
1446aef9ec39SRoland Dreier 
14478f26c9ffSDavid Dillow static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr,
14488f26c9ffSDavid Dillow 			 unsigned int dma_len, u32 rkey)
1449f5358a17SRoland Dreier {
14508f26c9ffSDavid Dillow 	struct srp_direct_buf *desc = state->desc;
14518f26c9ffSDavid Dillow 
14523ae95da8SBart Van Assche 	WARN_ON_ONCE(!dma_len);
14533ae95da8SBart Van Assche 
14548f26c9ffSDavid Dillow 	desc->va = cpu_to_be64(dma_addr);
14558f26c9ffSDavid Dillow 	desc->key = cpu_to_be32(rkey);
14568f26c9ffSDavid Dillow 	desc->len = cpu_to_be32(dma_len);
14578f26c9ffSDavid Dillow 
14588f26c9ffSDavid Dillow 	state->total_len += dma_len;
14598f26c9ffSDavid Dillow 	state->desc++;
14608f26c9ffSDavid Dillow 	state->ndesc++;
14618f26c9ffSDavid Dillow }
14628f26c9ffSDavid Dillow 
14638f26c9ffSDavid Dillow static int srp_map_finish_fmr(struct srp_map_state *state,
1464509c07bcSBart Van Assche 			      struct srp_rdma_ch *ch)
14658f26c9ffSDavid Dillow {
1466186fbc66SBart Van Assche 	struct srp_target_port *target = ch->target;
1467186fbc66SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
14688f26c9ffSDavid Dillow 	struct ib_pool_fmr *fmr;
1469f5358a17SRoland Dreier 	u64 io_addr = 0;
14708f26c9ffSDavid Dillow 
1471290081b4SBart Van Assche 	if (state->fmr.next >= state->fmr.end) {
1472290081b4SBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host,
1473290081b4SBart Van Assche 			     PFX "Out of MRs (mr_per_cmd = %d)\n",
1474290081b4SBart Van Assche 			     ch->target->mr_per_cmd);
1475f731ed62SBart Van Assche 		return -ENOMEM;
1476290081b4SBart Van Assche 	}
1477f731ed62SBart Van Assche 
147826630e8aSSagi Grimberg 	WARN_ON_ONCE(!dev->use_fmr);
147926630e8aSSagi Grimberg 
148026630e8aSSagi Grimberg 	if (state->npages == 0)
148126630e8aSSagi Grimberg 		return 0;
148226630e8aSSagi Grimberg 
1483cee687b6SBart Van Assche 	if (state->npages == 1 && target->global_rkey) {
148426630e8aSSagi Grimberg 		srp_map_desc(state, state->base_dma_addr, state->dma_len,
1485cee687b6SBart Van Assche 			     target->global_rkey);
148626630e8aSSagi Grimberg 		goto reset_state;
148726630e8aSSagi Grimberg 	}
148826630e8aSSagi Grimberg 
1489509c07bcSBart Van Assche 	fmr = ib_fmr_pool_map_phys(ch->fmr_pool, state->pages,
14908f26c9ffSDavid Dillow 				   state->npages, io_addr);
14918f26c9ffSDavid Dillow 	if (IS_ERR(fmr))
14928f26c9ffSDavid Dillow 		return PTR_ERR(fmr);
14938f26c9ffSDavid Dillow 
1494f731ed62SBart Van Assche 	*state->fmr.next++ = fmr;
149552ede08fSBart Van Assche 	state->nmdesc++;
14968f26c9ffSDavid Dillow 
1497186fbc66SBart Van Assche 	srp_map_desc(state, state->base_dma_addr & ~dev->mr_page_mask,
1498186fbc66SBart Van Assche 		     state->dma_len, fmr->fmr->rkey);
1499539dde6fSBart Van Assche 
150026630e8aSSagi Grimberg reset_state:
150126630e8aSSagi Grimberg 	state->npages = 0;
150226630e8aSSagi Grimberg 	state->dma_len = 0;
150326630e8aSSagi Grimberg 
15048f26c9ffSDavid Dillow 	return 0;
15058f26c9ffSDavid Dillow }
15068f26c9ffSDavid Dillow 
15071dc7b1f1SChristoph Hellwig static void srp_reg_mr_err_done(struct ib_cq *cq, struct ib_wc *wc)
15081dc7b1f1SChristoph Hellwig {
15091dc7b1f1SChristoph Hellwig 	srp_handle_qp_err(cq, wc, "FAST REG");
15101dc7b1f1SChristoph Hellwig }
15111dc7b1f1SChristoph Hellwig 
1512509c5f33SBart Van Assche /*
1513509c5f33SBart Van Assche  * Map up to sg_nents elements of state->sg where *sg_offset_p is the offset
1514509c5f33SBart Van Assche  * where to start in the first element. If sg_offset_p != NULL then
1515509c5f33SBart Van Assche  * *sg_offset_p is updated to the offset in state->sg[retval] of the first
1516509c5f33SBart Van Assche  * byte that has not yet been mapped.
1517509c5f33SBart Van Assche  */
15185cfb1782SBart Van Assche static int srp_map_finish_fr(struct srp_map_state *state,
15191dc7b1f1SChristoph Hellwig 			     struct srp_request *req,
1520509c5f33SBart Van Assche 			     struct srp_rdma_ch *ch, int sg_nents,
1521509c5f33SBart Van Assche 			     unsigned int *sg_offset_p)
15225cfb1782SBart Van Assche {
1523509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
15245cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
1525f7f7aab1SSagi Grimberg 	struct ib_reg_wr wr;
15265cfb1782SBart Van Assche 	struct srp_fr_desc *desc;
15275cfb1782SBart Van Assche 	u32 rkey;
1528f7f7aab1SSagi Grimberg 	int n, err;
15295cfb1782SBart Van Assche 
1530290081b4SBart Van Assche 	if (state->fr.next >= state->fr.end) {
1531290081b4SBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host,
1532290081b4SBart Van Assche 			     PFX "Out of MRs (mr_per_cmd = %d)\n",
1533290081b4SBart Van Assche 			     ch->target->mr_per_cmd);
1534f731ed62SBart Van Assche 		return -ENOMEM;
1535290081b4SBart Van Assche 	}
1536f731ed62SBart Van Assche 
153726630e8aSSagi Grimberg 	WARN_ON_ONCE(!dev->use_fast_reg);
153826630e8aSSagi Grimberg 
1539cee687b6SBart Van Assche 	if (sg_nents == 1 && target->global_rkey) {
1540509c5f33SBart Van Assche 		unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
1541509c5f33SBart Van Assche 
1542509c5f33SBart Van Assche 		srp_map_desc(state, sg_dma_address(state->sg) + sg_offset,
1543509c5f33SBart Van Assche 			     sg_dma_len(state->sg) - sg_offset,
1544cee687b6SBart Van Assche 			     target->global_rkey);
1545509c5f33SBart Van Assche 		if (sg_offset_p)
1546509c5f33SBart Van Assche 			*sg_offset_p = 0;
1547f7f7aab1SSagi Grimberg 		return 1;
154826630e8aSSagi Grimberg 	}
154926630e8aSSagi Grimberg 
1550509c07bcSBart Van Assche 	desc = srp_fr_pool_get(ch->fr_pool);
15515cfb1782SBart Van Assche 	if (!desc)
15525cfb1782SBart Van Assche 		return -ENOMEM;
15535cfb1782SBart Van Assche 
15545cfb1782SBart Van Assche 	rkey = ib_inc_rkey(desc->mr->rkey);
15555cfb1782SBart Van Assche 	ib_update_fast_reg_key(desc->mr, rkey);
15565cfb1782SBart Van Assche 
1557509c5f33SBart Van Assche 	n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, sg_offset_p,
1558509c5f33SBart Van Assche 			 dev->mr_page_size);
15599d8e7d0dSBart Van Assche 	if (unlikely(n < 0)) {
15609d8e7d0dSBart Van Assche 		srp_fr_pool_put(ch->fr_pool, &desc, 1);
1561509c5f33SBart Van Assche 		pr_debug("%s: ib_map_mr_sg(%d, %d) returned %d.\n",
15629d8e7d0dSBart Van Assche 			 dev_name(&req->scmnd->device->sdev_gendev), sg_nents,
1563509c5f33SBart Van Assche 			 sg_offset_p ? *sg_offset_p : -1, n);
1564f7f7aab1SSagi Grimberg 		return n;
15659d8e7d0dSBart Van Assche 	}
15665cfb1782SBart Van Assche 
1567509c5f33SBart Van Assche 	WARN_ON_ONCE(desc->mr->length == 0);
15685cfb1782SBart Van Assche 
15691dc7b1f1SChristoph Hellwig 	req->reg_cqe.done = srp_reg_mr_err_done;
15701dc7b1f1SChristoph Hellwig 
1571f7f7aab1SSagi Grimberg 	wr.wr.next = NULL;
1572f7f7aab1SSagi Grimberg 	wr.wr.opcode = IB_WR_REG_MR;
15731dc7b1f1SChristoph Hellwig 	wr.wr.wr_cqe = &req->reg_cqe;
1574f7f7aab1SSagi Grimberg 	wr.wr.num_sge = 0;
1575f7f7aab1SSagi Grimberg 	wr.wr.send_flags = 0;
1576f7f7aab1SSagi Grimberg 	wr.mr = desc->mr;
1577f7f7aab1SSagi Grimberg 	wr.key = desc->mr->rkey;
1578f7f7aab1SSagi Grimberg 	wr.access = (IB_ACCESS_LOCAL_WRITE |
15795cfb1782SBart Van Assche 		     IB_ACCESS_REMOTE_READ |
15805cfb1782SBart Van Assche 		     IB_ACCESS_REMOTE_WRITE);
15815cfb1782SBart Van Assche 
1582f731ed62SBart Van Assche 	*state->fr.next++ = desc;
15835cfb1782SBart Van Assche 	state->nmdesc++;
15845cfb1782SBart Van Assche 
1585f7f7aab1SSagi Grimberg 	srp_map_desc(state, desc->mr->iova,
1586f7f7aab1SSagi Grimberg 		     desc->mr->length, desc->mr->rkey);
15875cfb1782SBart Van Assche 
158871347b0cSBart Van Assche 	err = ib_post_send(ch->qp, &wr.wr, NULL);
1589509c5f33SBart Van Assche 	if (unlikely(err)) {
1590509c5f33SBart Van Assche 		WARN_ON_ONCE(err == -ENOMEM);
159126630e8aSSagi Grimberg 		return err;
1592509c5f33SBart Van Assche 	}
159326630e8aSSagi Grimberg 
1594f7f7aab1SSagi Grimberg 	return n;
15955cfb1782SBart Van Assche }
15965cfb1782SBart Van Assche 
15978f26c9ffSDavid Dillow static int srp_map_sg_entry(struct srp_map_state *state,
1598509c07bcSBart Van Assche 			    struct srp_rdma_ch *ch,
159952bb8c62SBart Van Assche 			    struct scatterlist *sg)
16008f26c9ffSDavid Dillow {
1601509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
160205321937SGreg Kroah-Hartman 	struct srp_device *dev = target->srp_host->srp_dev;
1603a163afc8SBart Van Assche 	dma_addr_t dma_addr = sg_dma_address(sg);
1604a163afc8SBart Van Assche 	unsigned int dma_len = sg_dma_len(sg);
16053ae95da8SBart Van Assche 	unsigned int len = 0;
16068f26c9ffSDavid Dillow 	int ret;
160785507bccSRalph Campbell 
16083ae95da8SBart Van Assche 	WARN_ON_ONCE(!dma_len);
1609f5358a17SRoland Dreier 
16108f26c9ffSDavid Dillow 	while (dma_len) {
16115cfb1782SBart Van Assche 		unsigned offset = dma_addr & ~dev->mr_page_mask;
1612681cc360SBart Van Assche 
1613681cc360SBart Van Assche 		if (state->npages == dev->max_pages_per_mr ||
1614681cc360SBart Van Assche 		    (state->npages > 0 && offset != 0)) {
1615f7f7aab1SSagi Grimberg 			ret = srp_map_finish_fmr(state, ch);
16168f26c9ffSDavid Dillow 			if (ret)
16178f26c9ffSDavid Dillow 				return ret;
161885507bccSRalph Campbell 		}
1619f5358a17SRoland Dreier 
16205cfb1782SBart Van Assche 		len = min_t(unsigned int, dma_len, dev->mr_page_size - offset);
16218f26c9ffSDavid Dillow 
16228f26c9ffSDavid Dillow 		if (!state->npages)
16238f26c9ffSDavid Dillow 			state->base_dma_addr = dma_addr;
16245cfb1782SBart Van Assche 		state->pages[state->npages++] = dma_addr & dev->mr_page_mask;
162552ede08fSBart Van Assche 		state->dma_len += len;
16268f26c9ffSDavid Dillow 		dma_addr += len;
16278f26c9ffSDavid Dillow 		dma_len -= len;
1628f5358a17SRoland Dreier 	}
1629f5358a17SRoland Dreier 
16305cfb1782SBart Van Assche 	/*
1631681cc360SBart Van Assche 	 * If the end of the MR is not on a page boundary then we need to
16328f26c9ffSDavid Dillow 	 * close it out and start a new one -- we can only merge at page
16331d3d98c4SBart Van Assche 	 * boundaries.
16348f26c9ffSDavid Dillow 	 */
1635f5358a17SRoland Dreier 	ret = 0;
1636681cc360SBart Van Assche 	if ((dma_addr & ~dev->mr_page_mask) != 0)
1637f7f7aab1SSagi Grimberg 		ret = srp_map_finish_fmr(state, ch);
1638f5358a17SRoland Dreier 	return ret;
1639f5358a17SRoland Dreier }
1640f5358a17SRoland Dreier 
164126630e8aSSagi Grimberg static int srp_map_sg_fmr(struct srp_map_state *state, struct srp_rdma_ch *ch,
164226630e8aSSagi Grimberg 			  struct srp_request *req, struct scatterlist *scat,
164326630e8aSSagi Grimberg 			  int count)
164426630e8aSSagi Grimberg {
164526630e8aSSagi Grimberg 	struct scatterlist *sg;
164626630e8aSSagi Grimberg 	int i, ret;
164726630e8aSSagi Grimberg 
164826630e8aSSagi Grimberg 	state->pages = req->map_page;
164926630e8aSSagi Grimberg 	state->fmr.next = req->fmr_list;
1650509c5f33SBart Van Assche 	state->fmr.end = req->fmr_list + ch->target->mr_per_cmd;
165126630e8aSSagi Grimberg 
165226630e8aSSagi Grimberg 	for_each_sg(scat, sg, count, i) {
165352bb8c62SBart Van Assche 		ret = srp_map_sg_entry(state, ch, sg);
165426630e8aSSagi Grimberg 		if (ret)
165526630e8aSSagi Grimberg 			return ret;
165626630e8aSSagi Grimberg 	}
165726630e8aSSagi Grimberg 
1658f7f7aab1SSagi Grimberg 	ret = srp_map_finish_fmr(state, ch);
165926630e8aSSagi Grimberg 	if (ret)
166026630e8aSSagi Grimberg 		return ret;
166126630e8aSSagi Grimberg 
166226630e8aSSagi Grimberg 	return 0;
166326630e8aSSagi Grimberg }
166426630e8aSSagi Grimberg 
166526630e8aSSagi Grimberg static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
166626630e8aSSagi Grimberg 			 struct srp_request *req, struct scatterlist *scat,
166726630e8aSSagi Grimberg 			 int count)
166826630e8aSSagi Grimberg {
1669509c5f33SBart Van Assche 	unsigned int sg_offset = 0;
1670509c5f33SBart Van Assche 
1671f7f7aab1SSagi Grimberg 	state->fr.next = req->fr_list;
1672509c5f33SBart Van Assche 	state->fr.end = req->fr_list + ch->target->mr_per_cmd;
1673f7f7aab1SSagi Grimberg 	state->sg = scat;
167426630e8aSSagi Grimberg 
16753b59b7a6SBart Van Assche 	if (count == 0)
16763b59b7a6SBart Van Assche 		return 0;
16773b59b7a6SBart Van Assche 
167857b0be9cSBart Van Assche 	while (count) {
1679f7f7aab1SSagi Grimberg 		int i, n;
1680f7f7aab1SSagi Grimberg 
1681509c5f33SBart Van Assche 		n = srp_map_finish_fr(state, req, ch, count, &sg_offset);
1682f7f7aab1SSagi Grimberg 		if (unlikely(n < 0))
1683f7f7aab1SSagi Grimberg 			return n;
1684f7f7aab1SSagi Grimberg 
168557b0be9cSBart Van Assche 		count -= n;
1686f7f7aab1SSagi Grimberg 		for (i = 0; i < n; i++)
1687f7f7aab1SSagi Grimberg 			state->sg = sg_next(state->sg);
168826630e8aSSagi Grimberg 	}
168926630e8aSSagi Grimberg 
169026630e8aSSagi Grimberg 	return 0;
169126630e8aSSagi Grimberg }
169226630e8aSSagi Grimberg 
169326630e8aSSagi Grimberg static int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
1694509c07bcSBart Van Assche 			  struct srp_request *req, struct scatterlist *scat,
1695509c07bcSBart Van Assche 			  int count)
169676bc1e1dSBart Van Assche {
1697509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
169876bc1e1dSBart Van Assche 	struct scatterlist *sg;
169926630e8aSSagi Grimberg 	int i;
170076bc1e1dSBart Van Assche 
17013ae95da8SBart Van Assche 	for_each_sg(scat, sg, count, i) {
1702a163afc8SBart Van Assche 		srp_map_desc(state, sg_dma_address(sg), sg_dma_len(sg),
1703cee687b6SBart Van Assche 			     target->global_rkey);
17043ae95da8SBart Van Assche 	}
170576bc1e1dSBart Van Assche 
170626630e8aSSagi Grimberg 	return 0;
170776bc1e1dSBart Van Assche }
170876bc1e1dSBart Van Assche 
1709330179f2SBart Van Assche /*
1710330179f2SBart Van Assche  * Register the indirect data buffer descriptor with the HCA.
1711330179f2SBart Van Assche  *
1712330179f2SBart Van Assche  * Note: since the indirect data buffer descriptor has been allocated with
1713330179f2SBart Van Assche  * kmalloc() it is guaranteed that this buffer is a physically contiguous
1714330179f2SBart Van Assche  * memory buffer.
1715330179f2SBart Van Assche  */
1716330179f2SBart Van Assche static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
1717330179f2SBart Van Assche 		       void **next_mr, void **end_mr, u32 idb_len,
1718330179f2SBart Van Assche 		       __be32 *idb_rkey)
1719330179f2SBart Van Assche {
1720330179f2SBart Van Assche 	struct srp_target_port *target = ch->target;
1721330179f2SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
1722330179f2SBart Van Assche 	struct srp_map_state state;
1723330179f2SBart Van Assche 	struct srp_direct_buf idb_desc;
1724330179f2SBart Van Assche 	u64 idb_pages[1];
1725f7f7aab1SSagi Grimberg 	struct scatterlist idb_sg[1];
1726330179f2SBart Van Assche 	int ret;
1727330179f2SBart Van Assche 
1728330179f2SBart Van Assche 	memset(&state, 0, sizeof(state));
1729330179f2SBart Van Assche 	memset(&idb_desc, 0, sizeof(idb_desc));
1730330179f2SBart Van Assche 	state.gen.next = next_mr;
1731330179f2SBart Van Assche 	state.gen.end = end_mr;
1732330179f2SBart Van Assche 	state.desc = &idb_desc;
1733f7f7aab1SSagi Grimberg 	state.base_dma_addr = req->indirect_dma_addr;
1734f7f7aab1SSagi Grimberg 	state.dma_len = idb_len;
1735f7f7aab1SSagi Grimberg 
1736f7f7aab1SSagi Grimberg 	if (dev->use_fast_reg) {
1737f7f7aab1SSagi Grimberg 		state.sg = idb_sg;
173854f5c9c5SBart Van Assche 		sg_init_one(idb_sg, req->indirect_desc, idb_len);
1739f7f7aab1SSagi Grimberg 		idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
1740fc925518SChristoph Hellwig #ifdef CONFIG_NEED_SG_DMA_LENGTH
1741fc925518SChristoph Hellwig 		idb_sg->dma_length = idb_sg->length;	      /* hack^2 */
1742fc925518SChristoph Hellwig #endif
1743509c5f33SBart Van Assche 		ret = srp_map_finish_fr(&state, req, ch, 1, NULL);
1744f7f7aab1SSagi Grimberg 		if (ret < 0)
1745f7f7aab1SSagi Grimberg 			return ret;
1746509c5f33SBart Van Assche 		WARN_ON_ONCE(ret < 1);
1747f7f7aab1SSagi Grimberg 	} else if (dev->use_fmr) {
1748330179f2SBart Van Assche 		state.pages = idb_pages;
1749330179f2SBart Van Assche 		state.pages[0] = (req->indirect_dma_addr &
1750330179f2SBart Van Assche 				  dev->mr_page_mask);
1751330179f2SBart Van Assche 		state.npages = 1;
1752f7f7aab1SSagi Grimberg 		ret = srp_map_finish_fmr(&state, ch);
1753330179f2SBart Van Assche 		if (ret < 0)
1754f7f7aab1SSagi Grimberg 			return ret;
1755f7f7aab1SSagi Grimberg 	} else {
1756f7f7aab1SSagi Grimberg 		return -EINVAL;
1757f7f7aab1SSagi Grimberg 	}
1758330179f2SBart Van Assche 
1759330179f2SBart Van Assche 	*idb_rkey = idb_desc.key;
1760330179f2SBart Van Assche 
1761f7f7aab1SSagi Grimberg 	return 0;
1762330179f2SBart Van Assche }
1763330179f2SBart Van Assche 
1764509c5f33SBart Van Assche static void srp_check_mapping(struct srp_map_state *state,
1765509c5f33SBart Van Assche 			      struct srp_rdma_ch *ch, struct srp_request *req,
1766509c5f33SBart Van Assche 			      struct scatterlist *scat, int count)
1767509c5f33SBart Van Assche {
1768509c5f33SBart Van Assche 	struct srp_device *dev = ch->target->srp_host->srp_dev;
1769509c5f33SBart Van Assche 	struct srp_fr_desc **pfr;
1770509c5f33SBart Van Assche 	u64 desc_len = 0, mr_len = 0;
1771509c5f33SBart Van Assche 	int i;
1772509c5f33SBart Van Assche 
1773509c5f33SBart Van Assche 	for (i = 0; i < state->ndesc; i++)
1774509c5f33SBart Van Assche 		desc_len += be32_to_cpu(req->indirect_desc[i].len);
1775509c5f33SBart Van Assche 	if (dev->use_fast_reg)
1776509c5f33SBart Van Assche 		for (i = 0, pfr = req->fr_list; i < state->nmdesc; i++, pfr++)
1777509c5f33SBart Van Assche 			mr_len += (*pfr)->mr->length;
1778509c5f33SBart Van Assche 	else if (dev->use_fmr)
1779509c5f33SBart Van Assche 		for (i = 0; i < state->nmdesc; i++)
1780509c5f33SBart Van Assche 			mr_len += be32_to_cpu(req->indirect_desc[i].len);
1781509c5f33SBart Van Assche 	if (desc_len != scsi_bufflen(req->scmnd) ||
1782509c5f33SBart Van Assche 	    mr_len > scsi_bufflen(req->scmnd))
1783509c5f33SBart Van Assche 		pr_err("Inconsistent: scsi len %d <> desc len %lld <> mr len %lld; ndesc %d; nmdesc = %d\n",
1784509c5f33SBart Van Assche 		       scsi_bufflen(req->scmnd), desc_len, mr_len,
1785509c5f33SBart Van Assche 		       state->ndesc, state->nmdesc);
1786509c5f33SBart Van Assche }
1787509c5f33SBart Van Assche 
178877269cdfSBart Van Assche /**
178977269cdfSBart Van Assche  * srp_map_data() - map SCSI data buffer onto an SRP request
179077269cdfSBart Van Assche  * @scmnd: SCSI command to map
179177269cdfSBart Van Assche  * @ch: SRP RDMA channel
179277269cdfSBart Van Assche  * @req: SRP request
179377269cdfSBart Van Assche  *
179477269cdfSBart Van Assche  * Returns the length in bytes of the SRP_CMD IU or a negative value if
1795882981f4SBart Van Assche  * mapping failed. The size of any immediate data is not included in the
1796882981f4SBart Van Assche  * return value.
179777269cdfSBart Van Assche  */
1798509c07bcSBart Van Assche static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
1799aef9ec39SRoland Dreier 			struct srp_request *req)
1800aef9ec39SRoland Dreier {
1801509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1802882981f4SBart Van Assche 	struct scatterlist *scat, *sg;
1803aef9ec39SRoland Dreier 	struct srp_cmd *cmd = req->cmd->buf;
1804882981f4SBart Van Assche 	int i, len, nents, count, ret;
180585507bccSRalph Campbell 	struct srp_device *dev;
180685507bccSRalph Campbell 	struct ib_device *ibdev;
18078f26c9ffSDavid Dillow 	struct srp_map_state state;
18088f26c9ffSDavid Dillow 	struct srp_indirect_buf *indirect_hdr;
1809882981f4SBart Van Assche 	u64 data_len;
1810330179f2SBart Van Assche 	u32 idb_len, table_len;
1811330179f2SBart Van Assche 	__be32 idb_rkey;
18128f26c9ffSDavid Dillow 	u8 fmt;
1813aef9ec39SRoland Dreier 
1814882981f4SBart Van Assche 	req->cmd->num_sge = 1;
1815882981f4SBart Van Assche 
1816bb350d1dSFUJITA Tomonori 	if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
1817482fffc4SBart Van Assche 		return sizeof(struct srp_cmd) + cmd->add_cdb_len;
1818aef9ec39SRoland Dreier 
1819aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
1820aef9ec39SRoland Dreier 	    scmnd->sc_data_direction != DMA_TO_DEVICE) {
18217aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
18227aa54bd7SDavid Dillow 			     PFX "Unhandled data direction %d\n",
1823aef9ec39SRoland Dreier 			     scmnd->sc_data_direction);
1824aef9ec39SRoland Dreier 		return -EINVAL;
1825aef9ec39SRoland Dreier 	}
1826aef9ec39SRoland Dreier 
1827bb350d1dSFUJITA Tomonori 	nents = scsi_sg_count(scmnd);
1828bb350d1dSFUJITA Tomonori 	scat  = scsi_sglist(scmnd);
1829882981f4SBart Van Assche 	data_len = scsi_bufflen(scmnd);
1830aef9ec39SRoland Dreier 
183105321937SGreg Kroah-Hartman 	dev = target->srp_host->srp_dev;
183285507bccSRalph Campbell 	ibdev = dev->dev;
183385507bccSRalph Campbell 
183485507bccSRalph Campbell 	count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
18358f26c9ffSDavid Dillow 	if (unlikely(count == 0))
18368f26c9ffSDavid Dillow 		return -EIO;
1837aef9ec39SRoland Dreier 
1838882981f4SBart Van Assche 	if (ch->use_imm_data &&
1839882981f4SBart Van Assche 	    count <= SRP_MAX_IMM_SGE &&
1840882981f4SBart Van Assche 	    SRP_IMM_DATA_OFFSET + data_len <= ch->max_it_iu_len &&
1841882981f4SBart Van Assche 	    scmnd->sc_data_direction == DMA_TO_DEVICE) {
1842882981f4SBart Van Assche 		struct srp_imm_buf *buf;
1843882981f4SBart Van Assche 		struct ib_sge *sge = &req->cmd->sge[1];
1844882981f4SBart Van Assche 
1845882981f4SBart Van Assche 		fmt = SRP_DATA_DESC_IMM;
1846882981f4SBart Van Assche 		len = SRP_IMM_DATA_OFFSET;
1847882981f4SBart Van Assche 		req->nmdesc = 0;
1848882981f4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1849882981f4SBart Van Assche 		buf->len = cpu_to_be32(data_len);
1850882981f4SBart Van Assche 		WARN_ON_ONCE((void *)(buf + 1) > (void *)cmd + len);
1851882981f4SBart Van Assche 		for_each_sg(scat, sg, count, i) {
1852a163afc8SBart Van Assche 			sge[i].addr   = sg_dma_address(sg);
1853a163afc8SBart Van Assche 			sge[i].length = sg_dma_len(sg);
1854882981f4SBart Van Assche 			sge[i].lkey   = target->lkey;
1855882981f4SBart Van Assche 		}
1856882981f4SBart Van Assche 		req->cmd->num_sge += count;
1857882981f4SBart Van Assche 		goto map_complete;
1858882981f4SBart Van Assche 	}
1859882981f4SBart Van Assche 
1860aef9ec39SRoland Dreier 	fmt = SRP_DATA_DESC_DIRECT;
1861482fffc4SBart Van Assche 	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
1862482fffc4SBart Van Assche 		sizeof(struct srp_direct_buf);
1863f5358a17SRoland Dreier 
1864cee687b6SBart Van Assche 	if (count == 1 && target->global_rkey) {
1865f5358a17SRoland Dreier 		/*
1866f5358a17SRoland Dreier 		 * The midlayer only generated a single gather/scatter
1867f5358a17SRoland Dreier 		 * entry, or DMA mapping coalesced everything to a
1868f5358a17SRoland Dreier 		 * single entry.  So a direct descriptor along with
1869f5358a17SRoland Dreier 		 * the DMA MR suffices.
1870f5358a17SRoland Dreier 		 */
1871482fffc4SBart Van Assche 		struct srp_direct_buf *buf;
1872aef9ec39SRoland Dreier 
1873482fffc4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1874a163afc8SBart Van Assche 		buf->va  = cpu_to_be64(sg_dma_address(scat));
1875cee687b6SBart Van Assche 		buf->key = cpu_to_be32(target->global_rkey);
1876a163afc8SBart Van Assche 		buf->len = cpu_to_be32(sg_dma_len(scat));
18778f26c9ffSDavid Dillow 
187852ede08fSBart Van Assche 		req->nmdesc = 0;
18798f26c9ffSDavid Dillow 		goto map_complete;
18808f26c9ffSDavid Dillow 	}
18818f26c9ffSDavid Dillow 
18825cfb1782SBart Van Assche 	/*
18835cfb1782SBart Van Assche 	 * We have more than one scatter/gather entry, so build our indirect
18845cfb1782SBart Van Assche 	 * descriptor table, trying to merge as many entries as we can.
1885f5358a17SRoland Dreier 	 */
1886482fffc4SBart Van Assche 	indirect_hdr = (void *)cmd->add_data + cmd->add_cdb_len;
18878f26c9ffSDavid Dillow 
1888c07d424dSDavid Dillow 	ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
1889c07d424dSDavid Dillow 				   target->indirect_size, DMA_TO_DEVICE);
1890c07d424dSDavid Dillow 
18918f26c9ffSDavid Dillow 	memset(&state, 0, sizeof(state));
18929edba790SBart Van Assche 	state.desc = req->indirect_desc;
189326630e8aSSagi Grimberg 	if (dev->use_fast_reg)
1894e012f363SBart Van Assche 		ret = srp_map_sg_fr(&state, ch, req, scat, count);
189526630e8aSSagi Grimberg 	else if (dev->use_fmr)
1896e012f363SBart Van Assche 		ret = srp_map_sg_fmr(&state, ch, req, scat, count);
189726630e8aSSagi Grimberg 	else
1898e012f363SBart Van Assche 		ret = srp_map_sg_dma(&state, ch, req, scat, count);
1899e012f363SBart Van Assche 	req->nmdesc = state.nmdesc;
1900e012f363SBart Van Assche 	if (ret < 0)
1901e012f363SBart Van Assche 		goto unmap;
19028f26c9ffSDavid Dillow 
1903509c5f33SBart Van Assche 	{
1904509c5f33SBart Van Assche 		DEFINE_DYNAMIC_DEBUG_METADATA(ddm,
1905509c5f33SBart Van Assche 			"Memory mapping consistency check");
19061a1faf7aSBart Van Assche 		if (DYNAMIC_DEBUG_BRANCH(ddm))
1907509c5f33SBart Van Assche 			srp_check_mapping(&state, ch, req, scat, count);
1908509c5f33SBart Van Assche 	}
19098f26c9ffSDavid Dillow 
1910c07d424dSDavid Dillow 	/* We've mapped the request, now pull as much of the indirect
1911c07d424dSDavid Dillow 	 * descriptor table as we can into the command buffer. If this
1912c07d424dSDavid Dillow 	 * target is not using an external indirect table, we are
1913c07d424dSDavid Dillow 	 * guaranteed to fit into the command, as the SCSI layer won't
1914c07d424dSDavid Dillow 	 * give us more S/G entries than we allow.
19158f26c9ffSDavid Dillow 	 */
19168f26c9ffSDavid Dillow 	if (state.ndesc == 1) {
19175cfb1782SBart Van Assche 		/*
19185cfb1782SBart Van Assche 		 * Memory registration collapsed the sg-list into one entry,
19198f26c9ffSDavid Dillow 		 * so use a direct descriptor.
19208f26c9ffSDavid Dillow 		 */
1921482fffc4SBart Van Assche 		struct srp_direct_buf *buf;
19228f26c9ffSDavid Dillow 
1923482fffc4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1924c07d424dSDavid Dillow 		*buf = req->indirect_desc[0];
19258f26c9ffSDavid Dillow 		goto map_complete;
19268f26c9ffSDavid Dillow 	}
19278f26c9ffSDavid Dillow 
1928c07d424dSDavid Dillow 	if (unlikely(target->cmd_sg_cnt < state.ndesc &&
1929c07d424dSDavid Dillow 						!target->allow_ext_sg)) {
1930c07d424dSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
1931c07d424dSDavid Dillow 			     "Could not fit S/G list into SRP_CMD\n");
1932e012f363SBart Van Assche 		ret = -EIO;
1933e012f363SBart Van Assche 		goto unmap;
1934c07d424dSDavid Dillow 	}
1935c07d424dSDavid Dillow 
1936c07d424dSDavid Dillow 	count = min(state.ndesc, target->cmd_sg_cnt);
19378f26c9ffSDavid Dillow 	table_len = state.ndesc * sizeof (struct srp_direct_buf);
1938330179f2SBart Van Assche 	idb_len = sizeof(struct srp_indirect_buf) + table_len;
1939aef9ec39SRoland Dreier 
1940aef9ec39SRoland Dreier 	fmt = SRP_DATA_DESC_INDIRECT;
1941482fffc4SBart Van Assche 	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
1942482fffc4SBart Van Assche 		sizeof(struct srp_indirect_buf);
1943c07d424dSDavid Dillow 	len += count * sizeof (struct srp_direct_buf);
1944f5358a17SRoland Dreier 
1945c07d424dSDavid Dillow 	memcpy(indirect_hdr->desc_list, req->indirect_desc,
1946c07d424dSDavid Dillow 	       count * sizeof (struct srp_direct_buf));
194785507bccSRalph Campbell 
1948cee687b6SBart Van Assche 	if (!target->global_rkey) {
1949330179f2SBart Van Assche 		ret = srp_map_idb(ch, req, state.gen.next, state.gen.end,
1950330179f2SBart Van Assche 				  idb_len, &idb_rkey);
1951330179f2SBart Van Assche 		if (ret < 0)
1952e012f363SBart Van Assche 			goto unmap;
1953330179f2SBart Van Assche 		req->nmdesc++;
1954330179f2SBart Van Assche 	} else {
1955cee687b6SBart Van Assche 		idb_rkey = cpu_to_be32(target->global_rkey);
1956330179f2SBart Van Assche 	}
1957330179f2SBart Van Assche 
1958c07d424dSDavid Dillow 	indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
1959330179f2SBart Van Assche 	indirect_hdr->table_desc.key = idb_rkey;
19608f26c9ffSDavid Dillow 	indirect_hdr->table_desc.len = cpu_to_be32(table_len);
19618f26c9ffSDavid Dillow 	indirect_hdr->len = cpu_to_be32(state.total_len);
1962aef9ec39SRoland Dreier 
1963aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
1964c07d424dSDavid Dillow 		cmd->data_out_desc_cnt = count;
1965aef9ec39SRoland Dreier 	else
1966c07d424dSDavid Dillow 		cmd->data_in_desc_cnt = count;
1967c07d424dSDavid Dillow 
1968c07d424dSDavid Dillow 	ib_dma_sync_single_for_device(ibdev, req->indirect_dma_addr, table_len,
1969c07d424dSDavid Dillow 				      DMA_TO_DEVICE);
1970aef9ec39SRoland Dreier 
19718f26c9ffSDavid Dillow map_complete:
1972aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
1973aef9ec39SRoland Dreier 		cmd->buf_fmt = fmt << 4;
1974aef9ec39SRoland Dreier 	else
1975aef9ec39SRoland Dreier 		cmd->buf_fmt = fmt;
1976aef9ec39SRoland Dreier 
1977aef9ec39SRoland Dreier 	return len;
1978e012f363SBart Van Assche 
1979e012f363SBart Van Assche unmap:
1980e012f363SBart Van Assche 	srp_unmap_data(scmnd, ch, req);
1981ffc548bbSBart Van Assche 	if (ret == -ENOMEM && req->nmdesc >= target->mr_pool_size)
1982ffc548bbSBart Van Assche 		ret = -E2BIG;
1983e012f363SBart Van Assche 	return ret;
1984aef9ec39SRoland Dreier }
1985aef9ec39SRoland Dreier 
198605a1d750SDavid Dillow /*
198776c75b25SBart Van Assche  * Return an IU and possible credit to the free pool
198876c75b25SBart Van Assche  */
1989509c07bcSBart Van Assche static void srp_put_tx_iu(struct srp_rdma_ch *ch, struct srp_iu *iu,
199076c75b25SBart Van Assche 			  enum srp_iu_type iu_type)
199176c75b25SBart Van Assche {
199276c75b25SBart Van Assche 	unsigned long flags;
199376c75b25SBart Van Assche 
1994509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1995509c07bcSBart Van Assche 	list_add(&iu->list, &ch->free_tx);
199676c75b25SBart Van Assche 	if (iu_type != SRP_IU_RSP)
1997509c07bcSBart Van Assche 		++ch->req_lim;
1998509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
199976c75b25SBart Van Assche }
200076c75b25SBart Van Assche 
200176c75b25SBart Van Assche /*
2002509c07bcSBart Van Assche  * Must be called with ch->lock held to protect req_lim and free_tx.
2003e9684678SBart Van Assche  * If IU is not sent, it must be returned using srp_put_tx_iu().
200405a1d750SDavid Dillow  *
200505a1d750SDavid Dillow  * Note:
200605a1d750SDavid Dillow  * An upper limit for the number of allocated information units for each
200705a1d750SDavid Dillow  * request type is:
200805a1d750SDavid Dillow  * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
200905a1d750SDavid Dillow  *   more than Scsi_Host.can_queue requests.
201005a1d750SDavid Dillow  * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
201105a1d750SDavid Dillow  * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
201205a1d750SDavid Dillow  *   one unanswered SRP request to an initiator.
201305a1d750SDavid Dillow  */
2014509c07bcSBart Van Assche static struct srp_iu *__srp_get_tx_iu(struct srp_rdma_ch *ch,
201505a1d750SDavid Dillow 				      enum srp_iu_type iu_type)
201605a1d750SDavid Dillow {
2017509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
201805a1d750SDavid Dillow 	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
201905a1d750SDavid Dillow 	struct srp_iu *iu;
202005a1d750SDavid Dillow 
202193c76dbbSBart Van Assche 	lockdep_assert_held(&ch->lock);
202293c76dbbSBart Van Assche 
20231dc7b1f1SChristoph Hellwig 	ib_process_cq_direct(ch->send_cq, -1);
202405a1d750SDavid Dillow 
2025509c07bcSBart Van Assche 	if (list_empty(&ch->free_tx))
202605a1d750SDavid Dillow 		return NULL;
202705a1d750SDavid Dillow 
202805a1d750SDavid Dillow 	/* Initiator responses to target requests do not consume credits */
202976c75b25SBart Van Assche 	if (iu_type != SRP_IU_RSP) {
2030509c07bcSBart Van Assche 		if (ch->req_lim <= rsv) {
203105a1d750SDavid Dillow 			++target->zero_req_lim;
203205a1d750SDavid Dillow 			return NULL;
203305a1d750SDavid Dillow 		}
203405a1d750SDavid Dillow 
2035509c07bcSBart Van Assche 		--ch->req_lim;
203676c75b25SBart Van Assche 	}
203776c75b25SBart Van Assche 
2038509c07bcSBart Van Assche 	iu = list_first_entry(&ch->free_tx, struct srp_iu, list);
203976c75b25SBart Van Assche 	list_del(&iu->list);
204005a1d750SDavid Dillow 	return iu;
204105a1d750SDavid Dillow }
204205a1d750SDavid Dillow 
20439294000dSBart Van Assche /*
20449294000dSBart Van Assche  * Note: if this function is called from inside ib_drain_sq() then it will
20459294000dSBart Van Assche  * be called without ch->lock being held. If ib_drain_sq() dequeues a WQE
20469294000dSBart Van Assche  * with status IB_WC_SUCCESS then that's a bug.
20479294000dSBart Van Assche  */
20481dc7b1f1SChristoph Hellwig static void srp_send_done(struct ib_cq *cq, struct ib_wc *wc)
20491dc7b1f1SChristoph Hellwig {
20501dc7b1f1SChristoph Hellwig 	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
20511dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
20521dc7b1f1SChristoph Hellwig 
20531dc7b1f1SChristoph Hellwig 	if (unlikely(wc->status != IB_WC_SUCCESS)) {
20541dc7b1f1SChristoph Hellwig 		srp_handle_qp_err(cq, wc, "SEND");
20551dc7b1f1SChristoph Hellwig 		return;
20561dc7b1f1SChristoph Hellwig 	}
20571dc7b1f1SChristoph Hellwig 
205893c76dbbSBart Van Assche 	lockdep_assert_held(&ch->lock);
205993c76dbbSBart Van Assche 
20601dc7b1f1SChristoph Hellwig 	list_add(&iu->list, &ch->free_tx);
20611dc7b1f1SChristoph Hellwig }
20621dc7b1f1SChristoph Hellwig 
2063882981f4SBart Van Assche /**
2064882981f4SBart Van Assche  * srp_post_send() - send an SRP information unit
2065882981f4SBart Van Assche  * @ch: RDMA channel over which to send the information unit.
2066882981f4SBart Van Assche  * @iu: Information unit to send.
2067882981f4SBart Van Assche  * @len: Length of the information unit excluding immediate data.
2068882981f4SBart Van Assche  */
2069509c07bcSBart Van Assche static int srp_post_send(struct srp_rdma_ch *ch, struct srp_iu *iu, int len)
207005a1d750SDavid Dillow {
2071509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
207271347b0cSBart Van Assche 	struct ib_send_wr wr;
207305a1d750SDavid Dillow 
2074882981f4SBart Van Assche 	if (WARN_ON_ONCE(iu->num_sge > SRP_MAX_SGE))
2075882981f4SBart Van Assche 		return -EINVAL;
2076882981f4SBart Van Assche 
2077882981f4SBart Van Assche 	iu->sge[0].addr   = iu->dma;
2078882981f4SBart Van Assche 	iu->sge[0].length = len;
2079882981f4SBart Van Assche 	iu->sge[0].lkey   = target->lkey;
208005a1d750SDavid Dillow 
20811dc7b1f1SChristoph Hellwig 	iu->cqe.done = srp_send_done;
20821dc7b1f1SChristoph Hellwig 
208305a1d750SDavid Dillow 	wr.next       = NULL;
20841dc7b1f1SChristoph Hellwig 	wr.wr_cqe     = &iu->cqe;
2085882981f4SBart Van Assche 	wr.sg_list    = &iu->sge[0];
2086882981f4SBart Van Assche 	wr.num_sge    = iu->num_sge;
208705a1d750SDavid Dillow 	wr.opcode     = IB_WR_SEND;
208805a1d750SDavid Dillow 	wr.send_flags = IB_SEND_SIGNALED;
208905a1d750SDavid Dillow 
209071347b0cSBart Van Assche 	return ib_post_send(ch->qp, &wr, NULL);
209105a1d750SDavid Dillow }
209205a1d750SDavid Dillow 
2093509c07bcSBart Van Assche static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
2094c996bb47SBart Van Assche {
2095509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
209671347b0cSBart Van Assche 	struct ib_recv_wr wr;
2097dcb4cb85SBart Van Assche 	struct ib_sge list;
2098c996bb47SBart Van Assche 
2099c996bb47SBart Van Assche 	list.addr   = iu->dma;
2100c996bb47SBart Van Assche 	list.length = iu->size;
21019af76271SDavid Dillow 	list.lkey   = target->lkey;
2102c996bb47SBart Van Assche 
21031dc7b1f1SChristoph Hellwig 	iu->cqe.done = srp_recv_done;
21041dc7b1f1SChristoph Hellwig 
2105c996bb47SBart Van Assche 	wr.next     = NULL;
21061dc7b1f1SChristoph Hellwig 	wr.wr_cqe   = &iu->cqe;
2107c996bb47SBart Van Assche 	wr.sg_list  = &list;
2108c996bb47SBart Van Assche 	wr.num_sge  = 1;
2109c996bb47SBart Van Assche 
211071347b0cSBart Van Assche 	return ib_post_recv(ch->qp, &wr, NULL);
2111c996bb47SBart Van Assche }
2112c996bb47SBart Van Assche 
2113509c07bcSBart Van Assche static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
2114aef9ec39SRoland Dreier {
2115509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2116aef9ec39SRoland Dreier 	struct srp_request *req;
2117aef9ec39SRoland Dreier 	struct scsi_cmnd *scmnd;
2118aef9ec39SRoland Dreier 	unsigned long flags;
2119aef9ec39SRoland Dreier 
2120aef9ec39SRoland Dreier 	if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
2121509c07bcSBart Van Assche 		spin_lock_irqsave(&ch->lock, flags);
2122509c07bcSBart Van Assche 		ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
21230a6fdbdeSBart Van Assche 		if (rsp->tag == ch->tsk_mgmt_tag) {
2124509c07bcSBart Van Assche 			ch->tsk_mgmt_status = -1;
2125f8b6e31eSDavid Dillow 			if (be32_to_cpu(rsp->resp_data_len) >= 4)
2126509c07bcSBart Van Assche 				ch->tsk_mgmt_status = rsp->data[3];
2127509c07bcSBart Van Assche 			complete(&ch->tsk_mgmt_done);
2128aef9ec39SRoland Dreier 		} else {
21290a6fdbdeSBart Van Assche 			shost_printk(KERN_ERR, target->scsi_host,
21300a6fdbdeSBart Van Assche 				     "Received tsk mgmt response too late for tag %#llx\n",
21310a6fdbdeSBart Van Assche 				     rsp->tag);
21320a6fdbdeSBart Van Assche 		}
21330a6fdbdeSBart Van Assche 		spin_unlock_irqrestore(&ch->lock, flags);
21340a6fdbdeSBart Van Assche 	} else {
213577f2c1a4SBart Van Assche 		scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
21366cb72bc1SBart Van Assche 		if (scmnd && scmnd->host_scribble) {
213777f2c1a4SBart Van Assche 			req = (void *)scmnd->host_scribble;
213877f2c1a4SBart Van Assche 			scmnd = srp_claim_req(ch, req, NULL, scmnd);
21396cb72bc1SBart Van Assche 		} else {
21406cb72bc1SBart Van Assche 			scmnd = NULL;
214177f2c1a4SBart Van Assche 		}
214222032991SBart Van Assche 		if (!scmnd) {
21437aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
2144d92c0da7SBart Van Assche 				     "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
2145d92c0da7SBart Van Assche 				     rsp->tag, ch - target->ch, ch->qp->qp_num);
214622032991SBart Van Assche 
2147509c07bcSBart Van Assche 			spin_lock_irqsave(&ch->lock, flags);
2148509c07bcSBart Van Assche 			ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
2149509c07bcSBart Van Assche 			spin_unlock_irqrestore(&ch->lock, flags);
215022032991SBart Van Assche 
215122032991SBart Van Assche 			return;
215222032991SBart Van Assche 		}
2153aef9ec39SRoland Dreier 		scmnd->result = rsp->status;
2154aef9ec39SRoland Dreier 
2155aef9ec39SRoland Dreier 		if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
2156aef9ec39SRoland Dreier 			memcpy(scmnd->sense_buffer, rsp->data +
2157aef9ec39SRoland Dreier 			       be32_to_cpu(rsp->resp_data_len),
2158aef9ec39SRoland Dreier 			       min_t(int, be32_to_cpu(rsp->sense_data_len),
2159aef9ec39SRoland Dreier 				     SCSI_SENSE_BUFFERSIZE));
2160aef9ec39SRoland Dreier 		}
2161aef9ec39SRoland Dreier 
2162e714531aSBart Van Assche 		if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
2163bb350d1dSFUJITA Tomonori 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
2164e714531aSBart Van Assche 		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DIOVER))
2165e714531aSBart Van Assche 			scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_in_res_cnt));
2166e714531aSBart Van Assche 		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOUNDER))
2167e714531aSBart Van Assche 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
2168e714531aSBart Van Assche 		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOOVER))
2169e714531aSBart Van Assche 			scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_out_res_cnt));
2170aef9ec39SRoland Dreier 
2171509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd,
217222032991SBart Van Assche 			     be32_to_cpu(rsp->req_lim_delta));
217322032991SBart Van Assche 
2174f8b6e31eSDavid Dillow 		scmnd->host_scribble = NULL;
2175aef9ec39SRoland Dreier 		scmnd->scsi_done(scmnd);
2176aef9ec39SRoland Dreier 	}
2177aef9ec39SRoland Dreier }
2178aef9ec39SRoland Dreier 
2179509c07bcSBart Van Assche static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
2180bb12588aSDavid Dillow 			       void *rsp, int len)
2181bb12588aSDavid Dillow {
2182509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
218376c75b25SBart Van Assche 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2184bb12588aSDavid Dillow 	unsigned long flags;
2185bb12588aSDavid Dillow 	struct srp_iu *iu;
218676c75b25SBart Van Assche 	int err;
2187bb12588aSDavid Dillow 
2188509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
2189509c07bcSBart Van Assche 	ch->req_lim += req_delta;
2190509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_RSP);
2191509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
219276c75b25SBart Van Assche 
2193bb12588aSDavid Dillow 	if (!iu) {
2194bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2195bb12588aSDavid Dillow 			     "no IU available to send response\n");
219676c75b25SBart Van Assche 		return 1;
2197bb12588aSDavid Dillow 	}
2198bb12588aSDavid Dillow 
2199882981f4SBart Van Assche 	iu->num_sge = 1;
2200bb12588aSDavid Dillow 	ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
2201bb12588aSDavid Dillow 	memcpy(iu->buf, rsp, len);
2202bb12588aSDavid Dillow 	ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
2203bb12588aSDavid Dillow 
2204509c07bcSBart Van Assche 	err = srp_post_send(ch, iu, len);
220576c75b25SBart Van Assche 	if (err) {
2206bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2207bb12588aSDavid Dillow 			     "unable to post response: %d\n", err);
2208509c07bcSBart Van Assche 		srp_put_tx_iu(ch, iu, SRP_IU_RSP);
220976c75b25SBart Van Assche 	}
2210bb12588aSDavid Dillow 
2211bb12588aSDavid Dillow 	return err;
2212bb12588aSDavid Dillow }
2213bb12588aSDavid Dillow 
2214509c07bcSBart Van Assche static void srp_process_cred_req(struct srp_rdma_ch *ch,
2215bb12588aSDavid Dillow 				 struct srp_cred_req *req)
2216bb12588aSDavid Dillow {
2217bb12588aSDavid Dillow 	struct srp_cred_rsp rsp = {
2218bb12588aSDavid Dillow 		.opcode = SRP_CRED_RSP,
2219bb12588aSDavid Dillow 		.tag = req->tag,
2220bb12588aSDavid Dillow 	};
2221bb12588aSDavid Dillow 	s32 delta = be32_to_cpu(req->req_lim_delta);
2222bb12588aSDavid Dillow 
2223509c07bcSBart Van Assche 	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
2224509c07bcSBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host, PFX
2225bb12588aSDavid Dillow 			     "problems processing SRP_CRED_REQ\n");
2226bb12588aSDavid Dillow }
2227bb12588aSDavid Dillow 
2228509c07bcSBart Van Assche static void srp_process_aer_req(struct srp_rdma_ch *ch,
2229bb12588aSDavid Dillow 				struct srp_aer_req *req)
2230bb12588aSDavid Dillow {
2231509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2232bb12588aSDavid Dillow 	struct srp_aer_rsp rsp = {
2233bb12588aSDavid Dillow 		.opcode = SRP_AER_RSP,
2234bb12588aSDavid Dillow 		.tag = req->tag,
2235bb12588aSDavid Dillow 	};
2236bb12588aSDavid Dillow 	s32 delta = be32_to_cpu(req->req_lim_delta);
2237bb12588aSDavid Dillow 
2238bb12588aSDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, PFX
2239985aa495SBart Van Assche 		     "ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
2240bb12588aSDavid Dillow 
2241509c07bcSBart Van Assche 	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
2242bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2243bb12588aSDavid Dillow 			     "problems processing SRP_AER_REQ\n");
2244bb12588aSDavid Dillow }
2245bb12588aSDavid Dillow 
22461dc7b1f1SChristoph Hellwig static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
2247aef9ec39SRoland Dreier {
22481dc7b1f1SChristoph Hellwig 	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
22491dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
2250509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2251dcb4cb85SBart Van Assche 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2252c996bb47SBart Van Assche 	int res;
2253aef9ec39SRoland Dreier 	u8 opcode;
2254aef9ec39SRoland Dreier 
22551dc7b1f1SChristoph Hellwig 	if (unlikely(wc->status != IB_WC_SUCCESS)) {
22561dc7b1f1SChristoph Hellwig 		srp_handle_qp_err(cq, wc, "RECV");
22571dc7b1f1SChristoph Hellwig 		return;
22581dc7b1f1SChristoph Hellwig 	}
22591dc7b1f1SChristoph Hellwig 
2260509c07bcSBart Van Assche 	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_ti_iu_len,
226185507bccSRalph Campbell 				   DMA_FROM_DEVICE);
2262aef9ec39SRoland Dreier 
2263aef9ec39SRoland Dreier 	opcode = *(u8 *) iu->buf;
2264aef9ec39SRoland Dreier 
2265aef9ec39SRoland Dreier 	if (0) {
22667aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
22677aa54bd7SDavid Dillow 			     PFX "recv completion, opcode 0x%02x\n", opcode);
22687a700811SBart Van Assche 		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 8, 1,
22697a700811SBart Van Assche 			       iu->buf, wc->byte_len, true);
2270aef9ec39SRoland Dreier 	}
2271aef9ec39SRoland Dreier 
2272aef9ec39SRoland Dreier 	switch (opcode) {
2273aef9ec39SRoland Dreier 	case SRP_RSP:
2274509c07bcSBart Van Assche 		srp_process_rsp(ch, iu->buf);
2275aef9ec39SRoland Dreier 		break;
2276aef9ec39SRoland Dreier 
2277bb12588aSDavid Dillow 	case SRP_CRED_REQ:
2278509c07bcSBart Van Assche 		srp_process_cred_req(ch, iu->buf);
2279bb12588aSDavid Dillow 		break;
2280bb12588aSDavid Dillow 
2281bb12588aSDavid Dillow 	case SRP_AER_REQ:
2282509c07bcSBart Van Assche 		srp_process_aer_req(ch, iu->buf);
2283bb12588aSDavid Dillow 		break;
2284bb12588aSDavid Dillow 
2285aef9ec39SRoland Dreier 	case SRP_T_LOGOUT:
2286aef9ec39SRoland Dreier 		/* XXX Handle target logout */
22877aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
22887aa54bd7SDavid Dillow 			     PFX "Got target logout request\n");
2289aef9ec39SRoland Dreier 		break;
2290aef9ec39SRoland Dreier 
2291aef9ec39SRoland Dreier 	default:
22927aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
22937aa54bd7SDavid Dillow 			     PFX "Unhandled SRP opcode 0x%02x\n", opcode);
2294aef9ec39SRoland Dreier 		break;
2295aef9ec39SRoland Dreier 	}
2296aef9ec39SRoland Dreier 
2297509c07bcSBart Van Assche 	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_ti_iu_len,
229885507bccSRalph Campbell 				      DMA_FROM_DEVICE);
2299c996bb47SBart Van Assche 
2300509c07bcSBart Van Assche 	res = srp_post_recv(ch, iu);
2301c996bb47SBart Van Assche 	if (res != 0)
2302c996bb47SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
2303c996bb47SBart Van Assche 			     PFX "Recv failed with error code %d\n", res);
2304aef9ec39SRoland Dreier }
2305aef9ec39SRoland Dreier 
2306c1120f89SBart Van Assche /**
2307c1120f89SBart Van Assche  * srp_tl_err_work() - handle a transport layer error
2308af24663bSBart Van Assche  * @work: Work structure embedded in an SRP target port.
2309c1120f89SBart Van Assche  *
2310c1120f89SBart Van Assche  * Note: This function may get invoked before the rport has been created,
2311c1120f89SBart Van Assche  * hence the target->rport test.
2312c1120f89SBart Van Assche  */
2313c1120f89SBart Van Assche static void srp_tl_err_work(struct work_struct *work)
2314c1120f89SBart Van Assche {
2315c1120f89SBart Van Assche 	struct srp_target_port *target;
2316c1120f89SBart Van Assche 
2317c1120f89SBart Van Assche 	target = container_of(work, struct srp_target_port, tl_err_work);
2318c1120f89SBart Van Assche 	if (target->rport)
2319c1120f89SBart Van Assche 		srp_start_tl_fail_timers(target->rport);
2320c1120f89SBart Van Assche }
2321c1120f89SBart Van Assche 
23221dc7b1f1SChristoph Hellwig static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
23231dc7b1f1SChristoph Hellwig 		const char *opname)
2324948d1e88SBart Van Assche {
23251dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
23267dad6b2eSBart Van Assche 	struct srp_target_port *target = ch->target;
23277dad6b2eSBart Van Assche 
2328c014c8cdSBart Van Assche 	if (ch->connected && !target->qp_in_error) {
23295cfb1782SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
23301dc7b1f1SChristoph Hellwig 			     PFX "failed %s status %s (%d) for CQE %p\n",
23311dc7b1f1SChristoph Hellwig 			     opname, ib_wc_status_msg(wc->status), wc->status,
23321dc7b1f1SChristoph Hellwig 			     wc->wr_cqe);
2333c1120f89SBart Van Assche 		queue_work(system_long_wq, &target->tl_err_work);
23344f0af697SBart Van Assche 	}
2335948d1e88SBart Van Assche 	target->qp_in_error = true;
2336948d1e88SBart Van Assche }
2337948d1e88SBart Van Assche 
233876c75b25SBart Van Assche static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
2339aef9ec39SRoland Dreier {
234076c75b25SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
2341a95cadb9SBart Van Assche 	struct srp_rport *rport = target->rport;
2342509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
2343aef9ec39SRoland Dreier 	struct srp_request *req;
2344aef9ec39SRoland Dreier 	struct srp_iu *iu;
2345aef9ec39SRoland Dreier 	struct srp_cmd *cmd;
234685507bccSRalph Campbell 	struct ib_device *dev;
234776c75b25SBart Van Assche 	unsigned long flags;
234877f2c1a4SBart Van Assche 	u32 tag;
234977f2c1a4SBart Van Assche 	u16 idx;
2350d1b4289eSBart Van Assche 	int len, ret;
2351a95cadb9SBart Van Assche 	const bool in_scsi_eh = !in_interrupt() && current == shost->ehandler;
2352a95cadb9SBart Van Assche 
2353a95cadb9SBart Van Assche 	/*
2354a95cadb9SBart Van Assche 	 * The SCSI EH thread is the only context from which srp_queuecommand()
2355a95cadb9SBart Van Assche 	 * can get invoked for blocked devices (SDEV_BLOCK /
2356a95cadb9SBart Van Assche 	 * SDEV_CREATED_BLOCK). Avoid racing with srp_reconnect_rport() by
2357a95cadb9SBart Van Assche 	 * locking the rport mutex if invoked from inside the SCSI EH.
2358a95cadb9SBart Van Assche 	 */
2359a95cadb9SBart Van Assche 	if (in_scsi_eh)
2360a95cadb9SBart Van Assche 		mutex_lock(&rport->mutex);
2361aef9ec39SRoland Dreier 
2362d1b4289eSBart Van Assche 	scmnd->result = srp_chkready(target->rport);
2363d1b4289eSBart Van Assche 	if (unlikely(scmnd->result))
2364d1b4289eSBart Van Assche 		goto err;
23652ce19e72SBart Van Assche 
236677f2c1a4SBart Van Assche 	WARN_ON_ONCE(scmnd->request->tag < 0);
236777f2c1a4SBart Van Assche 	tag = blk_mq_unique_tag(scmnd->request);
2368d92c0da7SBart Van Assche 	ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
236977f2c1a4SBart Van Assche 	idx = blk_mq_unique_tag_to_tag(tag);
237077f2c1a4SBart Van Assche 	WARN_ONCE(idx >= target->req_ring_size, "%s: tag %#x: idx %d >= %d\n",
237177f2c1a4SBart Van Assche 		  dev_name(&shost->shost_gendev), tag, idx,
237277f2c1a4SBart Van Assche 		  target->req_ring_size);
2373509c07bcSBart Van Assche 
2374509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
2375509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_CMD);
2376509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
2377aef9ec39SRoland Dreier 
237877f2c1a4SBart Van Assche 	if (!iu)
237977f2c1a4SBart Van Assche 		goto err;
238077f2c1a4SBart Van Assche 
238177f2c1a4SBart Van Assche 	req = &ch->req_ring[idx];
238205321937SGreg Kroah-Hartman 	dev = target->srp_host->srp_dev->dev;
2383513d5647SBart Van Assche 	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_it_iu_len,
238485507bccSRalph Campbell 				   DMA_TO_DEVICE);
2385aef9ec39SRoland Dreier 
2386f8b6e31eSDavid Dillow 	scmnd->host_scribble = (void *) req;
2387aef9ec39SRoland Dreier 
2388aef9ec39SRoland Dreier 	cmd = iu->buf;
2389aef9ec39SRoland Dreier 	memset(cmd, 0, sizeof *cmd);
2390aef9ec39SRoland Dreier 
2391aef9ec39SRoland Dreier 	cmd->opcode = SRP_CMD;
2392985aa495SBart Van Assche 	int_to_scsilun(scmnd->device->lun, &cmd->lun);
239377f2c1a4SBart Van Assche 	cmd->tag    = tag;
2394aef9ec39SRoland Dreier 	memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
2395482fffc4SBart Van Assche 	if (unlikely(scmnd->cmd_len > sizeof(cmd->cdb))) {
2396482fffc4SBart Van Assche 		cmd->add_cdb_len = round_up(scmnd->cmd_len - sizeof(cmd->cdb),
2397482fffc4SBart Van Assche 					    4);
2398482fffc4SBart Van Assche 		if (WARN_ON_ONCE(cmd->add_cdb_len > SRP_MAX_ADD_CDB_LEN))
2399482fffc4SBart Van Assche 			goto err_iu;
2400482fffc4SBart Van Assche 	}
2401aef9ec39SRoland Dreier 
2402aef9ec39SRoland Dreier 	req->scmnd    = scmnd;
2403aef9ec39SRoland Dreier 	req->cmd      = iu;
2404aef9ec39SRoland Dreier 
2405509c07bcSBart Van Assche 	len = srp_map_data(scmnd, ch, req);
2406aef9ec39SRoland Dreier 	if (len < 0) {
24077aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
2408d1b4289eSBart Van Assche 			     PFX "Failed to map data (%d)\n", len);
2409d1b4289eSBart Van Assche 		/*
2410d1b4289eSBart Van Assche 		 * If we ran out of memory descriptors (-ENOMEM) because an
2411d1b4289eSBart Van Assche 		 * application is queuing many requests with more than
241252ede08fSBart Van Assche 		 * max_pages_per_mr sg-list elements, tell the SCSI mid-layer
2413d1b4289eSBart Van Assche 		 * to reduce queue depth temporarily.
2414d1b4289eSBart Van Assche 		 */
2415d1b4289eSBart Van Assche 		scmnd->result = len == -ENOMEM ?
2416d1b4289eSBart Van Assche 			DID_OK << 16 | QUEUE_FULL << 1 : DID_ERROR << 16;
241776c75b25SBart Van Assche 		goto err_iu;
2418aef9ec39SRoland Dreier 	}
2419aef9ec39SRoland Dreier 
2420513d5647SBart Van Assche 	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_it_iu_len,
242185507bccSRalph Campbell 				      DMA_TO_DEVICE);
2422aef9ec39SRoland Dreier 
2423509c07bcSBart Van Assche 	if (srp_post_send(ch, iu, len)) {
24247aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
24252ee00f6aSBart Van Assche 		scmnd->result = DID_ERROR << 16;
2426aef9ec39SRoland Dreier 		goto err_unmap;
2427aef9ec39SRoland Dreier 	}
2428aef9ec39SRoland Dreier 
2429d1b4289eSBart Van Assche 	ret = 0;
2430d1b4289eSBart Van Assche 
2431a95cadb9SBart Van Assche unlock_rport:
2432a95cadb9SBart Van Assche 	if (in_scsi_eh)
2433a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2434a95cadb9SBart Van Assche 
2435d1b4289eSBart Van Assche 	return ret;
2436aef9ec39SRoland Dreier 
2437aef9ec39SRoland Dreier err_unmap:
2438509c07bcSBart Van Assche 	srp_unmap_data(scmnd, ch, req);
2439aef9ec39SRoland Dreier 
244076c75b25SBart Van Assche err_iu:
2441509c07bcSBart Van Assche 	srp_put_tx_iu(ch, iu, SRP_IU_CMD);
244276c75b25SBart Van Assche 
2443024ca901SBart Van Assche 	/*
2444024ca901SBart Van Assche 	 * Avoid that the loops that iterate over the request ring can
2445024ca901SBart Van Assche 	 * encounter a dangling SCSI command pointer.
2446024ca901SBart Van Assche 	 */
2447024ca901SBart Van Assche 	req->scmnd = NULL;
2448024ca901SBart Van Assche 
2449d1b4289eSBart Van Assche err:
2450d1b4289eSBart Van Assche 	if (scmnd->result) {
2451d1b4289eSBart Van Assche 		scmnd->scsi_done(scmnd);
2452d1b4289eSBart Van Assche 		ret = 0;
2453d1b4289eSBart Van Assche 	} else {
2454d1b4289eSBart Van Assche 		ret = SCSI_MLQUEUE_HOST_BUSY;
2455d1b4289eSBart Van Assche 	}
2456a95cadb9SBart Van Assche 
2457d1b4289eSBart Van Assche 	goto unlock_rport;
2458aef9ec39SRoland Dreier }
2459aef9ec39SRoland Dreier 
24604d73f95fSBart Van Assche /*
24614d73f95fSBart Van Assche  * Note: the resources allocated in this function are freed in
2462509c07bcSBart Van Assche  * srp_free_ch_ib().
24634d73f95fSBart Van Assche  */
2464509c07bcSBart Van Assche static int srp_alloc_iu_bufs(struct srp_rdma_ch *ch)
2465aef9ec39SRoland Dreier {
2466509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2467aef9ec39SRoland Dreier 	int i;
2468aef9ec39SRoland Dreier 
2469509c07bcSBart Van Assche 	ch->rx_ring = kcalloc(target->queue_size, sizeof(*ch->rx_ring),
24704d73f95fSBart Van Assche 			      GFP_KERNEL);
2471509c07bcSBart Van Assche 	if (!ch->rx_ring)
24724d73f95fSBart Van Assche 		goto err_no_ring;
2473509c07bcSBart Van Assche 	ch->tx_ring = kcalloc(target->queue_size, sizeof(*ch->tx_ring),
24744d73f95fSBart Van Assche 			      GFP_KERNEL);
2475509c07bcSBart Van Assche 	if (!ch->tx_ring)
24764d73f95fSBart Van Assche 		goto err_no_ring;
24774d73f95fSBart Van Assche 
24784d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2479509c07bcSBart Van Assche 		ch->rx_ring[i] = srp_alloc_iu(target->srp_host,
2480509c07bcSBart Van Assche 					      ch->max_ti_iu_len,
2481aef9ec39SRoland Dreier 					      GFP_KERNEL, DMA_FROM_DEVICE);
2482509c07bcSBart Van Assche 		if (!ch->rx_ring[i])
2483aef9ec39SRoland Dreier 			goto err;
2484aef9ec39SRoland Dreier 	}
2485aef9ec39SRoland Dreier 
24864d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2487509c07bcSBart Van Assche 		ch->tx_ring[i] = srp_alloc_iu(target->srp_host,
2488513d5647SBart Van Assche 					      ch->max_it_iu_len,
2489aef9ec39SRoland Dreier 					      GFP_KERNEL, DMA_TO_DEVICE);
2490509c07bcSBart Van Assche 		if (!ch->tx_ring[i])
2491aef9ec39SRoland Dreier 			goto err;
2492dcb4cb85SBart Van Assche 
2493509c07bcSBart Van Assche 		list_add(&ch->tx_ring[i]->list, &ch->free_tx);
2494aef9ec39SRoland Dreier 	}
2495aef9ec39SRoland Dreier 
2496aef9ec39SRoland Dreier 	return 0;
2497aef9ec39SRoland Dreier 
2498aef9ec39SRoland Dreier err:
24994d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2500509c07bcSBart Van Assche 		srp_free_iu(target->srp_host, ch->rx_ring[i]);
2501509c07bcSBart Van Assche 		srp_free_iu(target->srp_host, ch->tx_ring[i]);
2502aef9ec39SRoland Dreier 	}
2503aef9ec39SRoland Dreier 
25044d73f95fSBart Van Assche 
25054d73f95fSBart Van Assche err_no_ring:
2506509c07bcSBart Van Assche 	kfree(ch->tx_ring);
2507509c07bcSBart Van Assche 	ch->tx_ring = NULL;
2508509c07bcSBart Van Assche 	kfree(ch->rx_ring);
2509509c07bcSBart Van Assche 	ch->rx_ring = NULL;
2510aef9ec39SRoland Dreier 
2511aef9ec39SRoland Dreier 	return -ENOMEM;
2512aef9ec39SRoland Dreier }
2513aef9ec39SRoland Dreier 
2514c9b03c1aSBart Van Assche static uint32_t srp_compute_rq_tmo(struct ib_qp_attr *qp_attr, int attr_mask)
2515c9b03c1aSBart Van Assche {
2516c9b03c1aSBart Van Assche 	uint64_t T_tr_ns, max_compl_time_ms;
2517c9b03c1aSBart Van Assche 	uint32_t rq_tmo_jiffies;
2518c9b03c1aSBart Van Assche 
2519c9b03c1aSBart Van Assche 	/*
2520c9b03c1aSBart Van Assche 	 * According to section 11.2.4.2 in the IBTA spec (Modify Queue Pair,
2521c9b03c1aSBart Van Assche 	 * table 91), both the QP timeout and the retry count have to be set
2522c9b03c1aSBart Van Assche 	 * for RC QP's during the RTR to RTS transition.
2523c9b03c1aSBart Van Assche 	 */
2524c9b03c1aSBart Van Assche 	WARN_ON_ONCE((attr_mask & (IB_QP_TIMEOUT | IB_QP_RETRY_CNT)) !=
2525c9b03c1aSBart Van Assche 		     (IB_QP_TIMEOUT | IB_QP_RETRY_CNT));
2526c9b03c1aSBart Van Assche 
2527c9b03c1aSBart Van Assche 	/*
2528c9b03c1aSBart Van Assche 	 * Set target->rq_tmo_jiffies to one second more than the largest time
2529c9b03c1aSBart Van Assche 	 * it can take before an error completion is generated. See also
2530c9b03c1aSBart Van Assche 	 * C9-140..142 in the IBTA spec for more information about how to
2531c9b03c1aSBart Van Assche 	 * convert the QP Local ACK Timeout value to nanoseconds.
2532c9b03c1aSBart Van Assche 	 */
2533c9b03c1aSBart Van Assche 	T_tr_ns = 4096 * (1ULL << qp_attr->timeout);
2534c9b03c1aSBart Van Assche 	max_compl_time_ms = qp_attr->retry_cnt * 4 * T_tr_ns;
2535c9b03c1aSBart Van Assche 	do_div(max_compl_time_ms, NSEC_PER_MSEC);
2536c9b03c1aSBart Van Assche 	rq_tmo_jiffies = msecs_to_jiffies(max_compl_time_ms + 1000);
2537c9b03c1aSBart Van Assche 
2538c9b03c1aSBart Van Assche 	return rq_tmo_jiffies;
2539c9b03c1aSBart Van Assche }
2540c9b03c1aSBart Van Assche 
2541961e0be8SDavid Dillow static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
2542e6300cbdSBart Van Assche 			       const struct srp_login_rsp *lrsp,
2543509c07bcSBart Van Assche 			       struct srp_rdma_ch *ch)
2544961e0be8SDavid Dillow {
2545509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2546961e0be8SDavid Dillow 	struct ib_qp_attr *qp_attr = NULL;
2547961e0be8SDavid Dillow 	int attr_mask = 0;
254819f31343SBart Van Assche 	int ret = 0;
2549961e0be8SDavid Dillow 	int i;
2550961e0be8SDavid Dillow 
2551961e0be8SDavid Dillow 	if (lrsp->opcode == SRP_LOGIN_RSP) {
2552509c07bcSBart Van Assche 		ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
2553509c07bcSBart Van Assche 		ch->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
2554882981f4SBart Van Assche 		ch->use_imm_data  = lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP;
2555882981f4SBart Van Assche 		ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
2556882981f4SBart Van Assche 						      ch->use_imm_data);
2557513d5647SBart Van Assche 		WARN_ON_ONCE(ch->max_it_iu_len >
2558513d5647SBart Van Assche 			     be32_to_cpu(lrsp->max_it_iu_len));
2559961e0be8SDavid Dillow 
2560882981f4SBart Van Assche 		if (ch->use_imm_data)
2561882981f4SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host,
2562882981f4SBart Van Assche 				     PFX "using immediate data\n");
2563961e0be8SDavid Dillow 
2564961e0be8SDavid Dillow 		/*
2565961e0be8SDavid Dillow 		 * Reserve credits for task management so we don't
2566961e0be8SDavid Dillow 		 * bounce requests back to the SCSI mid-layer.
2567961e0be8SDavid Dillow 		 */
2568961e0be8SDavid Dillow 		target->scsi_host->can_queue
2569509c07bcSBart Van Assche 			= min(ch->req_lim - SRP_TSK_MGMT_SQ_SIZE,
2570961e0be8SDavid Dillow 			      target->scsi_host->can_queue);
25714d73f95fSBart Van Assche 		target->scsi_host->cmd_per_lun
25724d73f95fSBart Van Assche 			= min_t(int, target->scsi_host->can_queue,
25734d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun);
2574961e0be8SDavid Dillow 	} else {
2575961e0be8SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
2576961e0be8SDavid Dillow 			     PFX "Unhandled RSP opcode %#x\n", lrsp->opcode);
2577961e0be8SDavid Dillow 		ret = -ECONNRESET;
2578961e0be8SDavid Dillow 		goto error;
2579961e0be8SDavid Dillow 	}
2580961e0be8SDavid Dillow 
2581509c07bcSBart Van Assche 	if (!ch->rx_ring) {
2582509c07bcSBart Van Assche 		ret = srp_alloc_iu_bufs(ch);
2583961e0be8SDavid Dillow 		if (ret)
2584961e0be8SDavid Dillow 			goto error;
2585961e0be8SDavid Dillow 	}
2586961e0be8SDavid Dillow 
258719f31343SBart Van Assche 	for (i = 0; i < target->queue_size; i++) {
258819f31343SBart Van Assche 		struct srp_iu *iu = ch->rx_ring[i];
258919f31343SBart Van Assche 
259019f31343SBart Van Assche 		ret = srp_post_recv(ch, iu);
259119f31343SBart Van Assche 		if (ret)
259219f31343SBart Van Assche 			goto error;
259319f31343SBart Van Assche 	}
259419f31343SBart Van Assche 
259519f31343SBart Van Assche 	if (!target->using_rdma_cm) {
2596961e0be8SDavid Dillow 		ret = -ENOMEM;
259719f31343SBart Van Assche 		qp_attr = kmalloc(sizeof(*qp_attr), GFP_KERNEL);
2598961e0be8SDavid Dillow 		if (!qp_attr)
2599961e0be8SDavid Dillow 			goto error;
2600961e0be8SDavid Dillow 
2601961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTR;
2602961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2603961e0be8SDavid Dillow 		if (ret)
2604961e0be8SDavid Dillow 			goto error_free;
2605961e0be8SDavid Dillow 
2606509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2607961e0be8SDavid Dillow 		if (ret)
2608961e0be8SDavid Dillow 			goto error_free;
2609961e0be8SDavid Dillow 
2610961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTS;
2611961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2612961e0be8SDavid Dillow 		if (ret)
2613961e0be8SDavid Dillow 			goto error_free;
2614961e0be8SDavid Dillow 
2615c9b03c1aSBart Van Assche 		target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
2616c9b03c1aSBart Van Assche 
2617509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2618961e0be8SDavid Dillow 		if (ret)
2619961e0be8SDavid Dillow 			goto error_free;
2620961e0be8SDavid Dillow 
2621961e0be8SDavid Dillow 		ret = ib_send_cm_rtu(cm_id, NULL, 0);
262219f31343SBart Van Assche 	}
2623961e0be8SDavid Dillow 
2624961e0be8SDavid Dillow error_free:
2625961e0be8SDavid Dillow 	kfree(qp_attr);
2626961e0be8SDavid Dillow 
2627961e0be8SDavid Dillow error:
2628509c07bcSBart Van Assche 	ch->status = ret;
2629961e0be8SDavid Dillow }
2630961e0be8SDavid Dillow 
263119f31343SBart Van Assche static void srp_ib_cm_rej_handler(struct ib_cm_id *cm_id,
2632e7ff98aeSParav Pandit 				  const struct ib_cm_event *event,
2633509c07bcSBart Van Assche 				  struct srp_rdma_ch *ch)
2634aef9ec39SRoland Dreier {
2635509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
26367aa54bd7SDavid Dillow 	struct Scsi_Host *shost = target->scsi_host;
2637aef9ec39SRoland Dreier 	struct ib_class_port_info *cpi;
2638aef9ec39SRoland Dreier 	int opcode;
263919f31343SBart Van Assche 	u16 dlid;
2640aef9ec39SRoland Dreier 
2641aef9ec39SRoland Dreier 	switch (event->param.rej_rcvd.reason) {
2642aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_CM_REDIRECT:
2643aef9ec39SRoland Dreier 		cpi = event->param.rej_rcvd.ari;
264419f31343SBart Van Assche 		dlid = be16_to_cpu(cpi->redirect_lid);
264519f31343SBart Van Assche 		sa_path_set_dlid(&ch->ib_cm.path, dlid);
264619f31343SBart Van Assche 		ch->ib_cm.path.pkey = cpi->redirect_pkey;
2647aef9ec39SRoland Dreier 		cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
264819f31343SBart Van Assche 		memcpy(ch->ib_cm.path.dgid.raw, cpi->redirect_gid, 16);
2649aef9ec39SRoland Dreier 
265019f31343SBart Van Assche 		ch->status = dlid ? SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
2651aef9ec39SRoland Dreier 		break;
2652aef9ec39SRoland Dreier 
2653aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_REDIRECT:
26545d7cbfd6SRoland Dreier 		if (srp_target_is_topspin(target)) {
265519f31343SBart Van Assche 			union ib_gid *dgid = &ch->ib_cm.path.dgid;
265619f31343SBart Van Assche 
2657aef9ec39SRoland Dreier 			/*
2658aef9ec39SRoland Dreier 			 * Topspin/Cisco SRP gateways incorrectly send
2659aef9ec39SRoland Dreier 			 * reject reason code 25 when they mean 24
2660aef9ec39SRoland Dreier 			 * (port redirect).
2661aef9ec39SRoland Dreier 			 */
266219f31343SBart Van Assche 			memcpy(dgid->raw, event->param.rej_rcvd.ari, 16);
2663aef9ec39SRoland Dreier 
26647aa54bd7SDavid Dillow 			shost_printk(KERN_DEBUG, shost,
26657aa54bd7SDavid Dillow 				     PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
266619f31343SBart Van Assche 				     be64_to_cpu(dgid->global.subnet_prefix),
266719f31343SBart Van Assche 				     be64_to_cpu(dgid->global.interface_id));
2668aef9ec39SRoland Dreier 
2669509c07bcSBart Van Assche 			ch->status = SRP_PORT_REDIRECT;
2670aef9ec39SRoland Dreier 		} else {
26717aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
26727aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
2673509c07bcSBart Van Assche 			ch->status = -ECONNRESET;
2674aef9ec39SRoland Dreier 		}
2675aef9ec39SRoland Dreier 		break;
2676aef9ec39SRoland Dreier 
2677aef9ec39SRoland Dreier 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
26787aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost,
26797aa54bd7SDavid Dillow 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
2680509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2681aef9ec39SRoland Dreier 		break;
2682aef9ec39SRoland Dreier 
2683aef9ec39SRoland Dreier 	case IB_CM_REJ_CONSUMER_DEFINED:
2684aef9ec39SRoland Dreier 		opcode = *(u8 *) event->private_data;
2685aef9ec39SRoland Dreier 		if (opcode == SRP_LOGIN_REJ) {
2686aef9ec39SRoland Dreier 			struct srp_login_rej *rej = event->private_data;
2687aef9ec39SRoland Dreier 			u32 reason = be32_to_cpu(rej->reason);
2688aef9ec39SRoland Dreier 
2689aef9ec39SRoland Dreier 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
26907aa54bd7SDavid Dillow 				shost_printk(KERN_WARNING, shost,
26917aa54bd7SDavid Dillow 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
2692aef9ec39SRoland Dreier 			else
2693e7ffde01SBart Van Assche 				shost_printk(KERN_WARNING, shost, PFX
2694e7ffde01SBart Van Assche 					     "SRP LOGIN from %pI6 to %pI6 REJECTED, reason 0x%08x\n",
2695747fe000SBart Van Assche 					     target->sgid.raw,
269619f31343SBart Van Assche 					     target->ib_cm.orig_dgid.raw,
269719f31343SBart Van Assche 					     reason);
2698aef9ec39SRoland Dreier 		} else
26997aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
27007aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
2701aef9ec39SRoland Dreier 				     " opcode 0x%02x\n", opcode);
2702509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2703aef9ec39SRoland Dreier 		break;
2704aef9ec39SRoland Dreier 
27059fe4bcf4SDavid Dillow 	case IB_CM_REJ_STALE_CONN:
27069fe4bcf4SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason: stale connection\n");
2707509c07bcSBart Van Assche 		ch->status = SRP_STALE_CONN;
27089fe4bcf4SDavid Dillow 		break;
27099fe4bcf4SDavid Dillow 
2710aef9ec39SRoland Dreier 	default:
27117aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
2712aef9ec39SRoland Dreier 			     event->param.rej_rcvd.reason);
2713509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2714aef9ec39SRoland Dreier 	}
2715aef9ec39SRoland Dreier }
2716aef9ec39SRoland Dreier 
2717e7ff98aeSParav Pandit static int srp_ib_cm_handler(struct ib_cm_id *cm_id,
2718e7ff98aeSParav Pandit 			     const struct ib_cm_event *event)
2719aef9ec39SRoland Dreier {
2720509c07bcSBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
2721509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2722aef9ec39SRoland Dreier 	int comp = 0;
2723aef9ec39SRoland Dreier 
2724aef9ec39SRoland Dreier 	switch (event->event) {
2725aef9ec39SRoland Dreier 	case IB_CM_REQ_ERROR:
27267aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host,
27277aa54bd7SDavid Dillow 			     PFX "Sending CM REQ failed\n");
2728aef9ec39SRoland Dreier 		comp = 1;
2729509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2730aef9ec39SRoland Dreier 		break;
2731aef9ec39SRoland Dreier 
2732aef9ec39SRoland Dreier 	case IB_CM_REP_RECEIVED:
2733aef9ec39SRoland Dreier 		comp = 1;
2734509c07bcSBart Van Assche 		srp_cm_rep_handler(cm_id, event->private_data, ch);
2735aef9ec39SRoland Dreier 		break;
2736aef9ec39SRoland Dreier 
2737aef9ec39SRoland Dreier 	case IB_CM_REJ_RECEIVED:
27387aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
2739aef9ec39SRoland Dreier 		comp = 1;
2740aef9ec39SRoland Dreier 
274119f31343SBart Van Assche 		srp_ib_cm_rej_handler(cm_id, event, ch);
2742aef9ec39SRoland Dreier 		break;
2743aef9ec39SRoland Dreier 
2744b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_RECEIVED:
27457aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
27467aa54bd7SDavid Dillow 			     PFX "DREQ received - connection closed\n");
2747c014c8cdSBart Van Assche 		ch->connected = false;
2748b7ac4ab4SIshai Rabinovitz 		if (ib_send_cm_drep(cm_id, NULL, 0))
27497aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
27507aa54bd7SDavid Dillow 				     PFX "Sending CM DREP failed\n");
2751c1120f89SBart Van Assche 		queue_work(system_long_wq, &target->tl_err_work);
2752aef9ec39SRoland Dreier 		break;
2753aef9ec39SRoland Dreier 
2754aef9ec39SRoland Dreier 	case IB_CM_TIMEWAIT_EXIT:
27557aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
27567aa54bd7SDavid Dillow 			     PFX "connection closed\n");
2757ac72d766SBart Van Assche 		comp = 1;
2758aef9ec39SRoland Dreier 
2759509c07bcSBart Van Assche 		ch->status = 0;
2760aef9ec39SRoland Dreier 		break;
2761aef9ec39SRoland Dreier 
2762b7ac4ab4SIshai Rabinovitz 	case IB_CM_MRA_RECEIVED:
2763b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_ERROR:
2764b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREP_RECEIVED:
2765b7ac4ab4SIshai Rabinovitz 		break;
2766b7ac4ab4SIshai Rabinovitz 
2767aef9ec39SRoland Dreier 	default:
27687aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
27697aa54bd7SDavid Dillow 			     PFX "Unhandled CM event %d\n", event->event);
2770aef9ec39SRoland Dreier 		break;
2771aef9ec39SRoland Dreier 	}
2772aef9ec39SRoland Dreier 
2773aef9ec39SRoland Dreier 	if (comp)
2774509c07bcSBart Van Assche 		complete(&ch->done);
2775aef9ec39SRoland Dreier 
2776aef9ec39SRoland Dreier 	return 0;
2777aef9ec39SRoland Dreier }
2778aef9ec39SRoland Dreier 
277919f31343SBart Van Assche static void srp_rdma_cm_rej_handler(struct srp_rdma_ch *ch,
278019f31343SBart Van Assche 				    struct rdma_cm_event *event)
278119f31343SBart Van Assche {
278219f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
278319f31343SBart Van Assche 	struct Scsi_Host *shost = target->scsi_host;
278419f31343SBart Van Assche 	int opcode;
278519f31343SBart Van Assche 
278619f31343SBart Van Assche 	switch (event->status) {
278719f31343SBart Van Assche 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
278819f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
278919f31343SBart Van Assche 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
279019f31343SBart Van Assche 		ch->status = -ECONNRESET;
279119f31343SBart Van Assche 		break;
279219f31343SBart Van Assche 
279319f31343SBart Van Assche 	case IB_CM_REJ_CONSUMER_DEFINED:
279419f31343SBart Van Assche 		opcode = *(u8 *) event->param.conn.private_data;
279519f31343SBart Van Assche 		if (opcode == SRP_LOGIN_REJ) {
279619f31343SBart Van Assche 			struct srp_login_rej *rej =
279719f31343SBart Van Assche 				(struct srp_login_rej *)
279819f31343SBart Van Assche 				event->param.conn.private_data;
279919f31343SBart Van Assche 			u32 reason = be32_to_cpu(rej->reason);
280019f31343SBart Van Assche 
280119f31343SBart Van Assche 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
280219f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
280319f31343SBart Van Assche 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
280419f31343SBart Van Assche 			else
280519f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
280619f31343SBart Van Assche 					    PFX "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
280719f31343SBart Van Assche 		} else {
280819f31343SBart Van Assche 			shost_printk(KERN_WARNING, shost,
280919f31343SBart Van Assche 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED, opcode 0x%02x\n",
281019f31343SBart Van Assche 				     opcode);
281119f31343SBart Van Assche 		}
281219f31343SBart Van Assche 		ch->status = -ECONNRESET;
281319f31343SBart Van Assche 		break;
281419f31343SBart Van Assche 
281519f31343SBart Van Assche 	case IB_CM_REJ_STALE_CONN:
281619f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
281719f31343SBart Van Assche 			     "  REJ reason: stale connection\n");
281819f31343SBart Van Assche 		ch->status = SRP_STALE_CONN;
281919f31343SBart Van Assche 		break;
282019f31343SBart Van Assche 
282119f31343SBart Van Assche 	default:
282219f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
282319f31343SBart Van Assche 			     event->status);
282419f31343SBart Van Assche 		ch->status = -ECONNRESET;
282519f31343SBart Van Assche 		break;
282619f31343SBart Van Assche 	}
282719f31343SBart Van Assche }
282819f31343SBart Van Assche 
282919f31343SBart Van Assche static int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
283019f31343SBart Van Assche 			       struct rdma_cm_event *event)
283119f31343SBart Van Assche {
283219f31343SBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
283319f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
283419f31343SBart Van Assche 	int comp = 0;
283519f31343SBart Van Assche 
283619f31343SBart Van Assche 	switch (event->event) {
283719f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_RESOLVED:
283819f31343SBart Van Assche 		ch->status = 0;
283919f31343SBart Van Assche 		comp = 1;
284019f31343SBart Van Assche 		break;
284119f31343SBart Van Assche 
284219f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_ERROR:
284319f31343SBart Van Assche 		ch->status = -ENXIO;
284419f31343SBart Van Assche 		comp = 1;
284519f31343SBart Van Assche 		break;
284619f31343SBart Van Assche 
284719f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_RESOLVED:
284819f31343SBart Van Assche 		ch->status = 0;
284919f31343SBart Van Assche 		comp = 1;
285019f31343SBart Van Assche 		break;
285119f31343SBart Van Assche 
285219f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_ERROR:
285319f31343SBart Van Assche 	case RDMA_CM_EVENT_UNREACHABLE:
285419f31343SBart Van Assche 		ch->status = -EHOSTUNREACH;
285519f31343SBart Van Assche 		comp = 1;
285619f31343SBart Van Assche 		break;
285719f31343SBart Van Assche 
285819f31343SBart Van Assche 	case RDMA_CM_EVENT_CONNECT_ERROR:
285919f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host,
286019f31343SBart Van Assche 			     PFX "Sending CM REQ failed\n");
286119f31343SBart Van Assche 		comp = 1;
286219f31343SBart Van Assche 		ch->status = -ECONNRESET;
286319f31343SBart Van Assche 		break;
286419f31343SBart Van Assche 
286519f31343SBart Van Assche 	case RDMA_CM_EVENT_ESTABLISHED:
286619f31343SBart Van Assche 		comp = 1;
286719f31343SBart Van Assche 		srp_cm_rep_handler(NULL, event->param.conn.private_data, ch);
286819f31343SBart Van Assche 		break;
286919f31343SBart Van Assche 
287019f31343SBart Van Assche 	case RDMA_CM_EVENT_REJECTED:
287119f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
287219f31343SBart Van Assche 		comp = 1;
287319f31343SBart Van Assche 
287419f31343SBart Van Assche 		srp_rdma_cm_rej_handler(ch, event);
287519f31343SBart Van Assche 		break;
287619f31343SBart Van Assche 
287719f31343SBart Van Assche 	case RDMA_CM_EVENT_DISCONNECTED:
287819f31343SBart Van Assche 		if (ch->connected) {
287919f31343SBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host,
288019f31343SBart Van Assche 				     PFX "received DREQ\n");
288119f31343SBart Van Assche 			rdma_disconnect(ch->rdma_cm.cm_id);
288219f31343SBart Van Assche 			comp = 1;
288319f31343SBart Van Assche 			ch->status = 0;
288419f31343SBart Van Assche 			queue_work(system_long_wq, &target->tl_err_work);
288519f31343SBart Van Assche 		}
288619f31343SBart Van Assche 		break;
288719f31343SBart Van Assche 
288819f31343SBart Van Assche 	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
288919f31343SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
289019f31343SBart Van Assche 			     PFX "connection closed\n");
289119f31343SBart Van Assche 
289219f31343SBart Van Assche 		comp = 1;
289319f31343SBart Van Assche 		ch->status = 0;
289419f31343SBart Van Assche 		break;
289519f31343SBart Van Assche 
289619f31343SBart Van Assche 	default:
289719f31343SBart Van Assche 		shost_printk(KERN_WARNING, target->scsi_host,
289819f31343SBart Van Assche 			     PFX "Unhandled CM event %d\n", event->event);
289919f31343SBart Van Assche 		break;
290019f31343SBart Van Assche 	}
290119f31343SBart Van Assche 
290219f31343SBart Van Assche 	if (comp)
290319f31343SBart Van Assche 		complete(&ch->done);
290419f31343SBart Van Assche 
290519f31343SBart Van Assche 	return 0;
290619f31343SBart Van Assche }
290719f31343SBart Van Assche 
290871444b97SJack Wang /**
290971444b97SJack Wang  * srp_change_queue_depth - setting device queue depth
291071444b97SJack Wang  * @sdev: scsi device struct
291171444b97SJack Wang  * @qdepth: requested queue depth
291271444b97SJack Wang  *
291371444b97SJack Wang  * Returns queue depth.
291471444b97SJack Wang  */
291571444b97SJack Wang static int
2916db5ed4dfSChristoph Hellwig srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
291771444b97SJack Wang {
291871444b97SJack Wang 	if (!sdev->tagged_supported)
29191e6f2416SChristoph Hellwig 		qdepth = 1;
2920db5ed4dfSChristoph Hellwig 	return scsi_change_queue_depth(sdev, qdepth);
292171444b97SJack Wang }
292271444b97SJack Wang 
2923985aa495SBart Van Assche static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
29240a6fdbdeSBart Van Assche 			     u8 func, u8 *status)
2925aef9ec39SRoland Dreier {
2926509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2927a95cadb9SBart Van Assche 	struct srp_rport *rport = target->rport;
292819081f31SDavid Dillow 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2929aef9ec39SRoland Dreier 	struct srp_iu *iu;
2930aef9ec39SRoland Dreier 	struct srp_tsk_mgmt *tsk_mgmt;
29310a6fdbdeSBart Van Assche 	int res;
2932aef9ec39SRoland Dreier 
2933c014c8cdSBart Van Assche 	if (!ch->connected || target->qp_in_error)
29343780d1f0SBart Van Assche 		return -1;
29353780d1f0SBart Van Assche 
2936a95cadb9SBart Van Assche 	/*
2937509c07bcSBart Van Assche 	 * Lock the rport mutex to avoid that srp_create_ch_ib() is
2938a95cadb9SBart Van Assche 	 * invoked while a task management function is being sent.
2939a95cadb9SBart Van Assche 	 */
2940a95cadb9SBart Van Assche 	mutex_lock(&rport->mutex);
2941509c07bcSBart Van Assche 	spin_lock_irq(&ch->lock);
2942509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_TSK_MGMT);
2943509c07bcSBart Van Assche 	spin_unlock_irq(&ch->lock);
294476c75b25SBart Van Assche 
2945a95cadb9SBart Van Assche 	if (!iu) {
2946a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2947a95cadb9SBart Van Assche 
294876c75b25SBart Van Assche 		return -1;
2949a95cadb9SBart Van Assche 	}
2950aef9ec39SRoland Dreier 
2951882981f4SBart Van Assche 	iu->num_sge = 1;
2952882981f4SBart Van Assche 
295319081f31SDavid Dillow 	ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
295419081f31SDavid Dillow 				   DMA_TO_DEVICE);
2955aef9ec39SRoland Dreier 	tsk_mgmt = iu->buf;
2956aef9ec39SRoland Dreier 	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
2957aef9ec39SRoland Dreier 
2958aef9ec39SRoland Dreier 	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
2959985aa495SBart Van Assche 	int_to_scsilun(lun, &tsk_mgmt->lun);
2960aef9ec39SRoland Dreier 	tsk_mgmt->tsk_mgmt_func = func;
2961f8b6e31eSDavid Dillow 	tsk_mgmt->task_tag	= req_tag;
2962aef9ec39SRoland Dreier 
29630a6fdbdeSBart Van Assche 	spin_lock_irq(&ch->lock);
29640a6fdbdeSBart Van Assche 	ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT;
29650a6fdbdeSBart Van Assche 	tsk_mgmt->tag = ch->tsk_mgmt_tag;
29660a6fdbdeSBart Van Assche 	spin_unlock_irq(&ch->lock);
29670a6fdbdeSBart Van Assche 
29680a6fdbdeSBart Van Assche 	init_completion(&ch->tsk_mgmt_done);
29690a6fdbdeSBart Van Assche 
297019081f31SDavid Dillow 	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
297119081f31SDavid Dillow 				      DMA_TO_DEVICE);
2972509c07bcSBart Van Assche 	if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
2973509c07bcSBart Van Assche 		srp_put_tx_iu(ch, iu, SRP_IU_TSK_MGMT);
2974a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2975a95cadb9SBart Van Assche 
297676c75b25SBart Van Assche 		return -1;
297776c75b25SBart Van Assche 	}
29780a6fdbdeSBart Van Assche 	res = wait_for_completion_timeout(&ch->tsk_mgmt_done,
29790a6fdbdeSBart Van Assche 					msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS));
29800a6fdbdeSBart Van Assche 	if (res > 0 && status)
29810a6fdbdeSBart Van Assche 		*status = ch->tsk_mgmt_status;
2982a95cadb9SBart Van Assche 	mutex_unlock(&rport->mutex);
2983d945e1dfSRoland Dreier 
29840a6fdbdeSBart Van Assche 	WARN_ON_ONCE(res < 0);
2985aef9ec39SRoland Dreier 
29860a6fdbdeSBart Van Assche 	return res > 0 ? 0 : -1;
2987d945e1dfSRoland Dreier }
2988d945e1dfSRoland Dreier 
2989aef9ec39SRoland Dreier static int srp_abort(struct scsi_cmnd *scmnd)
2990aef9ec39SRoland Dreier {
2991d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
2992f8b6e31eSDavid Dillow 	struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
299377f2c1a4SBart Van Assche 	u32 tag;
2994d92c0da7SBart Van Assche 	u16 ch_idx;
2995509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
2996086f44f5SBart Van Assche 	int ret;
2997d945e1dfSRoland Dreier 
29987aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
2999aef9ec39SRoland Dreier 
3000d92c0da7SBart Van Assche 	if (!req)
300199b6697aSBart Van Assche 		return SUCCESS;
300277f2c1a4SBart Van Assche 	tag = blk_mq_unique_tag(scmnd->request);
3003d92c0da7SBart Van Assche 	ch_idx = blk_mq_unique_tag_to_hwq(tag);
3004d92c0da7SBart Van Assche 	if (WARN_ON_ONCE(ch_idx >= target->ch_count))
3005d92c0da7SBart Van Assche 		return SUCCESS;
3006d92c0da7SBart Van Assche 	ch = &target->ch[ch_idx];
3007d92c0da7SBart Van Assche 	if (!srp_claim_req(ch, req, NULL, scmnd))
3008d92c0da7SBart Van Assche 		return SUCCESS;
3009d92c0da7SBart Van Assche 	shost_printk(KERN_ERR, target->scsi_host,
3010d92c0da7SBart Van Assche 		     "Sending SRP abort for tag %#x\n", tag);
301177f2c1a4SBart Van Assche 	if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
30120a6fdbdeSBart Van Assche 			      SRP_TSK_ABORT_TASK, NULL) == 0)
3013086f44f5SBart Van Assche 		ret = SUCCESS;
3014ed9b2264SBart Van Assche 	else if (target->rport->state == SRP_RPORT_LOST)
301599e1c139SBart Van Assche 		ret = FAST_IO_FAIL;
3016086f44f5SBart Van Assche 	else
3017086f44f5SBart Van Assche 		ret = FAILED;
3018e68088e7SBart Van Assche 	if (ret == SUCCESS) {
3019509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd, 0);
3020d945e1dfSRoland Dreier 		scmnd->result = DID_ABORT << 16;
3021d8536670SBart Van Assche 		scmnd->scsi_done(scmnd);
3022e68088e7SBart Van Assche 	}
3023d945e1dfSRoland Dreier 
3024086f44f5SBart Van Assche 	return ret;
3025aef9ec39SRoland Dreier }
3026aef9ec39SRoland Dreier 
3027aef9ec39SRoland Dreier static int srp_reset_device(struct scsi_cmnd *scmnd)
3028aef9ec39SRoland Dreier {
3029d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
3030d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
30310a6fdbdeSBart Van Assche 	u8 status;
3032d945e1dfSRoland Dreier 
30337aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
3034aef9ec39SRoland Dreier 
3035d92c0da7SBart Van Assche 	ch = &target->ch[0];
3036509c07bcSBart Van Assche 	if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
30370a6fdbdeSBart Van Assche 			      SRP_TSK_LUN_RESET, &status))
3038d945e1dfSRoland Dreier 		return FAILED;
30390a6fdbdeSBart Van Assche 	if (status)
3040d945e1dfSRoland Dreier 		return FAILED;
3041d945e1dfSRoland Dreier 
3042d945e1dfSRoland Dreier 	return SUCCESS;
3043aef9ec39SRoland Dreier }
3044aef9ec39SRoland Dreier 
3045aef9ec39SRoland Dreier static int srp_reset_host(struct scsi_cmnd *scmnd)
3046aef9ec39SRoland Dreier {
3047aef9ec39SRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
3048aef9ec39SRoland Dreier 
30497aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, PFX "SRP reset_host called\n");
3050aef9ec39SRoland Dreier 
3051ed9b2264SBart Van Assche 	return srp_reconnect_rport(target->rport) == 0 ? SUCCESS : FAILED;
3052aef9ec39SRoland Dreier }
3053aef9ec39SRoland Dreier 
3054b0780ee5SBart Van Assche static int srp_target_alloc(struct scsi_target *starget)
3055b0780ee5SBart Van Assche {
3056b0780ee5SBart Van Assche 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
3057b0780ee5SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
3058b0780ee5SBart Van Assche 
3059b0780ee5SBart Van Assche 	if (target->target_can_queue)
3060b0780ee5SBart Van Assche 		starget->can_queue = target->target_can_queue;
3061b0780ee5SBart Van Assche 	return 0;
3062b0780ee5SBart Van Assche }
3063b0780ee5SBart Van Assche 
3064509c5f33SBart Van Assche static int srp_slave_alloc(struct scsi_device *sdev)
3065509c5f33SBart Van Assche {
3066509c5f33SBart Van Assche 	struct Scsi_Host *shost = sdev->host;
3067509c5f33SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
3068509c5f33SBart Van Assche 	struct srp_device *srp_dev = target->srp_host->srp_dev;
3069fbd36818SSergey Gorenko 	struct ib_device *ibdev = srp_dev->dev;
3070509c5f33SBart Van Assche 
3071fbd36818SSergey Gorenko 	if (!(ibdev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG))
3072509c5f33SBart Van Assche 		blk_queue_virt_boundary(sdev->request_queue,
3073509c5f33SBart Van Assche 					~srp_dev->mr_page_mask);
3074509c5f33SBart Van Assche 
3075509c5f33SBart Van Assche 	return 0;
3076509c5f33SBart Van Assche }
3077509c5f33SBart Van Assche 
3078c9b03c1aSBart Van Assche static int srp_slave_configure(struct scsi_device *sdev)
3079c9b03c1aSBart Van Assche {
3080c9b03c1aSBart Van Assche 	struct Scsi_Host *shost = sdev->host;
3081c9b03c1aSBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
3082c9b03c1aSBart Van Assche 	struct request_queue *q = sdev->request_queue;
3083c9b03c1aSBart Van Assche 	unsigned long timeout;
3084c9b03c1aSBart Van Assche 
3085c9b03c1aSBart Van Assche 	if (sdev->type == TYPE_DISK) {
3086c9b03c1aSBart Van Assche 		timeout = max_t(unsigned, 30 * HZ, target->rq_tmo_jiffies);
3087c9b03c1aSBart Van Assche 		blk_queue_rq_timeout(q, timeout);
3088c9b03c1aSBart Van Assche 	}
3089c9b03c1aSBart Van Assche 
3090c9b03c1aSBart Van Assche 	return 0;
3091c9b03c1aSBart Van Assche }
3092c9b03c1aSBart Van Assche 
3093ee959b00STony Jones static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
3094ee959b00STony Jones 			   char *buf)
30956ecb0c84SRoland Dreier {
3096ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30976ecb0c84SRoland Dreier 
309845c37cadSBart Van Assche 	return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->id_ext));
30996ecb0c84SRoland Dreier }
31006ecb0c84SRoland Dreier 
3101ee959b00STony Jones static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
3102ee959b00STony Jones 			     char *buf)
31036ecb0c84SRoland Dreier {
3104ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31056ecb0c84SRoland Dreier 
310645c37cadSBart Van Assche 	return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid));
31076ecb0c84SRoland Dreier }
31086ecb0c84SRoland Dreier 
3109ee959b00STony Jones static ssize_t show_service_id(struct device *dev,
3110ee959b00STony Jones 			       struct device_attribute *attr, char *buf)
31116ecb0c84SRoland Dreier {
3112ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31136ecb0c84SRoland Dreier 
311419f31343SBart Van Assche 	if (target->using_rdma_cm)
311519f31343SBart Van Assche 		return -ENOENT;
311619f31343SBart Van Assche 	return sprintf(buf, "0x%016llx\n",
311719f31343SBart Van Assche 		       be64_to_cpu(target->ib_cm.service_id));
31186ecb0c84SRoland Dreier }
31196ecb0c84SRoland Dreier 
3120ee959b00STony Jones static ssize_t show_pkey(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));
31246ecb0c84SRoland Dreier 
312519f31343SBart Van Assche 	if (target->using_rdma_cm)
312619f31343SBart Van Assche 		return -ENOENT;
312719f31343SBart Van Assche 	return sprintf(buf, "0x%04x\n", be16_to_cpu(target->ib_cm.pkey));
31286ecb0c84SRoland Dreier }
31296ecb0c84SRoland Dreier 
3130848b3082SBart Van Assche static ssize_t show_sgid(struct device *dev, struct device_attribute *attr,
3131848b3082SBart Van Assche 			 char *buf)
3132848b3082SBart Van Assche {
3133848b3082SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3134848b3082SBart Van Assche 
3135747fe000SBart Van Assche 	return sprintf(buf, "%pI6\n", target->sgid.raw);
3136848b3082SBart Van Assche }
3137848b3082SBart Van Assche 
3138ee959b00STony Jones static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
3139ee959b00STony Jones 			 char *buf)
31406ecb0c84SRoland Dreier {
3141ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3142d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch = &target->ch[0];
31436ecb0c84SRoland Dreier 
314419f31343SBart Van Assche 	if (target->using_rdma_cm)
314519f31343SBart Van Assche 		return -ENOENT;
314619f31343SBart Van Assche 	return sprintf(buf, "%pI6\n", ch->ib_cm.path.dgid.raw);
31476ecb0c84SRoland Dreier }
31486ecb0c84SRoland Dreier 
3149ee959b00STony Jones static ssize_t show_orig_dgid(struct device *dev,
3150ee959b00STony Jones 			      struct device_attribute *attr, char *buf)
31513633b3d0SIshai Rabinovitz {
3152ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31533633b3d0SIshai Rabinovitz 
315419f31343SBart Van Assche 	if (target->using_rdma_cm)
315519f31343SBart Van Assche 		return -ENOENT;
315619f31343SBart Van Assche 	return sprintf(buf, "%pI6\n", target->ib_cm.orig_dgid.raw);
31573633b3d0SIshai Rabinovitz }
31583633b3d0SIshai Rabinovitz 
315989de7486SBart Van Assche static ssize_t show_req_lim(struct device *dev,
316089de7486SBart Van Assche 			    struct device_attribute *attr, char *buf)
316189de7486SBart Van Assche {
316289de7486SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3163d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
3164d92c0da7SBart Van Assche 	int i, req_lim = INT_MAX;
316589de7486SBart Van Assche 
3166d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
3167d92c0da7SBart Van Assche 		ch = &target->ch[i];
3168d92c0da7SBart Van Assche 		req_lim = min(req_lim, ch->req_lim);
3169d92c0da7SBart Van Assche 	}
3170d92c0da7SBart Van Assche 	return sprintf(buf, "%d\n", req_lim);
317189de7486SBart Van Assche }
317289de7486SBart Van Assche 
3173ee959b00STony Jones static ssize_t show_zero_req_lim(struct device *dev,
3174ee959b00STony Jones 				 struct device_attribute *attr, char *buf)
31756bfa24faSRoland Dreier {
3176ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
31776bfa24faSRoland Dreier 
31786bfa24faSRoland Dreier 	return sprintf(buf, "%d\n", target->zero_req_lim);
31796bfa24faSRoland Dreier }
31806bfa24faSRoland Dreier 
3181ee959b00STony Jones static ssize_t show_local_ib_port(struct device *dev,
3182ee959b00STony Jones 				  struct device_attribute *attr, char *buf)
3183ded7f1a1SIshai Rabinovitz {
3184ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3185ded7f1a1SIshai Rabinovitz 
3186ded7f1a1SIshai Rabinovitz 	return sprintf(buf, "%d\n", target->srp_host->port);
3187ded7f1a1SIshai Rabinovitz }
3188ded7f1a1SIshai Rabinovitz 
3189ee959b00STony Jones static ssize_t show_local_ib_device(struct device *dev,
3190ee959b00STony Jones 				    struct device_attribute *attr, char *buf)
3191ded7f1a1SIshai Rabinovitz {
3192ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3193ded7f1a1SIshai Rabinovitz 
31946c854111SJason Gunthorpe 	return sprintf(buf, "%s\n",
31956c854111SJason Gunthorpe 		       dev_name(&target->srp_host->srp_dev->dev->dev));
3196ded7f1a1SIshai Rabinovitz }
3197ded7f1a1SIshai Rabinovitz 
3198d92c0da7SBart Van Assche static ssize_t show_ch_count(struct device *dev, struct device_attribute *attr,
3199d92c0da7SBart Van Assche 			     char *buf)
3200d92c0da7SBart Van Assche {
3201d92c0da7SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3202d92c0da7SBart Van Assche 
3203d92c0da7SBart Van Assche 	return sprintf(buf, "%d\n", target->ch_count);
3204d92c0da7SBart Van Assche }
3205d92c0da7SBart Van Assche 
32064b5e5f41SBart Van Assche static ssize_t show_comp_vector(struct device *dev,
32074b5e5f41SBart Van Assche 				struct device_attribute *attr, char *buf)
32084b5e5f41SBart Van Assche {
32094b5e5f41SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
32104b5e5f41SBart Van Assche 
32114b5e5f41SBart Van Assche 	return sprintf(buf, "%d\n", target->comp_vector);
32124b5e5f41SBart Van Assche }
32134b5e5f41SBart Van Assche 
32147bb312e4SVu Pham static ssize_t show_tl_retry_count(struct device *dev,
32157bb312e4SVu Pham 				   struct device_attribute *attr, char *buf)
32167bb312e4SVu Pham {
32177bb312e4SVu Pham 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
32187bb312e4SVu Pham 
32197bb312e4SVu Pham 	return sprintf(buf, "%d\n", target->tl_retry_count);
32207bb312e4SVu Pham }
32217bb312e4SVu Pham 
322249248644SDavid Dillow static ssize_t show_cmd_sg_entries(struct device *dev,
322349248644SDavid Dillow 				   struct device_attribute *attr, char *buf)
322449248644SDavid Dillow {
322549248644SDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
322649248644SDavid Dillow 
322749248644SDavid Dillow 	return sprintf(buf, "%u\n", target->cmd_sg_cnt);
322849248644SDavid Dillow }
322949248644SDavid Dillow 
3230c07d424dSDavid Dillow static ssize_t show_allow_ext_sg(struct device *dev,
3231c07d424dSDavid Dillow 				 struct device_attribute *attr, char *buf)
3232c07d424dSDavid Dillow {
3233c07d424dSDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3234c07d424dSDavid Dillow 
3235c07d424dSDavid Dillow 	return sprintf(buf, "%s\n", target->allow_ext_sg ? "true" : "false");
3236c07d424dSDavid Dillow }
3237c07d424dSDavid Dillow 
3238ee959b00STony Jones static DEVICE_ATTR(id_ext,	    S_IRUGO, show_id_ext,	   NULL);
3239ee959b00STony Jones static DEVICE_ATTR(ioc_guid,	    S_IRUGO, show_ioc_guid,	   NULL);
3240ee959b00STony Jones static DEVICE_ATTR(service_id,	    S_IRUGO, show_service_id,	   NULL);
3241ee959b00STony Jones static DEVICE_ATTR(pkey,	    S_IRUGO, show_pkey,		   NULL);
3242848b3082SBart Van Assche static DEVICE_ATTR(sgid,	    S_IRUGO, show_sgid,		   NULL);
3243ee959b00STony Jones static DEVICE_ATTR(dgid,	    S_IRUGO, show_dgid,		   NULL);
3244ee959b00STony Jones static DEVICE_ATTR(orig_dgid,	    S_IRUGO, show_orig_dgid,	   NULL);
324589de7486SBart Van Assche static DEVICE_ATTR(req_lim,         S_IRUGO, show_req_lim,         NULL);
3246ee959b00STony Jones static DEVICE_ATTR(zero_req_lim,    S_IRUGO, show_zero_req_lim,	   NULL);
3247ee959b00STony Jones static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
3248ee959b00STony Jones static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
3249d92c0da7SBart Van Assche static DEVICE_ATTR(ch_count,        S_IRUGO, show_ch_count,        NULL);
32504b5e5f41SBart Van Assche static DEVICE_ATTR(comp_vector,     S_IRUGO, show_comp_vector,     NULL);
32517bb312e4SVu Pham static DEVICE_ATTR(tl_retry_count,  S_IRUGO, show_tl_retry_count,  NULL);
325249248644SDavid Dillow static DEVICE_ATTR(cmd_sg_entries,  S_IRUGO, show_cmd_sg_entries,  NULL);
3253c07d424dSDavid Dillow static DEVICE_ATTR(allow_ext_sg,    S_IRUGO, show_allow_ext_sg,    NULL);
32546ecb0c84SRoland Dreier 
3255ee959b00STony Jones static struct device_attribute *srp_host_attrs[] = {
3256ee959b00STony Jones 	&dev_attr_id_ext,
3257ee959b00STony Jones 	&dev_attr_ioc_guid,
3258ee959b00STony Jones 	&dev_attr_service_id,
3259ee959b00STony Jones 	&dev_attr_pkey,
3260848b3082SBart Van Assche 	&dev_attr_sgid,
3261ee959b00STony Jones 	&dev_attr_dgid,
3262ee959b00STony Jones 	&dev_attr_orig_dgid,
326389de7486SBart Van Assche 	&dev_attr_req_lim,
3264ee959b00STony Jones 	&dev_attr_zero_req_lim,
3265ee959b00STony Jones 	&dev_attr_local_ib_port,
3266ee959b00STony Jones 	&dev_attr_local_ib_device,
3267d92c0da7SBart Van Assche 	&dev_attr_ch_count,
32684b5e5f41SBart Van Assche 	&dev_attr_comp_vector,
32697bb312e4SVu Pham 	&dev_attr_tl_retry_count,
327049248644SDavid Dillow 	&dev_attr_cmd_sg_entries,
3271c07d424dSDavid Dillow 	&dev_attr_allow_ext_sg,
32726ecb0c84SRoland Dreier 	NULL
32736ecb0c84SRoland Dreier };
32746ecb0c84SRoland Dreier 
3275aef9ec39SRoland Dreier static struct scsi_host_template srp_template = {
3276aef9ec39SRoland Dreier 	.module				= THIS_MODULE,
3277b7f008fdSRoland Dreier 	.name				= "InfiniBand SRP initiator",
3278b7f008fdSRoland Dreier 	.proc_name			= DRV_NAME,
3279b0780ee5SBart Van Assche 	.target_alloc			= srp_target_alloc,
3280509c5f33SBart Van Assche 	.slave_alloc			= srp_slave_alloc,
3281c9b03c1aSBart Van Assche 	.slave_configure		= srp_slave_configure,
3282aef9ec39SRoland Dreier 	.info				= srp_target_info,
3283aef9ec39SRoland Dreier 	.queuecommand			= srp_queuecommand,
328471444b97SJack Wang 	.change_queue_depth             = srp_change_queue_depth,
3285b6a05c82SChristoph Hellwig 	.eh_timed_out			= srp_timed_out,
3286aef9ec39SRoland Dreier 	.eh_abort_handler		= srp_abort,
3287aef9ec39SRoland Dreier 	.eh_device_reset_handler	= srp_reset_device,
3288aef9ec39SRoland Dreier 	.eh_host_reset_handler		= srp_reset_host,
32892742c1daSBart Van Assche 	.skip_settle_delay		= true,
329049248644SDavid Dillow 	.sg_tablesize			= SRP_DEF_SG_TABLESIZE,
32914d73f95fSBart Van Assche 	.can_queue			= SRP_DEFAULT_CMD_SQ_SIZE,
3292aef9ec39SRoland Dreier 	.this_id			= -1,
32934d73f95fSBart Van Assche 	.cmd_per_lun			= SRP_DEFAULT_CMD_SQ_SIZE,
329477f2c1a4SBart Van Assche 	.shost_attrs			= srp_host_attrs,
3295c40ecc12SChristoph Hellwig 	.track_queue_depth		= 1,
3296aef9ec39SRoland Dreier };
3297aef9ec39SRoland Dreier 
329834aa654eSBart Van Assche static int srp_sdev_count(struct Scsi_Host *host)
329934aa654eSBart Van Assche {
330034aa654eSBart Van Assche 	struct scsi_device *sdev;
330134aa654eSBart Van Assche 	int c = 0;
330234aa654eSBart Van Assche 
330334aa654eSBart Van Assche 	shost_for_each_device(sdev, host)
330434aa654eSBart Van Assche 		c++;
330534aa654eSBart Van Assche 
330634aa654eSBart Van Assche 	return c;
330734aa654eSBart Van Assche }
330834aa654eSBart Van Assche 
3309bc44bd1dSBart Van Assche /*
3310bc44bd1dSBart Van Assche  * Return values:
3311bc44bd1dSBart Van Assche  * < 0 upon failure. Caller is responsible for SRP target port cleanup.
3312bc44bd1dSBart Van Assche  * 0 and target->state == SRP_TARGET_REMOVED if asynchronous target port
3313bc44bd1dSBart Van Assche  *    removal has been scheduled.
3314bc44bd1dSBart Van Assche  * 0 and target->state != SRP_TARGET_REMOVED upon success.
3315bc44bd1dSBart Van Assche  */
3316aef9ec39SRoland Dreier static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
3317aef9ec39SRoland Dreier {
33183236822bSFUJITA Tomonori 	struct srp_rport_identifiers ids;
33193236822bSFUJITA Tomonori 	struct srp_rport *rport;
33203236822bSFUJITA Tomonori 
332134aa654eSBart Van Assche 	target->state = SRP_TARGET_SCANNING;
3322aef9ec39SRoland Dreier 	sprintf(target->target_name, "SRP.T10:%016llX",
332345c37cadSBart Van Assche 		be64_to_cpu(target->id_ext));
3324aef9ec39SRoland Dreier 
3325dee2b82aSBart Van Assche 	if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dev.parent))
3326aef9ec39SRoland Dreier 		return -ENODEV;
3327aef9ec39SRoland Dreier 
33283236822bSFUJITA Tomonori 	memcpy(ids.port_id, &target->id_ext, 8);
33293236822bSFUJITA Tomonori 	memcpy(ids.port_id + 8, &target->ioc_guid, 8);
3330aebd5e47SFUJITA Tomonori 	ids.roles = SRP_RPORT_ROLE_TARGET;
33313236822bSFUJITA Tomonori 	rport = srp_rport_add(target->scsi_host, &ids);
33323236822bSFUJITA Tomonori 	if (IS_ERR(rport)) {
33333236822bSFUJITA Tomonori 		scsi_remove_host(target->scsi_host);
33343236822bSFUJITA Tomonori 		return PTR_ERR(rport);
33353236822bSFUJITA Tomonori 	}
33363236822bSFUJITA Tomonori 
3337dc1bdbd9SBart Van Assche 	rport->lld_data = target;
33389dd69a60SBart Van Assche 	target->rport = rport;
3339dc1bdbd9SBart Van Assche 
3340b3589fd4SMatthew Wilcox 	spin_lock(&host->target_lock);
3341aef9ec39SRoland Dreier 	list_add_tail(&target->list, &host->target_list);
3342b3589fd4SMatthew Wilcox 	spin_unlock(&host->target_lock);
3343aef9ec39SRoland Dreier 
3344aef9ec39SRoland Dreier 	scsi_scan_target(&target->scsi_host->shost_gendev,
33451d645088SHannes Reinecke 			 0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
3346aef9ec39SRoland Dreier 
3347c014c8cdSBart Van Assche 	if (srp_connected_ch(target) < target->ch_count ||
3348c014c8cdSBart Van Assche 	    target->qp_in_error) {
334934aa654eSBart Van Assche 		shost_printk(KERN_INFO, target->scsi_host,
335034aa654eSBart Van Assche 			     PFX "SCSI scan failed - removing SCSI host\n");
335134aa654eSBart Van Assche 		srp_queue_remove_work(target);
335234aa654eSBart Van Assche 		goto out;
335334aa654eSBart Van Assche 	}
335434aa654eSBart Van Assche 
3355cf1acab7SBart Van Assche 	pr_debug("%s: SCSI scan succeeded - detected %d LUNs\n",
335634aa654eSBart Van Assche 		 dev_name(&target->scsi_host->shost_gendev),
335734aa654eSBart Van Assche 		 srp_sdev_count(target->scsi_host));
335834aa654eSBart Van Assche 
335934aa654eSBart Van Assche 	spin_lock_irq(&target->lock);
336034aa654eSBart Van Assche 	if (target->state == SRP_TARGET_SCANNING)
336134aa654eSBart Van Assche 		target->state = SRP_TARGET_LIVE;
336234aa654eSBart Van Assche 	spin_unlock_irq(&target->lock);
336334aa654eSBart Van Assche 
336434aa654eSBart Van Assche out:
3365aef9ec39SRoland Dreier 	return 0;
3366aef9ec39SRoland Dreier }
3367aef9ec39SRoland Dreier 
3368ee959b00STony Jones static void srp_release_dev(struct device *dev)
3369aef9ec39SRoland Dreier {
3370aef9ec39SRoland Dreier 	struct srp_host *host =
3371ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3372aef9ec39SRoland Dreier 
3373aef9ec39SRoland Dreier 	complete(&host->released);
3374aef9ec39SRoland Dreier }
3375aef9ec39SRoland Dreier 
3376aef9ec39SRoland Dreier static struct class srp_class = {
3377aef9ec39SRoland Dreier 	.name    = "infiniband_srp",
3378ee959b00STony Jones 	.dev_release = srp_release_dev
3379aef9ec39SRoland Dreier };
3380aef9ec39SRoland Dreier 
338196fc248aSBart Van Assche /**
338296fc248aSBart Van Assche  * srp_conn_unique() - check whether the connection to a target is unique
3383af24663bSBart Van Assche  * @host:   SRP host.
3384af24663bSBart Van Assche  * @target: SRP target port.
338596fc248aSBart Van Assche  */
338696fc248aSBart Van Assche static bool srp_conn_unique(struct srp_host *host,
338796fc248aSBart Van Assche 			    struct srp_target_port *target)
338896fc248aSBart Van Assche {
338996fc248aSBart Van Assche 	struct srp_target_port *t;
339096fc248aSBart Van Assche 	bool ret = false;
339196fc248aSBart Van Assche 
339296fc248aSBart Van Assche 	if (target->state == SRP_TARGET_REMOVED)
339396fc248aSBart Van Assche 		goto out;
339496fc248aSBart Van Assche 
339596fc248aSBart Van Assche 	ret = true;
339696fc248aSBart Van Assche 
339796fc248aSBart Van Assche 	spin_lock(&host->target_lock);
339896fc248aSBart Van Assche 	list_for_each_entry(t, &host->target_list, list) {
339996fc248aSBart Van Assche 		if (t != target &&
340096fc248aSBart Van Assche 		    target->id_ext == t->id_ext &&
340196fc248aSBart Van Assche 		    target->ioc_guid == t->ioc_guid &&
340296fc248aSBart Van Assche 		    target->initiator_ext == t->initiator_ext) {
340396fc248aSBart Van Assche 			ret = false;
340496fc248aSBart Van Assche 			break;
340596fc248aSBart Van Assche 		}
340696fc248aSBart Van Assche 	}
340796fc248aSBart Van Assche 	spin_unlock(&host->target_lock);
340896fc248aSBart Van Assche 
340996fc248aSBart Van Assche out:
341096fc248aSBart Van Assche 	return ret;
341196fc248aSBart Van Assche }
341296fc248aSBart Van Assche 
3413aef9ec39SRoland Dreier /*
3414aef9ec39SRoland Dreier  * Target ports are added by writing
3415aef9ec39SRoland Dreier  *
3416aef9ec39SRoland Dreier  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>,
3417aef9ec39SRoland Dreier  *     pkey=<P_Key>,service_id=<service ID>
341819f31343SBart Van Assche  * or
341919f31343SBart Van Assche  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,
342019f31343SBart Van Assche  *     [src=<IPv4 address>,]dest=<IPv4 address>:<port number>
3421aef9ec39SRoland Dreier  *
3422aef9ec39SRoland Dreier  * to the add_target sysfs attribute.
3423aef9ec39SRoland Dreier  */
3424aef9ec39SRoland Dreier enum {
3425aef9ec39SRoland Dreier 	SRP_OPT_ERR		= 0,
3426aef9ec39SRoland Dreier 	SRP_OPT_ID_EXT		= 1 << 0,
3427aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	= 1 << 1,
3428aef9ec39SRoland Dreier 	SRP_OPT_DGID		= 1 << 2,
3429aef9ec39SRoland Dreier 	SRP_OPT_PKEY		= 1 << 3,
3430aef9ec39SRoland Dreier 	SRP_OPT_SERVICE_ID	= 1 << 4,
3431aef9ec39SRoland Dreier 	SRP_OPT_MAX_SECT	= 1 << 5,
343252fb2b50SVu Pham 	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
34330c0450dbSRamachandra K 	SRP_OPT_IO_CLASS	= 1 << 7,
343401cb9bcbSIshai Rabinovitz 	SRP_OPT_INITIATOR_EXT	= 1 << 8,
343549248644SDavid Dillow 	SRP_OPT_CMD_SG_ENTRIES	= 1 << 9,
3436c07d424dSDavid Dillow 	SRP_OPT_ALLOW_EXT_SG	= 1 << 10,
3437c07d424dSDavid Dillow 	SRP_OPT_SG_TABLESIZE	= 1 << 11,
34384b5e5f41SBart Van Assche 	SRP_OPT_COMP_VECTOR	= 1 << 12,
34397bb312e4SVu Pham 	SRP_OPT_TL_RETRY_COUNT	= 1 << 13,
34404d73f95fSBart Van Assche 	SRP_OPT_QUEUE_SIZE	= 1 << 14,
344119f31343SBart Van Assche 	SRP_OPT_IP_SRC		= 1 << 15,
344219f31343SBart Van Assche 	SRP_OPT_IP_DEST		= 1 << 16,
3443b0780ee5SBart Van Assche 	SRP_OPT_TARGET_CAN_QUEUE= 1 << 17,
344419f31343SBart Van Assche };
344519f31343SBart Van Assche 
344619f31343SBart Van Assche static unsigned int srp_opt_mandatory[] = {
344719f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
3448aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	|
3449aef9ec39SRoland Dreier 	SRP_OPT_DGID		|
3450aef9ec39SRoland Dreier 	SRP_OPT_PKEY		|
345119f31343SBart Van Assche 	SRP_OPT_SERVICE_ID,
345219f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
345319f31343SBart Van Assche 	SRP_OPT_IOC_GUID	|
345419f31343SBart Van Assche 	SRP_OPT_IP_DEST,
3455aef9ec39SRoland Dreier };
3456aef9ec39SRoland Dreier 
3457a447c093SSteven Whitehouse static const match_table_t srp_opt_tokens = {
3458aef9ec39SRoland Dreier 	{ SRP_OPT_ID_EXT,		"id_ext=%s" 		},
3459aef9ec39SRoland Dreier 	{ SRP_OPT_IOC_GUID,		"ioc_guid=%s" 		},
3460aef9ec39SRoland Dreier 	{ SRP_OPT_DGID,			"dgid=%s" 		},
3461aef9ec39SRoland Dreier 	{ SRP_OPT_PKEY,			"pkey=%x" 		},
3462aef9ec39SRoland Dreier 	{ SRP_OPT_SERVICE_ID,		"service_id=%s"		},
3463aef9ec39SRoland Dreier 	{ SRP_OPT_MAX_SECT,		"max_sect=%d" 		},
346452fb2b50SVu Pham 	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
3465b0780ee5SBart Van Assche 	{ SRP_OPT_TARGET_CAN_QUEUE,	"target_can_queue=%d"	},
34660c0450dbSRamachandra K 	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
346701cb9bcbSIshai Rabinovitz 	{ SRP_OPT_INITIATOR_EXT,	"initiator_ext=%s"	},
346849248644SDavid Dillow 	{ SRP_OPT_CMD_SG_ENTRIES,	"cmd_sg_entries=%u"	},
3469c07d424dSDavid Dillow 	{ SRP_OPT_ALLOW_EXT_SG,		"allow_ext_sg=%u"	},
3470c07d424dSDavid Dillow 	{ SRP_OPT_SG_TABLESIZE,		"sg_tablesize=%u"	},
34714b5e5f41SBart Van Assche 	{ SRP_OPT_COMP_VECTOR,		"comp_vector=%u"	},
34727bb312e4SVu Pham 	{ SRP_OPT_TL_RETRY_COUNT,	"tl_retry_count=%u"	},
34734d73f95fSBart Van Assche 	{ SRP_OPT_QUEUE_SIZE,		"queue_size=%d"		},
347419f31343SBart Van Assche 	{ SRP_OPT_IP_SRC,		"src=%s"		},
347519f31343SBart Van Assche 	{ SRP_OPT_IP_DEST,		"dest=%s"		},
3476aef9ec39SRoland Dreier 	{ SRP_OPT_ERR,			NULL 			}
3477aef9ec39SRoland Dreier };
3478aef9ec39SRoland Dreier 
3479c62adb7dSBart Van Assche /**
3480c62adb7dSBart Van Assche  * srp_parse_in - parse an IP address and port number combination
3481e37df2d5SBart Van Assche  * @net:	   [in]  Network namespace.
3482e37df2d5SBart Van Assche  * @sa:		   [out] Address family, IP address and port number.
3483e37df2d5SBart Van Assche  * @addr_port_str: [in]  IP address and port number.
3484*bcef5b72SBart Van Assche  * @has_port:	   [out] Whether or not @addr_port_str includes a port number.
3485c62adb7dSBart Van Assche  *
3486c62adb7dSBart Van Assche  * Parse the following address formats:
3487c62adb7dSBart Van Assche  * - IPv4: <ip_address>:<port>, e.g. 1.2.3.4:5.
3488c62adb7dSBart Van Assche  * - IPv6: \[<ipv6_address>\]:<port>, e.g. [1::2:3%4]:5.
3489c62adb7dSBart Van Assche  */
349019f31343SBart Van Assche static int srp_parse_in(struct net *net, struct sockaddr_storage *sa,
3491*bcef5b72SBart Van Assche 			const char *addr_port_str, bool *has_port)
349219f31343SBart Van Assche {
3493c62adb7dSBart Van Assche 	char *addr_end, *addr = kstrdup(addr_port_str, GFP_KERNEL);
3494c62adb7dSBart Van Assche 	char *port_str;
349519f31343SBart Van Assche 	int ret;
349619f31343SBart Van Assche 
349719f31343SBart Van Assche 	if (!addr)
349819f31343SBart Van Assche 		return -ENOMEM;
3499c62adb7dSBart Van Assche 	port_str = strrchr(addr, ':');
3500*bcef5b72SBart Van Assche 	if (port_str && strchr(port_str, ']'))
3501*bcef5b72SBart Van Assche 		port_str = NULL;
3502*bcef5b72SBart Van Assche 	if (port_str)
3503c62adb7dSBart Van Assche 		*port_str++ = '\0';
3504*bcef5b72SBart Van Assche 	if (has_port)
3505*bcef5b72SBart Van Assche 		*has_port = port_str != NULL;
3506c62adb7dSBart Van Assche 	ret = inet_pton_with_scope(net, AF_INET, addr, port_str, sa);
3507c62adb7dSBart Van Assche 	if (ret && addr[0]) {
3508c62adb7dSBart Van Assche 		addr_end = addr + strlen(addr) - 1;
3509c62adb7dSBart Van Assche 		if (addr[0] == '[' && *addr_end == ']') {
3510c62adb7dSBart Van Assche 			*addr_end = '\0';
3511c62adb7dSBart Van Assche 			ret = inet_pton_with_scope(net, AF_INET6, addr + 1,
3512c62adb7dSBart Van Assche 						   port_str, sa);
3513c62adb7dSBart Van Assche 		}
3514c62adb7dSBart Van Assche 	}
351519f31343SBart Van Assche 	kfree(addr);
3516c62adb7dSBart Van Assche 	pr_debug("%s -> %pISpfsc\n", addr_port_str, sa);
351719f31343SBart Van Assche 	return ret;
351819f31343SBart Van Assche }
351919f31343SBart Van Assche 
352019f31343SBart Van Assche static int srp_parse_options(struct net *net, const char *buf,
352119f31343SBart Van Assche 			     struct srp_target_port *target)
3522aef9ec39SRoland Dreier {
3523aef9ec39SRoland Dreier 	char *options, *sep_opt;
3524aef9ec39SRoland Dreier 	char *p;
3525aef9ec39SRoland Dreier 	substring_t args[MAX_OPT_ARGS];
35262a174df0SBart Van Assche 	unsigned long long ull;
3527*bcef5b72SBart Van Assche 	bool has_port;
3528aef9ec39SRoland Dreier 	int opt_mask = 0;
3529aef9ec39SRoland Dreier 	int token;
3530aef9ec39SRoland Dreier 	int ret = -EINVAL;
3531aef9ec39SRoland Dreier 	int i;
3532aef9ec39SRoland Dreier 
3533aef9ec39SRoland Dreier 	options = kstrdup(buf, GFP_KERNEL);
3534aef9ec39SRoland Dreier 	if (!options)
3535aef9ec39SRoland Dreier 		return -ENOMEM;
3536aef9ec39SRoland Dreier 
3537aef9ec39SRoland Dreier 	sep_opt = options;
35387dcf9c19SSagi Grimberg 	while ((p = strsep(&sep_opt, ",\n")) != NULL) {
3539aef9ec39SRoland Dreier 		if (!*p)
3540aef9ec39SRoland Dreier 			continue;
3541aef9ec39SRoland Dreier 
3542aef9ec39SRoland Dreier 		token = match_token(p, srp_opt_tokens, args);
3543aef9ec39SRoland Dreier 		opt_mask |= token;
3544aef9ec39SRoland Dreier 
3545aef9ec39SRoland Dreier 		switch (token) {
3546aef9ec39SRoland Dreier 		case SRP_OPT_ID_EXT:
3547aef9ec39SRoland Dreier 			p = match_strdup(args);
3548a20f3a6dSIshai Rabinovitz 			if (!p) {
3549a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3550a20f3a6dSIshai Rabinovitz 				goto out;
3551a20f3a6dSIshai Rabinovitz 			}
35522a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35532a174df0SBart Van Assche 			if (ret) {
35542a174df0SBart Van Assche 				pr_warn("invalid id_ext parameter '%s'\n", p);
35552a174df0SBart Van Assche 				kfree(p);
35562a174df0SBart Van Assche 				goto out;
35572a174df0SBart Van Assche 			}
35582a174df0SBart Van Assche 			target->id_ext = cpu_to_be64(ull);
3559aef9ec39SRoland Dreier 			kfree(p);
3560aef9ec39SRoland Dreier 			break;
3561aef9ec39SRoland Dreier 
3562aef9ec39SRoland Dreier 		case SRP_OPT_IOC_GUID:
3563aef9ec39SRoland Dreier 			p = match_strdup(args);
3564a20f3a6dSIshai Rabinovitz 			if (!p) {
3565a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3566a20f3a6dSIshai Rabinovitz 				goto out;
3567a20f3a6dSIshai Rabinovitz 			}
35682a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35692a174df0SBart Van Assche 			if (ret) {
35702a174df0SBart Van Assche 				pr_warn("invalid ioc_guid parameter '%s'\n", p);
35712a174df0SBart Van Assche 				kfree(p);
35722a174df0SBart Van Assche 				goto out;
35732a174df0SBart Van Assche 			}
35742a174df0SBart Van Assche 			target->ioc_guid = cpu_to_be64(ull);
3575aef9ec39SRoland Dreier 			kfree(p);
3576aef9ec39SRoland Dreier 			break;
3577aef9ec39SRoland Dreier 
3578aef9ec39SRoland Dreier 		case SRP_OPT_DGID:
3579aef9ec39SRoland Dreier 			p = match_strdup(args);
3580a20f3a6dSIshai Rabinovitz 			if (!p) {
3581a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3582a20f3a6dSIshai Rabinovitz 				goto out;
3583a20f3a6dSIshai Rabinovitz 			}
3584aef9ec39SRoland Dreier 			if (strlen(p) != 32) {
3585e0bda7d8SBart Van Assche 				pr_warn("bad dest GID parameter '%s'\n", p);
3586ce1823f0SRoland Dreier 				kfree(p);
3587aef9ec39SRoland Dreier 				goto out;
3588aef9ec39SRoland Dreier 			}
3589aef9ec39SRoland Dreier 
359019f31343SBart Van Assche 			ret = hex2bin(target->ib_cm.orig_dgid.raw, p, 16);
3591747fe000SBart Van Assche 			kfree(p);
3592e711f968SAndy Shevchenko 			if (ret < 0)
3593747fe000SBart Van Assche 				goto out;
3594aef9ec39SRoland Dreier 			break;
3595aef9ec39SRoland Dreier 
3596aef9ec39SRoland Dreier 		case SRP_OPT_PKEY:
3597aef9ec39SRoland Dreier 			if (match_hex(args, &token)) {
3598e0bda7d8SBart Van Assche 				pr_warn("bad P_Key parameter '%s'\n", p);
3599aef9ec39SRoland Dreier 				goto out;
3600aef9ec39SRoland Dreier 			}
360119f31343SBart Van Assche 			target->ib_cm.pkey = cpu_to_be16(token);
3602aef9ec39SRoland Dreier 			break;
3603aef9ec39SRoland Dreier 
3604aef9ec39SRoland Dreier 		case SRP_OPT_SERVICE_ID:
3605aef9ec39SRoland Dreier 			p = match_strdup(args);
3606a20f3a6dSIshai Rabinovitz 			if (!p) {
3607a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3608a20f3a6dSIshai Rabinovitz 				goto out;
3609a20f3a6dSIshai Rabinovitz 			}
36102a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
36112a174df0SBart Van Assche 			if (ret) {
36122a174df0SBart Van Assche 				pr_warn("bad service_id parameter '%s'\n", p);
36132a174df0SBart Van Assche 				kfree(p);
36142a174df0SBart Van Assche 				goto out;
36152a174df0SBart Van Assche 			}
361619f31343SBart Van Assche 			target->ib_cm.service_id = cpu_to_be64(ull);
361719f31343SBart Van Assche 			kfree(p);
361819f31343SBart Van Assche 			break;
361919f31343SBart Van Assche 
362019f31343SBart Van Assche 		case SRP_OPT_IP_SRC:
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 			}
3626*bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.src.ss, p,
3627*bcef5b72SBart Van Assche 					   NULL);
362819f31343SBart Van Assche 			if (ret < 0) {
362919f31343SBart Van Assche 				pr_warn("bad source parameter '%s'\n", p);
363019f31343SBart Van Assche 				kfree(p);
363119f31343SBart Van Assche 				goto out;
363219f31343SBart Van Assche 			}
363319f31343SBart Van Assche 			target->rdma_cm.src_specified = true;
363419f31343SBart Van Assche 			kfree(p);
363519f31343SBart Van Assche 			break;
363619f31343SBart Van Assche 
363719f31343SBart Van Assche 		case SRP_OPT_IP_DEST:
363819f31343SBart Van Assche 			p = match_strdup(args);
363919f31343SBart Van Assche 			if (!p) {
364019f31343SBart Van Assche 				ret = -ENOMEM;
364119f31343SBart Van Assche 				goto out;
364219f31343SBart Van Assche 			}
3643*bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.dst.ss, p,
3644*bcef5b72SBart Van Assche 					   &has_port);
3645*bcef5b72SBart Van Assche 			if (!has_port)
3646*bcef5b72SBart Van Assche 				ret = -EINVAL;
364719f31343SBart Van Assche 			if (ret < 0) {
364819f31343SBart Van Assche 				pr_warn("bad dest parameter '%s'\n", p);
364919f31343SBart Van Assche 				kfree(p);
365019f31343SBart Van Assche 				goto out;
365119f31343SBart Van Assche 			}
365219f31343SBart Van Assche 			target->using_rdma_cm = true;
3653aef9ec39SRoland Dreier 			kfree(p);
3654aef9ec39SRoland Dreier 			break;
3655aef9ec39SRoland Dreier 
3656aef9ec39SRoland Dreier 		case SRP_OPT_MAX_SECT:
3657aef9ec39SRoland Dreier 			if (match_int(args, &token)) {
3658e0bda7d8SBart Van Assche 				pr_warn("bad max sect parameter '%s'\n", p);
3659aef9ec39SRoland Dreier 				goto out;
3660aef9ec39SRoland Dreier 			}
3661aef9ec39SRoland Dreier 			target->scsi_host->max_sectors = token;
3662aef9ec39SRoland Dreier 			break;
3663aef9ec39SRoland Dreier 
36644d73f95fSBart Van Assche 		case SRP_OPT_QUEUE_SIZE:
36654d73f95fSBart Van Assche 			if (match_int(args, &token) || token < 1) {
36664d73f95fSBart Van Assche 				pr_warn("bad queue_size parameter '%s'\n", p);
36674d73f95fSBart Van Assche 				goto out;
36684d73f95fSBart Van Assche 			}
36694d73f95fSBart Van Assche 			target->scsi_host->can_queue = token;
36704d73f95fSBart Van Assche 			target->queue_size = token + SRP_RSP_SQ_SIZE +
36714d73f95fSBart Van Assche 					     SRP_TSK_MGMT_SQ_SIZE;
36724d73f95fSBart Van Assche 			if (!(opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
36734d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun = token;
36744d73f95fSBart Van Assche 			break;
36754d73f95fSBart Van Assche 
367652fb2b50SVu Pham 		case SRP_OPT_MAX_CMD_PER_LUN:
36774d73f95fSBart Van Assche 			if (match_int(args, &token) || token < 1) {
3678e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_per_lun parameter '%s'\n",
3679e0bda7d8SBart Van Assche 					p);
368052fb2b50SVu Pham 				goto out;
368152fb2b50SVu Pham 			}
36824d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun = token;
368352fb2b50SVu Pham 			break;
368452fb2b50SVu Pham 
3685b0780ee5SBart Van Assche 		case SRP_OPT_TARGET_CAN_QUEUE:
3686b0780ee5SBart Van Assche 			if (match_int(args, &token) || token < 1) {
3687b0780ee5SBart Van Assche 				pr_warn("bad max target_can_queue parameter '%s'\n",
3688b0780ee5SBart Van Assche 					p);
3689b0780ee5SBart Van Assche 				goto out;
3690b0780ee5SBart Van Assche 			}
3691b0780ee5SBart Van Assche 			target->target_can_queue = token;
3692b0780ee5SBart Van Assche 			break;
3693b0780ee5SBart Van Assche 
36940c0450dbSRamachandra K 		case SRP_OPT_IO_CLASS:
36950c0450dbSRamachandra K 			if (match_hex(args, &token)) {
3696e0bda7d8SBart Van Assche 				pr_warn("bad IO class parameter '%s'\n", p);
36970c0450dbSRamachandra K 				goto out;
36980c0450dbSRamachandra K 			}
36990c0450dbSRamachandra K 			if (token != SRP_REV10_IB_IO_CLASS &&
37000c0450dbSRamachandra K 			    token != SRP_REV16A_IB_IO_CLASS) {
3701e0bda7d8SBart Van Assche 				pr_warn("unknown IO class parameter value %x specified (use %x or %x).\n",
3702e0bda7d8SBart Van Assche 					token, SRP_REV10_IB_IO_CLASS,
3703e0bda7d8SBart Van Assche 					SRP_REV16A_IB_IO_CLASS);
37040c0450dbSRamachandra K 				goto out;
37050c0450dbSRamachandra K 			}
37060c0450dbSRamachandra K 			target->io_class = token;
37070c0450dbSRamachandra K 			break;
37080c0450dbSRamachandra K 
370901cb9bcbSIshai Rabinovitz 		case SRP_OPT_INITIATOR_EXT:
371001cb9bcbSIshai Rabinovitz 			p = match_strdup(args);
3711a20f3a6dSIshai Rabinovitz 			if (!p) {
3712a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3713a20f3a6dSIshai Rabinovitz 				goto out;
3714a20f3a6dSIshai Rabinovitz 			}
37152a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
37162a174df0SBart Van Assche 			if (ret) {
37172a174df0SBart Van Assche 				pr_warn("bad initiator_ext value '%s'\n", p);
37182a174df0SBart Van Assche 				kfree(p);
37192a174df0SBart Van Assche 				goto out;
37202a174df0SBart Van Assche 			}
37212a174df0SBart Van Assche 			target->initiator_ext = cpu_to_be64(ull);
372201cb9bcbSIshai Rabinovitz 			kfree(p);
372301cb9bcbSIshai Rabinovitz 			break;
372401cb9bcbSIshai Rabinovitz 
372549248644SDavid Dillow 		case SRP_OPT_CMD_SG_ENTRIES:
372649248644SDavid Dillow 			if (match_int(args, &token) || token < 1 || token > 255) {
3727e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_sg_entries parameter '%s'\n",
3728e0bda7d8SBart Van Assche 					p);
372949248644SDavid Dillow 				goto out;
373049248644SDavid Dillow 			}
373149248644SDavid Dillow 			target->cmd_sg_cnt = token;
373249248644SDavid Dillow 			break;
373349248644SDavid Dillow 
3734c07d424dSDavid Dillow 		case SRP_OPT_ALLOW_EXT_SG:
3735c07d424dSDavid Dillow 			if (match_int(args, &token)) {
3736e0bda7d8SBart Van Assche 				pr_warn("bad allow_ext_sg parameter '%s'\n", p);
3737c07d424dSDavid Dillow 				goto out;
3738c07d424dSDavid Dillow 			}
3739c07d424dSDavid Dillow 			target->allow_ext_sg = !!token;
3740c07d424dSDavid Dillow 			break;
3741c07d424dSDavid Dillow 
3742c07d424dSDavid Dillow 		case SRP_OPT_SG_TABLESIZE:
3743c07d424dSDavid Dillow 			if (match_int(args, &token) || token < 1 ||
374465e8617fSMing Lin 					token > SG_MAX_SEGMENTS) {
3745e0bda7d8SBart Van Assche 				pr_warn("bad max sg_tablesize parameter '%s'\n",
3746e0bda7d8SBart Van Assche 					p);
3747c07d424dSDavid Dillow 				goto out;
3748c07d424dSDavid Dillow 			}
3749c07d424dSDavid Dillow 			target->sg_tablesize = token;
3750c07d424dSDavid Dillow 			break;
3751c07d424dSDavid Dillow 
37524b5e5f41SBart Van Assche 		case SRP_OPT_COMP_VECTOR:
37534b5e5f41SBart Van Assche 			if (match_int(args, &token) || token < 0) {
37544b5e5f41SBart Van Assche 				pr_warn("bad comp_vector parameter '%s'\n", p);
37554b5e5f41SBart Van Assche 				goto out;
37564b5e5f41SBart Van Assche 			}
37574b5e5f41SBart Van Assche 			target->comp_vector = token;
37584b5e5f41SBart Van Assche 			break;
37594b5e5f41SBart Van Assche 
37607bb312e4SVu Pham 		case SRP_OPT_TL_RETRY_COUNT:
37617bb312e4SVu Pham 			if (match_int(args, &token) || token < 2 || token > 7) {
37627bb312e4SVu Pham 				pr_warn("bad tl_retry_count parameter '%s' (must be a number between 2 and 7)\n",
37637bb312e4SVu Pham 					p);
37647bb312e4SVu Pham 				goto out;
37657bb312e4SVu Pham 			}
37667bb312e4SVu Pham 			target->tl_retry_count = token;
37677bb312e4SVu Pham 			break;
37687bb312e4SVu Pham 
3769aef9ec39SRoland Dreier 		default:
3770e0bda7d8SBart Van Assche 			pr_warn("unknown parameter or missing value '%s' in target creation request\n",
3771e0bda7d8SBart Van Assche 				p);
3772aef9ec39SRoland Dreier 			goto out;
3773aef9ec39SRoland Dreier 		}
3774aef9ec39SRoland Dreier 	}
3775aef9ec39SRoland Dreier 
377619f31343SBart Van Assche 	for (i = 0; i < ARRAY_SIZE(srp_opt_mandatory); i++) {
377719f31343SBart Van Assche 		if ((opt_mask & srp_opt_mandatory[i]) == srp_opt_mandatory[i]) {
3778aef9ec39SRoland Dreier 			ret = 0;
377919f31343SBart Van Assche 			break;
378019f31343SBart Van Assche 		}
378119f31343SBart Van Assche 	}
378219f31343SBart Van Assche 	if (ret)
378319f31343SBart Van Assche 		pr_warn("target creation request is missing one or more parameters\n");
3784aef9ec39SRoland Dreier 
37854d73f95fSBart Van Assche 	if (target->scsi_host->cmd_per_lun > target->scsi_host->can_queue
37864d73f95fSBart Van Assche 	    && (opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
37874d73f95fSBart Van Assche 		pr_warn("cmd_per_lun = %d > queue_size = %d\n",
37884d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun,
37894d73f95fSBart Van Assche 			target->scsi_host->can_queue);
37904d73f95fSBart Van Assche 
3791aef9ec39SRoland Dreier out:
3792aef9ec39SRoland Dreier 	kfree(options);
3793aef9ec39SRoland Dreier 	return ret;
3794aef9ec39SRoland Dreier }
3795aef9ec39SRoland Dreier 
3796ee959b00STony Jones static ssize_t srp_create_target(struct device *dev,
3797ee959b00STony Jones 				 struct device_attribute *attr,
3798aef9ec39SRoland Dreier 				 const char *buf, size_t count)
3799aef9ec39SRoland Dreier {
3800aef9ec39SRoland Dreier 	struct srp_host *host =
3801ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3802aef9ec39SRoland Dreier 	struct Scsi_Host *target_host;
3803aef9ec39SRoland Dreier 	struct srp_target_port *target;
3804509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
3805d1b4289eSBart Van Assche 	struct srp_device *srp_dev = host->srp_dev;
3806d1b4289eSBart Van Assche 	struct ib_device *ibdev = srp_dev->dev;
3807d92c0da7SBart Van Assche 	int ret, node_idx, node, cpu, i;
3808509c5f33SBart Van Assche 	unsigned int max_sectors_per_mr, mr_per_cmd = 0;
3809d92c0da7SBart Van Assche 	bool multich = false;
3810513d5647SBart Van Assche 	uint32_t max_iu_len;
3811aef9ec39SRoland Dreier 
3812aef9ec39SRoland Dreier 	target_host = scsi_host_alloc(&srp_template,
3813aef9ec39SRoland Dreier 				      sizeof (struct srp_target_port));
3814aef9ec39SRoland Dreier 	if (!target_host)
3815aef9ec39SRoland Dreier 		return -ENOMEM;
3816aef9ec39SRoland Dreier 
38173236822bSFUJITA Tomonori 	target_host->transportt  = ib_srp_transport_template;
3818fd1b6c4aSBart Van Assche 	target_host->max_channel = 0;
3819fd1b6c4aSBart Van Assche 	target_host->max_id      = 1;
3820985aa495SBart Van Assche 	target_host->max_lun     = -1LL;
38213c8edf0eSArne Redlich 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
38220b5cb330SBart Van Assche 	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
38235f068992SRoland Dreier 
3824aef9ec39SRoland Dreier 	target = host_to_target(target_host);
3825aef9ec39SRoland Dreier 
382619f31343SBart Van Assche 	target->net		= kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
38270c0450dbSRamachandra K 	target->io_class	= SRP_REV16A_IB_IO_CLASS;
3828aef9ec39SRoland Dreier 	target->scsi_host	= target_host;
3829aef9ec39SRoland Dreier 	target->srp_host	= host;
3830e6bf5f48SJason Gunthorpe 	target->lkey		= host->srp_dev->pd->local_dma_lkey;
3831cee687b6SBart Van Assche 	target->global_rkey	= host->srp_dev->global_rkey;
383249248644SDavid Dillow 	target->cmd_sg_cnt	= cmd_sg_entries;
3833c07d424dSDavid Dillow 	target->sg_tablesize	= indirect_sg_entries ? : cmd_sg_entries;
3834c07d424dSDavid Dillow 	target->allow_ext_sg	= allow_ext_sg;
38357bb312e4SVu Pham 	target->tl_retry_count	= 7;
38364d73f95fSBart Van Assche 	target->queue_size	= SRP_DEFAULT_QUEUE_SIZE;
3837aef9ec39SRoland Dreier 
383834aa654eSBart Van Assche 	/*
383934aa654eSBart Van Assche 	 * Avoid that the SCSI host can be removed by srp_remove_target()
384034aa654eSBart Van Assche 	 * before this function returns.
384134aa654eSBart Van Assche 	 */
384234aa654eSBart Van Assche 	scsi_host_get(target->scsi_host);
384334aa654eSBart Van Assche 
38444fa354c9SBart Van Assche 	ret = mutex_lock_interruptible(&host->add_target_mutex);
38454fa354c9SBart Van Assche 	if (ret < 0)
38464fa354c9SBart Van Assche 		goto put;
38472d7091bcSBart Van Assche 
384819f31343SBart Van Assche 	ret = srp_parse_options(target->net, buf, target);
3849aef9ec39SRoland Dreier 	if (ret)
3850fb49c8bbSBart Van Assche 		goto out;
3851aef9ec39SRoland Dreier 
38524d73f95fSBart Van Assche 	target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
38534d73f95fSBart Van Assche 
385496fc248aSBart Van Assche 	if (!srp_conn_unique(target->srp_host, target)) {
385519f31343SBart Van Assche 		if (target->using_rdma_cm) {
385619f31343SBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
38577da09af9SBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;dest=%pIS\n",
385819f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
385919f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
38607da09af9SBart Van Assche 				     &target->rdma_cm.dst);
386119f31343SBart Van Assche 		} else {
386296fc248aSBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
386396fc248aSBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n",
386496fc248aSBart Van Assche 				     be64_to_cpu(target->id_ext),
386596fc248aSBart Van Assche 				     be64_to_cpu(target->ioc_guid),
386696fc248aSBart Van Assche 				     be64_to_cpu(target->initiator_ext));
386719f31343SBart Van Assche 		}
386896fc248aSBart Van Assche 		ret = -EEXIST;
3869fb49c8bbSBart Van Assche 		goto out;
387096fc248aSBart Van Assche 	}
387196fc248aSBart Van Assche 
38725cfb1782SBart Van Assche 	if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg &&
3873c07d424dSDavid Dillow 	    target->cmd_sg_cnt < target->sg_tablesize) {
38745cfb1782SBart Van Assche 		pr_warn("No MR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
3875c07d424dSDavid Dillow 		target->sg_tablesize = target->cmd_sg_cnt;
3876c07d424dSDavid Dillow 	}
3877c07d424dSDavid Dillow 
3878509c5f33SBart Van Assche 	if (srp_dev->use_fast_reg || srp_dev->use_fmr) {
3879fbd36818SSergey Gorenko 		bool gaps_reg = (ibdev->attrs.device_cap_flags &
3880fbd36818SSergey Gorenko 				 IB_DEVICE_SG_GAPS_REG);
3881fbd36818SSergey Gorenko 
3882509c5f33SBart Van Assche 		max_sectors_per_mr = srp_dev->max_pages_per_mr <<
3883509c5f33SBart Van Assche 				  (ilog2(srp_dev->mr_page_size) - 9);
3884fbd36818SSergey Gorenko 		if (!gaps_reg) {
3885fbd36818SSergey Gorenko 			/*
3886fbd36818SSergey Gorenko 			 * FR and FMR can only map one HCA page per entry. If
3887fbd36818SSergey Gorenko 			 * the start address is not aligned on a HCA page
3888fbd36818SSergey Gorenko 			 * boundary two entries will be used for the head and
3889fbd36818SSergey Gorenko 			 * the tail although these two entries combined
3890fbd36818SSergey Gorenko 			 * contain at most one HCA page of data. Hence the "+
3891fbd36818SSergey Gorenko 			 * 1" in the calculation below.
3892fbd36818SSergey Gorenko 			 *
3893fbd36818SSergey Gorenko 			 * The indirect data buffer descriptor is contiguous
3894fbd36818SSergey Gorenko 			 * so the memory for that buffer will only be
3895fbd36818SSergey Gorenko 			 * registered if register_always is true. Hence add
3896fbd36818SSergey Gorenko 			 * one to mr_per_cmd if register_always has been set.
3897fbd36818SSergey Gorenko 			 */
3898509c5f33SBart Van Assche 			mr_per_cmd = register_always +
3899509c5f33SBart Van Assche 				(target->scsi_host->max_sectors + 1 +
3900509c5f33SBart Van Assche 				 max_sectors_per_mr - 1) / max_sectors_per_mr;
3901fbd36818SSergey Gorenko 		} else {
3902fbd36818SSergey Gorenko 			mr_per_cmd = register_always +
3903fbd36818SSergey Gorenko 				(target->sg_tablesize +
3904fbd36818SSergey Gorenko 				 srp_dev->max_pages_per_mr - 1) /
3905fbd36818SSergey Gorenko 				srp_dev->max_pages_per_mr;
3906fbd36818SSergey Gorenko 		}
3907509c5f33SBart 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",
3908fbd36818SSergey Gorenko 			 target->scsi_host->max_sectors, srp_dev->max_pages_per_mr, srp_dev->mr_page_size,
3909509c5f33SBart Van Assche 			 max_sectors_per_mr, mr_per_cmd);
3910509c5f33SBart Van Assche 	}
3911509c5f33SBart Van Assche 
3912c07d424dSDavid Dillow 	target_host->sg_tablesize = target->sg_tablesize;
3913509c5f33SBart Van Assche 	target->mr_pool_size = target->scsi_host->can_queue * mr_per_cmd;
3914509c5f33SBart Van Assche 	target->mr_per_cmd = mr_per_cmd;
3915c07d424dSDavid Dillow 	target->indirect_size = target->sg_tablesize *
3916c07d424dSDavid Dillow 				sizeof (struct srp_direct_buf);
3917882981f4SBart Van Assche 	max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt, srp_use_imm_data);
391849248644SDavid Dillow 
3919c1120f89SBart Van Assche 	INIT_WORK(&target->tl_err_work, srp_tl_err_work);
3920ef6c49d8SBart Van Assche 	INIT_WORK(&target->remove_work, srp_remove_work);
39218f26c9ffSDavid Dillow 	spin_lock_init(&target->lock);
39221dfce294SParav Pandit 	ret = rdma_query_gid(ibdev, host->port, 0, &target->sgid);
39232088ca66SSagi Grimberg 	if (ret)
3924fb49c8bbSBart Van Assche 		goto out;
3925d92c0da7SBart Van Assche 
3926d92c0da7SBart Van Assche 	ret = -ENOMEM;
3927d92c0da7SBart Van Assche 	target->ch_count = max_t(unsigned, num_online_nodes(),
3928d92c0da7SBart Van Assche 				 min(ch_count ? :
3929d92c0da7SBart Van Assche 				     min(4 * num_online_nodes(),
3930d92c0da7SBart Van Assche 					 ibdev->num_comp_vectors),
3931d92c0da7SBart Van Assche 				     num_online_cpus()));
3932d92c0da7SBart Van Assche 	target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
3933d92c0da7SBart Van Assche 			     GFP_KERNEL);
3934d92c0da7SBart Van Assche 	if (!target->ch)
3935fb49c8bbSBart Van Assche 		goto out;
3936d92c0da7SBart Van Assche 
3937d92c0da7SBart Van Assche 	node_idx = 0;
3938d92c0da7SBart Van Assche 	for_each_online_node(node) {
3939d92c0da7SBart Van Assche 		const int ch_start = (node_idx * target->ch_count /
3940d92c0da7SBart Van Assche 				      num_online_nodes());
3941d92c0da7SBart Van Assche 		const int ch_end = ((node_idx + 1) * target->ch_count /
3942d92c0da7SBart Van Assche 				    num_online_nodes());
39433a148896SBart Van Assche 		const int cv_start = node_idx * ibdev->num_comp_vectors /
39443a148896SBart Van Assche 				     num_online_nodes();
39453a148896SBart Van Assche 		const int cv_end = (node_idx + 1) * ibdev->num_comp_vectors /
39463a148896SBart Van Assche 				   num_online_nodes();
3947d92c0da7SBart Van Assche 		int cpu_idx = 0;
3948d92c0da7SBart Van Assche 
3949d92c0da7SBart Van Assche 		for_each_online_cpu(cpu) {
3950d92c0da7SBart Van Assche 			if (cpu_to_node(cpu) != node)
3951d92c0da7SBart Van Assche 				continue;
3952d92c0da7SBart Van Assche 			if (ch_start + cpu_idx >= ch_end)
3953d92c0da7SBart Van Assche 				continue;
3954d92c0da7SBart Van Assche 			ch = &target->ch[ch_start + cpu_idx];
3955d92c0da7SBart Van Assche 			ch->target = target;
3956d92c0da7SBart Van Assche 			ch->comp_vector = cv_start == cv_end ? cv_start :
3957d92c0da7SBart Van Assche 				cv_start + cpu_idx % (cv_end - cv_start);
3958d92c0da7SBart Van Assche 			spin_lock_init(&ch->lock);
3959d92c0da7SBart Van Assche 			INIT_LIST_HEAD(&ch->free_tx);
3960d92c0da7SBart Van Assche 			ret = srp_new_cm_id(ch);
3961d92c0da7SBart Van Assche 			if (ret)
3962d92c0da7SBart Van Assche 				goto err_disconnect;
3963aef9ec39SRoland Dreier 
3964509c07bcSBart Van Assche 			ret = srp_create_ch_ib(ch);
3965aef9ec39SRoland Dreier 			if (ret)
3966d92c0da7SBart Van Assche 				goto err_disconnect;
3967aef9ec39SRoland Dreier 
3968d92c0da7SBart Van Assche 			ret = srp_alloc_req_data(ch);
39699fe4bcf4SDavid Dillow 			if (ret)
3970d92c0da7SBart Van Assche 				goto err_disconnect;
3971aef9ec39SRoland Dreier 
3972513d5647SBart Van Assche 			ret = srp_connect_ch(ch, max_iu_len, multich);
3973aef9ec39SRoland Dreier 			if (ret) {
397419f31343SBart Van Assche 				char dst[64];
397519f31343SBart Van Assche 
397619f31343SBart Van Assche 				if (target->using_rdma_cm)
39777da09af9SBart Van Assche 					snprintf(dst, sizeof(dst), "%pIS",
39787da09af9SBart Van Assche 						 &target->rdma_cm.dst);
397919f31343SBart Van Assche 				else
398019f31343SBart Van Assche 					snprintf(dst, sizeof(dst), "%pI6",
398119f31343SBart Van Assche 						 target->ib_cm.orig_dgid.raw);
39827aa54bd7SDavid Dillow 				shost_printk(KERN_ERR, target->scsi_host,
398319f31343SBart Van Assche 					     PFX "Connection %d/%d to %s failed\n",
3984d92c0da7SBart Van Assche 					     ch_start + cpu_idx,
398519f31343SBart Van Assche 					     target->ch_count, dst);
3986d92c0da7SBart Van Assche 				if (node_idx == 0 && cpu_idx == 0) {
3987b02c1536SBart Van Assche 					goto free_ch;
3988d92c0da7SBart Van Assche 				} else {
3989d92c0da7SBart Van Assche 					srp_free_ch_ib(target, ch);
3990d92c0da7SBart Van Assche 					srp_free_req_data(target, ch);
3991d92c0da7SBart Van Assche 					target->ch_count = ch - target->ch;
3992c257ea6fSBart Van Assche 					goto connected;
3993aef9ec39SRoland Dreier 				}
3994d92c0da7SBart Van Assche 			}
3995d92c0da7SBart Van Assche 
3996d92c0da7SBart Van Assche 			multich = true;
3997d92c0da7SBart Van Assche 			cpu_idx++;
3998d92c0da7SBart Van Assche 		}
3999d92c0da7SBart Van Assche 		node_idx++;
4000d92c0da7SBart Van Assche 	}
4001d92c0da7SBart Van Assche 
4002c257ea6fSBart Van Assche connected:
4003d92c0da7SBart Van Assche 	target->scsi_host->nr_hw_queues = target->ch_count;
4004aef9ec39SRoland Dreier 
4005aef9ec39SRoland Dreier 	ret = srp_add_target(host, target);
4006aef9ec39SRoland Dreier 	if (ret)
4007aef9ec39SRoland Dreier 		goto err_disconnect;
4008aef9ec39SRoland Dreier 
400934aa654eSBart Van Assche 	if (target->state != SRP_TARGET_REMOVED) {
401019f31343SBart Van Assche 		if (target->using_rdma_cm) {
401119f31343SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
40127da09af9SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx sgid %pI6 dest %pIS\n",
401319f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
401419f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
40157da09af9SBart Van Assche 				     target->sgid.raw, &target->rdma_cm.dst);
401619f31343SBart Van Assche 		} else {
4017e7ffde01SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
4018e7ffde01SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
4019e7ffde01SBart Van Assche 				     be64_to_cpu(target->id_ext),
4020e7ffde01SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
402119f31343SBart Van Assche 				     be16_to_cpu(target->ib_cm.pkey),
402219f31343SBart Van Assche 				     be64_to_cpu(target->ib_cm.service_id),
402319f31343SBart Van Assche 				     target->sgid.raw,
402419f31343SBart Van Assche 				     target->ib_cm.orig_dgid.raw);
402519f31343SBart Van Assche 		}
402634aa654eSBart Van Assche 	}
4027e7ffde01SBart Van Assche 
40282d7091bcSBart Van Assche 	ret = count;
40292d7091bcSBart Van Assche 
40302d7091bcSBart Van Assche out:
40312d7091bcSBart Van Assche 	mutex_unlock(&host->add_target_mutex);
403234aa654eSBart Van Assche 
40334fa354c9SBart Van Assche put:
403434aa654eSBart Van Assche 	scsi_host_put(target->scsi_host);
403519f31343SBart Van Assche 	if (ret < 0) {
403619f31343SBart Van Assche 		/*
403719f31343SBart Van Assche 		 * If a call to srp_remove_target() has not been scheduled,
403819f31343SBart Van Assche 		 * drop the network namespace reference now that was obtained
403919f31343SBart Van Assche 		 * earlier in this function.
404019f31343SBart Van Assche 		 */
404119f31343SBart Van Assche 		if (target->state != SRP_TARGET_REMOVED)
404219f31343SBart Van Assche 			kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
4043bc44bd1dSBart Van Assche 		scsi_host_put(target->scsi_host);
404419f31343SBart Van Assche 	}
404534aa654eSBart Van Assche 
40462d7091bcSBart Van Assche 	return ret;
4047aef9ec39SRoland Dreier 
4048aef9ec39SRoland Dreier err_disconnect:
4049aef9ec39SRoland Dreier 	srp_disconnect_target(target);
4050aef9ec39SRoland Dreier 
4051b02c1536SBart Van Assche free_ch:
4052d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
4053d92c0da7SBart Van Assche 		ch = &target->ch[i];
4054509c07bcSBart Van Assche 		srp_free_ch_ib(target, ch);
4055509c07bcSBart Van Assche 		srp_free_req_data(target, ch);
4056d92c0da7SBart Van Assche 	}
4057d92c0da7SBart Van Assche 
4058d92c0da7SBart Van Assche 	kfree(target->ch);
40592d7091bcSBart Van Assche 	goto out;
4060aef9ec39SRoland Dreier }
4061aef9ec39SRoland Dreier 
4062ee959b00STony Jones static DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
4063aef9ec39SRoland Dreier 
4064ee959b00STony Jones static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
4065ee959b00STony Jones 			  char *buf)
4066aef9ec39SRoland Dreier {
4067ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
4068aef9ec39SRoland Dreier 
40696c854111SJason Gunthorpe 	return sprintf(buf, "%s\n", dev_name(&host->srp_dev->dev->dev));
4070aef9ec39SRoland Dreier }
4071aef9ec39SRoland Dreier 
4072ee959b00STony Jones static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
4073aef9ec39SRoland Dreier 
4074ee959b00STony Jones static ssize_t show_port(struct device *dev, struct device_attribute *attr,
4075ee959b00STony Jones 			 char *buf)
4076aef9ec39SRoland Dreier {
4077ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
4078aef9ec39SRoland Dreier 
4079aef9ec39SRoland Dreier 	return sprintf(buf, "%d\n", host->port);
4080aef9ec39SRoland Dreier }
4081aef9ec39SRoland Dreier 
4082ee959b00STony Jones static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
4083aef9ec39SRoland Dreier 
4084f5358a17SRoland Dreier static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
4085aef9ec39SRoland Dreier {
4086aef9ec39SRoland Dreier 	struct srp_host *host;
4087aef9ec39SRoland Dreier 
4088aef9ec39SRoland Dreier 	host = kzalloc(sizeof *host, GFP_KERNEL);
4089aef9ec39SRoland Dreier 	if (!host)
4090aef9ec39SRoland Dreier 		return NULL;
4091aef9ec39SRoland Dreier 
4092aef9ec39SRoland Dreier 	INIT_LIST_HEAD(&host->target_list);
4093b3589fd4SMatthew Wilcox 	spin_lock_init(&host->target_lock);
4094aef9ec39SRoland Dreier 	init_completion(&host->released);
40952d7091bcSBart Van Assche 	mutex_init(&host->add_target_mutex);
409605321937SGreg Kroah-Hartman 	host->srp_dev = device;
4097aef9ec39SRoland Dreier 	host->port = port;
4098aef9ec39SRoland Dreier 
4099ee959b00STony Jones 	host->dev.class = &srp_class;
4100dee2b82aSBart Van Assche 	host->dev.parent = device->dev->dev.parent;
41016c854111SJason Gunthorpe 	dev_set_name(&host->dev, "srp-%s-%d", dev_name(&device->dev->dev),
41026c854111SJason Gunthorpe 		     port);
4103aef9ec39SRoland Dreier 
4104ee959b00STony Jones 	if (device_register(&host->dev))
4105f5358a17SRoland Dreier 		goto free_host;
4106ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_add_target))
4107aef9ec39SRoland Dreier 		goto err_class;
4108ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_ibdev))
4109aef9ec39SRoland Dreier 		goto err_class;
4110ee959b00STony Jones 	if (device_create_file(&host->dev, &dev_attr_port))
4111aef9ec39SRoland Dreier 		goto err_class;
4112aef9ec39SRoland Dreier 
4113aef9ec39SRoland Dreier 	return host;
4114aef9ec39SRoland Dreier 
4115aef9ec39SRoland Dreier err_class:
4116ee959b00STony Jones 	device_unregister(&host->dev);
4117aef9ec39SRoland Dreier 
4118f5358a17SRoland Dreier free_host:
4119aef9ec39SRoland Dreier 	kfree(host);
4120aef9ec39SRoland Dreier 
4121aef9ec39SRoland Dreier 	return NULL;
4122aef9ec39SRoland Dreier }
4123aef9ec39SRoland Dreier 
4124aef9ec39SRoland Dreier static void srp_add_one(struct ib_device *device)
4125aef9ec39SRoland Dreier {
4126f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4127042dd765SBart Van Assche 	struct ib_device_attr *attr = &device->attrs;
4128aef9ec39SRoland Dreier 	struct srp_host *host;
4129ea1075edSJason Gunthorpe 	int mr_page_shift;
4130ea1075edSJason Gunthorpe 	unsigned int p;
413152ede08fSBart Van Assche 	u64 max_pages_per_mr;
41325f071777SChristoph Hellwig 	unsigned int flags = 0;
4133aef9ec39SRoland Dreier 
4134249f0656SBart Van Assche 	srp_dev = kzalloc(sizeof(*srp_dev), GFP_KERNEL);
4135f5358a17SRoland Dreier 	if (!srp_dev)
41364a061b28SOr Gerlitz 		return;
4137f5358a17SRoland Dreier 
4138f5358a17SRoland Dreier 	/*
4139f5358a17SRoland Dreier 	 * Use the smallest page size supported by the HCA, down to a
41408f26c9ffSDavid Dillow 	 * minimum of 4096 bytes. We're unlikely to build large sglists
41418f26c9ffSDavid Dillow 	 * out of smaller entries.
4142f5358a17SRoland Dreier 	 */
4143042dd765SBart Van Assche 	mr_page_shift		= max(12, ffs(attr->page_size_cap) - 1);
414452ede08fSBart Van Assche 	srp_dev->mr_page_size	= 1 << mr_page_shift;
414552ede08fSBart Van Assche 	srp_dev->mr_page_mask	= ~((u64) srp_dev->mr_page_size - 1);
4146042dd765SBart Van Assche 	max_pages_per_mr	= attr->max_mr_size;
414752ede08fSBart Van Assche 	do_div(max_pages_per_mr, srp_dev->mr_page_size);
4148509c5f33SBart Van Assche 	pr_debug("%s: %llu / %u = %llu <> %u\n", __func__,
4149042dd765SBart Van Assche 		 attr->max_mr_size, srp_dev->mr_page_size,
4150509c5f33SBart Van Assche 		 max_pages_per_mr, SRP_MAX_PAGES_PER_MR);
415152ede08fSBart Van Assche 	srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR,
415252ede08fSBart Van Assche 					  max_pages_per_mr);
4153835ee624SBart Van Assche 
41543023a1e9SKamal Heib 	srp_dev->has_fmr = (device->ops.alloc_fmr &&
41553023a1e9SKamal Heib 			    device->ops.dealloc_fmr &&
41563023a1e9SKamal Heib 			    device->ops.map_phys_fmr &&
41573023a1e9SKamal Heib 			    device->ops.unmap_fmr);
4158042dd765SBart Van Assche 	srp_dev->has_fr = (attr->device_cap_flags &
4159835ee624SBart Van Assche 			   IB_DEVICE_MEM_MGT_EXTENSIONS);
4160c222a39fSBart Van Assche 	if (!never_register && !srp_dev->has_fmr && !srp_dev->has_fr) {
4161835ee624SBart Van Assche 		dev_warn(&device->dev, "neither FMR nor FR is supported\n");
4162c222a39fSBart Van Assche 	} else if (!never_register &&
4163042dd765SBart Van Assche 		   attr->max_mr_size >= 2 * srp_dev->mr_page_size) {
4164835ee624SBart Van Assche 		srp_dev->use_fast_reg = (srp_dev->has_fr &&
4165835ee624SBart Van Assche 					 (!srp_dev->has_fmr || prefer_fr));
4166835ee624SBart Van Assche 		srp_dev->use_fmr = !srp_dev->use_fast_reg && srp_dev->has_fmr;
4167509c5f33SBart Van Assche 	}
4168835ee624SBart Van Assche 
41695f071777SChristoph Hellwig 	if (never_register || !register_always ||
41705f071777SChristoph Hellwig 	    (!srp_dev->has_fmr && !srp_dev->has_fr))
41715f071777SChristoph Hellwig 		flags |= IB_PD_UNSAFE_GLOBAL_RKEY;
41725f071777SChristoph Hellwig 
41735cfb1782SBart Van Assche 	if (srp_dev->use_fast_reg) {
41745cfb1782SBart Van Assche 		srp_dev->max_pages_per_mr =
41755cfb1782SBart Van Assche 			min_t(u32, srp_dev->max_pages_per_mr,
4176042dd765SBart Van Assche 			      attr->max_fast_reg_page_list_len);
41775cfb1782SBart Van Assche 	}
417852ede08fSBart Van Assche 	srp_dev->mr_max_size	= srp_dev->mr_page_size *
417952ede08fSBart Van Assche 				   srp_dev->max_pages_per_mr;
41804a061b28SOr 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",
41816c854111SJason Gunthorpe 		 dev_name(&device->dev), mr_page_shift, attr->max_mr_size,
4182042dd765SBart Van Assche 		 attr->max_fast_reg_page_list_len,
418352ede08fSBart Van Assche 		 srp_dev->max_pages_per_mr, srp_dev->mr_max_size);
4184f5358a17SRoland Dreier 
4185f5358a17SRoland Dreier 	INIT_LIST_HEAD(&srp_dev->dev_list);
4186f5358a17SRoland Dreier 
4187f5358a17SRoland Dreier 	srp_dev->dev = device;
41885f071777SChristoph Hellwig 	srp_dev->pd  = ib_alloc_pd(device, flags);
4189f5358a17SRoland Dreier 	if (IS_ERR(srp_dev->pd))
4190f5358a17SRoland Dreier 		goto free_dev;
4191f5358a17SRoland Dreier 
4192cee687b6SBart Van Assche 	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
4193cee687b6SBart Van Assche 		srp_dev->global_rkey = srp_dev->pd->unsafe_global_rkey;
4194cee687b6SBart Van Assche 		WARN_ON_ONCE(srp_dev->global_rkey == 0);
4195cee687b6SBart Van Assche 	}
4196f5358a17SRoland Dreier 
4197ea1075edSJason Gunthorpe 	rdma_for_each_port (device, p) {
4198f5358a17SRoland Dreier 		host = srp_add_port(srp_dev, p);
4199aef9ec39SRoland Dreier 		if (host)
4200f5358a17SRoland Dreier 			list_add_tail(&host->list, &srp_dev->dev_list);
4201aef9ec39SRoland Dreier 	}
4202aef9ec39SRoland Dreier 
4203f5358a17SRoland Dreier 	ib_set_client_data(device, &srp_client, srp_dev);
42044a061b28SOr Gerlitz 	return;
4205f5358a17SRoland Dreier 
4206f5358a17SRoland Dreier free_dev:
4207f5358a17SRoland Dreier 	kfree(srp_dev);
4208aef9ec39SRoland Dreier }
4209aef9ec39SRoland Dreier 
42107c1eb45aSHaggai Eran static void srp_remove_one(struct ib_device *device, void *client_data)
4211aef9ec39SRoland Dreier {
4212f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4213aef9ec39SRoland Dreier 	struct srp_host *host, *tmp_host;
4214ef6c49d8SBart Van Assche 	struct srp_target_port *target;
4215aef9ec39SRoland Dreier 
42167c1eb45aSHaggai Eran 	srp_dev = client_data;
42171fe0cb84SDotan Barak 	if (!srp_dev)
42181fe0cb84SDotan Barak 		return;
4219aef9ec39SRoland Dreier 
4220f5358a17SRoland Dreier 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
4221ee959b00STony Jones 		device_unregister(&host->dev);
4222aef9ec39SRoland Dreier 		/*
4223aef9ec39SRoland Dreier 		 * Wait for the sysfs entry to go away, so that no new
4224aef9ec39SRoland Dreier 		 * target ports can be created.
4225aef9ec39SRoland Dreier 		 */
4226aef9ec39SRoland Dreier 		wait_for_completion(&host->released);
4227aef9ec39SRoland Dreier 
4228aef9ec39SRoland Dreier 		/*
4229ef6c49d8SBart Van Assche 		 * Remove all target ports.
4230aef9ec39SRoland Dreier 		 */
4231b3589fd4SMatthew Wilcox 		spin_lock(&host->target_lock);
4232ef6c49d8SBart Van Assche 		list_for_each_entry(target, &host->target_list, list)
4233ef6c49d8SBart Van Assche 			srp_queue_remove_work(target);
4234b3589fd4SMatthew Wilcox 		spin_unlock(&host->target_lock);
4235aef9ec39SRoland Dreier 
4236aef9ec39SRoland Dreier 		/*
4237bcc05910SBart Van Assche 		 * Wait for tl_err and target port removal tasks.
4238aef9ec39SRoland Dreier 		 */
4239ef6c49d8SBart Van Assche 		flush_workqueue(system_long_wq);
4240bcc05910SBart Van Assche 		flush_workqueue(srp_remove_wq);
4241aef9ec39SRoland Dreier 
4242aef9ec39SRoland Dreier 		kfree(host);
4243aef9ec39SRoland Dreier 	}
4244aef9ec39SRoland Dreier 
4245f5358a17SRoland Dreier 	ib_dealloc_pd(srp_dev->pd);
4246f5358a17SRoland Dreier 
4247f5358a17SRoland Dreier 	kfree(srp_dev);
4248aef9ec39SRoland Dreier }
4249aef9ec39SRoland Dreier 
42503236822bSFUJITA Tomonori static struct srp_function_template ib_srp_transport_functions = {
4251ed9b2264SBart Van Assche 	.has_rport_state	 = true,
4252ed9b2264SBart Van Assche 	.reset_timer_if_blocked	 = true,
4253a95cadb9SBart Van Assche 	.reconnect_delay	 = &srp_reconnect_delay,
4254ed9b2264SBart Van Assche 	.fast_io_fail_tmo	 = &srp_fast_io_fail_tmo,
4255ed9b2264SBart Van Assche 	.dev_loss_tmo		 = &srp_dev_loss_tmo,
4256ed9b2264SBart Van Assche 	.reconnect		 = srp_rport_reconnect,
4257dc1bdbd9SBart Van Assche 	.rport_delete		 = srp_rport_delete,
4258ed9b2264SBart Van Assche 	.terminate_rport_io	 = srp_terminate_io,
42593236822bSFUJITA Tomonori };
42603236822bSFUJITA Tomonori 
4261aef9ec39SRoland Dreier static int __init srp_init_module(void)
4262aef9ec39SRoland Dreier {
4263aef9ec39SRoland Dreier 	int ret;
4264aef9ec39SRoland Dreier 
426516d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_imm_buf) != 4);
426616d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req) != 64);
426716d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req_rdma) != 56);
426816d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_cmd) != 48);
426916d14e01SBart Van Assche 
427049248644SDavid Dillow 	if (srp_sg_tablesize) {
4271e0bda7d8SBart Van Assche 		pr_warn("srp_sg_tablesize is deprecated, please use cmd_sg_entries\n");
427249248644SDavid Dillow 		if (!cmd_sg_entries)
427349248644SDavid Dillow 			cmd_sg_entries = srp_sg_tablesize;
427449248644SDavid Dillow 	}
427549248644SDavid Dillow 
427649248644SDavid Dillow 	if (!cmd_sg_entries)
427749248644SDavid Dillow 		cmd_sg_entries = SRP_DEF_SG_TABLESIZE;
427849248644SDavid Dillow 
427949248644SDavid Dillow 	if (cmd_sg_entries > 255) {
4280e0bda7d8SBart Van Assche 		pr_warn("Clamping cmd_sg_entries to 255\n");
428149248644SDavid Dillow 		cmd_sg_entries = 255;
42821e89a194SDavid Dillow 	}
42831e89a194SDavid Dillow 
4284c07d424dSDavid Dillow 	if (!indirect_sg_entries)
4285c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4286c07d424dSDavid Dillow 	else if (indirect_sg_entries < cmd_sg_entries) {
4287e0bda7d8SBart Van Assche 		pr_warn("Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n",
4288e0bda7d8SBart Van Assche 			cmd_sg_entries);
4289c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4290c07d424dSDavid Dillow 	}
4291c07d424dSDavid Dillow 
42920a475ef4SIsrael Rukshin 	if (indirect_sg_entries > SG_MAX_SEGMENTS) {
42930a475ef4SIsrael Rukshin 		pr_warn("Clamping indirect_sg_entries to %u\n",
42940a475ef4SIsrael Rukshin 			SG_MAX_SEGMENTS);
42950a475ef4SIsrael Rukshin 		indirect_sg_entries = SG_MAX_SEGMENTS;
42960a475ef4SIsrael Rukshin 	}
42970a475ef4SIsrael Rukshin 
4298bcc05910SBart Van Assche 	srp_remove_wq = create_workqueue("srp_remove");
4299da05be29SWei Yongjun 	if (!srp_remove_wq) {
4300da05be29SWei Yongjun 		ret = -ENOMEM;
4301bcc05910SBart Van Assche 		goto out;
4302bcc05910SBart Van Assche 	}
4303bcc05910SBart Van Assche 
4304bcc05910SBart Van Assche 	ret = -ENOMEM;
43053236822bSFUJITA Tomonori 	ib_srp_transport_template =
43063236822bSFUJITA Tomonori 		srp_attach_transport(&ib_srp_transport_functions);
43073236822bSFUJITA Tomonori 	if (!ib_srp_transport_template)
4308bcc05910SBart Van Assche 		goto destroy_wq;
43093236822bSFUJITA Tomonori 
4310aef9ec39SRoland Dreier 	ret = class_register(&srp_class);
4311aef9ec39SRoland Dreier 	if (ret) {
4312e0bda7d8SBart Van Assche 		pr_err("couldn't register class infiniband_srp\n");
4313bcc05910SBart Van Assche 		goto release_tr;
4314aef9ec39SRoland Dreier 	}
4315aef9ec39SRoland Dreier 
4316c1a0b23bSMichael S. Tsirkin 	ib_sa_register_client(&srp_sa_client);
4317c1a0b23bSMichael S. Tsirkin 
4318aef9ec39SRoland Dreier 	ret = ib_register_client(&srp_client);
4319aef9ec39SRoland Dreier 	if (ret) {
4320e0bda7d8SBart Van Assche 		pr_err("couldn't register IB client\n");
4321bcc05910SBart Van Assche 		goto unreg_sa;
4322aef9ec39SRoland Dreier 	}
4323aef9ec39SRoland Dreier 
4324bcc05910SBart Van Assche out:
4325bcc05910SBart Van Assche 	return ret;
4326bcc05910SBart Van Assche 
4327bcc05910SBart Van Assche unreg_sa:
4328bcc05910SBart Van Assche 	ib_sa_unregister_client(&srp_sa_client);
4329bcc05910SBart Van Assche 	class_unregister(&srp_class);
4330bcc05910SBart Van Assche 
4331bcc05910SBart Van Assche release_tr:
4332bcc05910SBart Van Assche 	srp_release_transport(ib_srp_transport_template);
4333bcc05910SBart Van Assche 
4334bcc05910SBart Van Assche destroy_wq:
4335bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4336bcc05910SBart Van Assche 	goto out;
4337aef9ec39SRoland Dreier }
4338aef9ec39SRoland Dreier 
4339aef9ec39SRoland Dreier static void __exit srp_cleanup_module(void)
4340aef9ec39SRoland Dreier {
4341aef9ec39SRoland Dreier 	ib_unregister_client(&srp_client);
4342c1a0b23bSMichael S. Tsirkin 	ib_sa_unregister_client(&srp_sa_client);
4343aef9ec39SRoland Dreier 	class_unregister(&srp_class);
43443236822bSFUJITA Tomonori 	srp_release_transport(ib_srp_transport_template);
4345bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4346aef9ec39SRoland Dreier }
4347aef9ec39SRoland Dreier 
4348aef9ec39SRoland Dreier module_init(srp_init_module);
4349aef9ec39SRoland Dreier module_exit(srp_cleanup_module);
4350