xref: /linux/drivers/infiniband/ulp/srp/ib_srp.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
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 
6549248644SDavid Dillow static unsigned int srp_sg_tablesize;
6649248644SDavid Dillow static unsigned int cmd_sg_entries;
67c07d424dSDavid Dillow static unsigned int indirect_sg_entries;
68c07d424dSDavid Dillow static bool allow_ext_sg;
6903f6fb93SBart Van Assche static bool register_always = true;
70c222a39fSBart Van Assche static bool never_register;
71aef9ec39SRoland Dreier static int topspin_workarounds = 1;
72aef9ec39SRoland Dreier 
7349248644SDavid Dillow module_param(srp_sg_tablesize, uint, 0444);
7449248644SDavid Dillow MODULE_PARM_DESC(srp_sg_tablesize, "Deprecated name for cmd_sg_entries");
7549248644SDavid Dillow 
7649248644SDavid Dillow module_param(cmd_sg_entries, uint, 0444);
7749248644SDavid Dillow MODULE_PARM_DESC(cmd_sg_entries,
7849248644SDavid Dillow 		 "Default number of gather/scatter entries in the SRP command (default is 12, max 255)");
7949248644SDavid Dillow 
80c07d424dSDavid Dillow module_param(indirect_sg_entries, uint, 0444);
81c07d424dSDavid Dillow MODULE_PARM_DESC(indirect_sg_entries,
8265e8617fSMing Lin 		 "Default max number of gather/scatter entries (default is 12, max is " __stringify(SG_MAX_SEGMENTS) ")");
83c07d424dSDavid Dillow 
84c07d424dSDavid Dillow module_param(allow_ext_sg, bool, 0444);
85c07d424dSDavid Dillow MODULE_PARM_DESC(allow_ext_sg,
86c07d424dSDavid Dillow 		  "Default behavior when there are more than cmd_sg_entries S/G entries after mapping; fails the request when false (default false)");
87c07d424dSDavid Dillow 
88aef9ec39SRoland Dreier module_param(topspin_workarounds, int, 0444);
89aef9ec39SRoland Dreier MODULE_PARM_DESC(topspin_workarounds,
90aef9ec39SRoland Dreier 		 "Enable workarounds for Topspin/Cisco SRP target bugs if != 0");
91aef9ec39SRoland Dreier 
92b1b8854dSBart Van Assche module_param(register_always, bool, 0444);
93b1b8854dSBart Van Assche MODULE_PARM_DESC(register_always,
94b1b8854dSBart Van Assche 		 "Use memory registration even for contiguous memory regions");
95b1b8854dSBart Van Assche 
96c222a39fSBart Van Assche module_param(never_register, bool, 0444);
97c222a39fSBart Van Assche MODULE_PARM_DESC(never_register, "Never register memory");
98c222a39fSBart Van Assche 
999c27847dSLuis R. Rodriguez static const struct kernel_param_ops srp_tmo_ops;
100ed9b2264SBart Van Assche 
101a95cadb9SBart Van Assche static int srp_reconnect_delay = 10;
102a95cadb9SBart Van Assche module_param_cb(reconnect_delay, &srp_tmo_ops, &srp_reconnect_delay,
103a95cadb9SBart Van Assche 		S_IRUGO | S_IWUSR);
104a95cadb9SBart Van Assche MODULE_PARM_DESC(reconnect_delay, "Time between successive reconnect attempts");
105a95cadb9SBart Van Assche 
106ed9b2264SBart Van Assche static int srp_fast_io_fail_tmo = 15;
107ed9b2264SBart Van Assche module_param_cb(fast_io_fail_tmo, &srp_tmo_ops, &srp_fast_io_fail_tmo,
108ed9b2264SBart Van Assche 		S_IRUGO | S_IWUSR);
109ed9b2264SBart Van Assche MODULE_PARM_DESC(fast_io_fail_tmo,
110ed9b2264SBart Van Assche 		 "Number of seconds between the observation of a transport"
111ed9b2264SBart Van Assche 		 " layer error and failing all I/O. \"off\" means that this"
112ed9b2264SBart Van Assche 		 " functionality is disabled.");
113ed9b2264SBart Van Assche 
114a95cadb9SBart Van Assche static int srp_dev_loss_tmo = 600;
115ed9b2264SBart Van Assche module_param_cb(dev_loss_tmo, &srp_tmo_ops, &srp_dev_loss_tmo,
116ed9b2264SBart Van Assche 		S_IRUGO | S_IWUSR);
117ed9b2264SBart Van Assche MODULE_PARM_DESC(dev_loss_tmo,
118ed9b2264SBart Van Assche 		 "Maximum number of seconds that the SRP transport should"
119ed9b2264SBart Van Assche 		 " insulate transport layer errors. After this time has been"
120ed9b2264SBart Van Assche 		 " exceeded the SCSI host is removed. Should be"
121ed9b2264SBart Van Assche 		 " between 1 and " __stringify(SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
122ed9b2264SBart Van Assche 		 " if fast_io_fail_tmo has not been set. \"off\" means that"
123ed9b2264SBart Van Assche 		 " this functionality is disabled.");
124ed9b2264SBart Van Assche 
125882981f4SBart Van Assche static bool srp_use_imm_data = true;
126882981f4SBart Van Assche module_param_named(use_imm_data, srp_use_imm_data, bool, 0644);
127882981f4SBart Van Assche MODULE_PARM_DESC(use_imm_data,
128882981f4SBart Van Assche 		 "Whether or not to request permission to use immediate data during SRP login.");
129882981f4SBart Van Assche 
130882981f4SBart Van Assche static unsigned int srp_max_imm_data = 8 * 1024;
131882981f4SBart Van Assche module_param_named(max_imm_data, srp_max_imm_data, uint, 0644);
132882981f4SBart Van Assche MODULE_PARM_DESC(max_imm_data, "Maximum immediate data size.");
133882981f4SBart Van Assche 
134d92c0da7SBart Van Assche static unsigned ch_count;
135d92c0da7SBart Van Assche module_param(ch_count, uint, 0444);
136d92c0da7SBart Van Assche MODULE_PARM_DESC(ch_count,
137d92c0da7SBart 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.");
138d92c0da7SBart Van Assche 
13911a0ae4cSJason Gunthorpe static int srp_add_one(struct ib_device *device);
1407c1eb45aSHaggai Eran static void srp_remove_one(struct ib_device *device, void *client_data);
141dc1435c0SLeon Romanovsky static void srp_rename_dev(struct ib_device *device, void *client_data);
1421dc7b1f1SChristoph Hellwig static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc);
1431dc7b1f1SChristoph Hellwig static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
1441dc7b1f1SChristoph Hellwig 		const char *opname);
145e7ff98aeSParav Pandit static int srp_ib_cm_handler(struct ib_cm_id *cm_id,
146e7ff98aeSParav Pandit 			     const struct ib_cm_event *event);
14719f31343SBart Van Assche static int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
14819f31343SBart Van Assche 			       struct rdma_cm_event *event);
149aef9ec39SRoland Dreier 
1503236822bSFUJITA Tomonori static struct scsi_transport_template *ib_srp_transport_template;
151bcc05910SBart Van Assche static struct workqueue_struct *srp_remove_wq;
1523236822bSFUJITA Tomonori 
153aef9ec39SRoland Dreier static struct ib_client srp_client = {
154aef9ec39SRoland Dreier 	.name   = "srp",
155aef9ec39SRoland Dreier 	.add    = srp_add_one,
156dc1435c0SLeon Romanovsky 	.remove = srp_remove_one,
157dc1435c0SLeon Romanovsky 	.rename = srp_rename_dev
158aef9ec39SRoland Dreier };
159aef9ec39SRoland Dreier 
160c1a0b23bSMichael S. Tsirkin static struct ib_sa_client srp_sa_client;
161c1a0b23bSMichael S. Tsirkin 
srp_tmo_get(char * buffer,const struct kernel_param * kp)162ed9b2264SBart Van Assche static int srp_tmo_get(char *buffer, const struct kernel_param *kp)
163ed9b2264SBart Van Assche {
164ed9b2264SBart Van Assche 	int tmo = *(int *)kp->arg;
165ed9b2264SBart Van Assche 
166ed9b2264SBart Van Assche 	if (tmo >= 0)
167e28bf1f0SJoe Perches 		return sysfs_emit(buffer, "%d\n", tmo);
168ed9b2264SBart Van Assche 	else
169e28bf1f0SJoe Perches 		return sysfs_emit(buffer, "off\n");
170ed9b2264SBart Van Assche }
171ed9b2264SBart Van Assche 
srp_tmo_set(const char * val,const struct kernel_param * kp)172ed9b2264SBart Van Assche static int srp_tmo_set(const char *val, const struct kernel_param *kp)
173ed9b2264SBart Van Assche {
174ed9b2264SBart Van Assche 	int tmo, res;
175ed9b2264SBart Van Assche 
1763fdf70acSSagi Grimberg 	res = srp_parse_tmo(&tmo, val);
177ed9b2264SBart Van Assche 	if (res)
178ed9b2264SBart Van Assche 		goto out;
1793fdf70acSSagi Grimberg 
180a95cadb9SBart Van Assche 	if (kp->arg == &srp_reconnect_delay)
181a95cadb9SBart Van Assche 		res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo,
182a95cadb9SBart Van Assche 				    srp_dev_loss_tmo);
183a95cadb9SBart Van Assche 	else if (kp->arg == &srp_fast_io_fail_tmo)
184a95cadb9SBart Van Assche 		res = srp_tmo_valid(srp_reconnect_delay, tmo, srp_dev_loss_tmo);
185ed9b2264SBart Van Assche 	else
186a95cadb9SBart Van Assche 		res = srp_tmo_valid(srp_reconnect_delay, srp_fast_io_fail_tmo,
187a95cadb9SBart Van Assche 				    tmo);
188ed9b2264SBart Van Assche 	if (res)
189ed9b2264SBart Van Assche 		goto out;
190ed9b2264SBart Van Assche 	*(int *)kp->arg = tmo;
191ed9b2264SBart Van Assche 
192ed9b2264SBart Van Assche out:
193ed9b2264SBart Van Assche 	return res;
194ed9b2264SBart Van Assche }
195ed9b2264SBart Van Assche 
1969c27847dSLuis R. Rodriguez static const struct kernel_param_ops srp_tmo_ops = {
197ed9b2264SBart Van Assche 	.get = srp_tmo_get,
198ed9b2264SBart Van Assche 	.set = srp_tmo_set,
199ed9b2264SBart Van Assche };
200ed9b2264SBart Van Assche 
host_to_target(struct Scsi_Host * host)201aef9ec39SRoland Dreier static inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
202aef9ec39SRoland Dreier {
203aef9ec39SRoland Dreier 	return (struct srp_target_port *) host->hostdata;
204aef9ec39SRoland Dreier }
205aef9ec39SRoland Dreier 
srp_target_info(struct Scsi_Host * host)206aef9ec39SRoland Dreier static const char *srp_target_info(struct Scsi_Host *host)
207aef9ec39SRoland Dreier {
208aef9ec39SRoland Dreier 	return host_to_target(host)->target_name;
209aef9ec39SRoland Dreier }
210aef9ec39SRoland Dreier 
srp_target_is_topspin(struct srp_target_port * target)2115d7cbfd6SRoland Dreier static int srp_target_is_topspin(struct srp_target_port *target)
2125d7cbfd6SRoland Dreier {
2135d7cbfd6SRoland Dreier 	static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
2143d1ff48dSRaghava Kondapalli 	static const u8 cisco_oui[3]   = { 0x00, 0x1b, 0x0d };
2155d7cbfd6SRoland Dreier 
2165d7cbfd6SRoland Dreier 	return topspin_workarounds &&
2173d1ff48dSRaghava Kondapalli 		(!memcmp(&target->ioc_guid, topspin_oui, sizeof topspin_oui) ||
2183d1ff48dSRaghava Kondapalli 		 !memcmp(&target->ioc_guid, cisco_oui, sizeof cisco_oui));
2195d7cbfd6SRoland Dreier }
2205d7cbfd6SRoland Dreier 
srp_alloc_iu(struct srp_host * host,size_t size,gfp_t gfp_mask,enum dma_data_direction direction)221aef9ec39SRoland Dreier static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
222aef9ec39SRoland Dreier 				   gfp_t gfp_mask,
223aef9ec39SRoland Dreier 				   enum dma_data_direction direction)
224aef9ec39SRoland Dreier {
225aef9ec39SRoland Dreier 	struct srp_iu *iu;
226aef9ec39SRoland Dreier 
227aef9ec39SRoland Dreier 	iu = kmalloc(sizeof *iu, gfp_mask);
228aef9ec39SRoland Dreier 	if (!iu)
229aef9ec39SRoland Dreier 		goto out;
230aef9ec39SRoland Dreier 
231aef9ec39SRoland Dreier 	iu->buf = kzalloc(size, gfp_mask);
232aef9ec39SRoland Dreier 	if (!iu->buf)
233aef9ec39SRoland Dreier 		goto out_free_iu;
234aef9ec39SRoland Dreier 
23505321937SGreg Kroah-Hartman 	iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size,
23605321937SGreg Kroah-Hartman 				    direction);
23705321937SGreg Kroah-Hartman 	if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma))
238aef9ec39SRoland Dreier 		goto out_free_buf;
239aef9ec39SRoland Dreier 
240aef9ec39SRoland Dreier 	iu->size      = size;
241aef9ec39SRoland Dreier 	iu->direction = direction;
242aef9ec39SRoland Dreier 
243aef9ec39SRoland Dreier 	return iu;
244aef9ec39SRoland Dreier 
245aef9ec39SRoland Dreier out_free_buf:
246aef9ec39SRoland Dreier 	kfree(iu->buf);
247aef9ec39SRoland Dreier out_free_iu:
248aef9ec39SRoland Dreier 	kfree(iu);
249aef9ec39SRoland Dreier out:
250aef9ec39SRoland Dreier 	return NULL;
251aef9ec39SRoland Dreier }
252aef9ec39SRoland Dreier 
srp_free_iu(struct srp_host * host,struct srp_iu * iu)253aef9ec39SRoland Dreier static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
254aef9ec39SRoland Dreier {
255aef9ec39SRoland Dreier 	if (!iu)
256aef9ec39SRoland Dreier 		return;
257aef9ec39SRoland Dreier 
25805321937SGreg Kroah-Hartman 	ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size,
25905321937SGreg Kroah-Hartman 			    iu->direction);
260aef9ec39SRoland Dreier 	kfree(iu->buf);
261aef9ec39SRoland Dreier 	kfree(iu);
262aef9ec39SRoland Dreier }
263aef9ec39SRoland Dreier 
srp_qp_event(struct ib_event * event,void * context)264aef9ec39SRoland Dreier static void srp_qp_event(struct ib_event *event, void *context)
265aef9ec39SRoland Dreier {
26657363d98SSagi Grimberg 	pr_debug("QP event %s (%d)\n",
26757363d98SSagi Grimberg 		 ib_event_msg(event->event), event->event);
268aef9ec39SRoland Dreier }
269aef9ec39SRoland Dreier 
srp_init_ib_qp(struct srp_target_port * target,struct ib_qp * qp)27019f31343SBart Van Assche static int srp_init_ib_qp(struct srp_target_port *target,
271aef9ec39SRoland Dreier 			  struct ib_qp *qp)
272aef9ec39SRoland Dreier {
273aef9ec39SRoland Dreier 	struct ib_qp_attr *attr;
274aef9ec39SRoland Dreier 	int ret;
275aef9ec39SRoland Dreier 
276aef9ec39SRoland Dreier 	attr = kmalloc(sizeof *attr, GFP_KERNEL);
277aef9ec39SRoland Dreier 	if (!attr)
278aef9ec39SRoland Dreier 		return -ENOMEM;
279aef9ec39SRoland Dreier 
28056b5390cSBart Van Assche 	ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev,
281aef9ec39SRoland Dreier 				  target->srp_host->port,
28219f31343SBart Van Assche 				  be16_to_cpu(target->ib_cm.pkey),
283aef9ec39SRoland Dreier 				  &attr->pkey_index);
284aef9ec39SRoland Dreier 	if (ret)
285aef9ec39SRoland Dreier 		goto out;
286aef9ec39SRoland Dreier 
287aef9ec39SRoland Dreier 	attr->qp_state        = IB_QPS_INIT;
288aef9ec39SRoland Dreier 	attr->qp_access_flags = (IB_ACCESS_REMOTE_READ |
289aef9ec39SRoland Dreier 				    IB_ACCESS_REMOTE_WRITE);
290aef9ec39SRoland Dreier 	attr->port_num        = target->srp_host->port;
291aef9ec39SRoland Dreier 
292aef9ec39SRoland Dreier 	ret = ib_modify_qp(qp, attr,
293aef9ec39SRoland Dreier 			   IB_QP_STATE		|
294aef9ec39SRoland Dreier 			   IB_QP_PKEY_INDEX	|
295aef9ec39SRoland Dreier 			   IB_QP_ACCESS_FLAGS	|
296aef9ec39SRoland Dreier 			   IB_QP_PORT);
297aef9ec39SRoland Dreier 
298aef9ec39SRoland Dreier out:
299aef9ec39SRoland Dreier 	kfree(attr);
300aef9ec39SRoland Dreier 	return ret;
301aef9ec39SRoland Dreier }
302aef9ec39SRoland Dreier 
srp_new_ib_cm_id(struct srp_rdma_ch * ch)30319f31343SBart Van Assche static int srp_new_ib_cm_id(struct srp_rdma_ch *ch)
3049fe4bcf4SDavid Dillow {
305509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
3069fe4bcf4SDavid Dillow 	struct ib_cm_id *new_cm_id;
3079fe4bcf4SDavid Dillow 
30805321937SGreg Kroah-Hartman 	new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
30919f31343SBart Van Assche 				    srp_ib_cm_handler, ch);
3109fe4bcf4SDavid Dillow 	if (IS_ERR(new_cm_id))
3119fe4bcf4SDavid Dillow 		return PTR_ERR(new_cm_id);
3129fe4bcf4SDavid Dillow 
31319f31343SBart Van Assche 	if (ch->ib_cm.cm_id)
31419f31343SBart Van Assche 		ib_destroy_cm_id(ch->ib_cm.cm_id);
31519f31343SBart Van Assche 	ch->ib_cm.cm_id = new_cm_id;
3164c33bd19SDasaratharaman Chandramouli 	if (rdma_cap_opa_ah(target->srp_host->srp_dev->dev,
3174c33bd19SDasaratharaman Chandramouli 			    target->srp_host->port))
31819f31343SBart Van Assche 		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_OPA;
3194c33bd19SDasaratharaman Chandramouli 	else
32019f31343SBart Van Assche 		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_IB;
32119f31343SBart Van Assche 	ch->ib_cm.path.sgid = target->sgid;
32219f31343SBart Van Assche 	ch->ib_cm.path.dgid = target->ib_cm.orig_dgid;
32319f31343SBart Van Assche 	ch->ib_cm.path.pkey = target->ib_cm.pkey;
32419f31343SBart Van Assche 	ch->ib_cm.path.service_id = target->ib_cm.service_id;
3259fe4bcf4SDavid Dillow 
3269fe4bcf4SDavid Dillow 	return 0;
3279fe4bcf4SDavid Dillow }
3289fe4bcf4SDavid Dillow 
srp_new_rdma_cm_id(struct srp_rdma_ch * ch)32919f31343SBart Van Assche static int srp_new_rdma_cm_id(struct srp_rdma_ch *ch)
33019f31343SBart Van Assche {
33119f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
33219f31343SBart Van Assche 	struct rdma_cm_id *new_cm_id;
33319f31343SBart Van Assche 	int ret;
33419f31343SBart Van Assche 
33519f31343SBart Van Assche 	new_cm_id = rdma_create_id(target->net, srp_rdma_cm_handler, ch,
33619f31343SBart Van Assche 				   RDMA_PS_TCP, IB_QPT_RC);
33719f31343SBart Van Assche 	if (IS_ERR(new_cm_id)) {
33819f31343SBart Van Assche 		ret = PTR_ERR(new_cm_id);
33919f31343SBart Van Assche 		new_cm_id = NULL;
34019f31343SBart Van Assche 		goto out;
34119f31343SBart Van Assche 	}
34219f31343SBart Van Assche 
34319f31343SBart Van Assche 	init_completion(&ch->done);
34419f31343SBart Van Assche 	ret = rdma_resolve_addr(new_cm_id, target->rdma_cm.src_specified ?
34514673778SBart Van Assche 				&target->rdma_cm.src.sa : NULL,
34614673778SBart Van Assche 				&target->rdma_cm.dst.sa,
34719f31343SBart Van Assche 				SRP_PATH_REC_TIMEOUT_MS);
34819f31343SBart Van Assche 	if (ret) {
349fdbcf5c0SBart Van Assche 		pr_err("No route available from %pISpsc to %pISpsc (%d)\n",
3507da09af9SBart Van Assche 		       &target->rdma_cm.src, &target->rdma_cm.dst, ret);
35119f31343SBart Van Assche 		goto out;
35219f31343SBart Van Assche 	}
35319f31343SBart Van Assche 	ret = wait_for_completion_interruptible(&ch->done);
35419f31343SBart Van Assche 	if (ret < 0)
35519f31343SBart Van Assche 		goto out;
35619f31343SBart Van Assche 
35719f31343SBart Van Assche 	ret = ch->status;
35819f31343SBart Van Assche 	if (ret) {
359fdbcf5c0SBart Van Assche 		pr_err("Resolving address %pISpsc failed (%d)\n",
3607da09af9SBart Van Assche 		       &target->rdma_cm.dst, ret);
36119f31343SBart Van Assche 		goto out;
36219f31343SBart Van Assche 	}
36319f31343SBart Van Assche 
36419f31343SBart Van Assche 	swap(ch->rdma_cm.cm_id, new_cm_id);
36519f31343SBart Van Assche 
36619f31343SBart Van Assche out:
36719f31343SBart Van Assche 	if (new_cm_id)
36819f31343SBart Van Assche 		rdma_destroy_id(new_cm_id);
36919f31343SBart Van Assche 
37019f31343SBart Van Assche 	return ret;
37119f31343SBart Van Assche }
37219f31343SBart Van Assche 
srp_new_cm_id(struct srp_rdma_ch * ch)37319f31343SBart Van Assche static int srp_new_cm_id(struct srp_rdma_ch *ch)
37419f31343SBart Van Assche {
37519f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
37619f31343SBart Van Assche 
37719f31343SBart Van Assche 	return target->using_rdma_cm ? srp_new_rdma_cm_id(ch) :
37819f31343SBart Van Assche 		srp_new_ib_cm_id(ch);
37919f31343SBart Van Assche }
38019f31343SBart Van Assche 
3815cfb1782SBart Van Assche /**
3825cfb1782SBart Van Assche  * srp_destroy_fr_pool() - free the resources owned by a pool
3835cfb1782SBart Van Assche  * @pool: Fast registration pool to be destroyed.
3845cfb1782SBart Van Assche  */
srp_destroy_fr_pool(struct srp_fr_pool * pool)3855cfb1782SBart Van Assche static void srp_destroy_fr_pool(struct srp_fr_pool *pool)
3865cfb1782SBart Van Assche {
3875cfb1782SBart Van Assche 	int i;
3885cfb1782SBart Van Assche 	struct srp_fr_desc *d;
3895cfb1782SBart Van Assche 
3905cfb1782SBart Van Assche 	if (!pool)
3915cfb1782SBart Van Assche 		return;
3925cfb1782SBart Van Assche 
3935cfb1782SBart Van Assche 	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
3945cfb1782SBart Van Assche 		if (d->mr)
3955cfb1782SBart Van Assche 			ib_dereg_mr(d->mr);
3965cfb1782SBart Van Assche 	}
3975cfb1782SBart Van Assche 	kfree(pool);
3985cfb1782SBart Van Assche }
3995cfb1782SBart Van Assche 
4005cfb1782SBart Van Assche /**
4015cfb1782SBart Van Assche  * srp_create_fr_pool() - allocate and initialize a pool for fast registration
4025cfb1782SBart Van Assche  * @device:            IB device to allocate fast registration descriptors for.
4035cfb1782SBart Van Assche  * @pd:                Protection domain associated with the FR descriptors.
4045cfb1782SBart Van Assche  * @pool_size:         Number of descriptors to allocate.
4055cfb1782SBart Van Assche  * @max_page_list_len: Maximum fast registration work request page list length.
4065cfb1782SBart Van Assche  */
srp_create_fr_pool(struct ib_device * device,struct ib_pd * pd,int pool_size,int max_page_list_len)4075cfb1782SBart Van Assche static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
4085cfb1782SBart Van Assche 					      struct ib_pd *pd, int pool_size,
4095cfb1782SBart Van Assche 					      int max_page_list_len)
4105cfb1782SBart Van Assche {
4115cfb1782SBart Van Assche 	struct srp_fr_pool *pool;
4125cfb1782SBart Van Assche 	struct srp_fr_desc *d;
4135cfb1782SBart Van Assche 	struct ib_mr *mr;
4145cfb1782SBart Van Assche 	int i, ret = -EINVAL;
415fbd36818SSergey Gorenko 	enum ib_mr_type mr_type;
4165cfb1782SBart Van Assche 
4175cfb1782SBart Van Assche 	if (pool_size <= 0)
4185cfb1782SBart Van Assche 		goto err;
4195cfb1782SBart Van Assche 	ret = -ENOMEM;
4207a7b0feaSGustavo A. R. Silva 	pool = kzalloc(struct_size(pool, desc, pool_size), GFP_KERNEL);
4215cfb1782SBart Van Assche 	if (!pool)
4225cfb1782SBart Van Assche 		goto err;
4235cfb1782SBart Van Assche 	pool->size = pool_size;
4245cfb1782SBart Van Assche 	pool->max_page_list_len = max_page_list_len;
4255cfb1782SBart Van Assche 	spin_lock_init(&pool->lock);
4265cfb1782SBart Van Assche 	INIT_LIST_HEAD(&pool->free_list);
4275cfb1782SBart Van Assche 
428e945c653SJason Gunthorpe 	if (device->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
429fbd36818SSergey Gorenko 		mr_type = IB_MR_TYPE_SG_GAPS;
430fbd36818SSergey Gorenko 	else
431fbd36818SSergey Gorenko 		mr_type = IB_MR_TYPE_MEM_REG;
432fbd36818SSergey Gorenko 
4335cfb1782SBart Van Assche 	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
434fbd36818SSergey Gorenko 		mr = ib_alloc_mr(pd, mr_type, max_page_list_len);
4355cfb1782SBart Van Assche 		if (IS_ERR(mr)) {
4365cfb1782SBart Van Assche 			ret = PTR_ERR(mr);
4373787d990SBart Van Assche 			if (ret == -ENOMEM)
4383787d990SBart Van Assche 				pr_info("%s: ib_alloc_mr() failed. Try to reduce max_cmd_per_lun, max_sect or ch_count\n",
4393787d990SBart Van Assche 					dev_name(&device->dev));
4405cfb1782SBart Van Assche 			goto destroy_pool;
4415cfb1782SBart Van Assche 		}
4425cfb1782SBart Van Assche 		d->mr = mr;
4435cfb1782SBart Van Assche 		list_add_tail(&d->entry, &pool->free_list);
4445cfb1782SBart Van Assche 	}
4455cfb1782SBart Van Assche 
4465cfb1782SBart Van Assche out:
4475cfb1782SBart Van Assche 	return pool;
4485cfb1782SBart Van Assche 
4495cfb1782SBart Van Assche destroy_pool:
4505cfb1782SBart Van Assche 	srp_destroy_fr_pool(pool);
4515cfb1782SBart Van Assche 
4525cfb1782SBart Van Assche err:
4535cfb1782SBart Van Assche 	pool = ERR_PTR(ret);
4545cfb1782SBart Van Assche 	goto out;
4555cfb1782SBart Van Assche }
4565cfb1782SBart Van Assche 
4575cfb1782SBart Van Assche /**
4585cfb1782SBart Van Assche  * srp_fr_pool_get() - obtain a descriptor suitable for fast registration
4595cfb1782SBart Van Assche  * @pool: Pool to obtain descriptor from.
4605cfb1782SBart Van Assche  */
srp_fr_pool_get(struct srp_fr_pool * pool)4615cfb1782SBart Van Assche static struct srp_fr_desc *srp_fr_pool_get(struct srp_fr_pool *pool)
4625cfb1782SBart Van Assche {
4635cfb1782SBart Van Assche 	struct srp_fr_desc *d = NULL;
4645cfb1782SBart Van Assche 	unsigned long flags;
4655cfb1782SBart Van Assche 
4665cfb1782SBart Van Assche 	spin_lock_irqsave(&pool->lock, flags);
4675cfb1782SBart Van Assche 	if (!list_empty(&pool->free_list)) {
4685cfb1782SBart Van Assche 		d = list_first_entry(&pool->free_list, typeof(*d), entry);
4695cfb1782SBart Van Assche 		list_del(&d->entry);
4705cfb1782SBart Van Assche 	}
4715cfb1782SBart Van Assche 	spin_unlock_irqrestore(&pool->lock, flags);
4725cfb1782SBart Van Assche 
4735cfb1782SBart Van Assche 	return d;
4745cfb1782SBart Van Assche }
4755cfb1782SBart Van Assche 
4765cfb1782SBart Van Assche /**
4775cfb1782SBart Van Assche  * srp_fr_pool_put() - put an FR descriptor back in the free list
4785cfb1782SBart Van Assche  * @pool: Pool the descriptor was allocated from.
4795cfb1782SBart Van Assche  * @desc: Pointer to an array of fast registration descriptor pointers.
4805cfb1782SBart Van Assche  * @n:    Number of descriptors to put back.
4815cfb1782SBart Van Assche  *
4825cfb1782SBart Van Assche  * Note: The caller must already have queued an invalidation request for
4835cfb1782SBart Van Assche  * desc->mr->rkey before calling this function.
4845cfb1782SBart Van Assche  */
srp_fr_pool_put(struct srp_fr_pool * pool,struct srp_fr_desc ** desc,int n)4855cfb1782SBart Van Assche static void srp_fr_pool_put(struct srp_fr_pool *pool, struct srp_fr_desc **desc,
4865cfb1782SBart Van Assche 			    int n)
4875cfb1782SBart Van Assche {
4885cfb1782SBart Van Assche 	unsigned long flags;
4895cfb1782SBart Van Assche 	int i;
4905cfb1782SBart Van Assche 
4915cfb1782SBart Van Assche 	spin_lock_irqsave(&pool->lock, flags);
4925cfb1782SBart Van Assche 	for (i = 0; i < n; i++)
4935cfb1782SBart Van Assche 		list_add(&desc[i]->entry, &pool->free_list);
4945cfb1782SBart Van Assche 	spin_unlock_irqrestore(&pool->lock, flags);
4955cfb1782SBart Van Assche }
4965cfb1782SBart Van Assche 
srp_alloc_fr_pool(struct srp_target_port * target)4975cfb1782SBart Van Assche static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
4985cfb1782SBart Van Assche {
4995cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
5005cfb1782SBart Van Assche 
501fa9863f8SBart Van Assche 	return srp_create_fr_pool(dev->dev, dev->pd, target->mr_pool_size,
5025cfb1782SBart Van Assche 				  dev->max_pages_per_mr);
5035cfb1782SBart Van Assche }
5045cfb1782SBart Van Assche 
5057dad6b2eSBart Van Assche /**
5067dad6b2eSBart Van Assche  * srp_destroy_qp() - destroy an RDMA queue pair
5079566b054SBart Van Assche  * @ch: SRP RDMA channel.
5087dad6b2eSBart Van Assche  *
509561392d4SSteve Wise  * Drain the qp before destroying it.  This avoids that the receive
510561392d4SSteve Wise  * completion handler can access the queue pair while it is
5117dad6b2eSBart Van Assche  * being destroyed.
5127dad6b2eSBart Van Assche  */
srp_destroy_qp(struct srp_rdma_ch * ch)5139566b054SBart Van Assche static void srp_destroy_qp(struct srp_rdma_ch *ch)
5147dad6b2eSBart Van Assche {
5159294000dSBart Van Assche 	spin_lock_irq(&ch->lock);
5169294000dSBart Van Assche 	ib_process_cq_direct(ch->send_cq, -1);
5179294000dSBart Van Assche 	spin_unlock_irq(&ch->lock);
5189294000dSBart Van Assche 
5199566b054SBart Van Assche 	ib_drain_qp(ch->qp);
5209566b054SBart Van Assche 	ib_destroy_qp(ch->qp);
5217dad6b2eSBart Van Assche }
5227dad6b2eSBart Van Assche 
srp_create_ch_ib(struct srp_rdma_ch * ch)523509c07bcSBart Van Assche static int srp_create_ch_ib(struct srp_rdma_ch *ch)
524aef9ec39SRoland Dreier {
525509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
52662154b2eSBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
527bf583470SBart Van Assche 	const struct ib_device_attr *attr = &dev->dev->attrs;
528aef9ec39SRoland Dreier 	struct ib_qp_init_attr *init_attr;
52973aa89edSIshai Rabinovitz 	struct ib_cq *recv_cq, *send_cq;
53073aa89edSIshai Rabinovitz 	struct ib_qp *qp;
5315cfb1782SBart Van Assche 	struct srp_fr_pool *fr_pool = NULL;
532509c5f33SBart Van Assche 	const int m = 1 + dev->use_fast_reg * target->mr_per_cmd * 2;
533aef9ec39SRoland Dreier 	int ret;
534aef9ec39SRoland Dreier 
535aef9ec39SRoland Dreier 	init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
536aef9ec39SRoland Dreier 	if (!init_attr)
537aef9ec39SRoland Dreier 		return -ENOMEM;
538aef9ec39SRoland Dreier 
539561392d4SSteve Wise 	/* queue_size + 1 for ib_drain_rq() */
5401dc7b1f1SChristoph Hellwig 	recv_cq = ib_alloc_cq(dev->dev, ch, target->queue_size + 1,
5411dc7b1f1SChristoph Hellwig 				ch->comp_vector, IB_POLL_SOFTIRQ);
54273aa89edSIshai Rabinovitz 	if (IS_ERR(recv_cq)) {
54373aa89edSIshai Rabinovitz 		ret = PTR_ERR(recv_cq);
544da9d2f07SRoland Dreier 		goto err;
545aef9ec39SRoland Dreier 	}
546aef9ec39SRoland Dreier 
5471dc7b1f1SChristoph Hellwig 	send_cq = ib_alloc_cq(dev->dev, ch, m * target->queue_size,
5481dc7b1f1SChristoph Hellwig 				ch->comp_vector, IB_POLL_DIRECT);
54973aa89edSIshai Rabinovitz 	if (IS_ERR(send_cq)) {
55073aa89edSIshai Rabinovitz 		ret = PTR_ERR(send_cq);
551da9d2f07SRoland Dreier 		goto err_recv_cq;
5529c03dc9fSBart Van Assche 	}
5539c03dc9fSBart Van Assche 
554aef9ec39SRoland Dreier 	init_attr->event_handler       = srp_qp_event;
5555cfb1782SBart Van Assche 	init_attr->cap.max_send_wr     = m * target->queue_size;
5567dad6b2eSBart Van Assche 	init_attr->cap.max_recv_wr     = target->queue_size + 1;
557aef9ec39SRoland Dreier 	init_attr->cap.max_recv_sge    = 1;
558bf583470SBart Van Assche 	init_attr->cap.max_send_sge    = min(SRP_MAX_SGE, attr->max_send_sge);
5595cfb1782SBart Van Assche 	init_attr->sq_sig_type         = IB_SIGNAL_REQ_WR;
560aef9ec39SRoland Dreier 	init_attr->qp_type             = IB_QPT_RC;
56173aa89edSIshai Rabinovitz 	init_attr->send_cq             = send_cq;
56273aa89edSIshai Rabinovitz 	init_attr->recv_cq             = recv_cq;
563aef9ec39SRoland Dreier 
564bf583470SBart Van Assche 	ch->max_imm_sge = min(init_attr->cap.max_send_sge - 1U, 255U);
565bf583470SBart Van Assche 
56619f31343SBart Van Assche 	if (target->using_rdma_cm) {
56719f31343SBart Van Assche 		ret = rdma_create_qp(ch->rdma_cm.cm_id, dev->pd, init_attr);
56819f31343SBart Van Assche 		qp = ch->rdma_cm.cm_id->qp;
56919f31343SBart Van Assche 	} else {
57062154b2eSBart Van Assche 		qp = ib_create_qp(dev->pd, init_attr);
57119f31343SBart Van Assche 		if (!IS_ERR(qp)) {
57219f31343SBart Van Assche 			ret = srp_init_ib_qp(target, qp);
57319f31343SBart Van Assche 			if (ret)
57419f31343SBart Van Assche 				ib_destroy_qp(qp);
57519f31343SBart Van Assche 		} else {
57673aa89edSIshai Rabinovitz 			ret = PTR_ERR(qp);
57719f31343SBart Van Assche 		}
57819f31343SBart Van Assche 	}
57919f31343SBart Van Assche 	if (ret) {
58019f31343SBart Van Assche 		pr_err("QP creation failed for dev %s: %d\n",
58119f31343SBart Van Assche 		       dev_name(&dev->dev->dev), ret);
582da9d2f07SRoland Dreier 		goto err_send_cq;
583aef9ec39SRoland Dreier 	}
584aef9ec39SRoland Dreier 
585002f1567SBart Van Assche 	if (dev->use_fast_reg) {
5865cfb1782SBart Van Assche 		fr_pool = srp_alloc_fr_pool(target);
5875cfb1782SBart Van Assche 		if (IS_ERR(fr_pool)) {
5885cfb1782SBart Van Assche 			ret = PTR_ERR(fr_pool);
5895cfb1782SBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host, PFX
5905cfb1782SBart Van Assche 				     "FR pool allocation failed (%d)\n", ret);
5915cfb1782SBart Van Assche 			goto err_qp;
5925cfb1782SBart Van Assche 		}
593d1b4289eSBart Van Assche 	}
594d1b4289eSBart Van Assche 
595509c07bcSBart Van Assche 	if (ch->qp)
5969566b054SBart Van Assche 		srp_destroy_qp(ch);
597509c07bcSBart Van Assche 	if (ch->recv_cq)
5981dc7b1f1SChristoph Hellwig 		ib_free_cq(ch->recv_cq);
599509c07bcSBart Van Assche 	if (ch->send_cq)
6001dc7b1f1SChristoph Hellwig 		ib_free_cq(ch->send_cq);
60173aa89edSIshai Rabinovitz 
602509c07bcSBart Van Assche 	ch->qp = qp;
603509c07bcSBart Van Assche 	ch->recv_cq = recv_cq;
604509c07bcSBart Van Assche 	ch->send_cq = send_cq;
60573aa89edSIshai Rabinovitz 
6067fbc67dfSSagi Grimberg 	if (dev->use_fast_reg) {
6077fbc67dfSSagi Grimberg 		if (ch->fr_pool)
6087fbc67dfSSagi Grimberg 			srp_destroy_fr_pool(ch->fr_pool);
6097fbc67dfSSagi Grimberg 		ch->fr_pool = fr_pool;
6107fbc67dfSSagi Grimberg 	}
6117fbc67dfSSagi Grimberg 
612da9d2f07SRoland Dreier 	kfree(init_attr);
613da9d2f07SRoland Dreier 	return 0;
614da9d2f07SRoland Dreier 
615da9d2f07SRoland Dreier err_qp:
61619f31343SBart Van Assche 	if (target->using_rdma_cm)
61719f31343SBart Van Assche 		rdma_destroy_qp(ch->rdma_cm.cm_id);
61819f31343SBart Van Assche 	else
61995c2ef50SIsrael Rukshin 		ib_destroy_qp(qp);
620da9d2f07SRoland Dreier 
621da9d2f07SRoland Dreier err_send_cq:
6221dc7b1f1SChristoph Hellwig 	ib_free_cq(send_cq);
623da9d2f07SRoland Dreier 
624da9d2f07SRoland Dreier err_recv_cq:
6251dc7b1f1SChristoph Hellwig 	ib_free_cq(recv_cq);
626da9d2f07SRoland Dreier 
627da9d2f07SRoland Dreier err:
628aef9ec39SRoland Dreier 	kfree(init_attr);
629aef9ec39SRoland Dreier 	return ret;
630aef9ec39SRoland Dreier }
631aef9ec39SRoland Dreier 
6324d73f95fSBart Van Assche /*
6334d73f95fSBart Van Assche  * Note: this function may be called without srp_alloc_iu_bufs() having been
634509c07bcSBart Van Assche  * invoked. Hence the ch->[rt]x_ring checks.
6354d73f95fSBart Van Assche  */
srp_free_ch_ib(struct srp_target_port * target,struct srp_rdma_ch * ch)636509c07bcSBart Van Assche static void srp_free_ch_ib(struct srp_target_port *target,
637509c07bcSBart Van Assche 			   struct srp_rdma_ch *ch)
638aef9ec39SRoland Dreier {
6395cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
640aef9ec39SRoland Dreier 	int i;
641aef9ec39SRoland Dreier 
642d92c0da7SBart Van Assche 	if (!ch->target)
643d92c0da7SBart Van Assche 		return;
644d92c0da7SBart Van Assche 
64519f31343SBart Van Assche 	if (target->using_rdma_cm) {
64619f31343SBart Van Assche 		if (ch->rdma_cm.cm_id) {
64719f31343SBart Van Assche 			rdma_destroy_id(ch->rdma_cm.cm_id);
64819f31343SBart Van Assche 			ch->rdma_cm.cm_id = NULL;
64919f31343SBart Van Assche 		}
65019f31343SBart Van Assche 	} else {
65119f31343SBart Van Assche 		if (ch->ib_cm.cm_id) {
65219f31343SBart Van Assche 			ib_destroy_cm_id(ch->ib_cm.cm_id);
65319f31343SBart Van Assche 			ch->ib_cm.cm_id = NULL;
65419f31343SBart Van Assche 		}
655394c595eSBart Van Assche 	}
656394c595eSBart Van Assche 
657d92c0da7SBart Van Assche 	/* If srp_new_cm_id() succeeded but srp_create_ch_ib() not, return. */
658d92c0da7SBart Van Assche 	if (!ch->qp)
659d92c0da7SBart Van Assche 		return;
660d92c0da7SBart Van Assche 
6615cfb1782SBart Van Assche 	if (dev->use_fast_reg) {
662509c07bcSBart Van Assche 		if (ch->fr_pool)
663509c07bcSBart Van Assche 			srp_destroy_fr_pool(ch->fr_pool);
6645cfb1782SBart Van Assche 	}
6651dc7b1f1SChristoph Hellwig 
6669566b054SBart Van Assche 	srp_destroy_qp(ch);
6671dc7b1f1SChristoph Hellwig 	ib_free_cq(ch->send_cq);
6681dc7b1f1SChristoph Hellwig 	ib_free_cq(ch->recv_cq);
669aef9ec39SRoland Dreier 
670d92c0da7SBart Van Assche 	/*
671d92c0da7SBart Van Assche 	 * Avoid that the SCSI error handler tries to use this channel after
672d92c0da7SBart Van Assche 	 * it has been freed. The SCSI error handler can namely continue
673d92c0da7SBart Van Assche 	 * trying to perform recovery actions after scsi_remove_host()
674d92c0da7SBart Van Assche 	 * returned.
675d92c0da7SBart Van Assche 	 */
676d92c0da7SBart Van Assche 	ch->target = NULL;
677d92c0da7SBart Van Assche 
678509c07bcSBart Van Assche 	ch->qp = NULL;
679509c07bcSBart Van Assche 	ch->send_cq = ch->recv_cq = NULL;
68073aa89edSIshai Rabinovitz 
681509c07bcSBart Van Assche 	if (ch->rx_ring) {
6824d73f95fSBart Van Assche 		for (i = 0; i < target->queue_size; ++i)
683509c07bcSBart Van Assche 			srp_free_iu(target->srp_host, ch->rx_ring[i]);
684509c07bcSBart Van Assche 		kfree(ch->rx_ring);
685509c07bcSBart Van Assche 		ch->rx_ring = NULL;
6864d73f95fSBart Van Assche 	}
687509c07bcSBart Van Assche 	if (ch->tx_ring) {
6884d73f95fSBart Van Assche 		for (i = 0; i < target->queue_size; ++i)
689509c07bcSBart Van Assche 			srp_free_iu(target->srp_host, ch->tx_ring[i]);
690509c07bcSBart Van Assche 		kfree(ch->tx_ring);
691509c07bcSBart Van Assche 		ch->tx_ring = NULL;
6924d73f95fSBart Van Assche 	}
693aef9ec39SRoland Dreier }
694aef9ec39SRoland Dreier 
srp_path_rec_completion(int status,struct sa_path_rec * pathrec,unsigned int num_paths,void * ch_ptr)695aef9ec39SRoland Dreier static void srp_path_rec_completion(int status,
696c2f8fc4eSDasaratharaman Chandramouli 				    struct sa_path_rec *pathrec,
697ccae0447SMark Zhang 				    unsigned int num_paths, void *ch_ptr)
698aef9ec39SRoland Dreier {
699509c07bcSBart Van Assche 	struct srp_rdma_ch *ch = ch_ptr;
700509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
701aef9ec39SRoland Dreier 
702509c07bcSBart Van Assche 	ch->status = status;
703aef9ec39SRoland Dreier 	if (status)
7047aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
7057aa54bd7SDavid Dillow 			     PFX "Got failed path rec status %d\n", status);
706aef9ec39SRoland Dreier 	else
70719f31343SBart Van Assche 		ch->ib_cm.path = *pathrec;
708509c07bcSBart Van Assche 	complete(&ch->done);
709aef9ec39SRoland Dreier }
710aef9ec39SRoland Dreier 
srp_ib_lookup_path(struct srp_rdma_ch * ch)71119f31343SBart Van Assche static int srp_ib_lookup_path(struct srp_rdma_ch *ch)
712aef9ec39SRoland Dreier {
713509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
714c74ff750SBart Van Assche 	int ret;
715a702adceSBart Van Assche 
71619f31343SBart Van Assche 	ch->ib_cm.path.numb_path = 1;
717aef9ec39SRoland Dreier 
718509c07bcSBart Van Assche 	init_completion(&ch->done);
719aef9ec39SRoland Dreier 
72019f31343SBart Van Assche 	ch->ib_cm.path_query_id = ib_sa_path_rec_get(&srp_sa_client,
72105321937SGreg Kroah-Hartman 					       target->srp_host->srp_dev->dev,
722aef9ec39SRoland Dreier 					       target->srp_host->port,
72319f31343SBart Van Assche 					       &ch->ib_cm.path,
724247e020eSSean Hefty 					       IB_SA_PATH_REC_SERVICE_ID |
725aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_DGID	 |
726aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_SGID	 |
727aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_NUMB_PATH	 |
728aef9ec39SRoland Dreier 					       IB_SA_PATH_REC_PKEY,
729aef9ec39SRoland Dreier 					       SRP_PATH_REC_TIMEOUT_MS,
730aef9ec39SRoland Dreier 					       GFP_KERNEL,
731aef9ec39SRoland Dreier 					       srp_path_rec_completion,
73219f31343SBart Van Assche 					       ch, &ch->ib_cm.path_query);
733c74ff750SBart Van Assche 	if (ch->ib_cm.path_query_id < 0)
734c74ff750SBart Van Assche 		return ch->ib_cm.path_query_id;
735aef9ec39SRoland Dreier 
736509c07bcSBart Van Assche 	ret = wait_for_completion_interruptible(&ch->done);
737a702adceSBart Van Assche 	if (ret < 0)
738c74ff750SBart Van Assche 		return ret;
739aef9ec39SRoland Dreier 
740c74ff750SBart Van Assche 	if (ch->status < 0)
7417aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
74285769c6fSBart Van Assche 			     PFX "Path record query failed: sgid %pI6, dgid %pI6, pkey %#04x, service_id %#16llx\n",
74319f31343SBart Van Assche 			     ch->ib_cm.path.sgid.raw, ch->ib_cm.path.dgid.raw,
74419f31343SBart Van Assche 			     be16_to_cpu(target->ib_cm.pkey),
74519f31343SBart Van Assche 			     be64_to_cpu(target->ib_cm.service_id));
746aef9ec39SRoland Dreier 
747c74ff750SBart Van Assche 	return ch->status;
748aef9ec39SRoland Dreier }
749aef9ec39SRoland Dreier 
srp_rdma_lookup_path(struct srp_rdma_ch * ch)75019f31343SBart Van Assche static int srp_rdma_lookup_path(struct srp_rdma_ch *ch)
75119f31343SBart Van Assche {
75219f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
75319f31343SBart Van Assche 	int ret;
75419f31343SBart Van Assche 
75519f31343SBart Van Assche 	init_completion(&ch->done);
75619f31343SBart Van Assche 
75719f31343SBart Van Assche 	ret = rdma_resolve_route(ch->rdma_cm.cm_id, SRP_PATH_REC_TIMEOUT_MS);
75819f31343SBart Van Assche 	if (ret)
75919f31343SBart Van Assche 		return ret;
76019f31343SBart Van Assche 
76119f31343SBart Van Assche 	wait_for_completion_interruptible(&ch->done);
76219f31343SBart Van Assche 
76319f31343SBart Van Assche 	if (ch->status != 0)
76419f31343SBart Van Assche 		shost_printk(KERN_WARNING, target->scsi_host,
76519f31343SBart Van Assche 			     PFX "Path resolution failed\n");
76619f31343SBart Van Assche 
76719f31343SBart Van Assche 	return ch->status;
76819f31343SBart Van Assche }
76919f31343SBart Van Assche 
srp_lookup_path(struct srp_rdma_ch * ch)77019f31343SBart Van Assche static int srp_lookup_path(struct srp_rdma_ch *ch)
77119f31343SBart Van Assche {
77219f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
77319f31343SBart Van Assche 
77419f31343SBart Van Assche 	return target->using_rdma_cm ? srp_rdma_lookup_path(ch) :
77519f31343SBart Van Assche 		srp_ib_lookup_path(ch);
77619f31343SBart Van Assche }
77719f31343SBart Van Assche 
srp_get_subnet_timeout(struct srp_host * host)7784c532d6cSBart Van Assche static u8 srp_get_subnet_timeout(struct srp_host *host)
7794c532d6cSBart Van Assche {
7804c532d6cSBart Van Assche 	struct ib_port_attr attr;
7814c532d6cSBart Van Assche 	int ret;
7824c532d6cSBart Van Assche 	u8 subnet_timeout = 18;
7834c532d6cSBart Van Assche 
7844c532d6cSBart Van Assche 	ret = ib_query_port(host->srp_dev->dev, host->port, &attr);
7854c532d6cSBart Van Assche 	if (ret == 0)
7864c532d6cSBart Van Assche 		subnet_timeout = attr.subnet_timeout;
7874c532d6cSBart Van Assche 
7884c532d6cSBart Van Assche 	if (unlikely(subnet_timeout < 15))
7894c532d6cSBart Van Assche 		pr_warn("%s: subnet timeout %d may cause SRP login to fail.\n",
7904c532d6cSBart Van Assche 			dev_name(&host->srp_dev->dev->dev), subnet_timeout);
7914c532d6cSBart Van Assche 
7924c532d6cSBart Van Assche 	return subnet_timeout;
7934c532d6cSBart Van Assche }
7944c532d6cSBart Van Assche 
srp_send_req(struct srp_rdma_ch * ch,uint32_t max_iu_len,bool multich)795513d5647SBart Van Assche static int srp_send_req(struct srp_rdma_ch *ch, uint32_t max_iu_len,
796513d5647SBart Van Assche 			bool multich)
797aef9ec39SRoland Dreier {
798509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
799aef9ec39SRoland Dreier 	struct {
80019f31343SBart Van Assche 		struct rdma_conn_param	  rdma_param;
80119f31343SBart Van Assche 		struct srp_login_req_rdma rdma_req;
80219f31343SBart Van Assche 		struct ib_cm_req_param	  ib_param;
80319f31343SBart Van Assche 		struct srp_login_req	  ib_req;
804aef9ec39SRoland Dreier 	} *req = NULL;
80548900a28SBart Van Assche 	char *ipi, *tpi;
806aef9ec39SRoland Dreier 	int status;
807aef9ec39SRoland Dreier 
808aef9ec39SRoland Dreier 	req = kzalloc(sizeof *req, GFP_KERNEL);
809aef9ec39SRoland Dreier 	if (!req)
810aef9ec39SRoland Dreier 		return -ENOMEM;
811aef9ec39SRoland Dreier 
81219f31343SBart Van Assche 	req->ib_param.flow_control = 1;
81319f31343SBart Van Assche 	req->ib_param.retry_count = target->tl_retry_count;
814aef9ec39SRoland Dreier 
815aef9ec39SRoland Dreier 	/*
816aef9ec39SRoland Dreier 	 * Pick some arbitrary defaults here; we could make these
817aef9ec39SRoland Dreier 	 * module parameters if anyone cared about setting them.
818aef9ec39SRoland Dreier 	 */
81919f31343SBart Van Assche 	req->ib_param.responder_resources = 4;
82019f31343SBart Van Assche 	req->ib_param.rnr_retry_count = 7;
82119f31343SBart Van Assche 	req->ib_param.max_cm_retries = 15;
822aef9ec39SRoland Dreier 
82319f31343SBart Van Assche 	req->ib_req.opcode = SRP_LOGIN_REQ;
82419f31343SBart Van Assche 	req->ib_req.tag = 0;
825513d5647SBart Van Assche 	req->ib_req.req_it_iu_len = cpu_to_be32(max_iu_len);
82619f31343SBart Van Assche 	req->ib_req.req_buf_fmt	= cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
827aef9ec39SRoland Dreier 					      SRP_BUF_FORMAT_INDIRECT);
82819f31343SBart Van Assche 	req->ib_req.req_flags = (multich ? SRP_MULTICHAN_MULTI :
829d92c0da7SBart Van Assche 				 SRP_MULTICHAN_SINGLE);
830882981f4SBart Van Assche 	if (srp_use_imm_data) {
831882981f4SBart Van Assche 		req->ib_req.req_flags |= SRP_IMMED_REQUESTED;
832882981f4SBart Van Assche 		req->ib_req.imm_data_offset = cpu_to_be16(SRP_IMM_DATA_OFFSET);
833882981f4SBart Van Assche 	}
83448900a28SBart Van Assche 
83519f31343SBart Van Assche 	if (target->using_rdma_cm) {
83619f31343SBart Van Assche 		req->rdma_param.flow_control = req->ib_param.flow_control;
83719f31343SBart Van Assche 		req->rdma_param.responder_resources =
83819f31343SBart Van Assche 			req->ib_param.responder_resources;
83919f31343SBart Van Assche 		req->rdma_param.initiator_depth = req->ib_param.initiator_depth;
84019f31343SBart Van Assche 		req->rdma_param.retry_count = req->ib_param.retry_count;
84119f31343SBart Van Assche 		req->rdma_param.rnr_retry_count = req->ib_param.rnr_retry_count;
84219f31343SBart Van Assche 		req->rdma_param.private_data = &req->rdma_req;
84319f31343SBart Van Assche 		req->rdma_param.private_data_len = sizeof(req->rdma_req);
84419f31343SBart Van Assche 
84519f31343SBart Van Assche 		req->rdma_req.opcode = req->ib_req.opcode;
84619f31343SBart Van Assche 		req->rdma_req.tag = req->ib_req.tag;
84719f31343SBart Van Assche 		req->rdma_req.req_it_iu_len = req->ib_req.req_it_iu_len;
84819f31343SBart Van Assche 		req->rdma_req.req_buf_fmt = req->ib_req.req_buf_fmt;
84919f31343SBart Van Assche 		req->rdma_req.req_flags	= req->ib_req.req_flags;
850882981f4SBart Van Assche 		req->rdma_req.imm_data_offset = req->ib_req.imm_data_offset;
85119f31343SBart Van Assche 
85219f31343SBart Van Assche 		ipi = req->rdma_req.initiator_port_id;
85319f31343SBart Van Assche 		tpi = req->rdma_req.target_port_id;
85419f31343SBart Van Assche 	} else {
85548900a28SBart Van Assche 		u8 subnet_timeout;
85648900a28SBart Van Assche 
85748900a28SBart Van Assche 		subnet_timeout = srp_get_subnet_timeout(target->srp_host);
85848900a28SBart Van Assche 
85919f31343SBart Van Assche 		req->ib_param.primary_path = &ch->ib_cm.path;
86019f31343SBart Van Assche 		req->ib_param.alternate_path = NULL;
86119f31343SBart Van Assche 		req->ib_param.service_id = target->ib_cm.service_id;
86219f31343SBart Van Assche 		get_random_bytes(&req->ib_param.starting_psn, 4);
86319f31343SBart Van Assche 		req->ib_param.starting_psn &= 0xffffff;
86419f31343SBart Van Assche 		req->ib_param.qp_num = ch->qp->qp_num;
86519f31343SBart Van Assche 		req->ib_param.qp_type = ch->qp->qp_type;
86619f31343SBart Van Assche 		req->ib_param.local_cm_response_timeout = subnet_timeout + 2;
86719f31343SBart Van Assche 		req->ib_param.remote_cm_response_timeout = subnet_timeout + 2;
86819f31343SBart Van Assche 		req->ib_param.private_data = &req->ib_req;
86919f31343SBart Van Assche 		req->ib_param.private_data_len = sizeof(req->ib_req);
87048900a28SBart Van Assche 
87119f31343SBart Van Assche 		ipi = req->ib_req.initiator_port_id;
87219f31343SBart Van Assche 		tpi = req->ib_req.target_port_id;
87348900a28SBart Van Assche 	}
87448900a28SBart Van Assche 
8750c0450dbSRamachandra K 	/*
8760c0450dbSRamachandra K 	 * In the published SRP specification (draft rev. 16a), the
8770c0450dbSRamachandra K 	 * port identifier format is 8 bytes of ID extension followed
8780c0450dbSRamachandra K 	 * by 8 bytes of GUID.  Older drafts put the two halves in the
8790c0450dbSRamachandra K 	 * opposite order, so that the GUID comes first.
8800c0450dbSRamachandra K 	 *
8810c0450dbSRamachandra K 	 * Targets conforming to these obsolete drafts can be
8820c0450dbSRamachandra K 	 * recognized by the I/O Class they report.
8830c0450dbSRamachandra K 	 */
8840c0450dbSRamachandra K 	if (target->io_class == SRP_REV10_IB_IO_CLASS) {
88548900a28SBart Van Assche 		memcpy(ipi,     &target->sgid.global.interface_id, 8);
88648900a28SBart Van Assche 		memcpy(ipi + 8, &target->initiator_ext, 8);
88748900a28SBart Van Assche 		memcpy(tpi,     &target->ioc_guid, 8);
88848900a28SBart Van Assche 		memcpy(tpi + 8, &target->id_ext, 8);
8890c0450dbSRamachandra K 	} else {
89048900a28SBart Van Assche 		memcpy(ipi,     &target->initiator_ext, 8);
89148900a28SBart Van Assche 		memcpy(ipi + 8, &target->sgid.global.interface_id, 8);
89248900a28SBart Van Assche 		memcpy(tpi,     &target->id_ext, 8);
89348900a28SBart Van Assche 		memcpy(tpi + 8, &target->ioc_guid, 8);
8940c0450dbSRamachandra K 	}
8950c0450dbSRamachandra K 
896aef9ec39SRoland Dreier 	/*
897aef9ec39SRoland Dreier 	 * Topspin/Cisco SRP targets will reject our login unless we
89801cb9bcbSIshai Rabinovitz 	 * zero out the first 8 bytes of our initiator port ID and set
89901cb9bcbSIshai Rabinovitz 	 * the second 8 bytes to the local node GUID.
900aef9ec39SRoland Dreier 	 */
9015d7cbfd6SRoland Dreier 	if (srp_target_is_topspin(target)) {
9027aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host,
9037aa54bd7SDavid Dillow 			     PFX "Topspin/Cisco initiator port ID workaround "
904aef9ec39SRoland Dreier 			     "activated for target GUID %016llx\n",
90545c37cadSBart Van Assche 			     be64_to_cpu(target->ioc_guid));
90648900a28SBart Van Assche 		memset(ipi, 0, 8);
90748900a28SBart Van Assche 		memcpy(ipi + 8, &target->srp_host->srp_dev->dev->node_guid, 8);
908aef9ec39SRoland Dreier 	}
909aef9ec39SRoland Dreier 
91019f31343SBart Van Assche 	if (target->using_rdma_cm)
91119f31343SBart Van Assche 		status = rdma_connect(ch->rdma_cm.cm_id, &req->rdma_param);
91219f31343SBart Van Assche 	else
91319f31343SBart Van Assche 		status = ib_send_cm_req(ch->ib_cm.cm_id, &req->ib_param);
914aef9ec39SRoland Dreier 
915aef9ec39SRoland Dreier 	kfree(req);
916aef9ec39SRoland Dreier 
917aef9ec39SRoland Dreier 	return status;
918aef9ec39SRoland Dreier }
919aef9ec39SRoland Dreier 
srp_queue_remove_work(struct srp_target_port * target)920ef6c49d8SBart Van Assche static bool srp_queue_remove_work(struct srp_target_port *target)
921ef6c49d8SBart Van Assche {
922ef6c49d8SBart Van Assche 	bool changed = false;
923ef6c49d8SBart Van Assche 
924ef6c49d8SBart Van Assche 	spin_lock_irq(&target->lock);
925ef6c49d8SBart Van Assche 	if (target->state != SRP_TARGET_REMOVED) {
926ef6c49d8SBart Van Assche 		target->state = SRP_TARGET_REMOVED;
927ef6c49d8SBart Van Assche 		changed = true;
928ef6c49d8SBart Van Assche 	}
929ef6c49d8SBart Van Assche 	spin_unlock_irq(&target->lock);
930ef6c49d8SBart Van Assche 
931ef6c49d8SBart Van Assche 	if (changed)
932bcc05910SBart Van Assche 		queue_work(srp_remove_wq, &target->remove_work);
933ef6c49d8SBart Van Assche 
934ef6c49d8SBart Van Assche 	return changed;
935ef6c49d8SBart Van Assche }
936ef6c49d8SBart Van Assche 
srp_disconnect_target(struct srp_target_port * target)937aef9ec39SRoland Dreier static void srp_disconnect_target(struct srp_target_port *target)
938aef9ec39SRoland Dreier {
939d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
94019f31343SBart Van Assche 	int i, ret;
941509c07bcSBart Van Assche 
942aef9ec39SRoland Dreier 	/* XXX should send SRP_I_LOGOUT request */
943aef9ec39SRoland Dreier 
944d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
945d92c0da7SBart Van Assche 		ch = &target->ch[i];
946c014c8cdSBart Van Assche 		ch->connected = false;
94719f31343SBart Van Assche 		ret = 0;
94819f31343SBart Van Assche 		if (target->using_rdma_cm) {
94919f31343SBart Van Assche 			if (ch->rdma_cm.cm_id)
95019f31343SBart Van Assche 				rdma_disconnect(ch->rdma_cm.cm_id);
95119f31343SBart Van Assche 		} else {
95219f31343SBart Van Assche 			if (ch->ib_cm.cm_id)
95319f31343SBart Van Assche 				ret = ib_send_cm_dreq(ch->ib_cm.cm_id,
95419f31343SBart Van Assche 						      NULL, 0);
95519f31343SBart Van Assche 		}
95619f31343SBart Van Assche 		if (ret < 0) {
9577aa54bd7SDavid Dillow 			shost_printk(KERN_DEBUG, target->scsi_host,
9587aa54bd7SDavid Dillow 				     PFX "Sending CM DREQ failed\n");
959aef9ec39SRoland Dreier 		}
960294c875aSBart Van Assche 	}
961294c875aSBart Van Assche }
962aef9ec39SRoland Dreier 
srp_exit_cmd_priv(struct Scsi_Host * shost,struct scsi_cmnd * cmd)963ad215aaeSBart Van Assche static int srp_exit_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
9648f26c9ffSDavid Dillow {
965ad215aaeSBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
9665cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
9675cfb1782SBart Van Assche 	struct ib_device *ibdev = dev->dev;
968ad215aaeSBart Van Assche 	struct srp_request *req = scsi_cmd_priv(cmd);
9698f26c9ffSDavid Dillow 
9705cfb1782SBart Van Assche 	kfree(req->fr_list);
971c07d424dSDavid Dillow 	if (req->indirect_dma_addr) {
972c07d424dSDavid Dillow 		ib_dma_unmap_single(ibdev, req->indirect_dma_addr,
973c07d424dSDavid Dillow 				    target->indirect_size,
974c07d424dSDavid Dillow 				    DMA_TO_DEVICE);
975c07d424dSDavid Dillow 	}
976c07d424dSDavid Dillow 	kfree(req->indirect_desc);
977ad215aaeSBart Van Assche 
978ad215aaeSBart Van Assche 	return 0;
9798f26c9ffSDavid Dillow }
9804d73f95fSBart Van Assche 
srp_init_cmd_priv(struct Scsi_Host * shost,struct scsi_cmnd * cmd)981ad215aaeSBart Van Assche static int srp_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
982b81d00bdSBart Van Assche {
983ad215aaeSBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
984b81d00bdSBart Van Assche 	struct srp_device *srp_dev = target->srp_host->srp_dev;
985b81d00bdSBart Van Assche 	struct ib_device *ibdev = srp_dev->dev;
986ad215aaeSBart Van Assche 	struct srp_request *req = scsi_cmd_priv(cmd);
987b81d00bdSBart Van Assche 	dma_addr_t dma_addr;
988ad215aaeSBart Van Assche 	int ret = -ENOMEM;
989b81d00bdSBart Van Assche 
9907ec2e27aSBart Van Assche 	if (srp_dev->use_fast_reg) {
991ad215aaeSBart Van Assche 		req->fr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *),
992ad215aaeSBart Van Assche 					GFP_KERNEL);
9937ec2e27aSBart Van Assche 		if (!req->fr_list)
9945cfb1782SBart Van Assche 			goto out;
9957ec2e27aSBart Van Assche 	}
996b81d00bdSBart Van Assche 	req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
9975cfb1782SBart Van Assche 	if (!req->indirect_desc)
998b81d00bdSBart Van Assche 		goto out;
999b81d00bdSBart Van Assche 
1000b81d00bdSBart Van Assche 	dma_addr = ib_dma_map_single(ibdev, req->indirect_desc,
1001b81d00bdSBart Van Assche 				     target->indirect_size,
1002b81d00bdSBart Van Assche 				     DMA_TO_DEVICE);
1003ad215aaeSBart Van Assche 	if (ib_dma_mapping_error(ibdev, dma_addr)) {
1004ad215aaeSBart Van Assche 		srp_exit_cmd_priv(shost, cmd);
1005b81d00bdSBart Van Assche 		goto out;
1006ad215aaeSBart Van Assche 	}
1007b81d00bdSBart Van Assche 
1008b81d00bdSBart Van Assche 	req->indirect_dma_addr = dma_addr;
1009b81d00bdSBart Van Assche 	ret = 0;
1010b81d00bdSBart Van Assche 
1011b81d00bdSBart Van Assche out:
1012b81d00bdSBart Van Assche 	return ret;
1013b81d00bdSBart Van Assche }
1014b81d00bdSBart Van Assche 
1015683b159aSBart Van Assche /**
1016683b159aSBart Van Assche  * srp_del_scsi_host_attr() - Remove attributes defined in the host template.
1017683b159aSBart Van Assche  * @shost: SCSI host whose attributes to remove from sysfs.
1018683b159aSBart Van Assche  *
1019683b159aSBart Van Assche  * Note: Any attributes defined in the host template and that did not exist
1020683b159aSBart Van Assche  * before invocation of this function will be ignored.
1021683b159aSBart Van Assche  */
srp_del_scsi_host_attr(struct Scsi_Host * shost)1022683b159aSBart Van Assche static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
1023683b159aSBart Van Assche {
1024a3cf94c9SBart Van Assche 	const struct attribute_group **g;
1025a3cf94c9SBart Van Assche 	struct attribute **attr;
1026683b159aSBart Van Assche 
1027a3cf94c9SBart Van Assche 	for (g = shost->hostt->shost_groups; *g; ++g) {
1028a3cf94c9SBart Van Assche 		for (attr = (*g)->attrs; *attr; ++attr) {
1029a3cf94c9SBart Van Assche 			struct device_attribute *dev_attr =
1030a3cf94c9SBart Van Assche 				container_of(*attr, typeof(*dev_attr), attr);
1031a3cf94c9SBart Van Assche 
1032a3cf94c9SBart Van Assche 			device_remove_file(&shost->shost_dev, dev_attr);
1033a3cf94c9SBart Van Assche 		}
1034a3cf94c9SBart Van Assche 	}
1035683b159aSBart Van Assche }
1036683b159aSBart Van Assche 
srp_remove_target(struct srp_target_port * target)1037ee12d6a8SBart Van Assche static void srp_remove_target(struct srp_target_port *target)
1038ee12d6a8SBart Van Assche {
1039d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1040d92c0da7SBart Van Assche 	int i;
1041509c07bcSBart Van Assche 
1042ef6c49d8SBart Van Assche 	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
1043ef6c49d8SBart Van Assche 
1044ee12d6a8SBart Van Assche 	srp_del_scsi_host_attr(target->scsi_host);
10459dd69a60SBart Van Assche 	srp_rport_get(target->rport);
1046ee12d6a8SBart Van Assche 	srp_remove_host(target->scsi_host);
1047ee12d6a8SBart Van Assche 	scsi_remove_host(target->scsi_host);
104893079162SBart Van Assche 	srp_stop_rport_timers(target->rport);
1049ef6c49d8SBart Van Assche 	srp_disconnect_target(target);
105019f31343SBart Van Assche 	kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
1051d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1052d92c0da7SBart Van Assche 		ch = &target->ch[i];
1053509c07bcSBart Van Assche 		srp_free_ch_ib(target, ch);
1054d92c0da7SBart Van Assche 	}
1055c1120f89SBart Van Assche 	cancel_work_sync(&target->tl_err_work);
10569dd69a60SBart Van Assche 	srp_rport_put(target->rport);
1057d92c0da7SBart Van Assche 	kfree(target->ch);
1058d92c0da7SBart Van Assche 	target->ch = NULL;
105965d7dd2fSVu Pham 
106065d7dd2fSVu Pham 	spin_lock(&target->srp_host->target_lock);
106165d7dd2fSVu Pham 	list_del(&target->list);
106265d7dd2fSVu Pham 	spin_unlock(&target->srp_host->target_lock);
106365d7dd2fSVu Pham 
1064ee12d6a8SBart Van Assche 	scsi_host_put(target->scsi_host);
1065ee12d6a8SBart Van Assche }
1066ee12d6a8SBart Van Assche 
srp_remove_work(struct work_struct * work)1067c4028958SDavid Howells static void srp_remove_work(struct work_struct *work)
1068aef9ec39SRoland Dreier {
1069c4028958SDavid Howells 	struct srp_target_port *target =
1070ef6c49d8SBart Van Assche 		container_of(work, struct srp_target_port, remove_work);
1071aef9ec39SRoland Dreier 
1072ef6c49d8SBart Van Assche 	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
1073aef9ec39SRoland Dreier 
107496fc248aSBart Van Assche 	srp_remove_target(target);
1075aef9ec39SRoland Dreier }
1076aef9ec39SRoland Dreier 
srp_rport_delete(struct srp_rport * rport)1077dc1bdbd9SBart Van Assche static void srp_rport_delete(struct srp_rport *rport)
1078dc1bdbd9SBart Van Assche {
1079dc1bdbd9SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1080dc1bdbd9SBart Van Assche 
1081dc1bdbd9SBart Van Assche 	srp_queue_remove_work(target);
1082dc1bdbd9SBart Van Assche }
1083dc1bdbd9SBart Van Assche 
1084c014c8cdSBart Van Assche /**
1085c014c8cdSBart Van Assche  * srp_connected_ch() - number of connected channels
1086c014c8cdSBart Van Assche  * @target: SRP target port.
1087c014c8cdSBart Van Assche  */
srp_connected_ch(struct srp_target_port * target)1088c014c8cdSBart Van Assche static int srp_connected_ch(struct srp_target_port *target)
1089c014c8cdSBart Van Assche {
1090c014c8cdSBart Van Assche 	int i, c = 0;
1091c014c8cdSBart Van Assche 
1092c014c8cdSBart Van Assche 	for (i = 0; i < target->ch_count; i++)
1093c014c8cdSBart Van Assche 		c += target->ch[i].connected;
1094c014c8cdSBart Van Assche 
1095c014c8cdSBart Van Assche 	return c;
1096c014c8cdSBart Van Assche }
1097c014c8cdSBart Van Assche 
srp_connect_ch(struct srp_rdma_ch * ch,uint32_t max_iu_len,bool multich)1098513d5647SBart Van Assche static int srp_connect_ch(struct srp_rdma_ch *ch, uint32_t max_iu_len,
1099513d5647SBart Van Assche 			  bool multich)
1100aef9ec39SRoland Dreier {
1101509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1102aef9ec39SRoland Dreier 	int ret;
1103aef9ec39SRoland Dreier 
1104c014c8cdSBart Van Assche 	WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0);
1105294c875aSBart Van Assche 
1106509c07bcSBart Van Assche 	ret = srp_lookup_path(ch);
1107aef9ec39SRoland Dreier 	if (ret)
11084d59ad29SBart Van Assche 		goto out;
1109aef9ec39SRoland Dreier 
1110aef9ec39SRoland Dreier 	while (1) {
1111509c07bcSBart Van Assche 		init_completion(&ch->done);
1112513d5647SBart Van Assche 		ret = srp_send_req(ch, max_iu_len, multich);
1113aef9ec39SRoland Dreier 		if (ret)
11144d59ad29SBart Van Assche 			goto out;
1115509c07bcSBart Van Assche 		ret = wait_for_completion_interruptible(&ch->done);
1116a702adceSBart Van Assche 		if (ret < 0)
11174d59ad29SBart Van Assche 			goto out;
1118aef9ec39SRoland Dreier 
1119aef9ec39SRoland Dreier 		/*
1120aef9ec39SRoland Dreier 		 * The CM event handling code will set status to
1121aef9ec39SRoland Dreier 		 * SRP_PORT_REDIRECT if we get a port redirect REJ
1122aef9ec39SRoland Dreier 		 * back, or SRP_DLID_REDIRECT if we get a lid/qp
1123aef9ec39SRoland Dreier 		 * redirect REJ back.
1124aef9ec39SRoland Dreier 		 */
11254d59ad29SBart Van Assche 		ret = ch->status;
11264d59ad29SBart Van Assche 		switch (ret) {
1127aef9ec39SRoland Dreier 		case 0:
1128c014c8cdSBart Van Assche 			ch->connected = true;
11294d59ad29SBart Van Assche 			goto out;
1130aef9ec39SRoland Dreier 
1131aef9ec39SRoland Dreier 		case SRP_PORT_REDIRECT:
1132509c07bcSBart Van Assche 			ret = srp_lookup_path(ch);
1133aef9ec39SRoland Dreier 			if (ret)
11344d59ad29SBart Van Assche 				goto out;
1135aef9ec39SRoland Dreier 			break;
1136aef9ec39SRoland Dreier 
1137aef9ec39SRoland Dreier 		case SRP_DLID_REDIRECT:
1138aef9ec39SRoland Dreier 			break;
1139aef9ec39SRoland Dreier 
11409fe4bcf4SDavid Dillow 		case SRP_STALE_CONN:
11419fe4bcf4SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host, PFX
11429fe4bcf4SDavid Dillow 				     "giving up on stale connection\n");
11434d59ad29SBart Van Assche 			ret = -ECONNRESET;
11444d59ad29SBart Van Assche 			goto out;
11459fe4bcf4SDavid Dillow 
1146aef9ec39SRoland Dreier 		default:
11474d59ad29SBart Van Assche 			goto out;
1148aef9ec39SRoland Dreier 		}
1149aef9ec39SRoland Dreier 	}
11504d59ad29SBart Van Assche 
11514d59ad29SBart Van Assche out:
11524d59ad29SBart Van Assche 	return ret <= 0 ? ret : -ENODEV;
1153aef9ec39SRoland Dreier }
1154aef9ec39SRoland Dreier 
srp_inv_rkey_err_done(struct ib_cq * cq,struct ib_wc * wc)11551dc7b1f1SChristoph Hellwig static void srp_inv_rkey_err_done(struct ib_cq *cq, struct ib_wc *wc)
11561dc7b1f1SChristoph Hellwig {
11571dc7b1f1SChristoph Hellwig 	srp_handle_qp_err(cq, wc, "INV RKEY");
11581dc7b1f1SChristoph Hellwig }
11591dc7b1f1SChristoph Hellwig 
srp_inv_rkey(struct srp_request * req,struct srp_rdma_ch * ch,u32 rkey)11601dc7b1f1SChristoph Hellwig static int srp_inv_rkey(struct srp_request *req, struct srp_rdma_ch *ch,
11611dc7b1f1SChristoph Hellwig 		u32 rkey)
11625cfb1782SBart Van Assche {
11635cfb1782SBart Van Assche 	struct ib_send_wr wr = {
11645cfb1782SBart Van Assche 		.opcode		    = IB_WR_LOCAL_INV,
11655cfb1782SBart Van Assche 		.next		    = NULL,
11665cfb1782SBart Van Assche 		.num_sge	    = 0,
11675cfb1782SBart Van Assche 		.send_flags	    = 0,
11685cfb1782SBart Van Assche 		.ex.invalidate_rkey = rkey,
11695cfb1782SBart Van Assche 	};
11705cfb1782SBart Van Assche 
11711dc7b1f1SChristoph Hellwig 	wr.wr_cqe = &req->reg_cqe;
11721dc7b1f1SChristoph Hellwig 	req->reg_cqe.done = srp_inv_rkey_err_done;
117371347b0cSBart Van Assche 	return ib_post_send(ch->qp, &wr, NULL);
11745cfb1782SBart Van Assche }
11755cfb1782SBart Van Assche 
srp_unmap_data(struct scsi_cmnd * scmnd,struct srp_rdma_ch * ch,struct srp_request * req)1176d945e1dfSRoland Dreier static void srp_unmap_data(struct scsi_cmnd *scmnd,
1177509c07bcSBart Van Assche 			   struct srp_rdma_ch *ch,
1178d945e1dfSRoland Dreier 			   struct srp_request *req)
1179d945e1dfSRoland Dreier {
1180509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
11815cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
11825cfb1782SBart Van Assche 	struct ib_device *ibdev = dev->dev;
11835cfb1782SBart Van Assche 	int i, res;
11848f26c9ffSDavid Dillow 
1185bb350d1dSFUJITA Tomonori 	if (!scsi_sglist(scmnd) ||
1186d945e1dfSRoland Dreier 	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
1187d945e1dfSRoland Dreier 	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
1188d945e1dfSRoland Dreier 		return;
1189d945e1dfSRoland Dreier 
11905cfb1782SBart Van Assche 	if (dev->use_fast_reg) {
11915cfb1782SBart Van Assche 		struct srp_fr_desc **pfr;
11925cfb1782SBart Van Assche 
11935cfb1782SBart Van Assche 		for (i = req->nmdesc, pfr = req->fr_list; i > 0; i--, pfr++) {
11941dc7b1f1SChristoph Hellwig 			res = srp_inv_rkey(req, ch, (*pfr)->mr->rkey);
11955cfb1782SBart Van Assche 			if (res < 0) {
11965cfb1782SBart Van Assche 				shost_printk(KERN_ERR, target->scsi_host, PFX
11975cfb1782SBart Van Assche 				  "Queueing INV WR for rkey %#x failed (%d)\n",
11985cfb1782SBart Van Assche 				  (*pfr)->mr->rkey, res);
11995cfb1782SBart Van Assche 				queue_work(system_long_wq,
12005cfb1782SBart Van Assche 					   &target->tl_err_work);
12015cfb1782SBart Van Assche 			}
12025cfb1782SBart Van Assche 		}
12035cfb1782SBart Van Assche 		if (req->nmdesc)
1204509c07bcSBart Van Assche 			srp_fr_pool_put(ch->fr_pool, req->fr_list,
12055cfb1782SBart Van Assche 					req->nmdesc);
12065cfb1782SBart Van Assche 	}
1207f5358a17SRoland Dreier 
12088f26c9ffSDavid Dillow 	ib_dma_unmap_sg(ibdev, scsi_sglist(scmnd), scsi_sg_count(scmnd),
12098f26c9ffSDavid Dillow 			scmnd->sc_data_direction);
1210d945e1dfSRoland Dreier }
1211d945e1dfSRoland Dreier 
121222032991SBart Van Assche /**
121322032991SBart Van Assche  * srp_claim_req - Take ownership of the scmnd associated with a request.
1214509c07bcSBart Van Assche  * @ch: SRP RDMA channel.
121522032991SBart Van Assche  * @req: SRP request.
1216b3fe628dSBart Van Assche  * @sdev: If not NULL, only take ownership for this SCSI device.
121722032991SBart Van Assche  * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
121822032991SBart Van Assche  *         ownership of @req->scmnd if it equals @scmnd.
121922032991SBart Van Assche  *
122022032991SBart Van Assche  * Return value:
122122032991SBart Van Assche  * Either NULL or a pointer to the SCSI command the caller became owner of.
122222032991SBart Van Assche  */
srp_claim_req(struct srp_rdma_ch * ch,struct srp_request * req,struct scsi_device * sdev,struct scsi_cmnd * scmnd)1223509c07bcSBart Van Assche static struct scsi_cmnd *srp_claim_req(struct srp_rdma_ch *ch,
122422032991SBart Van Assche 				       struct srp_request *req,
1225b3fe628dSBart Van Assche 				       struct scsi_device *sdev,
122622032991SBart Van Assche 				       struct scsi_cmnd *scmnd)
1227526b4caaSIshai Rabinovitz {
122894a9174cSBart Van Assche 	unsigned long flags;
122994a9174cSBart Van Assche 
1230509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1231b3fe628dSBart Van Assche 	if (req->scmnd &&
1232b3fe628dSBart Van Assche 	    (!sdev || req->scmnd->device == sdev) &&
1233b3fe628dSBart Van Assche 	    (!scmnd || req->scmnd == scmnd)) {
123422032991SBart Van Assche 		scmnd = req->scmnd;
123522032991SBart Van Assche 		req->scmnd = NULL;
123622032991SBart Van Assche 	} else {
123722032991SBart Van Assche 		scmnd = NULL;
123822032991SBart Van Assche 	}
1239509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
124022032991SBart Van Assche 
124122032991SBart Van Assche 	return scmnd;
124222032991SBart Van Assche }
124322032991SBart Van Assche 
124422032991SBart Van Assche /**
12456ec2ba02SBart Van Assche  * srp_free_req() - Unmap data and adjust ch->req_lim.
1246509c07bcSBart Van Assche  * @ch:     SRP RDMA channel.
1247af24663bSBart Van Assche  * @req:    Request to be freed.
1248af24663bSBart Van Assche  * @scmnd:  SCSI command associated with @req.
1249af24663bSBart Van Assche  * @req_lim_delta: Amount to be added to @target->req_lim.
125022032991SBart Van Assche  */
srp_free_req(struct srp_rdma_ch * ch,struct srp_request * req,struct scsi_cmnd * scmnd,s32 req_lim_delta)1251509c07bcSBart Van Assche static void srp_free_req(struct srp_rdma_ch *ch, struct srp_request *req,
1252509c07bcSBart Van Assche 			 struct scsi_cmnd *scmnd, s32 req_lim_delta)
125322032991SBart Van Assche {
125422032991SBart Van Assche 	unsigned long flags;
125522032991SBart Van Assche 
1256509c07bcSBart Van Assche 	srp_unmap_data(scmnd, ch, req);
125722032991SBart Van Assche 
1258509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1259509c07bcSBart Van Assche 	ch->req_lim += req_lim_delta;
1260509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
1261526b4caaSIshai Rabinovitz }
1262526b4caaSIshai Rabinovitz 
srp_finish_req(struct srp_rdma_ch * ch,struct srp_request * req,struct scsi_device * sdev,int result)1263509c07bcSBart Van Assche static void srp_finish_req(struct srp_rdma_ch *ch, struct srp_request *req,
1264509c07bcSBart Van Assche 			   struct scsi_device *sdev, int result)
1265526b4caaSIshai Rabinovitz {
1266509c07bcSBart Van Assche 	struct scsi_cmnd *scmnd = srp_claim_req(ch, req, sdev, NULL);
126722032991SBart Van Assche 
126822032991SBart Van Assche 	if (scmnd) {
1269509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd, 0);
1270ed9b2264SBart Van Assche 		scmnd->result = result;
12715f9ae9eeSBart Van Assche 		scsi_done(scmnd);
127222032991SBart Van Assche 	}
1273526b4caaSIshai Rabinovitz }
1274526b4caaSIshai Rabinovitz 
1275ad215aaeSBart Van Assche struct srp_terminate_context {
1276ad215aaeSBart Van Assche 	struct srp_target_port *srp_target;
1277ad215aaeSBart Van Assche 	int scsi_result;
1278ad215aaeSBart Van Assche };
1279ad215aaeSBart Van Assche 
srp_terminate_cmd(struct scsi_cmnd * scmnd,void * context_ptr)12802dd6532eSJohn Garry static bool srp_terminate_cmd(struct scsi_cmnd *scmnd, void *context_ptr)
1281ad215aaeSBart Van Assche {
1282ad215aaeSBart Van Assche 	struct srp_terminate_context *context = context_ptr;
1283ad215aaeSBart Van Assche 	struct srp_target_port *target = context->srp_target;
12849c5274eeSBart Van Assche 	u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmnd));
1285ad215aaeSBart Van Assche 	struct srp_rdma_ch *ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
1286ad215aaeSBart Van Assche 	struct srp_request *req = scsi_cmd_priv(scmnd);
1287ad215aaeSBart Van Assche 
1288ad215aaeSBart Van Assche 	srp_finish_req(ch, req, NULL, context->scsi_result);
1289ad215aaeSBart Van Assche 
1290ad215aaeSBart Van Assche 	return true;
1291ad215aaeSBart Van Assche }
1292ad215aaeSBart Van Assche 
srp_terminate_io(struct srp_rport * rport)1293ed9b2264SBart Van Assche static void srp_terminate_io(struct srp_rport *rport)
1294aef9ec39SRoland Dreier {
1295ed9b2264SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1296ad215aaeSBart Van Assche 	struct srp_terminate_context context = { .srp_target = target,
1297ad215aaeSBart Van Assche 		.scsi_result = DID_TRANSPORT_FAILFAST << 16 };
1298aef9ec39SRoland Dreier 
1299ad215aaeSBart Van Assche 	scsi_host_busy_iter(target->scsi_host, srp_terminate_cmd, &context);
1300ed9b2264SBart Van Assche }
1301ed9b2264SBart Van Assche 
1302513d5647SBart Van Assche /* Calculate maximum initiator to target information unit length. */
srp_max_it_iu_len(int cmd_sg_cnt,bool use_imm_data,uint32_t max_it_iu_size)1303b2e872f4SHonggang Li static uint32_t srp_max_it_iu_len(int cmd_sg_cnt, bool use_imm_data,
1304b2e872f4SHonggang Li 				  uint32_t max_it_iu_size)
1305513d5647SBart Van Assche {
1306513d5647SBart Van Assche 	uint32_t max_iu_len = sizeof(struct srp_cmd) + SRP_MAX_ADD_CDB_LEN +
1307513d5647SBart Van Assche 		sizeof(struct srp_indirect_buf) +
1308513d5647SBart Van Assche 		cmd_sg_cnt * sizeof(struct srp_direct_buf);
1309513d5647SBart Van Assche 
1310882981f4SBart Van Assche 	if (use_imm_data)
1311882981f4SBart Van Assche 		max_iu_len = max(max_iu_len, SRP_IMM_DATA_OFFSET +
1312882981f4SBart Van Assche 				 srp_max_imm_data);
1313882981f4SBart Van Assche 
1314b2e872f4SHonggang Li 	if (max_it_iu_size)
1315b2e872f4SHonggang Li 		max_iu_len = min(max_iu_len, max_it_iu_size);
1316b2e872f4SHonggang Li 
1317b2e872f4SHonggang Li 	pr_debug("max_iu_len = %d\n", max_iu_len);
1318b2e872f4SHonggang Li 
1319513d5647SBart Van Assche 	return max_iu_len;
1320513d5647SBart Van Assche }
1321513d5647SBart Van Assche 
1322ed9b2264SBart Van Assche /*
1323ed9b2264SBart Van Assche  * It is up to the caller to ensure that srp_rport_reconnect() calls are
1324ed9b2264SBart Van Assche  * serialized and that no concurrent srp_queuecommand(), srp_abort(),
1325ed9b2264SBart Van Assche  * srp_reset_device() or srp_reset_host() calls will occur while this function
1326ed9b2264SBart Van Assche  * is in progress. One way to realize that is not to call this function
1327ed9b2264SBart Van Assche  * directly but to call srp_reconnect_rport() instead since that last function
1328ed9b2264SBart Van Assche  * serializes calls of this function via rport->mutex and also blocks
1329ed9b2264SBart Van Assche  * srp_queuecommand() calls before invoking this function.
1330ed9b2264SBart Van Assche  */
srp_rport_reconnect(struct srp_rport * rport)1331ed9b2264SBart Van Assche static int srp_rport_reconnect(struct srp_rport *rport)
1332ed9b2264SBart Van Assche {
1333ed9b2264SBart Van Assche 	struct srp_target_port *target = rport->lld_data;
1334d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
1335882981f4SBart Van Assche 	uint32_t max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
1336b2e872f4SHonggang Li 						srp_use_imm_data,
1337b2e872f4SHonggang Li 						target->max_it_iu_size);
1338d92c0da7SBart Van Assche 	int i, j, ret = 0;
1339d92c0da7SBart Van Assche 	bool multich = false;
134009be70a2SBart Van Assche 
1341aef9ec39SRoland Dreier 	srp_disconnect_target(target);
134234aa654eSBart Van Assche 
134334aa654eSBart Van Assche 	if (target->state == SRP_TARGET_SCANNING)
134434aa654eSBart Van Assche 		return -ENODEV;
134534aa654eSBart Van Assche 
1346aef9ec39SRoland Dreier 	/*
1347c7c4e7ffSBart Van Assche 	 * Now get a new local CM ID so that we avoid confusing the target in
1348c7c4e7ffSBart Van Assche 	 * case things are really fouled up. Doing so also ensures that all CM
1349c7c4e7ffSBart Van Assche 	 * callbacks will have finished before a new QP is allocated.
1350aef9ec39SRoland Dreier 	 */
1351d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1352d92c0da7SBart Van Assche 		ch = &target->ch[i];
1353d92c0da7SBart Van Assche 		ret += srp_new_cm_id(ch);
1354d92c0da7SBart Van Assche 	}
1355ad215aaeSBart Van Assche 	{
1356ad215aaeSBart Van Assche 		struct srp_terminate_context context = {
1357ad215aaeSBart Van Assche 			.srp_target = target, .scsi_result = DID_RESET << 16};
1358509c07bcSBart Van Assche 
1359ad215aaeSBart Van Assche 		scsi_host_busy_iter(target->scsi_host, srp_terminate_cmd,
1360ad215aaeSBart Van Assche 				    &context);
1361d92c0da7SBart Van Assche 	}
1362d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1363d92c0da7SBart Van Assche 		ch = &target->ch[i];
13645cfb1782SBart Van Assche 		/*
13655cfb1782SBart Van Assche 		 * Whether or not creating a new CM ID succeeded, create a new
1366d92c0da7SBart Van Assche 		 * QP. This guarantees that all completion callback function
1367d92c0da7SBart Van Assche 		 * invocations have finished before request resetting starts.
13685cfb1782SBart Van Assche 		 */
1369509c07bcSBart Van Assche 		ret += srp_create_ch_ib(ch);
13705cfb1782SBart Van Assche 
1371509c07bcSBart Van Assche 		INIT_LIST_HEAD(&ch->free_tx);
1372d92c0da7SBart Van Assche 		for (j = 0; j < target->queue_size; ++j)
1373d92c0da7SBart Van Assche 			list_add(&ch->tx_ring[j]->list, &ch->free_tx);
1374d92c0da7SBart Van Assche 	}
13758de9fe3aSBart Van Assche 
13768de9fe3aSBart Van Assche 	target->qp_in_error = false;
13778de9fe3aSBart Van Assche 
1378d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
1379d92c0da7SBart Van Assche 		ch = &target->ch[i];
1380bbac5ccfSBart Van Assche 		if (ret)
1381d92c0da7SBart Van Assche 			break;
1382513d5647SBart Van Assche 		ret = srp_connect_ch(ch, max_iu_len, multich);
1383d92c0da7SBart Van Assche 		multich = true;
1384d92c0da7SBart Van Assche 	}
138509be70a2SBart Van Assche 
1386ed9b2264SBart Van Assche 	if (ret == 0)
1387ed9b2264SBart Van Assche 		shost_printk(KERN_INFO, target->scsi_host,
1388ed9b2264SBart Van Assche 			     PFX "reconnect succeeded\n");
1389aef9ec39SRoland Dreier 
1390aef9ec39SRoland Dreier 	return ret;
1391aef9ec39SRoland Dreier }
1392aef9ec39SRoland Dreier 
srp_map_desc(struct srp_map_state * state,dma_addr_t dma_addr,unsigned int dma_len,u32 rkey)13938f26c9ffSDavid Dillow static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr,
13948f26c9ffSDavid Dillow 			 unsigned int dma_len, u32 rkey)
1395f5358a17SRoland Dreier {
13968f26c9ffSDavid Dillow 	struct srp_direct_buf *desc = state->desc;
13978f26c9ffSDavid Dillow 
13983ae95da8SBart Van Assche 	WARN_ON_ONCE(!dma_len);
13993ae95da8SBart Van Assche 
14008f26c9ffSDavid Dillow 	desc->va = cpu_to_be64(dma_addr);
14018f26c9ffSDavid Dillow 	desc->key = cpu_to_be32(rkey);
14028f26c9ffSDavid Dillow 	desc->len = cpu_to_be32(dma_len);
14038f26c9ffSDavid Dillow 
14048f26c9ffSDavid Dillow 	state->total_len += dma_len;
14058f26c9ffSDavid Dillow 	state->desc++;
14068f26c9ffSDavid Dillow 	state->ndesc++;
14078f26c9ffSDavid Dillow }
14088f26c9ffSDavid Dillow 
srp_reg_mr_err_done(struct ib_cq * cq,struct ib_wc * wc)14091dc7b1f1SChristoph Hellwig static void srp_reg_mr_err_done(struct ib_cq *cq, struct ib_wc *wc)
14101dc7b1f1SChristoph Hellwig {
14111dc7b1f1SChristoph Hellwig 	srp_handle_qp_err(cq, wc, "FAST REG");
14121dc7b1f1SChristoph Hellwig }
14131dc7b1f1SChristoph Hellwig 
1414509c5f33SBart Van Assche /*
1415509c5f33SBart Van Assche  * Map up to sg_nents elements of state->sg where *sg_offset_p is the offset
1416509c5f33SBart Van Assche  * where to start in the first element. If sg_offset_p != NULL then
1417509c5f33SBart Van Assche  * *sg_offset_p is updated to the offset in state->sg[retval] of the first
1418509c5f33SBart Van Assche  * byte that has not yet been mapped.
1419509c5f33SBart Van Assche  */
srp_map_finish_fr(struct srp_map_state * state,struct srp_request * req,struct srp_rdma_ch * ch,int sg_nents,unsigned int * sg_offset_p)14205cfb1782SBart Van Assche static int srp_map_finish_fr(struct srp_map_state *state,
14211dc7b1f1SChristoph Hellwig 			     struct srp_request *req,
1422509c5f33SBart Van Assche 			     struct srp_rdma_ch *ch, int sg_nents,
1423509c5f33SBart Van Assche 			     unsigned int *sg_offset_p)
14245cfb1782SBart Van Assche {
1425509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
14265cfb1782SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
1427f7f7aab1SSagi Grimberg 	struct ib_reg_wr wr;
14285cfb1782SBart Van Assche 	struct srp_fr_desc *desc;
14295cfb1782SBart Van Assche 	u32 rkey;
1430f7f7aab1SSagi Grimberg 	int n, err;
14315cfb1782SBart Van Assche 
1432290081b4SBart Van Assche 	if (state->fr.next >= state->fr.end) {
1433290081b4SBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host,
1434290081b4SBart Van Assche 			     PFX "Out of MRs (mr_per_cmd = %d)\n",
1435290081b4SBart Van Assche 			     ch->target->mr_per_cmd);
1436f731ed62SBart Van Assche 		return -ENOMEM;
1437290081b4SBart Van Assche 	}
1438f731ed62SBart Van Assche 
143926630e8aSSagi Grimberg 	WARN_ON_ONCE(!dev->use_fast_reg);
144026630e8aSSagi Grimberg 
1441cee687b6SBart Van Assche 	if (sg_nents == 1 && target->global_rkey) {
1442509c5f33SBart Van Assche 		unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
1443509c5f33SBart Van Assche 
1444509c5f33SBart Van Assche 		srp_map_desc(state, sg_dma_address(state->sg) + sg_offset,
1445509c5f33SBart Van Assche 			     sg_dma_len(state->sg) - sg_offset,
1446cee687b6SBart Van Assche 			     target->global_rkey);
1447509c5f33SBart Van Assche 		if (sg_offset_p)
1448509c5f33SBart Van Assche 			*sg_offset_p = 0;
1449f7f7aab1SSagi Grimberg 		return 1;
145026630e8aSSagi Grimberg 	}
145126630e8aSSagi Grimberg 
1452509c07bcSBart Van Assche 	desc = srp_fr_pool_get(ch->fr_pool);
14535cfb1782SBart Van Assche 	if (!desc)
14545cfb1782SBart Van Assche 		return -ENOMEM;
14555cfb1782SBart Van Assche 
14565cfb1782SBart Van Assche 	rkey = ib_inc_rkey(desc->mr->rkey);
14575cfb1782SBart Van Assche 	ib_update_fast_reg_key(desc->mr, rkey);
14585cfb1782SBart Van Assche 
1459509c5f33SBart Van Assche 	n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, sg_offset_p,
1460509c5f33SBart Van Assche 			 dev->mr_page_size);
14619d8e7d0dSBart Van Assche 	if (unlikely(n < 0)) {
14629d8e7d0dSBart Van Assche 		srp_fr_pool_put(ch->fr_pool, &desc, 1);
1463509c5f33SBart Van Assche 		pr_debug("%s: ib_map_mr_sg(%d, %d) returned %d.\n",
14649d8e7d0dSBart Van Assche 			 dev_name(&req->scmnd->device->sdev_gendev), sg_nents,
1465509c5f33SBart Van Assche 			 sg_offset_p ? *sg_offset_p : -1, n);
1466f7f7aab1SSagi Grimberg 		return n;
14679d8e7d0dSBart Van Assche 	}
14685cfb1782SBart Van Assche 
1469509c5f33SBart Van Assche 	WARN_ON_ONCE(desc->mr->length == 0);
14705cfb1782SBart Van Assche 
14711dc7b1f1SChristoph Hellwig 	req->reg_cqe.done = srp_reg_mr_err_done;
14721dc7b1f1SChristoph Hellwig 
1473f7f7aab1SSagi Grimberg 	wr.wr.next = NULL;
1474f7f7aab1SSagi Grimberg 	wr.wr.opcode = IB_WR_REG_MR;
14751dc7b1f1SChristoph Hellwig 	wr.wr.wr_cqe = &req->reg_cqe;
1476f7f7aab1SSagi Grimberg 	wr.wr.num_sge = 0;
1477f7f7aab1SSagi Grimberg 	wr.wr.send_flags = 0;
1478f7f7aab1SSagi Grimberg 	wr.mr = desc->mr;
1479f7f7aab1SSagi Grimberg 	wr.key = desc->mr->rkey;
1480f7f7aab1SSagi Grimberg 	wr.access = (IB_ACCESS_LOCAL_WRITE |
14815cfb1782SBart Van Assche 		     IB_ACCESS_REMOTE_READ |
14825cfb1782SBart Van Assche 		     IB_ACCESS_REMOTE_WRITE);
14835cfb1782SBart Van Assche 
1484f731ed62SBart Van Assche 	*state->fr.next++ = desc;
14855cfb1782SBart Van Assche 	state->nmdesc++;
14865cfb1782SBart Van Assche 
1487f7f7aab1SSagi Grimberg 	srp_map_desc(state, desc->mr->iova,
1488f7f7aab1SSagi Grimberg 		     desc->mr->length, desc->mr->rkey);
14895cfb1782SBart Van Assche 
149071347b0cSBart Van Assche 	err = ib_post_send(ch->qp, &wr.wr, NULL);
1491509c5f33SBart Van Assche 	if (unlikely(err)) {
1492509c5f33SBart Van Assche 		WARN_ON_ONCE(err == -ENOMEM);
149326630e8aSSagi Grimberg 		return err;
1494509c5f33SBart Van Assche 	}
149526630e8aSSagi Grimberg 
1496f7f7aab1SSagi Grimberg 	return n;
14975cfb1782SBart Van Assche }
14985cfb1782SBart Van Assche 
srp_map_sg_fr(struct srp_map_state * state,struct srp_rdma_ch * ch,struct srp_request * req,struct scatterlist * scat,int count)149926630e8aSSagi Grimberg static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
150026630e8aSSagi Grimberg 			 struct srp_request *req, struct scatterlist *scat,
150126630e8aSSagi Grimberg 			 int count)
150226630e8aSSagi Grimberg {
1503509c5f33SBart Van Assche 	unsigned int sg_offset = 0;
1504509c5f33SBart Van Assche 
1505f7f7aab1SSagi Grimberg 	state->fr.next = req->fr_list;
1506509c5f33SBart Van Assche 	state->fr.end = req->fr_list + ch->target->mr_per_cmd;
1507f7f7aab1SSagi Grimberg 	state->sg = scat;
150826630e8aSSagi Grimberg 
15093b59b7a6SBart Van Assche 	if (count == 0)
15103b59b7a6SBart Van Assche 		return 0;
15113b59b7a6SBart Van Assche 
151257b0be9cSBart Van Assche 	while (count) {
1513f7f7aab1SSagi Grimberg 		int i, n;
1514f7f7aab1SSagi Grimberg 
1515509c5f33SBart Van Assche 		n = srp_map_finish_fr(state, req, ch, count, &sg_offset);
1516f7f7aab1SSagi Grimberg 		if (unlikely(n < 0))
1517f7f7aab1SSagi Grimberg 			return n;
1518f7f7aab1SSagi Grimberg 
151957b0be9cSBart Van Assche 		count -= n;
1520f7f7aab1SSagi Grimberg 		for (i = 0; i < n; i++)
1521f7f7aab1SSagi Grimberg 			state->sg = sg_next(state->sg);
152226630e8aSSagi Grimberg 	}
152326630e8aSSagi Grimberg 
152426630e8aSSagi Grimberg 	return 0;
152526630e8aSSagi Grimberg }
152626630e8aSSagi Grimberg 
srp_map_sg_dma(struct srp_map_state * state,struct srp_rdma_ch * ch,struct srp_request * req,struct scatterlist * scat,int count)152726630e8aSSagi Grimberg static int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
1528509c07bcSBart Van Assche 			  struct srp_request *req, struct scatterlist *scat,
1529509c07bcSBart Van Assche 			  int count)
153076bc1e1dSBart Van Assche {
1531509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
153276bc1e1dSBart Van Assche 	struct scatterlist *sg;
153326630e8aSSagi Grimberg 	int i;
153476bc1e1dSBart Van Assche 
15353ae95da8SBart Van Assche 	for_each_sg(scat, sg, count, i) {
1536a163afc8SBart Van Assche 		srp_map_desc(state, sg_dma_address(sg), sg_dma_len(sg),
1537cee687b6SBart Van Assche 			     target->global_rkey);
15383ae95da8SBart Van Assche 	}
153976bc1e1dSBart Van Assche 
154026630e8aSSagi Grimberg 	return 0;
154176bc1e1dSBart Van Assche }
154276bc1e1dSBart Van Assche 
1543330179f2SBart Van Assche /*
1544330179f2SBart Van Assche  * Register the indirect data buffer descriptor with the HCA.
1545330179f2SBart Van Assche  *
1546330179f2SBart Van Assche  * Note: since the indirect data buffer descriptor has been allocated with
1547330179f2SBart Van Assche  * kmalloc() it is guaranteed that this buffer is a physically contiguous
1548330179f2SBart Van Assche  * memory buffer.
1549330179f2SBart Van Assche  */
srp_map_idb(struct srp_rdma_ch * ch,struct srp_request * req,void ** next_mr,void ** end_mr,u32 idb_len,__be32 * idb_rkey)1550330179f2SBart Van Assche static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
1551330179f2SBart Van Assche 		       void **next_mr, void **end_mr, u32 idb_len,
1552330179f2SBart Van Assche 		       __be32 *idb_rkey)
1553330179f2SBart Van Assche {
1554330179f2SBart Van Assche 	struct srp_target_port *target = ch->target;
1555330179f2SBart Van Assche 	struct srp_device *dev = target->srp_host->srp_dev;
1556330179f2SBart Van Assche 	struct srp_map_state state;
1557330179f2SBart Van Assche 	struct srp_direct_buf idb_desc;
1558f7f7aab1SSagi Grimberg 	struct scatterlist idb_sg[1];
1559330179f2SBart Van Assche 	int ret;
1560330179f2SBart Van Assche 
1561330179f2SBart Van Assche 	memset(&state, 0, sizeof(state));
1562330179f2SBart Van Assche 	memset(&idb_desc, 0, sizeof(idb_desc));
1563330179f2SBart Van Assche 	state.gen.next = next_mr;
1564330179f2SBart Van Assche 	state.gen.end = end_mr;
1565330179f2SBart Van Assche 	state.desc = &idb_desc;
1566f7f7aab1SSagi Grimberg 	state.base_dma_addr = req->indirect_dma_addr;
1567f7f7aab1SSagi Grimberg 	state.dma_len = idb_len;
1568f7f7aab1SSagi Grimberg 
1569f7f7aab1SSagi Grimberg 	if (dev->use_fast_reg) {
1570f7f7aab1SSagi Grimberg 		state.sg = idb_sg;
157154f5c9c5SBart Van Assche 		sg_init_one(idb_sg, req->indirect_desc, idb_len);
1572f7f7aab1SSagi Grimberg 		idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
1573fc925518SChristoph Hellwig #ifdef CONFIG_NEED_SG_DMA_LENGTH
1574fc925518SChristoph Hellwig 		idb_sg->dma_length = idb_sg->length;	      /* hack^2 */
1575fc925518SChristoph Hellwig #endif
1576509c5f33SBart Van Assche 		ret = srp_map_finish_fr(&state, req, ch, 1, NULL);
1577f7f7aab1SSagi Grimberg 		if (ret < 0)
1578f7f7aab1SSagi Grimberg 			return ret;
1579509c5f33SBart Van Assche 		WARN_ON_ONCE(ret < 1);
1580f7f7aab1SSagi Grimberg 	} else {
1581f7f7aab1SSagi Grimberg 		return -EINVAL;
1582f7f7aab1SSagi Grimberg 	}
1583330179f2SBart Van Assche 
1584330179f2SBart Van Assche 	*idb_rkey = idb_desc.key;
1585330179f2SBart Van Assche 
1586f7f7aab1SSagi Grimberg 	return 0;
1587330179f2SBart Van Assche }
1588330179f2SBart Van Assche 
srp_check_mapping(struct srp_map_state * state,struct srp_rdma_ch * ch,struct srp_request * req,struct scatterlist * scat,int count)1589509c5f33SBart Van Assche static void srp_check_mapping(struct srp_map_state *state,
1590509c5f33SBart Van Assche 			      struct srp_rdma_ch *ch, struct srp_request *req,
1591509c5f33SBart Van Assche 			      struct scatterlist *scat, int count)
1592509c5f33SBart Van Assche {
1593509c5f33SBart Van Assche 	struct srp_device *dev = ch->target->srp_host->srp_dev;
1594509c5f33SBart Van Assche 	struct srp_fr_desc **pfr;
1595509c5f33SBart Van Assche 	u64 desc_len = 0, mr_len = 0;
1596509c5f33SBart Van Assche 	int i;
1597509c5f33SBart Van Assche 
1598509c5f33SBart Van Assche 	for (i = 0; i < state->ndesc; i++)
1599509c5f33SBart Van Assche 		desc_len += be32_to_cpu(req->indirect_desc[i].len);
1600509c5f33SBart Van Assche 	if (dev->use_fast_reg)
1601509c5f33SBart Van Assche 		for (i = 0, pfr = req->fr_list; i < state->nmdesc; i++, pfr++)
1602509c5f33SBart Van Assche 			mr_len += (*pfr)->mr->length;
1603509c5f33SBart Van Assche 	if (desc_len != scsi_bufflen(req->scmnd) ||
1604509c5f33SBart Van Assche 	    mr_len > scsi_bufflen(req->scmnd))
1605509c5f33SBart Van Assche 		pr_err("Inconsistent: scsi len %d <> desc len %lld <> mr len %lld; ndesc %d; nmdesc = %d\n",
1606509c5f33SBart Van Assche 		       scsi_bufflen(req->scmnd), desc_len, mr_len,
1607509c5f33SBart Van Assche 		       state->ndesc, state->nmdesc);
1608509c5f33SBart Van Assche }
1609509c5f33SBart Van Assche 
161077269cdfSBart Van Assche /**
161177269cdfSBart Van Assche  * srp_map_data() - map SCSI data buffer onto an SRP request
161277269cdfSBart Van Assche  * @scmnd: SCSI command to map
161377269cdfSBart Van Assche  * @ch: SRP RDMA channel
161477269cdfSBart Van Assche  * @req: SRP request
161577269cdfSBart Van Assche  *
161677269cdfSBart Van Assche  * Returns the length in bytes of the SRP_CMD IU or a negative value if
1617882981f4SBart Van Assche  * mapping failed. The size of any immediate data is not included in the
1618882981f4SBart Van Assche  * return value.
161977269cdfSBart Van Assche  */
srp_map_data(struct scsi_cmnd * scmnd,struct srp_rdma_ch * ch,struct srp_request * req)1620509c07bcSBart Van Assche static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
1621aef9ec39SRoland Dreier 			struct srp_request *req)
1622aef9ec39SRoland Dreier {
1623509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1624882981f4SBart Van Assche 	struct scatterlist *scat, *sg;
1625aef9ec39SRoland Dreier 	struct srp_cmd *cmd = req->cmd->buf;
1626882981f4SBart Van Assche 	int i, len, nents, count, ret;
162785507bccSRalph Campbell 	struct srp_device *dev;
162885507bccSRalph Campbell 	struct ib_device *ibdev;
16298f26c9ffSDavid Dillow 	struct srp_map_state state;
16308f26c9ffSDavid Dillow 	struct srp_indirect_buf *indirect_hdr;
1631882981f4SBart Van Assche 	u64 data_len;
1632330179f2SBart Van Assche 	u32 idb_len, table_len;
1633330179f2SBart Van Assche 	__be32 idb_rkey;
16348f26c9ffSDavid Dillow 	u8 fmt;
1635aef9ec39SRoland Dreier 
1636882981f4SBart Van Assche 	req->cmd->num_sge = 1;
1637882981f4SBart Van Assche 
1638bb350d1dSFUJITA Tomonori 	if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
1639482fffc4SBart Van Assche 		return sizeof(struct srp_cmd) + cmd->add_cdb_len;
1640aef9ec39SRoland Dreier 
1641aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
1642aef9ec39SRoland Dreier 	    scmnd->sc_data_direction != DMA_TO_DEVICE) {
16437aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
16447aa54bd7SDavid Dillow 			     PFX "Unhandled data direction %d\n",
1645aef9ec39SRoland Dreier 			     scmnd->sc_data_direction);
1646aef9ec39SRoland Dreier 		return -EINVAL;
1647aef9ec39SRoland Dreier 	}
1648aef9ec39SRoland Dreier 
1649bb350d1dSFUJITA Tomonori 	nents = scsi_sg_count(scmnd);
1650bb350d1dSFUJITA Tomonori 	scat  = scsi_sglist(scmnd);
1651882981f4SBart Van Assche 	data_len = scsi_bufflen(scmnd);
1652aef9ec39SRoland Dreier 
165305321937SGreg Kroah-Hartman 	dev = target->srp_host->srp_dev;
165485507bccSRalph Campbell 	ibdev = dev->dev;
165585507bccSRalph Campbell 
165685507bccSRalph Campbell 	count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
16578f26c9ffSDavid Dillow 	if (unlikely(count == 0))
16588f26c9ffSDavid Dillow 		return -EIO;
1659aef9ec39SRoland Dreier 
1660882981f4SBart Van Assche 	if (ch->use_imm_data &&
1661bf583470SBart Van Assche 	    count <= ch->max_imm_sge &&
1662882981f4SBart Van Assche 	    SRP_IMM_DATA_OFFSET + data_len <= ch->max_it_iu_len &&
1663882981f4SBart Van Assche 	    scmnd->sc_data_direction == DMA_TO_DEVICE) {
1664882981f4SBart Van Assche 		struct srp_imm_buf *buf;
1665882981f4SBart Van Assche 		struct ib_sge *sge = &req->cmd->sge[1];
1666882981f4SBart Van Assche 
1667882981f4SBart Van Assche 		fmt = SRP_DATA_DESC_IMM;
1668882981f4SBart Van Assche 		len = SRP_IMM_DATA_OFFSET;
1669882981f4SBart Van Assche 		req->nmdesc = 0;
1670882981f4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1671882981f4SBart Van Assche 		buf->len = cpu_to_be32(data_len);
1672882981f4SBart Van Assche 		WARN_ON_ONCE((void *)(buf + 1) > (void *)cmd + len);
1673882981f4SBart Van Assche 		for_each_sg(scat, sg, count, i) {
1674a163afc8SBart Van Assche 			sge[i].addr   = sg_dma_address(sg);
1675a163afc8SBart Van Assche 			sge[i].length = sg_dma_len(sg);
1676882981f4SBart Van Assche 			sge[i].lkey   = target->lkey;
1677882981f4SBart Van Assche 		}
1678882981f4SBart Van Assche 		req->cmd->num_sge += count;
1679882981f4SBart Van Assche 		goto map_complete;
1680882981f4SBart Van Assche 	}
1681882981f4SBart Van Assche 
1682aef9ec39SRoland Dreier 	fmt = SRP_DATA_DESC_DIRECT;
1683482fffc4SBart Van Assche 	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
1684482fffc4SBart Van Assche 		sizeof(struct srp_direct_buf);
1685f5358a17SRoland Dreier 
1686cee687b6SBart Van Assche 	if (count == 1 && target->global_rkey) {
1687f5358a17SRoland Dreier 		/*
1688f5358a17SRoland Dreier 		 * The midlayer only generated a single gather/scatter
1689f5358a17SRoland Dreier 		 * entry, or DMA mapping coalesced everything to a
1690f5358a17SRoland Dreier 		 * single entry.  So a direct descriptor along with
1691f5358a17SRoland Dreier 		 * the DMA MR suffices.
1692f5358a17SRoland Dreier 		 */
1693482fffc4SBart Van Assche 		struct srp_direct_buf *buf;
1694aef9ec39SRoland Dreier 
1695482fffc4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1696a163afc8SBart Van Assche 		buf->va  = cpu_to_be64(sg_dma_address(scat));
1697cee687b6SBart Van Assche 		buf->key = cpu_to_be32(target->global_rkey);
1698a163afc8SBart Van Assche 		buf->len = cpu_to_be32(sg_dma_len(scat));
16998f26c9ffSDavid Dillow 
170052ede08fSBart Van Assche 		req->nmdesc = 0;
17018f26c9ffSDavid Dillow 		goto map_complete;
17028f26c9ffSDavid Dillow 	}
17038f26c9ffSDavid Dillow 
17045cfb1782SBart Van Assche 	/*
17055cfb1782SBart Van Assche 	 * We have more than one scatter/gather entry, so build our indirect
17065cfb1782SBart Van Assche 	 * descriptor table, trying to merge as many entries as we can.
1707f5358a17SRoland Dreier 	 */
1708482fffc4SBart Van Assche 	indirect_hdr = (void *)cmd->add_data + cmd->add_cdb_len;
17098f26c9ffSDavid Dillow 
1710c07d424dSDavid Dillow 	ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
1711c07d424dSDavid Dillow 				   target->indirect_size, DMA_TO_DEVICE);
1712c07d424dSDavid Dillow 
17138f26c9ffSDavid Dillow 	memset(&state, 0, sizeof(state));
17149edba790SBart Van Assche 	state.desc = req->indirect_desc;
171526630e8aSSagi Grimberg 	if (dev->use_fast_reg)
1716e012f363SBart Van Assche 		ret = srp_map_sg_fr(&state, ch, req, scat, count);
171726630e8aSSagi Grimberg 	else
1718e012f363SBart Van Assche 		ret = srp_map_sg_dma(&state, ch, req, scat, count);
1719e012f363SBart Van Assche 	req->nmdesc = state.nmdesc;
1720e012f363SBart Van Assche 	if (ret < 0)
1721e012f363SBart Van Assche 		goto unmap;
17228f26c9ffSDavid Dillow 
1723509c5f33SBart Van Assche 	{
1724509c5f33SBart Van Assche 		DEFINE_DYNAMIC_DEBUG_METADATA(ddm,
1725509c5f33SBart Van Assche 			"Memory mapping consistency check");
17261a1faf7aSBart Van Assche 		if (DYNAMIC_DEBUG_BRANCH(ddm))
1727509c5f33SBart Van Assche 			srp_check_mapping(&state, ch, req, scat, count);
1728509c5f33SBart Van Assche 	}
17298f26c9ffSDavid Dillow 
1730c07d424dSDavid Dillow 	/* We've mapped the request, now pull as much of the indirect
1731c07d424dSDavid Dillow 	 * descriptor table as we can into the command buffer. If this
1732c07d424dSDavid Dillow 	 * target is not using an external indirect table, we are
1733c07d424dSDavid Dillow 	 * guaranteed to fit into the command, as the SCSI layer won't
1734c07d424dSDavid Dillow 	 * give us more S/G entries than we allow.
17358f26c9ffSDavid Dillow 	 */
17368f26c9ffSDavid Dillow 	if (state.ndesc == 1) {
17375cfb1782SBart Van Assche 		/*
17385cfb1782SBart Van Assche 		 * Memory registration collapsed the sg-list into one entry,
17398f26c9ffSDavid Dillow 		 * so use a direct descriptor.
17408f26c9ffSDavid Dillow 		 */
1741482fffc4SBart Van Assche 		struct srp_direct_buf *buf;
17428f26c9ffSDavid Dillow 
1743482fffc4SBart Van Assche 		buf = (void *)cmd->add_data + cmd->add_cdb_len;
1744c07d424dSDavid Dillow 		*buf = req->indirect_desc[0];
17458f26c9ffSDavid Dillow 		goto map_complete;
17468f26c9ffSDavid Dillow 	}
17478f26c9ffSDavid Dillow 
1748c07d424dSDavid Dillow 	if (unlikely(target->cmd_sg_cnt < state.ndesc &&
1749c07d424dSDavid Dillow 						!target->allow_ext_sg)) {
1750c07d424dSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
1751c07d424dSDavid Dillow 			     "Could not fit S/G list into SRP_CMD\n");
1752e012f363SBart Van Assche 		ret = -EIO;
1753e012f363SBart Van Assche 		goto unmap;
1754c07d424dSDavid Dillow 	}
1755c07d424dSDavid Dillow 
1756c07d424dSDavid Dillow 	count = min(state.ndesc, target->cmd_sg_cnt);
17578f26c9ffSDavid Dillow 	table_len = state.ndesc * sizeof (struct srp_direct_buf);
1758330179f2SBart Van Assche 	idb_len = sizeof(struct srp_indirect_buf) + table_len;
1759aef9ec39SRoland Dreier 
1760aef9ec39SRoland Dreier 	fmt = SRP_DATA_DESC_INDIRECT;
1761482fffc4SBart Van Assche 	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
1762482fffc4SBart Van Assche 		sizeof(struct srp_indirect_buf);
1763c07d424dSDavid Dillow 	len += count * sizeof (struct srp_direct_buf);
1764f5358a17SRoland Dreier 
1765c07d424dSDavid Dillow 	memcpy(indirect_hdr->desc_list, req->indirect_desc,
1766c07d424dSDavid Dillow 	       count * sizeof (struct srp_direct_buf));
176785507bccSRalph Campbell 
1768cee687b6SBart Van Assche 	if (!target->global_rkey) {
1769330179f2SBart Van Assche 		ret = srp_map_idb(ch, req, state.gen.next, state.gen.end,
1770330179f2SBart Van Assche 				  idb_len, &idb_rkey);
1771330179f2SBart Van Assche 		if (ret < 0)
1772e012f363SBart Van Assche 			goto unmap;
1773330179f2SBart Van Assche 		req->nmdesc++;
1774330179f2SBart Van Assche 	} else {
1775cee687b6SBart Van Assche 		idb_rkey = cpu_to_be32(target->global_rkey);
1776330179f2SBart Van Assche 	}
1777330179f2SBart Van Assche 
1778c07d424dSDavid Dillow 	indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
1779330179f2SBart Van Assche 	indirect_hdr->table_desc.key = idb_rkey;
17808f26c9ffSDavid Dillow 	indirect_hdr->table_desc.len = cpu_to_be32(table_len);
17818f26c9ffSDavid Dillow 	indirect_hdr->len = cpu_to_be32(state.total_len);
1782aef9ec39SRoland Dreier 
1783aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
1784c07d424dSDavid Dillow 		cmd->data_out_desc_cnt = count;
1785aef9ec39SRoland Dreier 	else
1786c07d424dSDavid Dillow 		cmd->data_in_desc_cnt = count;
1787c07d424dSDavid Dillow 
1788c07d424dSDavid Dillow 	ib_dma_sync_single_for_device(ibdev, req->indirect_dma_addr, table_len,
1789c07d424dSDavid Dillow 				      DMA_TO_DEVICE);
1790aef9ec39SRoland Dreier 
17918f26c9ffSDavid Dillow map_complete:
1792aef9ec39SRoland Dreier 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
1793aef9ec39SRoland Dreier 		cmd->buf_fmt = fmt << 4;
1794aef9ec39SRoland Dreier 	else
1795aef9ec39SRoland Dreier 		cmd->buf_fmt = fmt;
1796aef9ec39SRoland Dreier 
1797aef9ec39SRoland Dreier 	return len;
1798e012f363SBart Van Assche 
1799e012f363SBart Van Assche unmap:
1800e012f363SBart Van Assche 	srp_unmap_data(scmnd, ch, req);
1801ffc548bbSBart Van Assche 	if (ret == -ENOMEM && req->nmdesc >= target->mr_pool_size)
1802ffc548bbSBart Van Assche 		ret = -E2BIG;
1803e012f363SBart Van Assche 	return ret;
1804aef9ec39SRoland Dreier }
1805aef9ec39SRoland Dreier 
180605a1d750SDavid Dillow /*
180776c75b25SBart Van Assche  * Return an IU and possible credit to the free pool
180876c75b25SBart Van Assche  */
srp_put_tx_iu(struct srp_rdma_ch * ch,struct srp_iu * iu,enum srp_iu_type iu_type)1809509c07bcSBart Van Assche static void srp_put_tx_iu(struct srp_rdma_ch *ch, struct srp_iu *iu,
181076c75b25SBart Van Assche 			  enum srp_iu_type iu_type)
181176c75b25SBart Van Assche {
181276c75b25SBart Van Assche 	unsigned long flags;
181376c75b25SBart Van Assche 
1814509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
1815509c07bcSBart Van Assche 	list_add(&iu->list, &ch->free_tx);
181676c75b25SBart Van Assche 	if (iu_type != SRP_IU_RSP)
1817509c07bcSBart Van Assche 		++ch->req_lim;
1818509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
181976c75b25SBart Van Assche }
182076c75b25SBart Van Assche 
182176c75b25SBart Van Assche /*
1822509c07bcSBart Van Assche  * Must be called with ch->lock held to protect req_lim and free_tx.
1823e9684678SBart Van Assche  * If IU is not sent, it must be returned using srp_put_tx_iu().
182405a1d750SDavid Dillow  *
182505a1d750SDavid Dillow  * Note:
182605a1d750SDavid Dillow  * An upper limit for the number of allocated information units for each
182705a1d750SDavid Dillow  * request type is:
182805a1d750SDavid Dillow  * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
182905a1d750SDavid Dillow  *   more than Scsi_Host.can_queue requests.
183005a1d750SDavid Dillow  * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
183105a1d750SDavid Dillow  * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
183205a1d750SDavid Dillow  *   one unanswered SRP request to an initiator.
183305a1d750SDavid Dillow  */
__srp_get_tx_iu(struct srp_rdma_ch * ch,enum srp_iu_type iu_type)1834509c07bcSBart Van Assche static struct srp_iu *__srp_get_tx_iu(struct srp_rdma_ch *ch,
183505a1d750SDavid Dillow 				      enum srp_iu_type iu_type)
183605a1d750SDavid Dillow {
1837509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
183805a1d750SDavid Dillow 	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
183905a1d750SDavid Dillow 	struct srp_iu *iu;
184005a1d750SDavid Dillow 
184193c76dbbSBart Van Assche 	lockdep_assert_held(&ch->lock);
184293c76dbbSBart Van Assche 
18431dc7b1f1SChristoph Hellwig 	ib_process_cq_direct(ch->send_cq, -1);
184405a1d750SDavid Dillow 
1845509c07bcSBart Van Assche 	if (list_empty(&ch->free_tx))
184605a1d750SDavid Dillow 		return NULL;
184705a1d750SDavid Dillow 
184805a1d750SDavid Dillow 	/* Initiator responses to target requests do not consume credits */
184976c75b25SBart Van Assche 	if (iu_type != SRP_IU_RSP) {
1850509c07bcSBart Van Assche 		if (ch->req_lim <= rsv) {
185105a1d750SDavid Dillow 			++target->zero_req_lim;
185205a1d750SDavid Dillow 			return NULL;
185305a1d750SDavid Dillow 		}
185405a1d750SDavid Dillow 
1855509c07bcSBart Van Assche 		--ch->req_lim;
185676c75b25SBart Van Assche 	}
185776c75b25SBart Van Assche 
1858509c07bcSBart Van Assche 	iu = list_first_entry(&ch->free_tx, struct srp_iu, list);
185976c75b25SBart Van Assche 	list_del(&iu->list);
186005a1d750SDavid Dillow 	return iu;
186105a1d750SDavid Dillow }
186205a1d750SDavid Dillow 
18639294000dSBart Van Assche /*
18649294000dSBart Van Assche  * Note: if this function is called from inside ib_drain_sq() then it will
18659294000dSBart Van Assche  * be called without ch->lock being held. If ib_drain_sq() dequeues a WQE
18669294000dSBart Van Assche  * with status IB_WC_SUCCESS then that's a bug.
18679294000dSBart Van Assche  */
srp_send_done(struct ib_cq * cq,struct ib_wc * wc)18681dc7b1f1SChristoph Hellwig static void srp_send_done(struct ib_cq *cq, struct ib_wc *wc)
18691dc7b1f1SChristoph Hellwig {
18701dc7b1f1SChristoph Hellwig 	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
18711dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
18721dc7b1f1SChristoph Hellwig 
18731dc7b1f1SChristoph Hellwig 	if (unlikely(wc->status != IB_WC_SUCCESS)) {
18741dc7b1f1SChristoph Hellwig 		srp_handle_qp_err(cq, wc, "SEND");
18751dc7b1f1SChristoph Hellwig 		return;
18761dc7b1f1SChristoph Hellwig 	}
18771dc7b1f1SChristoph Hellwig 
187893c76dbbSBart Van Assche 	lockdep_assert_held(&ch->lock);
187993c76dbbSBart Van Assche 
18801dc7b1f1SChristoph Hellwig 	list_add(&iu->list, &ch->free_tx);
18811dc7b1f1SChristoph Hellwig }
18821dc7b1f1SChristoph Hellwig 
1883882981f4SBart Van Assche /**
1884882981f4SBart Van Assche  * srp_post_send() - send an SRP information unit
1885882981f4SBart Van Assche  * @ch: RDMA channel over which to send the information unit.
1886882981f4SBart Van Assche  * @iu: Information unit to send.
1887882981f4SBart Van Assche  * @len: Length of the information unit excluding immediate data.
1888882981f4SBart Van Assche  */
srp_post_send(struct srp_rdma_ch * ch,struct srp_iu * iu,int len)1889509c07bcSBart Van Assche static int srp_post_send(struct srp_rdma_ch *ch, struct srp_iu *iu, int len)
189005a1d750SDavid Dillow {
1891509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
189271347b0cSBart Van Assche 	struct ib_send_wr wr;
189305a1d750SDavid Dillow 
1894882981f4SBart Van Assche 	if (WARN_ON_ONCE(iu->num_sge > SRP_MAX_SGE))
1895882981f4SBart Van Assche 		return -EINVAL;
1896882981f4SBart Van Assche 
1897882981f4SBart Van Assche 	iu->sge[0].addr   = iu->dma;
1898882981f4SBart Van Assche 	iu->sge[0].length = len;
1899882981f4SBart Van Assche 	iu->sge[0].lkey   = target->lkey;
190005a1d750SDavid Dillow 
19011dc7b1f1SChristoph Hellwig 	iu->cqe.done = srp_send_done;
19021dc7b1f1SChristoph Hellwig 
190305a1d750SDavid Dillow 	wr.next       = NULL;
19041dc7b1f1SChristoph Hellwig 	wr.wr_cqe     = &iu->cqe;
1905882981f4SBart Van Assche 	wr.sg_list    = &iu->sge[0];
1906882981f4SBart Van Assche 	wr.num_sge    = iu->num_sge;
190705a1d750SDavid Dillow 	wr.opcode     = IB_WR_SEND;
190805a1d750SDavid Dillow 	wr.send_flags = IB_SEND_SIGNALED;
190905a1d750SDavid Dillow 
191071347b0cSBart Van Assche 	return ib_post_send(ch->qp, &wr, NULL);
191105a1d750SDavid Dillow }
191205a1d750SDavid Dillow 
srp_post_recv(struct srp_rdma_ch * ch,struct srp_iu * iu)1913509c07bcSBart Van Assche static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
1914c996bb47SBart Van Assche {
1915509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
191671347b0cSBart Van Assche 	struct ib_recv_wr wr;
1917dcb4cb85SBart Van Assche 	struct ib_sge list;
1918c996bb47SBart Van Assche 
1919c996bb47SBart Van Assche 	list.addr   = iu->dma;
1920c996bb47SBart Van Assche 	list.length = iu->size;
19219af76271SDavid Dillow 	list.lkey   = target->lkey;
1922c996bb47SBart Van Assche 
19231dc7b1f1SChristoph Hellwig 	iu->cqe.done = srp_recv_done;
19241dc7b1f1SChristoph Hellwig 
1925c996bb47SBart Van Assche 	wr.next     = NULL;
19261dc7b1f1SChristoph Hellwig 	wr.wr_cqe   = &iu->cqe;
1927c996bb47SBart Van Assche 	wr.sg_list  = &list;
1928c996bb47SBart Van Assche 	wr.num_sge  = 1;
1929c996bb47SBart Van Assche 
193071347b0cSBart Van Assche 	return ib_post_recv(ch->qp, &wr, NULL);
1931c996bb47SBart Van Assche }
1932c996bb47SBart Van Assche 
srp_process_rsp(struct srp_rdma_ch * ch,struct srp_rsp * rsp)1933509c07bcSBart Van Assche static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
1934aef9ec39SRoland Dreier {
1935509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
1936aef9ec39SRoland Dreier 	struct srp_request *req;
1937aef9ec39SRoland Dreier 	struct scsi_cmnd *scmnd;
1938aef9ec39SRoland Dreier 	unsigned long flags;
1939aef9ec39SRoland Dreier 
1940aef9ec39SRoland Dreier 	if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
1941509c07bcSBart Van Assche 		spin_lock_irqsave(&ch->lock, flags);
1942509c07bcSBart Van Assche 		ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
19430a6fdbdeSBart Van Assche 		if (rsp->tag == ch->tsk_mgmt_tag) {
1944509c07bcSBart Van Assche 			ch->tsk_mgmt_status = -1;
1945f8b6e31eSDavid Dillow 			if (be32_to_cpu(rsp->resp_data_len) >= 4)
1946509c07bcSBart Van Assche 				ch->tsk_mgmt_status = rsp->data[3];
1947509c07bcSBart Van Assche 			complete(&ch->tsk_mgmt_done);
1948aef9ec39SRoland Dreier 		} else {
19490a6fdbdeSBart Van Assche 			shost_printk(KERN_ERR, target->scsi_host,
19500a6fdbdeSBart Van Assche 				     "Received tsk mgmt response too late for tag %#llx\n",
19510a6fdbdeSBart Van Assche 				     rsp->tag);
19520a6fdbdeSBart Van Assche 		}
19530a6fdbdeSBart Van Assche 		spin_unlock_irqrestore(&ch->lock, flags);
19540a6fdbdeSBart Van Assche 	} else {
195577f2c1a4SBart Van Assche 		scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
1956ad215aaeSBart Van Assche 		if (scmnd) {
1957ad215aaeSBart Van Assche 			req = scsi_cmd_priv(scmnd);
195877f2c1a4SBart Van Assche 			scmnd = srp_claim_req(ch, req, NULL, scmnd);
195912f35199Syangx.jy@fujitsu.com 		}
196012f35199Syangx.jy@fujitsu.com 		if (!scmnd) {
19617aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
1962d92c0da7SBart Van Assche 				     "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
1963d92c0da7SBart Van Assche 				     rsp->tag, ch - target->ch, ch->qp->qp_num);
196422032991SBart Van Assche 
1965509c07bcSBart Van Assche 			spin_lock_irqsave(&ch->lock, flags);
1966509c07bcSBart Van Assche 			ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
1967509c07bcSBart Van Assche 			spin_unlock_irqrestore(&ch->lock, flags);
196822032991SBart Van Assche 
196922032991SBart Van Assche 			return;
197022032991SBart Van Assche 		}
1971aef9ec39SRoland Dreier 		scmnd->result = rsp->status;
1972aef9ec39SRoland Dreier 
1973aef9ec39SRoland Dreier 		if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
1974aef9ec39SRoland Dreier 			memcpy(scmnd->sense_buffer, rsp->data +
1975aef9ec39SRoland Dreier 			       be32_to_cpu(rsp->resp_data_len),
1976aef9ec39SRoland Dreier 			       min_t(int, be32_to_cpu(rsp->sense_data_len),
1977aef9ec39SRoland Dreier 				     SCSI_SENSE_BUFFERSIZE));
1978aef9ec39SRoland Dreier 		}
1979aef9ec39SRoland Dreier 
1980e714531aSBart Van Assche 		if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
1981bb350d1dSFUJITA Tomonori 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
1982e714531aSBart Van Assche 		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOUNDER))
1983e714531aSBart Van Assche 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
1984aef9ec39SRoland Dreier 
1985509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd,
198622032991SBart Van Assche 			     be32_to_cpu(rsp->req_lim_delta));
198722032991SBart Van Assche 
19885f9ae9eeSBart Van Assche 		scsi_done(scmnd);
1989aef9ec39SRoland Dreier 	}
1990aef9ec39SRoland Dreier }
1991aef9ec39SRoland Dreier 
srp_response_common(struct srp_rdma_ch * ch,s32 req_delta,void * rsp,int len)1992509c07bcSBart Van Assche static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
1993bb12588aSDavid Dillow 			       void *rsp, int len)
1994bb12588aSDavid Dillow {
1995509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
199676c75b25SBart Van Assche 	struct ib_device *dev = target->srp_host->srp_dev->dev;
1997bb12588aSDavid Dillow 	unsigned long flags;
1998bb12588aSDavid Dillow 	struct srp_iu *iu;
199976c75b25SBart Van Assche 	int err;
2000bb12588aSDavid Dillow 
2001509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
2002509c07bcSBart Van Assche 	ch->req_lim += req_delta;
2003509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_RSP);
2004509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
200576c75b25SBart Van Assche 
2006bb12588aSDavid Dillow 	if (!iu) {
2007bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2008bb12588aSDavid Dillow 			     "no IU available to send response\n");
200976c75b25SBart Van Assche 		return 1;
2010bb12588aSDavid Dillow 	}
2011bb12588aSDavid Dillow 
2012882981f4SBart Van Assche 	iu->num_sge = 1;
2013bb12588aSDavid Dillow 	ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
2014bb12588aSDavid Dillow 	memcpy(iu->buf, rsp, len);
2015bb12588aSDavid Dillow 	ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
2016bb12588aSDavid Dillow 
2017509c07bcSBart Van Assche 	err = srp_post_send(ch, iu, len);
201876c75b25SBart Van Assche 	if (err) {
2019bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2020bb12588aSDavid Dillow 			     "unable to post response: %d\n", err);
2021509c07bcSBart Van Assche 		srp_put_tx_iu(ch, iu, SRP_IU_RSP);
202276c75b25SBart Van Assche 	}
2023bb12588aSDavid Dillow 
2024bb12588aSDavid Dillow 	return err;
2025bb12588aSDavid Dillow }
2026bb12588aSDavid Dillow 
srp_process_cred_req(struct srp_rdma_ch * ch,struct srp_cred_req * req)2027509c07bcSBart Van Assche static void srp_process_cred_req(struct srp_rdma_ch *ch,
2028bb12588aSDavid Dillow 				 struct srp_cred_req *req)
2029bb12588aSDavid Dillow {
2030bb12588aSDavid Dillow 	struct srp_cred_rsp rsp = {
2031bb12588aSDavid Dillow 		.opcode = SRP_CRED_RSP,
2032bb12588aSDavid Dillow 		.tag = req->tag,
2033bb12588aSDavid Dillow 	};
2034bb12588aSDavid Dillow 	s32 delta = be32_to_cpu(req->req_lim_delta);
2035bb12588aSDavid Dillow 
2036509c07bcSBart Van Assche 	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
2037509c07bcSBart Van Assche 		shost_printk(KERN_ERR, ch->target->scsi_host, PFX
2038bb12588aSDavid Dillow 			     "problems processing SRP_CRED_REQ\n");
2039bb12588aSDavid Dillow }
2040bb12588aSDavid Dillow 
srp_process_aer_req(struct srp_rdma_ch * ch,struct srp_aer_req * req)2041509c07bcSBart Van Assche static void srp_process_aer_req(struct srp_rdma_ch *ch,
2042bb12588aSDavid Dillow 				struct srp_aer_req *req)
2043bb12588aSDavid Dillow {
2044509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2045bb12588aSDavid Dillow 	struct srp_aer_rsp rsp = {
2046bb12588aSDavid Dillow 		.opcode = SRP_AER_RSP,
2047bb12588aSDavid Dillow 		.tag = req->tag,
2048bb12588aSDavid Dillow 	};
2049bb12588aSDavid Dillow 	s32 delta = be32_to_cpu(req->req_lim_delta);
2050bb12588aSDavid Dillow 
2051bb12588aSDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, PFX
2052985aa495SBart Van Assche 		     "ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
2053bb12588aSDavid Dillow 
2054509c07bcSBart Van Assche 	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
2055bb12588aSDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX
2056bb12588aSDavid Dillow 			     "problems processing SRP_AER_REQ\n");
2057bb12588aSDavid Dillow }
2058bb12588aSDavid Dillow 
srp_recv_done(struct ib_cq * cq,struct ib_wc * wc)20591dc7b1f1SChristoph Hellwig static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
2060aef9ec39SRoland Dreier {
20611dc7b1f1SChristoph Hellwig 	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
20621dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
2063509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2064dcb4cb85SBart Van Assche 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2065c996bb47SBart Van Assche 	int res;
2066aef9ec39SRoland Dreier 	u8 opcode;
2067aef9ec39SRoland Dreier 
20681dc7b1f1SChristoph Hellwig 	if (unlikely(wc->status != IB_WC_SUCCESS)) {
20691dc7b1f1SChristoph Hellwig 		srp_handle_qp_err(cq, wc, "RECV");
20701dc7b1f1SChristoph Hellwig 		return;
20711dc7b1f1SChristoph Hellwig 	}
20721dc7b1f1SChristoph Hellwig 
2073509c07bcSBart Van Assche 	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_ti_iu_len,
207485507bccSRalph Campbell 				   DMA_FROM_DEVICE);
2075aef9ec39SRoland Dreier 
2076aef9ec39SRoland Dreier 	opcode = *(u8 *) iu->buf;
2077aef9ec39SRoland Dreier 
2078aef9ec39SRoland Dreier 	if (0) {
20797aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
20807aa54bd7SDavid Dillow 			     PFX "recv completion, opcode 0x%02x\n", opcode);
20817a700811SBart Van Assche 		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 8, 1,
20827a700811SBart Van Assche 			       iu->buf, wc->byte_len, true);
2083aef9ec39SRoland Dreier 	}
2084aef9ec39SRoland Dreier 
2085aef9ec39SRoland Dreier 	switch (opcode) {
2086aef9ec39SRoland Dreier 	case SRP_RSP:
2087509c07bcSBart Van Assche 		srp_process_rsp(ch, iu->buf);
2088aef9ec39SRoland Dreier 		break;
2089aef9ec39SRoland Dreier 
2090bb12588aSDavid Dillow 	case SRP_CRED_REQ:
2091509c07bcSBart Van Assche 		srp_process_cred_req(ch, iu->buf);
2092bb12588aSDavid Dillow 		break;
2093bb12588aSDavid Dillow 
2094bb12588aSDavid Dillow 	case SRP_AER_REQ:
2095509c07bcSBart Van Assche 		srp_process_aer_req(ch, iu->buf);
2096bb12588aSDavid Dillow 		break;
2097bb12588aSDavid Dillow 
2098aef9ec39SRoland Dreier 	case SRP_T_LOGOUT:
2099aef9ec39SRoland Dreier 		/* XXX Handle target logout */
21007aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
21017aa54bd7SDavid Dillow 			     PFX "Got target logout request\n");
2102aef9ec39SRoland Dreier 		break;
2103aef9ec39SRoland Dreier 
2104aef9ec39SRoland Dreier 	default:
21057aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
21067aa54bd7SDavid Dillow 			     PFX "Unhandled SRP opcode 0x%02x\n", opcode);
2107aef9ec39SRoland Dreier 		break;
2108aef9ec39SRoland Dreier 	}
2109aef9ec39SRoland Dreier 
2110509c07bcSBart Van Assche 	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_ti_iu_len,
211185507bccSRalph Campbell 				      DMA_FROM_DEVICE);
2112c996bb47SBart Van Assche 
2113509c07bcSBart Van Assche 	res = srp_post_recv(ch, iu);
2114c996bb47SBart Van Assche 	if (res != 0)
2115c996bb47SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
2116c996bb47SBart Van Assche 			     PFX "Recv failed with error code %d\n", res);
2117aef9ec39SRoland Dreier }
2118aef9ec39SRoland Dreier 
2119c1120f89SBart Van Assche /**
2120c1120f89SBart Van Assche  * srp_tl_err_work() - handle a transport layer error
2121af24663bSBart Van Assche  * @work: Work structure embedded in an SRP target port.
2122c1120f89SBart Van Assche  *
2123c1120f89SBart Van Assche  * Note: This function may get invoked before the rport has been created,
2124c1120f89SBart Van Assche  * hence the target->rport test.
2125c1120f89SBart Van Assche  */
srp_tl_err_work(struct work_struct * work)2126c1120f89SBart Van Assche static void srp_tl_err_work(struct work_struct *work)
2127c1120f89SBart Van Assche {
2128c1120f89SBart Van Assche 	struct srp_target_port *target;
2129c1120f89SBart Van Assche 
2130c1120f89SBart Van Assche 	target = container_of(work, struct srp_target_port, tl_err_work);
2131c1120f89SBart Van Assche 	if (target->rport)
2132c1120f89SBart Van Assche 		srp_start_tl_fail_timers(target->rport);
2133c1120f89SBart Van Assche }
2134c1120f89SBart Van Assche 
srp_handle_qp_err(struct ib_cq * cq,struct ib_wc * wc,const char * opname)21351dc7b1f1SChristoph Hellwig static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
21361dc7b1f1SChristoph Hellwig 		const char *opname)
2137948d1e88SBart Van Assche {
21381dc7b1f1SChristoph Hellwig 	struct srp_rdma_ch *ch = cq->cq_context;
21397dad6b2eSBart Van Assche 	struct srp_target_port *target = ch->target;
21407dad6b2eSBart Van Assche 
2141c014c8cdSBart Van Assche 	if (ch->connected && !target->qp_in_error) {
21425cfb1782SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
21431dc7b1f1SChristoph Hellwig 			     PFX "failed %s status %s (%d) for CQE %p\n",
21441dc7b1f1SChristoph Hellwig 			     opname, ib_wc_status_msg(wc->status), wc->status,
21451dc7b1f1SChristoph Hellwig 			     wc->wr_cqe);
2146c1120f89SBart Van Assche 		queue_work(system_long_wq, &target->tl_err_work);
21474f0af697SBart Van Assche 	}
2148948d1e88SBart Van Assche 	target->qp_in_error = true;
2149948d1e88SBart Van Assche }
2150948d1e88SBart Van Assche 
srp_queuecommand(struct Scsi_Host * shost,struct scsi_cmnd * scmnd)215176c75b25SBart Van Assche static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
2152aef9ec39SRoland Dreier {
21539c5274eeSBart Van Assche 	struct request *rq = scsi_cmd_to_rq(scmnd);
215476c75b25SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
2155509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
2156ad215aaeSBart Van Assche 	struct srp_request *req = scsi_cmd_priv(scmnd);
2157aef9ec39SRoland Dreier 	struct srp_iu *iu;
2158aef9ec39SRoland Dreier 	struct srp_cmd *cmd;
215985507bccSRalph Campbell 	struct ib_device *dev;
216076c75b25SBart Van Assche 	unsigned long flags;
216177f2c1a4SBart Van Assche 	u32 tag;
2162d1b4289eSBart Van Assche 	int len, ret;
2163aef9ec39SRoland Dreier 
2164d1b4289eSBart Van Assche 	scmnd->result = srp_chkready(target->rport);
2165d1b4289eSBart Van Assche 	if (unlikely(scmnd->result))
2166d1b4289eSBart Van Assche 		goto err;
21672ce19e72SBart Van Assche 
21689c5274eeSBart Van Assche 	WARN_ON_ONCE(rq->tag < 0);
21699c5274eeSBart Van Assche 	tag = blk_mq_unique_tag(rq);
2170d92c0da7SBart Van Assche 	ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
2171509c07bcSBart Van Assche 
2172509c07bcSBart Van Assche 	spin_lock_irqsave(&ch->lock, flags);
2173509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_CMD);
2174509c07bcSBart Van Assche 	spin_unlock_irqrestore(&ch->lock, flags);
2175aef9ec39SRoland Dreier 
217677f2c1a4SBart Van Assche 	if (!iu)
217777f2c1a4SBart Van Assche 		goto err;
217877f2c1a4SBart Van Assche 
217905321937SGreg Kroah-Hartman 	dev = target->srp_host->srp_dev->dev;
2180513d5647SBart Van Assche 	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_it_iu_len,
218185507bccSRalph Campbell 				   DMA_TO_DEVICE);
2182aef9ec39SRoland Dreier 
2183aef9ec39SRoland Dreier 	cmd = iu->buf;
2184aef9ec39SRoland Dreier 	memset(cmd, 0, sizeof *cmd);
2185aef9ec39SRoland Dreier 
2186aef9ec39SRoland Dreier 	cmd->opcode = SRP_CMD;
2187985aa495SBart Van Assche 	int_to_scsilun(scmnd->device->lun, &cmd->lun);
218877f2c1a4SBart Van Assche 	cmd->tag    = tag;
2189aef9ec39SRoland Dreier 	memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
2190482fffc4SBart Van Assche 	if (unlikely(scmnd->cmd_len > sizeof(cmd->cdb))) {
2191482fffc4SBart Van Assche 		cmd->add_cdb_len = round_up(scmnd->cmd_len - sizeof(cmd->cdb),
2192482fffc4SBart Van Assche 					    4);
2193482fffc4SBart Van Assche 		if (WARN_ON_ONCE(cmd->add_cdb_len > SRP_MAX_ADD_CDB_LEN))
2194482fffc4SBart Van Assche 			goto err_iu;
2195482fffc4SBart Van Assche 	}
2196aef9ec39SRoland Dreier 
2197aef9ec39SRoland Dreier 	req->scmnd    = scmnd;
2198aef9ec39SRoland Dreier 	req->cmd      = iu;
2199aef9ec39SRoland Dreier 
2200509c07bcSBart Van Assche 	len = srp_map_data(scmnd, ch, req);
2201aef9ec39SRoland Dreier 	if (len < 0) {
22027aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
2203d1b4289eSBart Van Assche 			     PFX "Failed to map data (%d)\n", len);
2204d1b4289eSBart Van Assche 		/*
2205d1b4289eSBart Van Assche 		 * If we ran out of memory descriptors (-ENOMEM) because an
2206d1b4289eSBart Van Assche 		 * application is queuing many requests with more than
220752ede08fSBart Van Assche 		 * max_pages_per_mr sg-list elements, tell the SCSI mid-layer
2208d1b4289eSBart Van Assche 		 * to reduce queue depth temporarily.
2209d1b4289eSBart Van Assche 		 */
2210d1b4289eSBart Van Assche 		scmnd->result = len == -ENOMEM ?
22113d45cefcSHannes Reinecke 			DID_OK << 16 | SAM_STAT_TASK_SET_FULL : DID_ERROR << 16;
221276c75b25SBart Van Assche 		goto err_iu;
2213aef9ec39SRoland Dreier 	}
2214aef9ec39SRoland Dreier 
2215513d5647SBart Van Assche 	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_it_iu_len,
221685507bccSRalph Campbell 				      DMA_TO_DEVICE);
2217aef9ec39SRoland Dreier 
2218509c07bcSBart Van Assche 	if (srp_post_send(ch, iu, len)) {
22197aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
22202ee00f6aSBart Van Assche 		scmnd->result = DID_ERROR << 16;
2221aef9ec39SRoland Dreier 		goto err_unmap;
2222aef9ec39SRoland Dreier 	}
2223aef9ec39SRoland Dreier 
2224fd561412SBart Van Assche 	return 0;
2225aef9ec39SRoland Dreier 
2226aef9ec39SRoland Dreier err_unmap:
2227509c07bcSBart Van Assche 	srp_unmap_data(scmnd, ch, req);
2228aef9ec39SRoland Dreier 
222976c75b25SBart Van Assche err_iu:
2230509c07bcSBart Van Assche 	srp_put_tx_iu(ch, iu, SRP_IU_CMD);
223176c75b25SBart Van Assche 
2232024ca901SBart Van Assche 	/*
2233024ca901SBart Van Assche 	 * Avoid that the loops that iterate over the request ring can
2234024ca901SBart Van Assche 	 * encounter a dangling SCSI command pointer.
2235024ca901SBart Van Assche 	 */
2236024ca901SBart Van Assche 	req->scmnd = NULL;
2237024ca901SBart Van Assche 
2238d1b4289eSBart Van Assche err:
2239d1b4289eSBart Van Assche 	if (scmnd->result) {
22405f9ae9eeSBart Van Assche 		scsi_done(scmnd);
2241d1b4289eSBart Van Assche 		ret = 0;
2242d1b4289eSBart Van Assche 	} else {
2243d1b4289eSBart Van Assche 		ret = SCSI_MLQUEUE_HOST_BUSY;
2244d1b4289eSBart Van Assche 	}
2245a95cadb9SBart Van Assche 
2246fd561412SBart Van Assche 	return ret;
2247aef9ec39SRoland Dreier }
2248aef9ec39SRoland Dreier 
22494d73f95fSBart Van Assche /*
22504d73f95fSBart Van Assche  * Note: the resources allocated in this function are freed in
2251509c07bcSBart Van Assche  * srp_free_ch_ib().
22524d73f95fSBart Van Assche  */
srp_alloc_iu_bufs(struct srp_rdma_ch * ch)2253509c07bcSBart Van Assche static int srp_alloc_iu_bufs(struct srp_rdma_ch *ch)
2254aef9ec39SRoland Dreier {
2255509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2256aef9ec39SRoland Dreier 	int i;
2257aef9ec39SRoland Dreier 
2258509c07bcSBart Van Assche 	ch->rx_ring = kcalloc(target->queue_size, sizeof(*ch->rx_ring),
22594d73f95fSBart Van Assche 			      GFP_KERNEL);
2260509c07bcSBart Van Assche 	if (!ch->rx_ring)
22614d73f95fSBart Van Assche 		goto err_no_ring;
2262509c07bcSBart Van Assche 	ch->tx_ring = kcalloc(target->queue_size, sizeof(*ch->tx_ring),
22634d73f95fSBart Van Assche 			      GFP_KERNEL);
2264509c07bcSBart Van Assche 	if (!ch->tx_ring)
22654d73f95fSBart Van Assche 		goto err_no_ring;
22664d73f95fSBart Van Assche 
22674d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2268509c07bcSBart Van Assche 		ch->rx_ring[i] = srp_alloc_iu(target->srp_host,
2269509c07bcSBart Van Assche 					      ch->max_ti_iu_len,
2270aef9ec39SRoland Dreier 					      GFP_KERNEL, DMA_FROM_DEVICE);
2271509c07bcSBart Van Assche 		if (!ch->rx_ring[i])
2272aef9ec39SRoland Dreier 			goto err;
2273aef9ec39SRoland Dreier 	}
2274aef9ec39SRoland Dreier 
22754d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2276509c07bcSBart Van Assche 		ch->tx_ring[i] = srp_alloc_iu(target->srp_host,
2277513d5647SBart Van Assche 					      ch->max_it_iu_len,
2278aef9ec39SRoland Dreier 					      GFP_KERNEL, DMA_TO_DEVICE);
2279509c07bcSBart Van Assche 		if (!ch->tx_ring[i])
2280aef9ec39SRoland Dreier 			goto err;
2281dcb4cb85SBart Van Assche 
2282509c07bcSBart Van Assche 		list_add(&ch->tx_ring[i]->list, &ch->free_tx);
2283aef9ec39SRoland Dreier 	}
2284aef9ec39SRoland Dreier 
2285aef9ec39SRoland Dreier 	return 0;
2286aef9ec39SRoland Dreier 
2287aef9ec39SRoland Dreier err:
22884d73f95fSBart Van Assche 	for (i = 0; i < target->queue_size; ++i) {
2289509c07bcSBart Van Assche 		srp_free_iu(target->srp_host, ch->rx_ring[i]);
2290509c07bcSBart Van Assche 		srp_free_iu(target->srp_host, ch->tx_ring[i]);
2291aef9ec39SRoland Dreier 	}
2292aef9ec39SRoland Dreier 
22934d73f95fSBart Van Assche 
22944d73f95fSBart Van Assche err_no_ring:
2295509c07bcSBart Van Assche 	kfree(ch->tx_ring);
2296509c07bcSBart Van Assche 	ch->tx_ring = NULL;
2297509c07bcSBart Van Assche 	kfree(ch->rx_ring);
2298509c07bcSBart Van Assche 	ch->rx_ring = NULL;
2299aef9ec39SRoland Dreier 
2300aef9ec39SRoland Dreier 	return -ENOMEM;
2301aef9ec39SRoland Dreier }
2302aef9ec39SRoland Dreier 
srp_compute_rq_tmo(struct ib_qp_attr * qp_attr,int attr_mask)2303c9b03c1aSBart Van Assche static uint32_t srp_compute_rq_tmo(struct ib_qp_attr *qp_attr, int attr_mask)
2304c9b03c1aSBart Van Assche {
2305c9b03c1aSBart Van Assche 	uint64_t T_tr_ns, max_compl_time_ms;
2306c9b03c1aSBart Van Assche 	uint32_t rq_tmo_jiffies;
2307c9b03c1aSBart Van Assche 
2308c9b03c1aSBart Van Assche 	/*
2309c9b03c1aSBart Van Assche 	 * According to section 11.2.4.2 in the IBTA spec (Modify Queue Pair,
2310c9b03c1aSBart Van Assche 	 * table 91), both the QP timeout and the retry count have to be set
2311c9b03c1aSBart Van Assche 	 * for RC QP's during the RTR to RTS transition.
2312c9b03c1aSBart Van Assche 	 */
2313c9b03c1aSBart Van Assche 	WARN_ON_ONCE((attr_mask & (IB_QP_TIMEOUT | IB_QP_RETRY_CNT)) !=
2314c9b03c1aSBart Van Assche 		     (IB_QP_TIMEOUT | IB_QP_RETRY_CNT));
2315c9b03c1aSBart Van Assche 
2316c9b03c1aSBart Van Assche 	/*
2317c9b03c1aSBart Van Assche 	 * Set target->rq_tmo_jiffies to one second more than the largest time
2318c9b03c1aSBart Van Assche 	 * it can take before an error completion is generated. See also
2319c9b03c1aSBart Van Assche 	 * C9-140..142 in the IBTA spec for more information about how to
2320c9b03c1aSBart Van Assche 	 * convert the QP Local ACK Timeout value to nanoseconds.
2321c9b03c1aSBart Van Assche 	 */
2322c9b03c1aSBart Van Assche 	T_tr_ns = 4096 * (1ULL << qp_attr->timeout);
2323c9b03c1aSBart Van Assche 	max_compl_time_ms = qp_attr->retry_cnt * 4 * T_tr_ns;
2324c9b03c1aSBart Van Assche 	do_div(max_compl_time_ms, NSEC_PER_MSEC);
2325c9b03c1aSBart Van Assche 	rq_tmo_jiffies = msecs_to_jiffies(max_compl_time_ms + 1000);
2326c9b03c1aSBart Van Assche 
2327c9b03c1aSBart Van Assche 	return rq_tmo_jiffies;
2328c9b03c1aSBart Van Assche }
2329c9b03c1aSBart Van Assche 
srp_cm_rep_handler(struct ib_cm_id * cm_id,const struct srp_login_rsp * lrsp,struct srp_rdma_ch * ch)2330961e0be8SDavid Dillow static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
2331e6300cbdSBart Van Assche 			       const struct srp_login_rsp *lrsp,
2332509c07bcSBart Van Assche 			       struct srp_rdma_ch *ch)
2333961e0be8SDavid Dillow {
2334509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2335961e0be8SDavid Dillow 	struct ib_qp_attr *qp_attr = NULL;
2336961e0be8SDavid Dillow 	int attr_mask = 0;
233719f31343SBart Van Assche 	int ret = 0;
2338961e0be8SDavid Dillow 	int i;
2339961e0be8SDavid Dillow 
2340961e0be8SDavid Dillow 	if (lrsp->opcode == SRP_LOGIN_RSP) {
2341509c07bcSBart Van Assche 		ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
2342509c07bcSBart Van Assche 		ch->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
23430fbb37ddSSergey Gorenko 		ch->use_imm_data  = srp_use_imm_data &&
23440fbb37ddSSergey Gorenko 			(lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP);
2345882981f4SBart Van Assche 		ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
2346b2e872f4SHonggang Li 						      ch->use_imm_data,
2347b2e872f4SHonggang Li 						      target->max_it_iu_size);
2348513d5647SBart Van Assche 		WARN_ON_ONCE(ch->max_it_iu_len >
2349513d5647SBart Van Assche 			     be32_to_cpu(lrsp->max_it_iu_len));
2350961e0be8SDavid Dillow 
2351882981f4SBart Van Assche 		if (ch->use_imm_data)
2352882981f4SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host,
2353882981f4SBart Van Assche 				     PFX "using immediate data\n");
2354961e0be8SDavid Dillow 
2355961e0be8SDavid Dillow 		/*
2356961e0be8SDavid Dillow 		 * Reserve credits for task management so we don't
2357961e0be8SDavid Dillow 		 * bounce requests back to the SCSI mid-layer.
2358961e0be8SDavid Dillow 		 */
2359961e0be8SDavid Dillow 		target->scsi_host->can_queue
2360509c07bcSBart Van Assche 			= min(ch->req_lim - SRP_TSK_MGMT_SQ_SIZE,
2361961e0be8SDavid Dillow 			      target->scsi_host->can_queue);
23624d73f95fSBart Van Assche 		target->scsi_host->cmd_per_lun
23634d73f95fSBart Van Assche 			= min_t(int, target->scsi_host->can_queue,
23644d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun);
2365961e0be8SDavid Dillow 	} else {
2366961e0be8SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
2367961e0be8SDavid Dillow 			     PFX "Unhandled RSP opcode %#x\n", lrsp->opcode);
2368961e0be8SDavid Dillow 		ret = -ECONNRESET;
2369961e0be8SDavid Dillow 		goto error;
2370961e0be8SDavid Dillow 	}
2371961e0be8SDavid Dillow 
2372509c07bcSBart Van Assche 	if (!ch->rx_ring) {
2373509c07bcSBart Van Assche 		ret = srp_alloc_iu_bufs(ch);
2374961e0be8SDavid Dillow 		if (ret)
2375961e0be8SDavid Dillow 			goto error;
2376961e0be8SDavid Dillow 	}
2377961e0be8SDavid Dillow 
237819f31343SBart Van Assche 	for (i = 0; i < target->queue_size; i++) {
237919f31343SBart Van Assche 		struct srp_iu *iu = ch->rx_ring[i];
238019f31343SBart Van Assche 
238119f31343SBart Van Assche 		ret = srp_post_recv(ch, iu);
238219f31343SBart Van Assche 		if (ret)
238319f31343SBart Van Assche 			goto error;
238419f31343SBart Van Assche 	}
238519f31343SBart Van Assche 
238619f31343SBart Van Assche 	if (!target->using_rdma_cm) {
2387961e0be8SDavid Dillow 		ret = -ENOMEM;
238819f31343SBart Van Assche 		qp_attr = kmalloc(sizeof(*qp_attr), GFP_KERNEL);
2389961e0be8SDavid Dillow 		if (!qp_attr)
2390961e0be8SDavid Dillow 			goto error;
2391961e0be8SDavid Dillow 
2392961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTR;
2393961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2394961e0be8SDavid Dillow 		if (ret)
2395961e0be8SDavid Dillow 			goto error_free;
2396961e0be8SDavid Dillow 
2397509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2398961e0be8SDavid Dillow 		if (ret)
2399961e0be8SDavid Dillow 			goto error_free;
2400961e0be8SDavid Dillow 
2401961e0be8SDavid Dillow 		qp_attr->qp_state = IB_QPS_RTS;
2402961e0be8SDavid Dillow 		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
2403961e0be8SDavid Dillow 		if (ret)
2404961e0be8SDavid Dillow 			goto error_free;
2405961e0be8SDavid Dillow 
2406c9b03c1aSBart Van Assche 		target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
2407c9b03c1aSBart Van Assche 
2408509c07bcSBart Van Assche 		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
2409961e0be8SDavid Dillow 		if (ret)
2410961e0be8SDavid Dillow 			goto error_free;
2411961e0be8SDavid Dillow 
2412961e0be8SDavid Dillow 		ret = ib_send_cm_rtu(cm_id, NULL, 0);
241319f31343SBart Van Assche 	}
2414961e0be8SDavid Dillow 
2415961e0be8SDavid Dillow error_free:
2416961e0be8SDavid Dillow 	kfree(qp_attr);
2417961e0be8SDavid Dillow 
2418961e0be8SDavid Dillow error:
2419509c07bcSBart Van Assche 	ch->status = ret;
2420961e0be8SDavid Dillow }
2421961e0be8SDavid Dillow 
srp_ib_cm_rej_handler(struct ib_cm_id * cm_id,const struct ib_cm_event * event,struct srp_rdma_ch * ch)242219f31343SBart Van Assche static void srp_ib_cm_rej_handler(struct ib_cm_id *cm_id,
2423e7ff98aeSParav Pandit 				  const struct ib_cm_event *event,
2424509c07bcSBart Van Assche 				  struct srp_rdma_ch *ch)
2425aef9ec39SRoland Dreier {
2426509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
24277aa54bd7SDavid Dillow 	struct Scsi_Host *shost = target->scsi_host;
2428aef9ec39SRoland Dreier 	struct ib_class_port_info *cpi;
2429aef9ec39SRoland Dreier 	int opcode;
243019f31343SBart Van Assche 	u16 dlid;
2431aef9ec39SRoland Dreier 
2432aef9ec39SRoland Dreier 	switch (event->param.rej_rcvd.reason) {
2433aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_CM_REDIRECT:
2434aef9ec39SRoland Dreier 		cpi = event->param.rej_rcvd.ari;
243519f31343SBart Van Assche 		dlid = be16_to_cpu(cpi->redirect_lid);
243619f31343SBart Van Assche 		sa_path_set_dlid(&ch->ib_cm.path, dlid);
243719f31343SBart Van Assche 		ch->ib_cm.path.pkey = cpi->redirect_pkey;
2438aef9ec39SRoland Dreier 		cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
243919f31343SBart Van Assche 		memcpy(ch->ib_cm.path.dgid.raw, cpi->redirect_gid, 16);
2440aef9ec39SRoland Dreier 
244119f31343SBart Van Assche 		ch->status = dlid ? SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
2442aef9ec39SRoland Dreier 		break;
2443aef9ec39SRoland Dreier 
2444aef9ec39SRoland Dreier 	case IB_CM_REJ_PORT_REDIRECT:
24455d7cbfd6SRoland Dreier 		if (srp_target_is_topspin(target)) {
244619f31343SBart Van Assche 			union ib_gid *dgid = &ch->ib_cm.path.dgid;
244719f31343SBart Van Assche 
2448aef9ec39SRoland Dreier 			/*
2449aef9ec39SRoland Dreier 			 * Topspin/Cisco SRP gateways incorrectly send
2450aef9ec39SRoland Dreier 			 * reject reason code 25 when they mean 24
2451aef9ec39SRoland Dreier 			 * (port redirect).
2452aef9ec39SRoland Dreier 			 */
245319f31343SBart Van Assche 			memcpy(dgid->raw, event->param.rej_rcvd.ari, 16);
2454aef9ec39SRoland Dreier 
24557aa54bd7SDavid Dillow 			shost_printk(KERN_DEBUG, shost,
24567aa54bd7SDavid Dillow 				     PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
245719f31343SBart Van Assche 				     be64_to_cpu(dgid->global.subnet_prefix),
245819f31343SBart Van Assche 				     be64_to_cpu(dgid->global.interface_id));
2459aef9ec39SRoland Dreier 
2460509c07bcSBart Van Assche 			ch->status = SRP_PORT_REDIRECT;
2461aef9ec39SRoland Dreier 		} else {
24627aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
24637aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
2464509c07bcSBart Van Assche 			ch->status = -ECONNRESET;
2465aef9ec39SRoland Dreier 		}
2466aef9ec39SRoland Dreier 		break;
2467aef9ec39SRoland Dreier 
2468aef9ec39SRoland Dreier 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
24697aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost,
24707aa54bd7SDavid Dillow 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
2471509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2472aef9ec39SRoland Dreier 		break;
2473aef9ec39SRoland Dreier 
2474aef9ec39SRoland Dreier 	case IB_CM_REJ_CONSUMER_DEFINED:
2475aef9ec39SRoland Dreier 		opcode = *(u8 *) event->private_data;
2476aef9ec39SRoland Dreier 		if (opcode == SRP_LOGIN_REJ) {
2477aef9ec39SRoland Dreier 			struct srp_login_rej *rej = event->private_data;
2478aef9ec39SRoland Dreier 			u32 reason = be32_to_cpu(rej->reason);
2479aef9ec39SRoland Dreier 
2480aef9ec39SRoland Dreier 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
24817aa54bd7SDavid Dillow 				shost_printk(KERN_WARNING, shost,
24827aa54bd7SDavid Dillow 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
2483aef9ec39SRoland Dreier 			else
2484e7ffde01SBart Van Assche 				shost_printk(KERN_WARNING, shost, PFX
2485e7ffde01SBart Van Assche 					     "SRP LOGIN from %pI6 to %pI6 REJECTED, reason 0x%08x\n",
2486747fe000SBart Van Assche 					     target->sgid.raw,
248719f31343SBart Van Assche 					     target->ib_cm.orig_dgid.raw,
248819f31343SBart Van Assche 					     reason);
2489aef9ec39SRoland Dreier 		} else
24907aa54bd7SDavid Dillow 			shost_printk(KERN_WARNING, shost,
24917aa54bd7SDavid Dillow 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
2492aef9ec39SRoland Dreier 				     " opcode 0x%02x\n", opcode);
2493509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2494aef9ec39SRoland Dreier 		break;
2495aef9ec39SRoland Dreier 
24969fe4bcf4SDavid Dillow 	case IB_CM_REJ_STALE_CONN:
24979fe4bcf4SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason: stale connection\n");
2498509c07bcSBart Van Assche 		ch->status = SRP_STALE_CONN;
24999fe4bcf4SDavid Dillow 		break;
25009fe4bcf4SDavid Dillow 
2501aef9ec39SRoland Dreier 	default:
25027aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
2503aef9ec39SRoland Dreier 			     event->param.rej_rcvd.reason);
2504509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2505aef9ec39SRoland Dreier 	}
2506aef9ec39SRoland Dreier }
2507aef9ec39SRoland Dreier 
srp_ib_cm_handler(struct ib_cm_id * cm_id,const struct ib_cm_event * event)2508e7ff98aeSParav Pandit static int srp_ib_cm_handler(struct ib_cm_id *cm_id,
2509e7ff98aeSParav Pandit 			     const struct ib_cm_event *event)
2510aef9ec39SRoland Dreier {
2511509c07bcSBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
2512509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2513aef9ec39SRoland Dreier 	int comp = 0;
2514aef9ec39SRoland Dreier 
2515aef9ec39SRoland Dreier 	switch (event->event) {
2516aef9ec39SRoland Dreier 	case IB_CM_REQ_ERROR:
25177aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host,
25187aa54bd7SDavid Dillow 			     PFX "Sending CM REQ failed\n");
2519aef9ec39SRoland Dreier 		comp = 1;
2520509c07bcSBart Van Assche 		ch->status = -ECONNRESET;
2521aef9ec39SRoland Dreier 		break;
2522aef9ec39SRoland Dreier 
2523aef9ec39SRoland Dreier 	case IB_CM_REP_RECEIVED:
2524aef9ec39SRoland Dreier 		comp = 1;
2525509c07bcSBart Van Assche 		srp_cm_rep_handler(cm_id, event->private_data, ch);
2526aef9ec39SRoland Dreier 		break;
2527aef9ec39SRoland Dreier 
2528aef9ec39SRoland Dreier 	case IB_CM_REJ_RECEIVED:
25297aa54bd7SDavid Dillow 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
2530aef9ec39SRoland Dreier 		comp = 1;
2531aef9ec39SRoland Dreier 
253219f31343SBart Van Assche 		srp_ib_cm_rej_handler(cm_id, event, ch);
2533aef9ec39SRoland Dreier 		break;
2534aef9ec39SRoland Dreier 
2535b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_RECEIVED:
25367aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
25377aa54bd7SDavid Dillow 			     PFX "DREQ received - connection closed\n");
2538c014c8cdSBart Van Assche 		ch->connected = false;
2539b7ac4ab4SIshai Rabinovitz 		if (ib_send_cm_drep(cm_id, NULL, 0))
25407aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
25417aa54bd7SDavid Dillow 				     PFX "Sending CM DREP failed\n");
2542c1120f89SBart Van Assche 		queue_work(system_long_wq, &target->tl_err_work);
2543aef9ec39SRoland Dreier 		break;
2544aef9ec39SRoland Dreier 
2545aef9ec39SRoland Dreier 	case IB_CM_TIMEWAIT_EXIT:
25467aa54bd7SDavid Dillow 		shost_printk(KERN_ERR, target->scsi_host,
25477aa54bd7SDavid Dillow 			     PFX "connection closed\n");
2548ac72d766SBart Van Assche 		comp = 1;
2549aef9ec39SRoland Dreier 
2550509c07bcSBart Van Assche 		ch->status = 0;
2551aef9ec39SRoland Dreier 		break;
2552aef9ec39SRoland Dreier 
2553b7ac4ab4SIshai Rabinovitz 	case IB_CM_MRA_RECEIVED:
2554b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREQ_ERROR:
2555b7ac4ab4SIshai Rabinovitz 	case IB_CM_DREP_RECEIVED:
2556b7ac4ab4SIshai Rabinovitz 		break;
2557b7ac4ab4SIshai Rabinovitz 
2558aef9ec39SRoland Dreier 	default:
25597aa54bd7SDavid Dillow 		shost_printk(KERN_WARNING, target->scsi_host,
25607aa54bd7SDavid Dillow 			     PFX "Unhandled CM event %d\n", event->event);
2561aef9ec39SRoland Dreier 		break;
2562aef9ec39SRoland Dreier 	}
2563aef9ec39SRoland Dreier 
2564aef9ec39SRoland Dreier 	if (comp)
2565509c07bcSBart Van Assche 		complete(&ch->done);
2566aef9ec39SRoland Dreier 
2567aef9ec39SRoland Dreier 	return 0;
2568aef9ec39SRoland Dreier }
2569aef9ec39SRoland Dreier 
srp_rdma_cm_rej_handler(struct srp_rdma_ch * ch,struct rdma_cm_event * event)257019f31343SBart Van Assche static void srp_rdma_cm_rej_handler(struct srp_rdma_ch *ch,
257119f31343SBart Van Assche 				    struct rdma_cm_event *event)
257219f31343SBart Van Assche {
257319f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
257419f31343SBart Van Assche 	struct Scsi_Host *shost = target->scsi_host;
257519f31343SBart Van Assche 	int opcode;
257619f31343SBart Van Assche 
257719f31343SBart Van Assche 	switch (event->status) {
257819f31343SBart Van Assche 	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
257919f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
258019f31343SBart Van Assche 			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
258119f31343SBart Van Assche 		ch->status = -ECONNRESET;
258219f31343SBart Van Assche 		break;
258319f31343SBart Van Assche 
258419f31343SBart Van Assche 	case IB_CM_REJ_CONSUMER_DEFINED:
258519f31343SBart Van Assche 		opcode = *(u8 *) event->param.conn.private_data;
258619f31343SBart Van Assche 		if (opcode == SRP_LOGIN_REJ) {
258719f31343SBart Van Assche 			struct srp_login_rej *rej =
258819f31343SBart Van Assche 				(struct srp_login_rej *)
258919f31343SBart Van Assche 				event->param.conn.private_data;
259019f31343SBart Van Assche 			u32 reason = be32_to_cpu(rej->reason);
259119f31343SBart Van Assche 
259219f31343SBart Van Assche 			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
259319f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
259419f31343SBart Van Assche 					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
259519f31343SBart Van Assche 			else
259619f31343SBart Van Assche 				shost_printk(KERN_WARNING, shost,
259719f31343SBart Van Assche 					    PFX "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
259819f31343SBart Van Assche 		} else {
259919f31343SBart Van Assche 			shost_printk(KERN_WARNING, shost,
260019f31343SBart Van Assche 				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED, opcode 0x%02x\n",
260119f31343SBart Van Assche 				     opcode);
260219f31343SBart Van Assche 		}
260319f31343SBart Van Assche 		ch->status = -ECONNRESET;
260419f31343SBart Van Assche 		break;
260519f31343SBart Van Assche 
260619f31343SBart Van Assche 	case IB_CM_REJ_STALE_CONN:
260719f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost,
260819f31343SBart Van Assche 			     "  REJ reason: stale connection\n");
260919f31343SBart Van Assche 		ch->status = SRP_STALE_CONN;
261019f31343SBart Van Assche 		break;
261119f31343SBart Van Assche 
261219f31343SBart Van Assche 	default:
261319f31343SBart Van Assche 		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
261419f31343SBart Van Assche 			     event->status);
261519f31343SBart Van Assche 		ch->status = -ECONNRESET;
261619f31343SBart Van Assche 		break;
261719f31343SBart Van Assche 	}
261819f31343SBart Van Assche }
261919f31343SBart Van Assche 
srp_rdma_cm_handler(struct rdma_cm_id * cm_id,struct rdma_cm_event * event)262019f31343SBart Van Assche static int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
262119f31343SBart Van Assche 			       struct rdma_cm_event *event)
262219f31343SBart Van Assche {
262319f31343SBart Van Assche 	struct srp_rdma_ch *ch = cm_id->context;
262419f31343SBart Van Assche 	struct srp_target_port *target = ch->target;
262519f31343SBart Van Assche 	int comp = 0;
262619f31343SBart Van Assche 
262719f31343SBart Van Assche 	switch (event->event) {
262819f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_RESOLVED:
262919f31343SBart Van Assche 		ch->status = 0;
263019f31343SBart Van Assche 		comp = 1;
263119f31343SBart Van Assche 		break;
263219f31343SBart Van Assche 
263319f31343SBart Van Assche 	case RDMA_CM_EVENT_ADDR_ERROR:
263419f31343SBart Van Assche 		ch->status = -ENXIO;
263519f31343SBart Van Assche 		comp = 1;
263619f31343SBart Van Assche 		break;
263719f31343SBart Van Assche 
263819f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_RESOLVED:
263919f31343SBart Van Assche 		ch->status = 0;
264019f31343SBart Van Assche 		comp = 1;
264119f31343SBart Van Assche 		break;
264219f31343SBart Van Assche 
264319f31343SBart Van Assche 	case RDMA_CM_EVENT_ROUTE_ERROR:
264419f31343SBart Van Assche 	case RDMA_CM_EVENT_UNREACHABLE:
264519f31343SBart Van Assche 		ch->status = -EHOSTUNREACH;
264619f31343SBart Van Assche 		comp = 1;
264719f31343SBart Van Assche 		break;
264819f31343SBart Van Assche 
264919f31343SBart Van Assche 	case RDMA_CM_EVENT_CONNECT_ERROR:
265019f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host,
265119f31343SBart Van Assche 			     PFX "Sending CM REQ failed\n");
265219f31343SBart Van Assche 		comp = 1;
265319f31343SBart Van Assche 		ch->status = -ECONNRESET;
265419f31343SBart Van Assche 		break;
265519f31343SBart Van Assche 
265619f31343SBart Van Assche 	case RDMA_CM_EVENT_ESTABLISHED:
265719f31343SBart Van Assche 		comp = 1;
265819f31343SBart Van Assche 		srp_cm_rep_handler(NULL, event->param.conn.private_data, ch);
265919f31343SBart Van Assche 		break;
266019f31343SBart Van Assche 
266119f31343SBart Van Assche 	case RDMA_CM_EVENT_REJECTED:
266219f31343SBart Van Assche 		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
266319f31343SBart Van Assche 		comp = 1;
266419f31343SBart Van Assche 
266519f31343SBart Van Assche 		srp_rdma_cm_rej_handler(ch, event);
266619f31343SBart Van Assche 		break;
266719f31343SBart Van Assche 
266819f31343SBart Van Assche 	case RDMA_CM_EVENT_DISCONNECTED:
266919f31343SBart Van Assche 		if (ch->connected) {
267019f31343SBart Van Assche 			shost_printk(KERN_WARNING, target->scsi_host,
267119f31343SBart Van Assche 				     PFX "received DREQ\n");
267219f31343SBart Van Assche 			rdma_disconnect(ch->rdma_cm.cm_id);
267319f31343SBart Van Assche 			comp = 1;
267419f31343SBart Van Assche 			ch->status = 0;
267519f31343SBart Van Assche 			queue_work(system_long_wq, &target->tl_err_work);
267619f31343SBart Van Assche 		}
267719f31343SBart Van Assche 		break;
267819f31343SBart Van Assche 
267919f31343SBart Van Assche 	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
268019f31343SBart Van Assche 		shost_printk(KERN_ERR, target->scsi_host,
268119f31343SBart Van Assche 			     PFX "connection closed\n");
268219f31343SBart Van Assche 
268319f31343SBart Van Assche 		comp = 1;
268419f31343SBart Van Assche 		ch->status = 0;
268519f31343SBart Van Assche 		break;
268619f31343SBart Van Assche 
268719f31343SBart Van Assche 	default:
268819f31343SBart Van Assche 		shost_printk(KERN_WARNING, target->scsi_host,
268919f31343SBart Van Assche 			     PFX "Unhandled CM event %d\n", event->event);
269019f31343SBart Van Assche 		break;
269119f31343SBart Van Assche 	}
269219f31343SBart Van Assche 
269319f31343SBart Van Assche 	if (comp)
269419f31343SBart Van Assche 		complete(&ch->done);
269519f31343SBart Van Assche 
269619f31343SBart Van Assche 	return 0;
269719f31343SBart Van Assche }
269819f31343SBart Van Assche 
269971444b97SJack Wang /**
270071444b97SJack Wang  * srp_change_queue_depth - setting device queue depth
270171444b97SJack Wang  * @sdev: scsi device struct
270271444b97SJack Wang  * @qdepth: requested queue depth
270371444b97SJack Wang  *
270471444b97SJack Wang  * Returns queue depth.
270571444b97SJack Wang  */
270671444b97SJack Wang static int
srp_change_queue_depth(struct scsi_device * sdev,int qdepth)2707db5ed4dfSChristoph Hellwig srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
270871444b97SJack Wang {
270971444b97SJack Wang 	if (!sdev->tagged_supported)
27101e6f2416SChristoph Hellwig 		qdepth = 1;
2711db5ed4dfSChristoph Hellwig 	return scsi_change_queue_depth(sdev, qdepth);
271271444b97SJack Wang }
271371444b97SJack Wang 
srp_send_tsk_mgmt(struct srp_rdma_ch * ch,u64 req_tag,u64 lun,u8 func,u8 * status)2714985aa495SBart Van Assche static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
27150a6fdbdeSBart Van Assche 			     u8 func, u8 *status)
2716aef9ec39SRoland Dreier {
2717509c07bcSBart Van Assche 	struct srp_target_port *target = ch->target;
2718a95cadb9SBart Van Assche 	struct srp_rport *rport = target->rport;
271919081f31SDavid Dillow 	struct ib_device *dev = target->srp_host->srp_dev->dev;
2720aef9ec39SRoland Dreier 	struct srp_iu *iu;
2721aef9ec39SRoland Dreier 	struct srp_tsk_mgmt *tsk_mgmt;
27220a6fdbdeSBart Van Assche 	int res;
2723aef9ec39SRoland Dreier 
2724c014c8cdSBart Van Assche 	if (!ch->connected || target->qp_in_error)
27253780d1f0SBart Van Assche 		return -1;
27263780d1f0SBart Van Assche 
2727a95cadb9SBart Van Assche 	/*
2728509c07bcSBart Van Assche 	 * Lock the rport mutex to avoid that srp_create_ch_ib() is
2729a95cadb9SBart Van Assche 	 * invoked while a task management function is being sent.
2730a95cadb9SBart Van Assche 	 */
2731a95cadb9SBart Van Assche 	mutex_lock(&rport->mutex);
2732509c07bcSBart Van Assche 	spin_lock_irq(&ch->lock);
2733509c07bcSBart Van Assche 	iu = __srp_get_tx_iu(ch, SRP_IU_TSK_MGMT);
2734509c07bcSBart Van Assche 	spin_unlock_irq(&ch->lock);
273576c75b25SBart Van Assche 
2736a95cadb9SBart Van Assche 	if (!iu) {
2737a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2738a95cadb9SBart Van Assche 
273976c75b25SBart Van Assche 		return -1;
2740a95cadb9SBart Van Assche 	}
2741aef9ec39SRoland Dreier 
2742882981f4SBart Van Assche 	iu->num_sge = 1;
2743882981f4SBart Van Assche 
274419081f31SDavid Dillow 	ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
274519081f31SDavid Dillow 				   DMA_TO_DEVICE);
2746aef9ec39SRoland Dreier 	tsk_mgmt = iu->buf;
2747aef9ec39SRoland Dreier 	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
2748aef9ec39SRoland Dreier 
2749aef9ec39SRoland Dreier 	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
2750985aa495SBart Van Assche 	int_to_scsilun(lun, &tsk_mgmt->lun);
2751aef9ec39SRoland Dreier 	tsk_mgmt->tsk_mgmt_func = func;
2752f8b6e31eSDavid Dillow 	tsk_mgmt->task_tag	= req_tag;
2753aef9ec39SRoland Dreier 
27540a6fdbdeSBart Van Assche 	spin_lock_irq(&ch->lock);
27550a6fdbdeSBart Van Assche 	ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT;
27560a6fdbdeSBart Van Assche 	tsk_mgmt->tag = ch->tsk_mgmt_tag;
27570a6fdbdeSBart Van Assche 	spin_unlock_irq(&ch->lock);
27580a6fdbdeSBart Van Assche 
27590a6fdbdeSBart Van Assche 	init_completion(&ch->tsk_mgmt_done);
27600a6fdbdeSBart Van Assche 
276119081f31SDavid Dillow 	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
276219081f31SDavid Dillow 				      DMA_TO_DEVICE);
2763509c07bcSBart Van Assche 	if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
2764509c07bcSBart Van Assche 		srp_put_tx_iu(ch, iu, SRP_IU_TSK_MGMT);
2765a95cadb9SBart Van Assche 		mutex_unlock(&rport->mutex);
2766a95cadb9SBart Van Assche 
276776c75b25SBart Van Assche 		return -1;
276876c75b25SBart Van Assche 	}
27690a6fdbdeSBart Van Assche 	res = wait_for_completion_timeout(&ch->tsk_mgmt_done,
27700a6fdbdeSBart Van Assche 					msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS));
27710a6fdbdeSBart Van Assche 	if (res > 0 && status)
27720a6fdbdeSBart Van Assche 		*status = ch->tsk_mgmt_status;
2773a95cadb9SBart Van Assche 	mutex_unlock(&rport->mutex);
2774d945e1dfSRoland Dreier 
27750a6fdbdeSBart Van Assche 	WARN_ON_ONCE(res < 0);
2776aef9ec39SRoland Dreier 
27770a6fdbdeSBart Van Assche 	return res > 0 ? 0 : -1;
2778d945e1dfSRoland Dreier }
2779d945e1dfSRoland Dreier 
srp_abort(struct scsi_cmnd * scmnd)2780aef9ec39SRoland Dreier static int srp_abort(struct scsi_cmnd *scmnd)
2781aef9ec39SRoland Dreier {
2782d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
27836dbe4a8dSBart Van Assche 	struct srp_request *req = scsi_cmd_priv(scmnd);
278477f2c1a4SBart Van Assche 	u32 tag;
2785d92c0da7SBart Van Assche 	u16 ch_idx;
2786509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
2787d945e1dfSRoland Dreier 
27887aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
2789aef9ec39SRoland Dreier 
27909c5274eeSBart Van Assche 	tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmnd));
2791d92c0da7SBart Van Assche 	ch_idx = blk_mq_unique_tag_to_hwq(tag);
2792d92c0da7SBart Van Assche 	if (WARN_ON_ONCE(ch_idx >= target->ch_count))
2793d92c0da7SBart Van Assche 		return SUCCESS;
2794d92c0da7SBart Van Assche 	ch = &target->ch[ch_idx];
2795d92c0da7SBart Van Assche 	if (!srp_claim_req(ch, req, NULL, scmnd))
2796d92c0da7SBart Van Assche 		return SUCCESS;
2797d92c0da7SBart Van Assche 	shost_printk(KERN_ERR, target->scsi_host,
2798d92c0da7SBart Van Assche 		     "Sending SRP abort for tag %#x\n", tag);
279977f2c1a4SBart Van Assche 	if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
2800*e193b795SBart Van Assche 			      SRP_TSK_ABORT_TASK, NULL) == 0) {
2801509c07bcSBart Van Assche 		srp_free_req(ch, req, scmnd, 0);
2802*e193b795SBart Van Assche 		return SUCCESS;
2803e68088e7SBart Van Assche 	}
2804*e193b795SBart Van Assche 	if (target->rport->state == SRP_RPORT_LOST)
2805*e193b795SBart Van Assche 		return FAST_IO_FAIL;
2806d945e1dfSRoland Dreier 
2807*e193b795SBart Van Assche 	return FAILED;
2808aef9ec39SRoland Dreier }
2809aef9ec39SRoland Dreier 
srp_reset_device(struct scsi_cmnd * scmnd)2810aef9ec39SRoland Dreier static int srp_reset_device(struct scsi_cmnd *scmnd)
2811aef9ec39SRoland Dreier {
2812d945e1dfSRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
2813d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
28140a6fdbdeSBart Van Assche 	u8 status;
2815d945e1dfSRoland Dreier 
28167aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
2817aef9ec39SRoland Dreier 
2818d92c0da7SBart Van Assche 	ch = &target->ch[0];
2819509c07bcSBart Van Assche 	if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
28200a6fdbdeSBart Van Assche 			      SRP_TSK_LUN_RESET, &status))
2821d945e1dfSRoland Dreier 		return FAILED;
28220a6fdbdeSBart Van Assche 	if (status)
2823d945e1dfSRoland Dreier 		return FAILED;
2824d945e1dfSRoland Dreier 
2825d945e1dfSRoland Dreier 	return SUCCESS;
2826aef9ec39SRoland Dreier }
2827aef9ec39SRoland Dreier 
srp_reset_host(struct scsi_cmnd * scmnd)2828aef9ec39SRoland Dreier static int srp_reset_host(struct scsi_cmnd *scmnd)
2829aef9ec39SRoland Dreier {
2830aef9ec39SRoland Dreier 	struct srp_target_port *target = host_to_target(scmnd->device->host);
2831aef9ec39SRoland Dreier 
28327aa54bd7SDavid Dillow 	shost_printk(KERN_ERR, target->scsi_host, PFX "SRP reset_host called\n");
2833aef9ec39SRoland Dreier 
2834ed9b2264SBart Van Assche 	return srp_reconnect_rport(target->rport) == 0 ? SUCCESS : FAILED;
2835aef9ec39SRoland Dreier }
2836aef9ec39SRoland Dreier 
srp_target_alloc(struct scsi_target * starget)2837b0780ee5SBart Van Assche static int srp_target_alloc(struct scsi_target *starget)
2838b0780ee5SBart Van Assche {
2839b0780ee5SBart Van Assche 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2840b0780ee5SBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
2841b0780ee5SBart Van Assche 
2842b0780ee5SBart Van Assche 	if (target->target_can_queue)
2843b0780ee5SBart Van Assche 		starget->can_queue = target->target_can_queue;
2844b0780ee5SBart Van Assche 	return 0;
2845b0780ee5SBart Van Assche }
2846b0780ee5SBart Van Assche 
srp_slave_configure(struct scsi_device * sdev)2847c9b03c1aSBart Van Assche static int srp_slave_configure(struct scsi_device *sdev)
2848c9b03c1aSBart Van Assche {
2849c9b03c1aSBart Van Assche 	struct Scsi_Host *shost = sdev->host;
2850c9b03c1aSBart Van Assche 	struct srp_target_port *target = host_to_target(shost);
2851c9b03c1aSBart Van Assche 	struct request_queue *q = sdev->request_queue;
2852c9b03c1aSBart Van Assche 	unsigned long timeout;
2853c9b03c1aSBart Van Assche 
2854c9b03c1aSBart Van Assche 	if (sdev->type == TYPE_DISK) {
2855c9b03c1aSBart Van Assche 		timeout = max_t(unsigned, 30 * HZ, target->rq_tmo_jiffies);
2856c9b03c1aSBart Van Assche 		blk_queue_rq_timeout(q, timeout);
2857c9b03c1aSBart Van Assche 	}
2858c9b03c1aSBart Van Assche 
2859c9b03c1aSBart Van Assche 	return 0;
2860c9b03c1aSBart Van Assche }
2861c9b03c1aSBart Van Assche 
id_ext_show(struct device * dev,struct device_attribute * attr,char * buf)286233e82346SYueHaibing static ssize_t id_ext_show(struct device *dev, struct device_attribute *attr,
2863ee959b00STony Jones 			   char *buf)
28646ecb0c84SRoland Dreier {
2865ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
28666ecb0c84SRoland Dreier 
28671c7fd726SJoe Perches 	return sysfs_emit(buf, "0x%016llx\n", be64_to_cpu(target->id_ext));
28686ecb0c84SRoland Dreier }
28696ecb0c84SRoland Dreier 
287033e82346SYueHaibing static DEVICE_ATTR_RO(id_ext);
287133e82346SYueHaibing 
ioc_guid_show(struct device * dev,struct device_attribute * attr,char * buf)287233e82346SYueHaibing static ssize_t ioc_guid_show(struct device *dev, struct device_attribute *attr,
2873ee959b00STony Jones 			     char *buf)
28746ecb0c84SRoland Dreier {
2875ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
28766ecb0c84SRoland Dreier 
28771c7fd726SJoe Perches 	return sysfs_emit(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid));
28786ecb0c84SRoland Dreier }
28796ecb0c84SRoland Dreier 
288033e82346SYueHaibing static DEVICE_ATTR_RO(ioc_guid);
288133e82346SYueHaibing 
service_id_show(struct device * dev,struct device_attribute * attr,char * buf)288233e82346SYueHaibing static ssize_t service_id_show(struct device *dev,
2883ee959b00STony Jones 			       struct device_attribute *attr, char *buf)
28846ecb0c84SRoland Dreier {
2885ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
28866ecb0c84SRoland Dreier 
288719f31343SBart Van Assche 	if (target->using_rdma_cm)
288819f31343SBart Van Assche 		return -ENOENT;
28891c7fd726SJoe Perches 	return sysfs_emit(buf, "0x%016llx\n",
289019f31343SBart Van Assche 			  be64_to_cpu(target->ib_cm.service_id));
28916ecb0c84SRoland Dreier }
28926ecb0c84SRoland Dreier 
289333e82346SYueHaibing static DEVICE_ATTR_RO(service_id);
289433e82346SYueHaibing 
pkey_show(struct device * dev,struct device_attribute * attr,char * buf)289533e82346SYueHaibing static ssize_t pkey_show(struct device *dev, struct device_attribute *attr,
2896ee959b00STony Jones 			 char *buf)
28976ecb0c84SRoland Dreier {
2898ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
28996ecb0c84SRoland Dreier 
290019f31343SBart Van Assche 	if (target->using_rdma_cm)
290119f31343SBart Van Assche 		return -ENOENT;
290245808361SJoe Perches 
29031c7fd726SJoe Perches 	return sysfs_emit(buf, "0x%04x\n", be16_to_cpu(target->ib_cm.pkey));
29046ecb0c84SRoland Dreier }
29056ecb0c84SRoland Dreier 
290633e82346SYueHaibing static DEVICE_ATTR_RO(pkey);
290733e82346SYueHaibing 
sgid_show(struct device * dev,struct device_attribute * attr,char * buf)290833e82346SYueHaibing static ssize_t sgid_show(struct device *dev, struct device_attribute *attr,
2909848b3082SBart Van Assche 			 char *buf)
2910848b3082SBart Van Assche {
2911848b3082SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
2912848b3082SBart Van Assche 
29131c7fd726SJoe Perches 	return sysfs_emit(buf, "%pI6\n", target->sgid.raw);
2914848b3082SBart Van Assche }
2915848b3082SBart Van Assche 
291633e82346SYueHaibing static DEVICE_ATTR_RO(sgid);
291733e82346SYueHaibing 
dgid_show(struct device * dev,struct device_attribute * attr,char * buf)291833e82346SYueHaibing static ssize_t dgid_show(struct device *dev, struct device_attribute *attr,
2919ee959b00STony Jones 			 char *buf)
29206ecb0c84SRoland Dreier {
2921ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
2922d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch = &target->ch[0];
29236ecb0c84SRoland Dreier 
292419f31343SBart Van Assche 	if (target->using_rdma_cm)
292519f31343SBart Van Assche 		return -ENOENT;
292645808361SJoe Perches 
29271c7fd726SJoe Perches 	return sysfs_emit(buf, "%pI6\n", ch->ib_cm.path.dgid.raw);
29286ecb0c84SRoland Dreier }
29296ecb0c84SRoland Dreier 
293033e82346SYueHaibing static DEVICE_ATTR_RO(dgid);
293133e82346SYueHaibing 
orig_dgid_show(struct device * dev,struct device_attribute * attr,char * buf)293233e82346SYueHaibing static ssize_t orig_dgid_show(struct device *dev, struct device_attribute *attr,
293333e82346SYueHaibing 			      char *buf)
29343633b3d0SIshai Rabinovitz {
2935ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
29363633b3d0SIshai Rabinovitz 
293719f31343SBart Van Assche 	if (target->using_rdma_cm)
293819f31343SBart Van Assche 		return -ENOENT;
293945808361SJoe Perches 
29401c7fd726SJoe Perches 	return sysfs_emit(buf, "%pI6\n", target->ib_cm.orig_dgid.raw);
29413633b3d0SIshai Rabinovitz }
29423633b3d0SIshai Rabinovitz 
294333e82346SYueHaibing static DEVICE_ATTR_RO(orig_dgid);
294433e82346SYueHaibing 
req_lim_show(struct device * dev,struct device_attribute * attr,char * buf)294533e82346SYueHaibing static ssize_t req_lim_show(struct device *dev, struct device_attribute *attr,
294633e82346SYueHaibing 			    char *buf)
294789de7486SBart Van Assche {
294889de7486SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
2949d92c0da7SBart Van Assche 	struct srp_rdma_ch *ch;
2950d92c0da7SBart Van Assche 	int i, req_lim = INT_MAX;
295189de7486SBart Van Assche 
2952d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
2953d92c0da7SBart Van Assche 		ch = &target->ch[i];
2954d92c0da7SBart Van Assche 		req_lim = min(req_lim, ch->req_lim);
2955d92c0da7SBart Van Assche 	}
295645808361SJoe Perches 
29571c7fd726SJoe Perches 	return sysfs_emit(buf, "%d\n", req_lim);
295889de7486SBart Van Assche }
295989de7486SBart Van Assche 
296033e82346SYueHaibing static DEVICE_ATTR_RO(req_lim);
296133e82346SYueHaibing 
zero_req_lim_show(struct device * dev,struct device_attribute * attr,char * buf)296233e82346SYueHaibing static ssize_t zero_req_lim_show(struct device *dev,
2963ee959b00STony Jones 				 struct device_attribute *attr, char *buf)
29646bfa24faSRoland Dreier {
2965ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
29666bfa24faSRoland Dreier 
29671c7fd726SJoe Perches 	return sysfs_emit(buf, "%d\n", target->zero_req_lim);
29686bfa24faSRoland Dreier }
29696bfa24faSRoland Dreier 
297033e82346SYueHaibing static DEVICE_ATTR_RO(zero_req_lim);
297133e82346SYueHaibing 
local_ib_port_show(struct device * dev,struct device_attribute * attr,char * buf)297233e82346SYueHaibing static ssize_t local_ib_port_show(struct device *dev,
2973ee959b00STony Jones 				  struct device_attribute *attr, char *buf)
2974ded7f1a1SIshai Rabinovitz {
2975ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
2976ded7f1a1SIshai Rabinovitz 
2977b05398afSMikhael Goikhman 	return sysfs_emit(buf, "%u\n", target->srp_host->port);
2978ded7f1a1SIshai Rabinovitz }
2979ded7f1a1SIshai Rabinovitz 
298033e82346SYueHaibing static DEVICE_ATTR_RO(local_ib_port);
298133e82346SYueHaibing 
local_ib_device_show(struct device * dev,struct device_attribute * attr,char * buf)298233e82346SYueHaibing static ssize_t local_ib_device_show(struct device *dev,
2983ee959b00STony Jones 				    struct device_attribute *attr, char *buf)
2984ded7f1a1SIshai Rabinovitz {
2985ee959b00STony Jones 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
2986ded7f1a1SIshai Rabinovitz 
29871c7fd726SJoe Perches 	return sysfs_emit(buf, "%s\n",
29886c854111SJason Gunthorpe 			  dev_name(&target->srp_host->srp_dev->dev->dev));
2989ded7f1a1SIshai Rabinovitz }
2990ded7f1a1SIshai Rabinovitz 
299133e82346SYueHaibing static DEVICE_ATTR_RO(local_ib_device);
299233e82346SYueHaibing 
ch_count_show(struct device * dev,struct device_attribute * attr,char * buf)299333e82346SYueHaibing static ssize_t ch_count_show(struct device *dev, struct device_attribute *attr,
2994d92c0da7SBart Van Assche 			     char *buf)
2995d92c0da7SBart Van Assche {
2996d92c0da7SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
2997d92c0da7SBart Van Assche 
29981c7fd726SJoe Perches 	return sysfs_emit(buf, "%d\n", target->ch_count);
2999d92c0da7SBart Van Assche }
3000d92c0da7SBart Van Assche 
300133e82346SYueHaibing static DEVICE_ATTR_RO(ch_count);
300233e82346SYueHaibing 
comp_vector_show(struct device * dev,struct device_attribute * attr,char * buf)300333e82346SYueHaibing static ssize_t comp_vector_show(struct device *dev,
30044b5e5f41SBart Van Assche 				struct device_attribute *attr, char *buf)
30054b5e5f41SBart Van Assche {
30064b5e5f41SBart Van Assche 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30074b5e5f41SBart Van Assche 
30081c7fd726SJoe Perches 	return sysfs_emit(buf, "%d\n", target->comp_vector);
30094b5e5f41SBart Van Assche }
30104b5e5f41SBart Van Assche 
301133e82346SYueHaibing static DEVICE_ATTR_RO(comp_vector);
301233e82346SYueHaibing 
tl_retry_count_show(struct device * dev,struct device_attribute * attr,char * buf)301333e82346SYueHaibing static ssize_t tl_retry_count_show(struct device *dev,
30147bb312e4SVu Pham 				   struct device_attribute *attr, char *buf)
30157bb312e4SVu Pham {
30167bb312e4SVu Pham 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
30177bb312e4SVu Pham 
30181c7fd726SJoe Perches 	return sysfs_emit(buf, "%d\n", target->tl_retry_count);
30197bb312e4SVu Pham }
30207bb312e4SVu Pham 
302133e82346SYueHaibing static DEVICE_ATTR_RO(tl_retry_count);
302233e82346SYueHaibing 
cmd_sg_entries_show(struct device * dev,struct device_attribute * attr,char * buf)302333e82346SYueHaibing static ssize_t cmd_sg_entries_show(struct device *dev,
302449248644SDavid Dillow 				   struct device_attribute *attr, char *buf)
302549248644SDavid Dillow {
302649248644SDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
302749248644SDavid Dillow 
30281c7fd726SJoe Perches 	return sysfs_emit(buf, "%u\n", target->cmd_sg_cnt);
302949248644SDavid Dillow }
303049248644SDavid Dillow 
303133e82346SYueHaibing static DEVICE_ATTR_RO(cmd_sg_entries);
303233e82346SYueHaibing 
allow_ext_sg_show(struct device * dev,struct device_attribute * attr,char * buf)303333e82346SYueHaibing static ssize_t allow_ext_sg_show(struct device *dev,
3034c07d424dSDavid Dillow 				 struct device_attribute *attr, char *buf)
3035c07d424dSDavid Dillow {
3036c07d424dSDavid Dillow 	struct srp_target_port *target = host_to_target(class_to_shost(dev));
3037c07d424dSDavid Dillow 
30381c7fd726SJoe Perches 	return sysfs_emit(buf, "%s\n", target->allow_ext_sg ? "true" : "false");
3039c07d424dSDavid Dillow }
3040c07d424dSDavid Dillow 
304133e82346SYueHaibing static DEVICE_ATTR_RO(allow_ext_sg);
30426ecb0c84SRoland Dreier 
3043a3cf94c9SBart Van Assche static struct attribute *srp_host_attrs[] = {
3044a3cf94c9SBart Van Assche 	&dev_attr_id_ext.attr,
3045a3cf94c9SBart Van Assche 	&dev_attr_ioc_guid.attr,
3046a3cf94c9SBart Van Assche 	&dev_attr_service_id.attr,
3047a3cf94c9SBart Van Assche 	&dev_attr_pkey.attr,
3048a3cf94c9SBart Van Assche 	&dev_attr_sgid.attr,
3049a3cf94c9SBart Van Assche 	&dev_attr_dgid.attr,
3050a3cf94c9SBart Van Assche 	&dev_attr_orig_dgid.attr,
3051a3cf94c9SBart Van Assche 	&dev_attr_req_lim.attr,
3052a3cf94c9SBart Van Assche 	&dev_attr_zero_req_lim.attr,
3053a3cf94c9SBart Van Assche 	&dev_attr_local_ib_port.attr,
3054a3cf94c9SBart Van Assche 	&dev_attr_local_ib_device.attr,
3055a3cf94c9SBart Van Assche 	&dev_attr_ch_count.attr,
3056a3cf94c9SBart Van Assche 	&dev_attr_comp_vector.attr,
3057a3cf94c9SBart Van Assche 	&dev_attr_tl_retry_count.attr,
3058a3cf94c9SBart Van Assche 	&dev_attr_cmd_sg_entries.attr,
3059a3cf94c9SBart Van Assche 	&dev_attr_allow_ext_sg.attr,
30606ecb0c84SRoland Dreier 	NULL
30616ecb0c84SRoland Dreier };
30626ecb0c84SRoland Dreier 
3063a3cf94c9SBart Van Assche ATTRIBUTE_GROUPS(srp_host);
3064a3cf94c9SBart Van Assche 
30654281af9dSBart Van Assche static const struct scsi_host_template srp_template = {
3066aef9ec39SRoland Dreier 	.module				= THIS_MODULE,
3067b7f008fdSRoland Dreier 	.name				= "InfiniBand SRP initiator",
3068b7f008fdSRoland Dreier 	.proc_name			= DRV_NAME,
3069b0780ee5SBart Van Assche 	.target_alloc			= srp_target_alloc,
3070c9b03c1aSBart Van Assche 	.slave_configure		= srp_slave_configure,
3071aef9ec39SRoland Dreier 	.info				= srp_target_info,
3072ad215aaeSBart Van Assche 	.init_cmd_priv			= srp_init_cmd_priv,
3073ad215aaeSBart Van Assche 	.exit_cmd_priv			= srp_exit_cmd_priv,
3074aef9ec39SRoland Dreier 	.queuecommand			= srp_queuecommand,
307571444b97SJack Wang 	.change_queue_depth             = srp_change_queue_depth,
3076b6a05c82SChristoph Hellwig 	.eh_timed_out			= srp_timed_out,
3077aef9ec39SRoland Dreier 	.eh_abort_handler		= srp_abort,
3078aef9ec39SRoland Dreier 	.eh_device_reset_handler	= srp_reset_device,
3079aef9ec39SRoland Dreier 	.eh_host_reset_handler		= srp_reset_host,
30802742c1daSBart Van Assche 	.skip_settle_delay		= true,
308149248644SDavid Dillow 	.sg_tablesize			= SRP_DEF_SG_TABLESIZE,
30824d73f95fSBart Van Assche 	.can_queue			= SRP_DEFAULT_CMD_SQ_SIZE,
3083aef9ec39SRoland Dreier 	.this_id			= -1,
30844d73f95fSBart Van Assche 	.cmd_per_lun			= SRP_DEFAULT_CMD_SQ_SIZE,
3085a3cf94c9SBart Van Assche 	.shost_groups			= srp_host_groups,
3086c40ecc12SChristoph Hellwig 	.track_queue_depth		= 1,
3087ad215aaeSBart Van Assche 	.cmd_size			= sizeof(struct srp_request),
3088aef9ec39SRoland Dreier };
3089aef9ec39SRoland Dreier 
srp_sdev_count(struct Scsi_Host * host)309034aa654eSBart Van Assche static int srp_sdev_count(struct Scsi_Host *host)
309134aa654eSBart Van Assche {
309234aa654eSBart Van Assche 	struct scsi_device *sdev;
309334aa654eSBart Van Assche 	int c = 0;
309434aa654eSBart Van Assche 
309534aa654eSBart Van Assche 	shost_for_each_device(sdev, host)
309634aa654eSBart Van Assche 		c++;
309734aa654eSBart Van Assche 
309834aa654eSBart Van Assche 	return c;
309934aa654eSBart Van Assche }
310034aa654eSBart Van Assche 
3101bc44bd1dSBart Van Assche /*
3102bc44bd1dSBart Van Assche  * Return values:
3103bc44bd1dSBart Van Assche  * < 0 upon failure. Caller is responsible for SRP target port cleanup.
3104bc44bd1dSBart Van Assche  * 0 and target->state == SRP_TARGET_REMOVED if asynchronous target port
3105bc44bd1dSBart Van Assche  *    removal has been scheduled.
3106bc44bd1dSBart Van Assche  * 0 and target->state != SRP_TARGET_REMOVED upon success.
3107bc44bd1dSBart Van Assche  */
srp_add_target(struct srp_host * host,struct srp_target_port * target)3108aef9ec39SRoland Dreier static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
3109aef9ec39SRoland Dreier {
31103236822bSFUJITA Tomonori 	struct srp_rport_identifiers ids;
31113236822bSFUJITA Tomonori 	struct srp_rport *rport;
31123236822bSFUJITA Tomonori 
311334aa654eSBart Van Assche 	target->state = SRP_TARGET_SCANNING;
3114aef9ec39SRoland Dreier 	sprintf(target->target_name, "SRP.T10:%016llX",
311545c37cadSBart Van Assche 		be64_to_cpu(target->id_ext));
3116aef9ec39SRoland Dreier 
3117dee2b82aSBart Van Assche 	if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dev.parent))
3118aef9ec39SRoland Dreier 		return -ENODEV;
3119aef9ec39SRoland Dreier 
31203236822bSFUJITA Tomonori 	memcpy(ids.port_id, &target->id_ext, 8);
31213236822bSFUJITA Tomonori 	memcpy(ids.port_id + 8, &target->ioc_guid, 8);
3122aebd5e47SFUJITA Tomonori 	ids.roles = SRP_RPORT_ROLE_TARGET;
31233236822bSFUJITA Tomonori 	rport = srp_rport_add(target->scsi_host, &ids);
31243236822bSFUJITA Tomonori 	if (IS_ERR(rport)) {
31253236822bSFUJITA Tomonori 		scsi_remove_host(target->scsi_host);
31263236822bSFUJITA Tomonori 		return PTR_ERR(rport);
31273236822bSFUJITA Tomonori 	}
31283236822bSFUJITA Tomonori 
3129dc1bdbd9SBart Van Assche 	rport->lld_data = target;
31309dd69a60SBart Van Assche 	target->rport = rport;
3131dc1bdbd9SBart Van Assche 
3132b3589fd4SMatthew Wilcox 	spin_lock(&host->target_lock);
3133aef9ec39SRoland Dreier 	list_add_tail(&target->list, &host->target_list);
3134b3589fd4SMatthew Wilcox 	spin_unlock(&host->target_lock);
3135aef9ec39SRoland Dreier 
3136aef9ec39SRoland Dreier 	scsi_scan_target(&target->scsi_host->shost_gendev,
31371d645088SHannes Reinecke 			 0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
3138aef9ec39SRoland Dreier 
3139c014c8cdSBart Van Assche 	if (srp_connected_ch(target) < target->ch_count ||
3140c014c8cdSBart Van Assche 	    target->qp_in_error) {
314134aa654eSBart Van Assche 		shost_printk(KERN_INFO, target->scsi_host,
314234aa654eSBart Van Assche 			     PFX "SCSI scan failed - removing SCSI host\n");
314334aa654eSBart Van Assche 		srp_queue_remove_work(target);
314434aa654eSBart Van Assche 		goto out;
314534aa654eSBart Van Assche 	}
314634aa654eSBart Van Assche 
3147cf1acab7SBart Van Assche 	pr_debug("%s: SCSI scan succeeded - detected %d LUNs\n",
314834aa654eSBart Van Assche 		 dev_name(&target->scsi_host->shost_gendev),
314934aa654eSBart Van Assche 		 srp_sdev_count(target->scsi_host));
315034aa654eSBart Van Assche 
315134aa654eSBart Van Assche 	spin_lock_irq(&target->lock);
315234aa654eSBart Van Assche 	if (target->state == SRP_TARGET_SCANNING)
315334aa654eSBart Van Assche 		target->state = SRP_TARGET_LIVE;
315434aa654eSBart Van Assche 	spin_unlock_irq(&target->lock);
315534aa654eSBart Van Assche 
315634aa654eSBart Van Assche out:
3157aef9ec39SRoland Dreier 	return 0;
3158aef9ec39SRoland Dreier }
3159aef9ec39SRoland Dreier 
srp_release_dev(struct device * dev)3160ee959b00STony Jones static void srp_release_dev(struct device *dev)
3161aef9ec39SRoland Dreier {
3162aef9ec39SRoland Dreier 	struct srp_host *host =
3163ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3164aef9ec39SRoland Dreier 
31650766fcaaSBart Van Assche 	kfree(host);
3166aef9ec39SRoland Dreier }
3167aef9ec39SRoland Dreier 
3168b8a9c18cSBart Van Assche static struct attribute *srp_class_attrs[];
3169b8a9c18cSBart Van Assche 
3170b8a9c18cSBart Van Assche ATTRIBUTE_GROUPS(srp_class);
3171b8a9c18cSBart Van Assche 
3172aef9ec39SRoland Dreier static struct class srp_class = {
3173aef9ec39SRoland Dreier 	.name    = "infiniband_srp",
3174b8a9c18cSBart Van Assche 	.dev_groups = srp_class_groups,
3175ee959b00STony Jones 	.dev_release = srp_release_dev
3176aef9ec39SRoland Dreier };
3177aef9ec39SRoland Dreier 
317896fc248aSBart Van Assche /**
317996fc248aSBart Van Assche  * srp_conn_unique() - check whether the connection to a target is unique
3180af24663bSBart Van Assche  * @host:   SRP host.
3181af24663bSBart Van Assche  * @target: SRP target port.
318296fc248aSBart Van Assche  */
srp_conn_unique(struct srp_host * host,struct srp_target_port * target)318396fc248aSBart Van Assche static bool srp_conn_unique(struct srp_host *host,
318496fc248aSBart Van Assche 			    struct srp_target_port *target)
318596fc248aSBart Van Assche {
318696fc248aSBart Van Assche 	struct srp_target_port *t;
318796fc248aSBart Van Assche 	bool ret = false;
318896fc248aSBart Van Assche 
318996fc248aSBart Van Assche 	if (target->state == SRP_TARGET_REMOVED)
319096fc248aSBart Van Assche 		goto out;
319196fc248aSBart Van Assche 
319296fc248aSBart Van Assche 	ret = true;
319396fc248aSBart Van Assche 
319496fc248aSBart Van Assche 	spin_lock(&host->target_lock);
319596fc248aSBart Van Assche 	list_for_each_entry(t, &host->target_list, list) {
319696fc248aSBart Van Assche 		if (t != target &&
319796fc248aSBart Van Assche 		    target->id_ext == t->id_ext &&
319896fc248aSBart Van Assche 		    target->ioc_guid == t->ioc_guid &&
319996fc248aSBart Van Assche 		    target->initiator_ext == t->initiator_ext) {
320096fc248aSBart Van Assche 			ret = false;
320196fc248aSBart Van Assche 			break;
320296fc248aSBart Van Assche 		}
320396fc248aSBart Van Assche 	}
320496fc248aSBart Van Assche 	spin_unlock(&host->target_lock);
320596fc248aSBart Van Assche 
320696fc248aSBart Van Assche out:
320796fc248aSBart Van Assche 	return ret;
320896fc248aSBart Van Assche }
320996fc248aSBart Van Assche 
3210aef9ec39SRoland Dreier /*
3211aef9ec39SRoland Dreier  * Target ports are added by writing
3212aef9ec39SRoland Dreier  *
3213aef9ec39SRoland Dreier  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>,
3214aef9ec39SRoland Dreier  *     pkey=<P_Key>,service_id=<service ID>
321519f31343SBart Van Assche  * or
321619f31343SBart Van Assche  *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,
321719f31343SBart Van Assche  *     [src=<IPv4 address>,]dest=<IPv4 address>:<port number>
3218aef9ec39SRoland Dreier  *
3219aef9ec39SRoland Dreier  * to the add_target sysfs attribute.
3220aef9ec39SRoland Dreier  */
3221aef9ec39SRoland Dreier enum {
3222aef9ec39SRoland Dreier 	SRP_OPT_ERR		= 0,
3223aef9ec39SRoland Dreier 	SRP_OPT_ID_EXT		= 1 << 0,
3224aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	= 1 << 1,
3225aef9ec39SRoland Dreier 	SRP_OPT_DGID		= 1 << 2,
3226aef9ec39SRoland Dreier 	SRP_OPT_PKEY		= 1 << 3,
3227aef9ec39SRoland Dreier 	SRP_OPT_SERVICE_ID	= 1 << 4,
3228aef9ec39SRoland Dreier 	SRP_OPT_MAX_SECT	= 1 << 5,
322952fb2b50SVu Pham 	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
32300c0450dbSRamachandra K 	SRP_OPT_IO_CLASS	= 1 << 7,
323101cb9bcbSIshai Rabinovitz 	SRP_OPT_INITIATOR_EXT	= 1 << 8,
323249248644SDavid Dillow 	SRP_OPT_CMD_SG_ENTRIES	= 1 << 9,
3233c07d424dSDavid Dillow 	SRP_OPT_ALLOW_EXT_SG	= 1 << 10,
3234c07d424dSDavid Dillow 	SRP_OPT_SG_TABLESIZE	= 1 << 11,
32354b5e5f41SBart Van Assche 	SRP_OPT_COMP_VECTOR	= 1 << 12,
32367bb312e4SVu Pham 	SRP_OPT_TL_RETRY_COUNT	= 1 << 13,
32374d73f95fSBart Van Assche 	SRP_OPT_QUEUE_SIZE	= 1 << 14,
323819f31343SBart Van Assche 	SRP_OPT_IP_SRC		= 1 << 15,
323919f31343SBart Van Assche 	SRP_OPT_IP_DEST		= 1 << 16,
3240b0780ee5SBart Van Assche 	SRP_OPT_TARGET_CAN_QUEUE= 1 << 17,
3241547ed331SHonggang Li 	SRP_OPT_MAX_IT_IU_SIZE  = 1 << 18,
324287fee61cSBart Van Assche 	SRP_OPT_CH_COUNT	= 1 << 19,
324319f31343SBart Van Assche };
324419f31343SBart Van Assche 
324519f31343SBart Van Assche static unsigned int srp_opt_mandatory[] = {
324619f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
3247aef9ec39SRoland Dreier 	SRP_OPT_IOC_GUID	|
3248aef9ec39SRoland Dreier 	SRP_OPT_DGID		|
3249aef9ec39SRoland Dreier 	SRP_OPT_PKEY		|
325019f31343SBart Van Assche 	SRP_OPT_SERVICE_ID,
325119f31343SBart Van Assche 	SRP_OPT_ID_EXT		|
325219f31343SBart Van Assche 	SRP_OPT_IOC_GUID	|
325319f31343SBart Van Assche 	SRP_OPT_IP_DEST,
3254aef9ec39SRoland Dreier };
3255aef9ec39SRoland Dreier 
3256a447c093SSteven Whitehouse static const match_table_t srp_opt_tokens = {
3257aef9ec39SRoland Dreier 	{ SRP_OPT_ID_EXT,		"id_ext=%s" 		},
3258aef9ec39SRoland Dreier 	{ SRP_OPT_IOC_GUID,		"ioc_guid=%s" 		},
3259aef9ec39SRoland Dreier 	{ SRP_OPT_DGID,			"dgid=%s" 		},
3260aef9ec39SRoland Dreier 	{ SRP_OPT_PKEY,			"pkey=%x" 		},
3261aef9ec39SRoland Dreier 	{ SRP_OPT_SERVICE_ID,		"service_id=%s"		},
3262aef9ec39SRoland Dreier 	{ SRP_OPT_MAX_SECT,		"max_sect=%d" 		},
326352fb2b50SVu Pham 	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
3264b0780ee5SBart Van Assche 	{ SRP_OPT_TARGET_CAN_QUEUE,	"target_can_queue=%d"	},
32650c0450dbSRamachandra K 	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
326601cb9bcbSIshai Rabinovitz 	{ SRP_OPT_INITIATOR_EXT,	"initiator_ext=%s"	},
326749248644SDavid Dillow 	{ SRP_OPT_CMD_SG_ENTRIES,	"cmd_sg_entries=%u"	},
3268c07d424dSDavid Dillow 	{ SRP_OPT_ALLOW_EXT_SG,		"allow_ext_sg=%u"	},
3269c07d424dSDavid Dillow 	{ SRP_OPT_SG_TABLESIZE,		"sg_tablesize=%u"	},
32704b5e5f41SBart Van Assche 	{ SRP_OPT_COMP_VECTOR,		"comp_vector=%u"	},
32717bb312e4SVu Pham 	{ SRP_OPT_TL_RETRY_COUNT,	"tl_retry_count=%u"	},
32724d73f95fSBart Van Assche 	{ SRP_OPT_QUEUE_SIZE,		"queue_size=%d"		},
327319f31343SBart Van Assche 	{ SRP_OPT_IP_SRC,		"src=%s"		},
327419f31343SBart Van Assche 	{ SRP_OPT_IP_DEST,		"dest=%s"		},
3275547ed331SHonggang Li 	{ SRP_OPT_MAX_IT_IU_SIZE,	"max_it_iu_size=%d"	},
327687fee61cSBart Van Assche 	{ SRP_OPT_CH_COUNT,		"ch_count=%u",		},
3277aef9ec39SRoland Dreier 	{ SRP_OPT_ERR,			NULL 			}
3278aef9ec39SRoland Dreier };
3279aef9ec39SRoland Dreier 
3280c62adb7dSBart Van Assche /**
3281c62adb7dSBart Van Assche  * srp_parse_in - parse an IP address and port number combination
3282e37df2d5SBart Van Assche  * @net:	   [in]  Network namespace.
3283e37df2d5SBart Van Assche  * @sa:		   [out] Address family, IP address and port number.
3284e37df2d5SBart Van Assche  * @addr_port_str: [in]  IP address and port number.
3285bcef5b72SBart Van Assche  * @has_port:	   [out] Whether or not @addr_port_str includes a port number.
3286c62adb7dSBart Van Assche  *
3287c62adb7dSBart Van Assche  * Parse the following address formats:
3288c62adb7dSBart Van Assche  * - IPv4: <ip_address>:<port>, e.g. 1.2.3.4:5.
3289c62adb7dSBart Van Assche  * - IPv6: \[<ipv6_address>\]:<port>, e.g. [1::2:3%4]:5.
3290c62adb7dSBart Van Assche  */
srp_parse_in(struct net * net,struct sockaddr_storage * sa,const char * addr_port_str,bool * has_port)329119f31343SBart Van Assche static int srp_parse_in(struct net *net, struct sockaddr_storage *sa,
3292bcef5b72SBart Van Assche 			const char *addr_port_str, bool *has_port)
329319f31343SBart Van Assche {
3294c62adb7dSBart Van Assche 	char *addr_end, *addr = kstrdup(addr_port_str, GFP_KERNEL);
3295c62adb7dSBart Van Assche 	char *port_str;
329619f31343SBart Van Assche 	int ret;
329719f31343SBart Van Assche 
329819f31343SBart Van Assche 	if (!addr)
329919f31343SBart Van Assche 		return -ENOMEM;
3300c62adb7dSBart Van Assche 	port_str = strrchr(addr, ':');
3301bcef5b72SBart Van Assche 	if (port_str && strchr(port_str, ']'))
3302bcef5b72SBart Van Assche 		port_str = NULL;
3303bcef5b72SBart Van Assche 	if (port_str)
3304c62adb7dSBart Van Assche 		*port_str++ = '\0';
3305bcef5b72SBart Van Assche 	if (has_port)
3306bcef5b72SBart Van Assche 		*has_port = port_str != NULL;
3307c62adb7dSBart Van Assche 	ret = inet_pton_with_scope(net, AF_INET, addr, port_str, sa);
3308c62adb7dSBart Van Assche 	if (ret && addr[0]) {
3309c62adb7dSBart Van Assche 		addr_end = addr + strlen(addr) - 1;
3310c62adb7dSBart Van Assche 		if (addr[0] == '[' && *addr_end == ']') {
3311c62adb7dSBart Van Assche 			*addr_end = '\0';
3312c62adb7dSBart Van Assche 			ret = inet_pton_with_scope(net, AF_INET6, addr + 1,
3313c62adb7dSBart Van Assche 						   port_str, sa);
3314c62adb7dSBart Van Assche 		}
3315c62adb7dSBart Van Assche 	}
331619f31343SBart Van Assche 	kfree(addr);
3317c62adb7dSBart Van Assche 	pr_debug("%s -> %pISpfsc\n", addr_port_str, sa);
331819f31343SBart Van Assche 	return ret;
331919f31343SBart Van Assche }
332019f31343SBart Van Assche 
srp_parse_options(struct net * net,const char * buf,struct srp_target_port * target)332119f31343SBart Van Assche static int srp_parse_options(struct net *net, const char *buf,
332219f31343SBart Van Assche 			     struct srp_target_port *target)
3323aef9ec39SRoland Dreier {
3324aef9ec39SRoland Dreier 	char *options, *sep_opt;
3325aef9ec39SRoland Dreier 	char *p;
3326aef9ec39SRoland Dreier 	substring_t args[MAX_OPT_ARGS];
33272a174df0SBart Van Assche 	unsigned long long ull;
3328bcef5b72SBart Van Assche 	bool has_port;
3329aef9ec39SRoland Dreier 	int opt_mask = 0;
3330aef9ec39SRoland Dreier 	int token;
3331aef9ec39SRoland Dreier 	int ret = -EINVAL;
3332aef9ec39SRoland Dreier 	int i;
3333aef9ec39SRoland Dreier 
3334aef9ec39SRoland Dreier 	options = kstrdup(buf, GFP_KERNEL);
3335aef9ec39SRoland Dreier 	if (!options)
3336aef9ec39SRoland Dreier 		return -ENOMEM;
3337aef9ec39SRoland Dreier 
3338aef9ec39SRoland Dreier 	sep_opt = options;
33397dcf9c19SSagi Grimberg 	while ((p = strsep(&sep_opt, ",\n")) != NULL) {
3340aef9ec39SRoland Dreier 		if (!*p)
3341aef9ec39SRoland Dreier 			continue;
3342aef9ec39SRoland Dreier 
3343aef9ec39SRoland Dreier 		token = match_token(p, srp_opt_tokens, args);
3344aef9ec39SRoland Dreier 		opt_mask |= token;
3345aef9ec39SRoland Dreier 
3346aef9ec39SRoland Dreier 		switch (token) {
3347aef9ec39SRoland Dreier 		case SRP_OPT_ID_EXT:
3348aef9ec39SRoland Dreier 			p = match_strdup(args);
3349a20f3a6dSIshai Rabinovitz 			if (!p) {
3350a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3351a20f3a6dSIshai Rabinovitz 				goto out;
3352a20f3a6dSIshai Rabinovitz 			}
33532a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
33542a174df0SBart Van Assche 			if (ret) {
33552a174df0SBart Van Assche 				pr_warn("invalid id_ext parameter '%s'\n", p);
33562a174df0SBart Van Assche 				kfree(p);
33572a174df0SBart Van Assche 				goto out;
33582a174df0SBart Van Assche 			}
33592a174df0SBart Van Assche 			target->id_ext = cpu_to_be64(ull);
3360aef9ec39SRoland Dreier 			kfree(p);
3361aef9ec39SRoland Dreier 			break;
3362aef9ec39SRoland Dreier 
3363aef9ec39SRoland Dreier 		case SRP_OPT_IOC_GUID:
3364aef9ec39SRoland Dreier 			p = match_strdup(args);
3365a20f3a6dSIshai Rabinovitz 			if (!p) {
3366a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3367a20f3a6dSIshai Rabinovitz 				goto out;
3368a20f3a6dSIshai Rabinovitz 			}
33692a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
33702a174df0SBart Van Assche 			if (ret) {
33712a174df0SBart Van Assche 				pr_warn("invalid ioc_guid parameter '%s'\n", p);
33722a174df0SBart Van Assche 				kfree(p);
33732a174df0SBart Van Assche 				goto out;
33742a174df0SBart Van Assche 			}
33752a174df0SBart Van Assche 			target->ioc_guid = cpu_to_be64(ull);
3376aef9ec39SRoland Dreier 			kfree(p);
3377aef9ec39SRoland Dreier 			break;
3378aef9ec39SRoland Dreier 
3379aef9ec39SRoland Dreier 		case SRP_OPT_DGID:
3380aef9ec39SRoland Dreier 			p = match_strdup(args);
3381a20f3a6dSIshai Rabinovitz 			if (!p) {
3382a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3383a20f3a6dSIshai Rabinovitz 				goto out;
3384a20f3a6dSIshai Rabinovitz 			}
3385aef9ec39SRoland Dreier 			if (strlen(p) != 32) {
3386e0bda7d8SBart Van Assche 				pr_warn("bad dest GID parameter '%s'\n", p);
3387ce1823f0SRoland Dreier 				kfree(p);
3388aef9ec39SRoland Dreier 				goto out;
3389aef9ec39SRoland Dreier 			}
3390aef9ec39SRoland Dreier 
339119f31343SBart Van Assche 			ret = hex2bin(target->ib_cm.orig_dgid.raw, p, 16);
3392747fe000SBart Van Assche 			kfree(p);
3393e711f968SAndy Shevchenko 			if (ret < 0)
3394747fe000SBart Van Assche 				goto out;
3395aef9ec39SRoland Dreier 			break;
3396aef9ec39SRoland Dreier 
3397aef9ec39SRoland Dreier 		case SRP_OPT_PKEY:
3398ed461b30SWang Yufen 			ret = match_hex(args, &token);
3399ed461b30SWang Yufen 			if (ret) {
3400e0bda7d8SBart Van Assche 				pr_warn("bad P_Key parameter '%s'\n", p);
3401aef9ec39SRoland Dreier 				goto out;
3402aef9ec39SRoland Dreier 			}
340319f31343SBart Van Assche 			target->ib_cm.pkey = cpu_to_be16(token);
3404aef9ec39SRoland Dreier 			break;
3405aef9ec39SRoland Dreier 
3406aef9ec39SRoland Dreier 		case SRP_OPT_SERVICE_ID:
3407aef9ec39SRoland Dreier 			p = match_strdup(args);
3408a20f3a6dSIshai Rabinovitz 			if (!p) {
3409a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3410a20f3a6dSIshai Rabinovitz 				goto out;
3411a20f3a6dSIshai Rabinovitz 			}
34122a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
34132a174df0SBart Van Assche 			if (ret) {
34142a174df0SBart Van Assche 				pr_warn("bad service_id parameter '%s'\n", p);
34152a174df0SBart Van Assche 				kfree(p);
34162a174df0SBart Van Assche 				goto out;
34172a174df0SBart Van Assche 			}
341819f31343SBart Van Assche 			target->ib_cm.service_id = cpu_to_be64(ull);
341919f31343SBart Van Assche 			kfree(p);
342019f31343SBart Van Assche 			break;
342119f31343SBart Van Assche 
342219f31343SBart Van Assche 		case SRP_OPT_IP_SRC:
342319f31343SBart Van Assche 			p = match_strdup(args);
342419f31343SBart Van Assche 			if (!p) {
342519f31343SBart Van Assche 				ret = -ENOMEM;
342619f31343SBart Van Assche 				goto out;
342719f31343SBart Van Assche 			}
3428bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.src.ss, p,
3429bcef5b72SBart Van Assche 					   NULL);
343019f31343SBart Van Assche 			if (ret < 0) {
343119f31343SBart Van Assche 				pr_warn("bad source parameter '%s'\n", p);
343219f31343SBart Van Assche 				kfree(p);
343319f31343SBart Van Assche 				goto out;
343419f31343SBart Van Assche 			}
343519f31343SBart Van Assche 			target->rdma_cm.src_specified = true;
343619f31343SBart Van Assche 			kfree(p);
343719f31343SBart Van Assche 			break;
343819f31343SBart Van Assche 
343919f31343SBart Van Assche 		case SRP_OPT_IP_DEST:
344019f31343SBart Van Assche 			p = match_strdup(args);
344119f31343SBart Van Assche 			if (!p) {
344219f31343SBart Van Assche 				ret = -ENOMEM;
344319f31343SBart Van Assche 				goto out;
344419f31343SBart Van Assche 			}
3445bcef5b72SBart Van Assche 			ret = srp_parse_in(net, &target->rdma_cm.dst.ss, p,
3446bcef5b72SBart Van Assche 					   &has_port);
3447bcef5b72SBart Van Assche 			if (!has_port)
3448bcef5b72SBart Van Assche 				ret = -EINVAL;
344919f31343SBart Van Assche 			if (ret < 0) {
345019f31343SBart Van Assche 				pr_warn("bad dest parameter '%s'\n", p);
345119f31343SBart Van Assche 				kfree(p);
345219f31343SBart Van Assche 				goto out;
345319f31343SBart Van Assche 			}
345419f31343SBart Van Assche 			target->using_rdma_cm = true;
3455aef9ec39SRoland Dreier 			kfree(p);
3456aef9ec39SRoland Dreier 			break;
3457aef9ec39SRoland Dreier 
3458aef9ec39SRoland Dreier 		case SRP_OPT_MAX_SECT:
3459ed461b30SWang Yufen 			ret = match_int(args, &token);
3460ed461b30SWang Yufen 			if (ret) {
3461e0bda7d8SBart Van Assche 				pr_warn("bad max sect parameter '%s'\n", p);
3462aef9ec39SRoland Dreier 				goto out;
3463aef9ec39SRoland Dreier 			}
3464aef9ec39SRoland Dreier 			target->scsi_host->max_sectors = token;
3465aef9ec39SRoland Dreier 			break;
3466aef9ec39SRoland Dreier 
34674d73f95fSBart Van Assche 		case SRP_OPT_QUEUE_SIZE:
3468ed461b30SWang Yufen 			ret = match_int(args, &token);
3469ed461b30SWang Yufen 			if (ret) {
3470ed461b30SWang Yufen 				pr_warn("match_int() failed for queue_size parameter '%s', Error %d\n",
3471ed461b30SWang Yufen 					p, ret);
3472ed461b30SWang Yufen 				goto out;
3473ed461b30SWang Yufen 			}
3474ed461b30SWang Yufen 			if (token < 1) {
34754d73f95fSBart Van Assche 				pr_warn("bad queue_size parameter '%s'\n", p);
3476ed461b30SWang Yufen 				ret = -EINVAL;
34774d73f95fSBart Van Assche 				goto out;
34784d73f95fSBart Van Assche 			}
34794d73f95fSBart Van Assche 			target->scsi_host->can_queue = token;
34804d73f95fSBart Van Assche 			target->queue_size = token + SRP_RSP_SQ_SIZE +
34814d73f95fSBart Van Assche 					     SRP_TSK_MGMT_SQ_SIZE;
34824d73f95fSBart Van Assche 			if (!(opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
34834d73f95fSBart Van Assche 				target->scsi_host->cmd_per_lun = token;
34844d73f95fSBart Van Assche 			break;
34854d73f95fSBart Van Assche 
348652fb2b50SVu Pham 		case SRP_OPT_MAX_CMD_PER_LUN:
3487ed461b30SWang Yufen 			ret = match_int(args, &token);
3488ed461b30SWang Yufen 			if (ret) {
3489ed461b30SWang Yufen 				pr_warn("match_int() failed for max cmd_per_lun parameter '%s', Error %d\n",
3490ed461b30SWang Yufen 					p, ret);
3491ed461b30SWang Yufen 				goto out;
3492ed461b30SWang Yufen 			}
3493ed461b30SWang Yufen 			if (token < 1) {
3494e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_per_lun parameter '%s'\n",
3495e0bda7d8SBart Van Assche 					p);
3496ed461b30SWang Yufen 				ret = -EINVAL;
349752fb2b50SVu Pham 				goto out;
349852fb2b50SVu Pham 			}
34994d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun = token;
350052fb2b50SVu Pham 			break;
350152fb2b50SVu Pham 
3502b0780ee5SBart Van Assche 		case SRP_OPT_TARGET_CAN_QUEUE:
3503ed461b30SWang Yufen 			ret = match_int(args, &token);
3504ed461b30SWang Yufen 			if (ret) {
3505ed461b30SWang Yufen 				pr_warn("match_int() failed for max target_can_queue parameter '%s', Error %d\n",
3506ed461b30SWang Yufen 					p, ret);
3507ed461b30SWang Yufen 				goto out;
3508ed461b30SWang Yufen 			}
3509ed461b30SWang Yufen 			if (token < 1) {
3510b0780ee5SBart Van Assche 				pr_warn("bad max target_can_queue parameter '%s'\n",
3511b0780ee5SBart Van Assche 					p);
3512ed461b30SWang Yufen 				ret = -EINVAL;
3513b0780ee5SBart Van Assche 				goto out;
3514b0780ee5SBart Van Assche 			}
3515b0780ee5SBart Van Assche 			target->target_can_queue = token;
3516b0780ee5SBart Van Assche 			break;
3517b0780ee5SBart Van Assche 
35180c0450dbSRamachandra K 		case SRP_OPT_IO_CLASS:
3519ed461b30SWang Yufen 			ret = match_hex(args, &token);
3520ed461b30SWang Yufen 			if (ret) {
3521e0bda7d8SBart Van Assche 				pr_warn("bad IO class parameter '%s'\n", p);
35220c0450dbSRamachandra K 				goto out;
35230c0450dbSRamachandra K 			}
35240c0450dbSRamachandra K 			if (token != SRP_REV10_IB_IO_CLASS &&
35250c0450dbSRamachandra K 			    token != SRP_REV16A_IB_IO_CLASS) {
3526e0bda7d8SBart Van Assche 				pr_warn("unknown IO class parameter value %x specified (use %x or %x).\n",
3527e0bda7d8SBart Van Assche 					token, SRP_REV10_IB_IO_CLASS,
3528e0bda7d8SBart Van Assche 					SRP_REV16A_IB_IO_CLASS);
3529ed461b30SWang Yufen 				ret = -EINVAL;
35300c0450dbSRamachandra K 				goto out;
35310c0450dbSRamachandra K 			}
35320c0450dbSRamachandra K 			target->io_class = token;
35330c0450dbSRamachandra K 			break;
35340c0450dbSRamachandra K 
353501cb9bcbSIshai Rabinovitz 		case SRP_OPT_INITIATOR_EXT:
353601cb9bcbSIshai Rabinovitz 			p = match_strdup(args);
3537a20f3a6dSIshai Rabinovitz 			if (!p) {
3538a20f3a6dSIshai Rabinovitz 				ret = -ENOMEM;
3539a20f3a6dSIshai Rabinovitz 				goto out;
3540a20f3a6dSIshai Rabinovitz 			}
35412a174df0SBart Van Assche 			ret = kstrtoull(p, 16, &ull);
35422a174df0SBart Van Assche 			if (ret) {
35432a174df0SBart Van Assche 				pr_warn("bad initiator_ext value '%s'\n", p);
35442a174df0SBart Van Assche 				kfree(p);
35452a174df0SBart Van Assche 				goto out;
35462a174df0SBart Van Assche 			}
35472a174df0SBart Van Assche 			target->initiator_ext = cpu_to_be64(ull);
354801cb9bcbSIshai Rabinovitz 			kfree(p);
354901cb9bcbSIshai Rabinovitz 			break;
355001cb9bcbSIshai Rabinovitz 
355149248644SDavid Dillow 		case SRP_OPT_CMD_SG_ENTRIES:
3552ed461b30SWang Yufen 			ret = match_int(args, &token);
3553ed461b30SWang Yufen 			if (ret) {
3554ed461b30SWang Yufen 				pr_warn("match_int() failed for max cmd_sg_entries parameter '%s', Error %d\n",
3555ed461b30SWang Yufen 					p, ret);
3556ed461b30SWang Yufen 				goto out;
3557ed461b30SWang Yufen 			}
3558ed461b30SWang Yufen 			if (token < 1 || token > 255) {
3559e0bda7d8SBart Van Assche 				pr_warn("bad max cmd_sg_entries parameter '%s'\n",
3560e0bda7d8SBart Van Assche 					p);
3561ed461b30SWang Yufen 				ret = -EINVAL;
356249248644SDavid Dillow 				goto out;
356349248644SDavid Dillow 			}
356449248644SDavid Dillow 			target->cmd_sg_cnt = token;
356549248644SDavid Dillow 			break;
356649248644SDavid Dillow 
3567c07d424dSDavid Dillow 		case SRP_OPT_ALLOW_EXT_SG:
3568ed461b30SWang Yufen 			ret = match_int(args, &token);
3569ed461b30SWang Yufen 			if (ret) {
3570e0bda7d8SBart Van Assche 				pr_warn("bad allow_ext_sg parameter '%s'\n", p);
3571c07d424dSDavid Dillow 				goto out;
3572c07d424dSDavid Dillow 			}
3573c07d424dSDavid Dillow 			target->allow_ext_sg = !!token;
3574c07d424dSDavid Dillow 			break;
3575c07d424dSDavid Dillow 
3576c07d424dSDavid Dillow 		case SRP_OPT_SG_TABLESIZE:
3577ed461b30SWang Yufen 			ret = match_int(args, &token);
3578ed461b30SWang Yufen 			if (ret) {
3579ed461b30SWang Yufen 				pr_warn("match_int() failed for max sg_tablesize parameter '%s', Error %d\n",
3580ed461b30SWang Yufen 					p, ret);
3581ed461b30SWang Yufen 				goto out;
3582ed461b30SWang Yufen 			}
3583ed461b30SWang Yufen 			if (token < 1 || token > SG_MAX_SEGMENTS) {
3584e0bda7d8SBart Van Assche 				pr_warn("bad max sg_tablesize parameter '%s'\n",
3585e0bda7d8SBart Van Assche 					p);
3586ed461b30SWang Yufen 				ret = -EINVAL;
3587c07d424dSDavid Dillow 				goto out;
3588c07d424dSDavid Dillow 			}
3589c07d424dSDavid Dillow 			target->sg_tablesize = token;
3590c07d424dSDavid Dillow 			break;
3591c07d424dSDavid Dillow 
35924b5e5f41SBart Van Assche 		case SRP_OPT_COMP_VECTOR:
3593ed461b30SWang Yufen 			ret = match_int(args, &token);
3594ed461b30SWang Yufen 			if (ret) {
3595ed461b30SWang Yufen 				pr_warn("match_int() failed for comp_vector parameter '%s', Error %d\n",
3596ed461b30SWang Yufen 					p, ret);
3597ed461b30SWang Yufen 				goto out;
3598ed461b30SWang Yufen 			}
3599ed461b30SWang Yufen 			if (token < 0) {
36004b5e5f41SBart Van Assche 				pr_warn("bad comp_vector parameter '%s'\n", p);
3601ed461b30SWang Yufen 				ret = -EINVAL;
36024b5e5f41SBart Van Assche 				goto out;
36034b5e5f41SBart Van Assche 			}
36044b5e5f41SBart Van Assche 			target->comp_vector = token;
36054b5e5f41SBart Van Assche 			break;
36064b5e5f41SBart Van Assche 
36077bb312e4SVu Pham 		case SRP_OPT_TL_RETRY_COUNT:
3608ed461b30SWang Yufen 			ret = match_int(args, &token);
3609ed461b30SWang Yufen 			if (ret) {
3610ed461b30SWang Yufen 				pr_warn("match_int() failed for tl_retry_count parameter '%s', Error %d\n",
3611ed461b30SWang Yufen 					p, ret);
3612ed461b30SWang Yufen 				goto out;
3613ed461b30SWang Yufen 			}
3614ed461b30SWang Yufen 			if (token < 2 || token > 7) {
36157bb312e4SVu Pham 				pr_warn("bad tl_retry_count parameter '%s' (must be a number between 2 and 7)\n",
36167bb312e4SVu Pham 					p);
3617ed461b30SWang Yufen 				ret = -EINVAL;
36187bb312e4SVu Pham 				goto out;
36197bb312e4SVu Pham 			}
36207bb312e4SVu Pham 			target->tl_retry_count = token;
36217bb312e4SVu Pham 			break;
36227bb312e4SVu Pham 
3623547ed331SHonggang Li 		case SRP_OPT_MAX_IT_IU_SIZE:
3624ed461b30SWang Yufen 			ret = match_int(args, &token);
3625ed461b30SWang Yufen 			if (ret) {
3626ed461b30SWang Yufen 				pr_warn("match_int() failed for max it_iu_size parameter '%s', Error %d\n",
3627ed461b30SWang Yufen 					p, ret);
3628ed461b30SWang Yufen 				goto out;
3629ed461b30SWang Yufen 			}
3630ed461b30SWang Yufen 			if (token < 0) {
3631547ed331SHonggang Li 				pr_warn("bad maximum initiator to target IU size '%s'\n", p);
3632ed461b30SWang Yufen 				ret = -EINVAL;
3633547ed331SHonggang Li 				goto out;
3634547ed331SHonggang Li 			}
3635547ed331SHonggang Li 			target->max_it_iu_size = token;
3636547ed331SHonggang Li 			break;
3637547ed331SHonggang Li 
363887fee61cSBart Van Assche 		case SRP_OPT_CH_COUNT:
3639ed461b30SWang Yufen 			ret = match_int(args, &token);
3640ed461b30SWang Yufen 			if (ret) {
3641ed461b30SWang Yufen 				pr_warn("match_int() failed for channel count parameter '%s', Error %d\n",
3642ed461b30SWang Yufen 					p, ret);
3643ed461b30SWang Yufen 				goto out;
3644ed461b30SWang Yufen 			}
3645ed461b30SWang Yufen 			if (token < 1) {
364687fee61cSBart Van Assche 				pr_warn("bad channel count %s\n", p);
3647ed461b30SWang Yufen 				ret = -EINVAL;
364887fee61cSBart Van Assche 				goto out;
364987fee61cSBart Van Assche 			}
365087fee61cSBart Van Assche 			target->ch_count = token;
365187fee61cSBart Van Assche 			break;
365287fee61cSBart Van Assche 
3653aef9ec39SRoland Dreier 		default:
3654e0bda7d8SBart Van Assche 			pr_warn("unknown parameter or missing value '%s' in target creation request\n",
3655e0bda7d8SBart Van Assche 				p);
3656ed461b30SWang Yufen 			ret = -EINVAL;
3657aef9ec39SRoland Dreier 			goto out;
3658aef9ec39SRoland Dreier 		}
3659aef9ec39SRoland Dreier 	}
3660aef9ec39SRoland Dreier 
366119f31343SBart Van Assche 	for (i = 0; i < ARRAY_SIZE(srp_opt_mandatory); i++) {
366219f31343SBart Van Assche 		if ((opt_mask & srp_opt_mandatory[i]) == srp_opt_mandatory[i]) {
3663aef9ec39SRoland Dreier 			ret = 0;
366419f31343SBart Van Assche 			break;
366519f31343SBart Van Assche 		}
366619f31343SBart Van Assche 	}
366719f31343SBart Van Assche 	if (ret)
366819f31343SBart Van Assche 		pr_warn("target creation request is missing one or more parameters\n");
3669aef9ec39SRoland Dreier 
36704d73f95fSBart Van Assche 	if (target->scsi_host->cmd_per_lun > target->scsi_host->can_queue
36714d73f95fSBart Van Assche 	    && (opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
36724d73f95fSBart Van Assche 		pr_warn("cmd_per_lun = %d > queue_size = %d\n",
36734d73f95fSBart Van Assche 			target->scsi_host->cmd_per_lun,
36744d73f95fSBart Van Assche 			target->scsi_host->can_queue);
36754d73f95fSBart Van Assche 
3676aef9ec39SRoland Dreier out:
3677aef9ec39SRoland Dreier 	kfree(options);
3678aef9ec39SRoland Dreier 	return ret;
3679aef9ec39SRoland Dreier }
3680aef9ec39SRoland Dreier 
add_target_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)368133e82346SYueHaibing static ssize_t add_target_store(struct device *dev,
368233e82346SYueHaibing 				struct device_attribute *attr, const char *buf,
368333e82346SYueHaibing 				size_t count)
3684aef9ec39SRoland Dreier {
3685aef9ec39SRoland Dreier 	struct srp_host *host =
3686ee959b00STony Jones 		container_of(dev, struct srp_host, dev);
3687aef9ec39SRoland Dreier 	struct Scsi_Host *target_host;
3688aef9ec39SRoland Dreier 	struct srp_target_port *target;
3689509c07bcSBart Van Assche 	struct srp_rdma_ch *ch;
3690d1b4289eSBart Van Assche 	struct srp_device *srp_dev = host->srp_dev;
3691d1b4289eSBart Van Assche 	struct ib_device *ibdev = srp_dev->dev;
36922b5715fcSNicolas Morey-Chaisemartin 	int ret, i, ch_idx;
3693509c5f33SBart Van Assche 	unsigned int max_sectors_per_mr, mr_per_cmd = 0;
3694d92c0da7SBart Van Assche 	bool multich = false;
3695513d5647SBart Van Assche 	uint32_t max_iu_len;
3696aef9ec39SRoland Dreier 
3697aef9ec39SRoland Dreier 	target_host = scsi_host_alloc(&srp_template,
3698aef9ec39SRoland Dreier 				      sizeof (struct srp_target_port));
3699aef9ec39SRoland Dreier 	if (!target_host)
3700aef9ec39SRoland Dreier 		return -ENOMEM;
3701aef9ec39SRoland Dreier 
37023236822bSFUJITA Tomonori 	target_host->transportt  = ib_srp_transport_template;
3703fd1b6c4aSBart Van Assche 	target_host->max_channel = 0;
3704fd1b6c4aSBart Van Assche 	target_host->max_id      = 1;
3705985aa495SBart Van Assche 	target_host->max_lun     = -1LL;
37063c8edf0eSArne Redlich 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
37070b5cb330SBart Van Assche 	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
37085f068992SRoland Dreier 
3709e945c653SJason Gunthorpe 	if (!(ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG))
37108c175d31SChristoph Hellwig 		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
37118c175d31SChristoph Hellwig 
3712aef9ec39SRoland Dreier 	target = host_to_target(target_host);
3713aef9ec39SRoland Dreier 
371419f31343SBart Van Assche 	target->net		= kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
37150c0450dbSRamachandra K 	target->io_class	= SRP_REV16A_IB_IO_CLASS;
3716aef9ec39SRoland Dreier 	target->scsi_host	= target_host;
3717aef9ec39SRoland Dreier 	target->srp_host	= host;
3718e6bf5f48SJason Gunthorpe 	target->lkey		= host->srp_dev->pd->local_dma_lkey;
3719cee687b6SBart Van Assche 	target->global_rkey	= host->srp_dev->global_rkey;
372049248644SDavid Dillow 	target->cmd_sg_cnt	= cmd_sg_entries;
3721c07d424dSDavid Dillow 	target->sg_tablesize	= indirect_sg_entries ? : cmd_sg_entries;
3722c07d424dSDavid Dillow 	target->allow_ext_sg	= allow_ext_sg;
37237bb312e4SVu Pham 	target->tl_retry_count	= 7;
37244d73f95fSBart Van Assche 	target->queue_size	= SRP_DEFAULT_QUEUE_SIZE;
3725aef9ec39SRoland Dreier 
372634aa654eSBart Van Assche 	/*
372734aa654eSBart Van Assche 	 * Avoid that the SCSI host can be removed by srp_remove_target()
372834aa654eSBart Van Assche 	 * before this function returns.
372934aa654eSBart Van Assche 	 */
373034aa654eSBart Van Assche 	scsi_host_get(target->scsi_host);
373134aa654eSBart Van Assche 
37324fa354c9SBart Van Assche 	ret = mutex_lock_interruptible(&host->add_target_mutex);
37334fa354c9SBart Van Assche 	if (ret < 0)
37344fa354c9SBart Van Assche 		goto put;
37352d7091bcSBart Van Assche 
373619f31343SBart Van Assche 	ret = srp_parse_options(target->net, buf, target);
3737aef9ec39SRoland Dreier 	if (ret)
3738fb49c8bbSBart Van Assche 		goto out;
3739aef9ec39SRoland Dreier 
374096fc248aSBart Van Assche 	if (!srp_conn_unique(target->srp_host, target)) {
374119f31343SBart Van Assche 		if (target->using_rdma_cm) {
374219f31343SBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
37437da09af9SBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;dest=%pIS\n",
374419f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
374519f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
37467da09af9SBart Van Assche 				     &target->rdma_cm.dst);
374719f31343SBart Van Assche 		} else {
374896fc248aSBart Van Assche 			shost_printk(KERN_INFO, target->scsi_host,
374996fc248aSBart Van Assche 				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n",
375096fc248aSBart Van Assche 				     be64_to_cpu(target->id_ext),
375196fc248aSBart Van Assche 				     be64_to_cpu(target->ioc_guid),
375296fc248aSBart Van Assche 				     be64_to_cpu(target->initiator_ext));
375319f31343SBart Van Assche 		}
375496fc248aSBart Van Assche 		ret = -EEXIST;
3755fb49c8bbSBart Van Assche 		goto out;
375696fc248aSBart Van Assche 	}
375796fc248aSBart Van Assche 
3758f273ad4fSMax Gurtovoy 	if (!srp_dev->has_fr && !target->allow_ext_sg &&
3759c07d424dSDavid Dillow 	    target->cmd_sg_cnt < target->sg_tablesize) {
37605cfb1782SBart Van Assche 		pr_warn("No MR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
3761c07d424dSDavid Dillow 		target->sg_tablesize = target->cmd_sg_cnt;
3762c07d424dSDavid Dillow 	}
3763c07d424dSDavid Dillow 
3764f273ad4fSMax Gurtovoy 	if (srp_dev->use_fast_reg) {
3765e945c653SJason Gunthorpe 		bool gaps_reg = ibdev->attrs.kernel_cap_flags &
3766e945c653SJason Gunthorpe 				 IBK_SG_GAPS_REG;
3767fbd36818SSergey Gorenko 
3768509c5f33SBart Van Assche 		max_sectors_per_mr = srp_dev->max_pages_per_mr <<
3769509c5f33SBart Van Assche 				  (ilog2(srp_dev->mr_page_size) - 9);
3770fbd36818SSergey Gorenko 		if (!gaps_reg) {
3771fbd36818SSergey Gorenko 			/*
3772f273ad4fSMax Gurtovoy 			 * FR can only map one HCA page per entry. If the start
3773f273ad4fSMax Gurtovoy 			 * address is not aligned on a HCA page boundary two
3774f273ad4fSMax Gurtovoy 			 * entries will be used for the head and the tail
3775f273ad4fSMax Gurtovoy 			 * although these two entries combined contain at most
3776f273ad4fSMax Gurtovoy 			 * one HCA page of data. Hence the "+ 1" in the
3777f273ad4fSMax Gurtovoy 			 * calculation below.
3778fbd36818SSergey Gorenko 			 *
3779fbd36818SSergey Gorenko 			 * The indirect data buffer descriptor is contiguous
3780fbd36818SSergey Gorenko 			 * so the memory for that buffer will only be
3781fbd36818SSergey Gorenko 			 * registered if register_always is true. Hence add
3782fbd36818SSergey Gorenko 			 * one to mr_per_cmd if register_always has been set.
3783fbd36818SSergey Gorenko 			 */
3784509c5f33SBart Van Assche 			mr_per_cmd = register_always +
3785509c5f33SBart Van Assche 				(target->scsi_host->max_sectors + 1 +
3786509c5f33SBart Van Assche 				 max_sectors_per_mr - 1) / max_sectors_per_mr;
3787fbd36818SSergey Gorenko 		} else {
3788fbd36818SSergey Gorenko 			mr_per_cmd = register_always +
3789fbd36818SSergey Gorenko 				(target->sg_tablesize +
3790fbd36818SSergey Gorenko 				 srp_dev->max_pages_per_mr - 1) /
3791fbd36818SSergey Gorenko 				srp_dev->max_pages_per_mr;
3792fbd36818SSergey Gorenko 		}
3793509c5f33SBart 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",
3794fbd36818SSergey Gorenko 			 target->scsi_host->max_sectors, srp_dev->max_pages_per_mr, srp_dev->mr_page_size,
3795509c5f33SBart Van Assche 			 max_sectors_per_mr, mr_per_cmd);
3796509c5f33SBart Van Assche 	}
3797509c5f33SBart Van Assche 
3798c07d424dSDavid Dillow 	target_host->sg_tablesize = target->sg_tablesize;
3799509c5f33SBart Van Assche 	target->mr_pool_size = target->scsi_host->can_queue * mr_per_cmd;
3800509c5f33SBart Van Assche 	target->mr_per_cmd = mr_per_cmd;
3801c07d424dSDavid Dillow 	target->indirect_size = target->sg_tablesize *
3802c07d424dSDavid Dillow 				sizeof (struct srp_direct_buf);
3803b2e872f4SHonggang Li 	max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
3804b2e872f4SHonggang Li 				       srp_use_imm_data,
3805b2e872f4SHonggang Li 				       target->max_it_iu_size);
380649248644SDavid Dillow 
3807c1120f89SBart Van Assche 	INIT_WORK(&target->tl_err_work, srp_tl_err_work);
3808ef6c49d8SBart Van Assche 	INIT_WORK(&target->remove_work, srp_remove_work);
38098f26c9ffSDavid Dillow 	spin_lock_init(&target->lock);
38101dfce294SParav Pandit 	ret = rdma_query_gid(ibdev, host->port, 0, &target->sgid);
38112088ca66SSagi Grimberg 	if (ret)
3812fb49c8bbSBart Van Assche 		goto out;
3813d92c0da7SBart Van Assche 
3814d92c0da7SBart Van Assche 	ret = -ENOMEM;
38152b5715fcSNicolas Morey-Chaisemartin 	if (target->ch_count == 0) {
381687fee61cSBart Van Assche 		target->ch_count =
3817d92c0da7SBart Van Assche 			min(ch_count ?:
38182b5715fcSNicolas Morey-Chaisemartin 				max(4 * num_online_nodes(),
3819d92c0da7SBart Van Assche 				    ibdev->num_comp_vectors),
38202b5715fcSNicolas Morey-Chaisemartin 				num_online_cpus());
38212b5715fcSNicolas Morey-Chaisemartin 	}
38222b5715fcSNicolas Morey-Chaisemartin 
3823d92c0da7SBart Van Assche 	target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
3824d92c0da7SBart Van Assche 			     GFP_KERNEL);
3825d92c0da7SBart Van Assche 	if (!target->ch)
3826fb49c8bbSBart Van Assche 		goto out;
3827d92c0da7SBart Van Assche 
38282b5715fcSNicolas Morey-Chaisemartin 	for (ch_idx = 0; ch_idx < target->ch_count; ++ch_idx) {
38292b5715fcSNicolas Morey-Chaisemartin 		ch = &target->ch[ch_idx];
3830d92c0da7SBart Van Assche 		ch->target = target;
38312b5715fcSNicolas Morey-Chaisemartin 		ch->comp_vector = ch_idx % ibdev->num_comp_vectors;
3832d92c0da7SBart Van Assche 		spin_lock_init(&ch->lock);
3833d92c0da7SBart Van Assche 		INIT_LIST_HEAD(&ch->free_tx);
3834d92c0da7SBart Van Assche 		ret = srp_new_cm_id(ch);
3835d92c0da7SBart Van Assche 		if (ret)
3836d92c0da7SBart Van Assche 			goto err_disconnect;
3837aef9ec39SRoland Dreier 
3838509c07bcSBart Van Assche 		ret = srp_create_ch_ib(ch);
3839aef9ec39SRoland Dreier 		if (ret)
3840d92c0da7SBart Van Assche 			goto err_disconnect;
3841aef9ec39SRoland Dreier 
3842513d5647SBart Van Assche 		ret = srp_connect_ch(ch, max_iu_len, multich);
3843aef9ec39SRoland Dreier 		if (ret) {
384419f31343SBart Van Assche 			char dst[64];
384519f31343SBart Van Assche 
384619f31343SBart Van Assche 			if (target->using_rdma_cm)
38477da09af9SBart Van Assche 				snprintf(dst, sizeof(dst), "%pIS",
38487da09af9SBart Van Assche 					&target->rdma_cm.dst);
384919f31343SBart Van Assche 			else
385019f31343SBart Van Assche 				snprintf(dst, sizeof(dst), "%pI6",
385119f31343SBart Van Assche 					target->ib_cm.orig_dgid.raw);
38527aa54bd7SDavid Dillow 			shost_printk(KERN_ERR, target->scsi_host,
385319f31343SBart Van Assche 				PFX "Connection %d/%d to %s failed\n",
38542b5715fcSNicolas Morey-Chaisemartin 				ch_idx,
385519f31343SBart Van Assche 				target->ch_count, dst);
38562b5715fcSNicolas Morey-Chaisemartin 			if (ch_idx == 0) {
3857b02c1536SBart Van Assche 				goto free_ch;
3858d92c0da7SBart Van Assche 			} else {
3859d92c0da7SBart Van Assche 				srp_free_ch_ib(target, ch);
3860d92c0da7SBart Van Assche 				target->ch_count = ch - target->ch;
3861c257ea6fSBart Van Assche 				goto connected;
3862aef9ec39SRoland Dreier 			}
3863d92c0da7SBart Van Assche 		}
3864d92c0da7SBart Van Assche 		multich = true;
3865d92c0da7SBart Van Assche 	}
3866d92c0da7SBart Van Assche 
3867c257ea6fSBart Van Assche connected:
3868d92c0da7SBart Van Assche 	target->scsi_host->nr_hw_queues = target->ch_count;
3869aef9ec39SRoland Dreier 
3870aef9ec39SRoland Dreier 	ret = srp_add_target(host, target);
3871aef9ec39SRoland Dreier 	if (ret)
3872aef9ec39SRoland Dreier 		goto err_disconnect;
3873aef9ec39SRoland Dreier 
387434aa654eSBart Van Assche 	if (target->state != SRP_TARGET_REMOVED) {
387519f31343SBart Van Assche 		if (target->using_rdma_cm) {
387619f31343SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
38777da09af9SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx sgid %pI6 dest %pIS\n",
387819f31343SBart Van Assche 				     be64_to_cpu(target->id_ext),
387919f31343SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
38807da09af9SBart Van Assche 				     target->sgid.raw, &target->rdma_cm.dst);
388119f31343SBart Van Assche 		} else {
3882e7ffde01SBart Van Assche 			shost_printk(KERN_DEBUG, target->scsi_host, PFX
3883e7ffde01SBart Van Assche 				     "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
3884e7ffde01SBart Van Assche 				     be64_to_cpu(target->id_ext),
3885e7ffde01SBart Van Assche 				     be64_to_cpu(target->ioc_guid),
388619f31343SBart Van Assche 				     be16_to_cpu(target->ib_cm.pkey),
388719f31343SBart Van Assche 				     be64_to_cpu(target->ib_cm.service_id),
388819f31343SBart Van Assche 				     target->sgid.raw,
388919f31343SBart Van Assche 				     target->ib_cm.orig_dgid.raw);
389019f31343SBart Van Assche 		}
389134aa654eSBart Van Assche 	}
3892e7ffde01SBart Van Assche 
38932d7091bcSBart Van Assche 	ret = count;
38942d7091bcSBart Van Assche 
38952d7091bcSBart Van Assche out:
38962d7091bcSBart Van Assche 	mutex_unlock(&host->add_target_mutex);
389734aa654eSBart Van Assche 
38984fa354c9SBart Van Assche put:
389934aa654eSBart Van Assche 	scsi_host_put(target->scsi_host);
390019f31343SBart Van Assche 	if (ret < 0) {
390119f31343SBart Van Assche 		/*
390219f31343SBart Van Assche 		 * If a call to srp_remove_target() has not been scheduled,
390319f31343SBart Van Assche 		 * drop the network namespace reference now that was obtained
390419f31343SBart Van Assche 		 * earlier in this function.
390519f31343SBart Van Assche 		 */
390619f31343SBart Van Assche 		if (target->state != SRP_TARGET_REMOVED)
390719f31343SBart Van Assche 			kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
3908bc44bd1dSBart Van Assche 		scsi_host_put(target->scsi_host);
390919f31343SBart Van Assche 	}
391034aa654eSBart Van Assche 
39112d7091bcSBart Van Assche 	return ret;
3912aef9ec39SRoland Dreier 
3913aef9ec39SRoland Dreier err_disconnect:
3914aef9ec39SRoland Dreier 	srp_disconnect_target(target);
3915aef9ec39SRoland Dreier 
3916b02c1536SBart Van Assche free_ch:
3917d92c0da7SBart Van Assche 	for (i = 0; i < target->ch_count; i++) {
3918d92c0da7SBart Van Assche 		ch = &target->ch[i];
3919509c07bcSBart Van Assche 		srp_free_ch_ib(target, ch);
3920d92c0da7SBart Van Assche 	}
3921d92c0da7SBart Van Assche 
3922d92c0da7SBart Van Assche 	kfree(target->ch);
39232d7091bcSBart Van Assche 	goto out;
3924aef9ec39SRoland Dreier }
3925aef9ec39SRoland Dreier 
392633e82346SYueHaibing static DEVICE_ATTR_WO(add_target);
3927aef9ec39SRoland Dreier 
ibdev_show(struct device * dev,struct device_attribute * attr,char * buf)392833e82346SYueHaibing static ssize_t ibdev_show(struct device *dev, struct device_attribute *attr,
3929ee959b00STony Jones 			  char *buf)
3930aef9ec39SRoland Dreier {
3931ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
3932aef9ec39SRoland Dreier 
39331c7fd726SJoe Perches 	return sysfs_emit(buf, "%s\n", dev_name(&host->srp_dev->dev->dev));
3934aef9ec39SRoland Dreier }
3935aef9ec39SRoland Dreier 
393633e82346SYueHaibing static DEVICE_ATTR_RO(ibdev);
3937aef9ec39SRoland Dreier 
port_show(struct device * dev,struct device_attribute * attr,char * buf)393833e82346SYueHaibing static ssize_t port_show(struct device *dev, struct device_attribute *attr,
3939ee959b00STony Jones 			 char *buf)
3940aef9ec39SRoland Dreier {
3941ee959b00STony Jones 	struct srp_host *host = container_of(dev, struct srp_host, dev);
3942aef9ec39SRoland Dreier 
3943b05398afSMikhael Goikhman 	return sysfs_emit(buf, "%u\n", host->port);
3944aef9ec39SRoland Dreier }
3945aef9ec39SRoland Dreier 
394633e82346SYueHaibing static DEVICE_ATTR_RO(port);
3947aef9ec39SRoland Dreier 
3948b8a9c18cSBart Van Assche static struct attribute *srp_class_attrs[] = {
3949b8a9c18cSBart Van Assche 	&dev_attr_add_target.attr,
3950b8a9c18cSBart Van Assche 	&dev_attr_ibdev.attr,
3951b8a9c18cSBart Van Assche 	&dev_attr_port.attr,
3952b8a9c18cSBart Van Assche 	NULL
3953b8a9c18cSBart Van Assche };
3954b8a9c18cSBart Van Assche 
srp_add_port(struct srp_device * device,u32 port)3955b05398afSMikhael Goikhman static struct srp_host *srp_add_port(struct srp_device *device, u32 port)
3956aef9ec39SRoland Dreier {
3957aef9ec39SRoland Dreier 	struct srp_host *host;
3958aef9ec39SRoland Dreier 
3959aef9ec39SRoland Dreier 	host = kzalloc(sizeof *host, GFP_KERNEL);
3960aef9ec39SRoland Dreier 	if (!host)
3961aef9ec39SRoland Dreier 		return NULL;
3962aef9ec39SRoland Dreier 
3963aef9ec39SRoland Dreier 	INIT_LIST_HEAD(&host->target_list);
3964b3589fd4SMatthew Wilcox 	spin_lock_init(&host->target_lock);
39652d7091bcSBart Van Assche 	mutex_init(&host->add_target_mutex);
396605321937SGreg Kroah-Hartman 	host->srp_dev = device;
3967aef9ec39SRoland Dreier 	host->port = port;
3968aef9ec39SRoland Dreier 
3969351e458fSBart Van Assche 	device_initialize(&host->dev);
3970ee959b00STony Jones 	host->dev.class = &srp_class;
3971dee2b82aSBart Van Assche 	host->dev.parent = device->dev->dev.parent;
3972b05398afSMikhael Goikhman 	if (dev_set_name(&host->dev, "srp-%s-%u", dev_name(&device->dev->dev),
3973351e458fSBart Van Assche 			 port))
3974351e458fSBart Van Assche 		goto put_host;
3975351e458fSBart Van Assche 	if (device_add(&host->dev))
3976c8e4c239SBart Van Assche 		goto put_host;
3977aef9ec39SRoland Dreier 
3978aef9ec39SRoland Dreier 	return host;
3979aef9ec39SRoland Dreier 
3980c8e4c239SBart Van Assche put_host:
3981c8e4c239SBart Van Assche 	device_del(&host->dev);
3982c8e4c239SBart Van Assche 	put_device(&host->dev);
3983aef9ec39SRoland Dreier 	return NULL;
3984aef9ec39SRoland Dreier }
3985aef9ec39SRoland Dreier 
srp_rename_dev(struct ib_device * device,void * client_data)3986dc1435c0SLeon Romanovsky static void srp_rename_dev(struct ib_device *device, void *client_data)
3987dc1435c0SLeon Romanovsky {
3988dc1435c0SLeon Romanovsky 	struct srp_device *srp_dev = client_data;
3989dc1435c0SLeon Romanovsky 	struct srp_host *host, *tmp_host;
3990dc1435c0SLeon Romanovsky 
3991dc1435c0SLeon Romanovsky 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
3992dc1435c0SLeon Romanovsky 		char name[IB_DEVICE_NAME_MAX + 8];
3993dc1435c0SLeon Romanovsky 
3994b05398afSMikhael Goikhman 		snprintf(name, sizeof(name), "srp-%s-%u",
3995dc1435c0SLeon Romanovsky 			 dev_name(&device->dev), host->port);
3996dc1435c0SLeon Romanovsky 		device_rename(&host->dev, name);
3997dc1435c0SLeon Romanovsky 	}
3998dc1435c0SLeon Romanovsky }
3999dc1435c0SLeon Romanovsky 
srp_add_one(struct ib_device * device)400011a0ae4cSJason Gunthorpe static int srp_add_one(struct ib_device *device)
4001aef9ec39SRoland Dreier {
4002f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4003042dd765SBart Van Assche 	struct ib_device_attr *attr = &device->attrs;
4004aef9ec39SRoland Dreier 	struct srp_host *host;
4005ea1075edSJason Gunthorpe 	int mr_page_shift;
4006b05398afSMikhael Goikhman 	u32 p;
400752ede08fSBart Van Assche 	u64 max_pages_per_mr;
40085f071777SChristoph Hellwig 	unsigned int flags = 0;
4009aef9ec39SRoland Dreier 
4010249f0656SBart Van Assche 	srp_dev = kzalloc(sizeof(*srp_dev), GFP_KERNEL);
4011f5358a17SRoland Dreier 	if (!srp_dev)
401211a0ae4cSJason Gunthorpe 		return -ENOMEM;
4013f5358a17SRoland Dreier 
4014f5358a17SRoland Dreier 	/*
4015f5358a17SRoland Dreier 	 * Use the smallest page size supported by the HCA, down to a
40168f26c9ffSDavid Dillow 	 * minimum of 4096 bytes. We're unlikely to build large sglists
40178f26c9ffSDavid Dillow 	 * out of smaller entries.
4018f5358a17SRoland Dreier 	 */
4019042dd765SBart Van Assche 	mr_page_shift		= max(12, ffs(attr->page_size_cap) - 1);
402052ede08fSBart Van Assche 	srp_dev->mr_page_size	= 1 << mr_page_shift;
402152ede08fSBart Van Assche 	srp_dev->mr_page_mask	= ~((u64) srp_dev->mr_page_size - 1);
4022042dd765SBart Van Assche 	max_pages_per_mr	= attr->max_mr_size;
402352ede08fSBart Van Assche 	do_div(max_pages_per_mr, srp_dev->mr_page_size);
4024509c5f33SBart Van Assche 	pr_debug("%s: %llu / %u = %llu <> %u\n", __func__,
4025042dd765SBart Van Assche 		 attr->max_mr_size, srp_dev->mr_page_size,
4026509c5f33SBart Van Assche 		 max_pages_per_mr, SRP_MAX_PAGES_PER_MR);
402752ede08fSBart Van Assche 	srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR,
402852ede08fSBart Van Assche 					  max_pages_per_mr);
4029835ee624SBart Van Assche 
4030042dd765SBart Van Assche 	srp_dev->has_fr = (attr->device_cap_flags &
4031835ee624SBart Van Assche 			   IB_DEVICE_MEM_MGT_EXTENSIONS);
4032f273ad4fSMax Gurtovoy 	if (!never_register && !srp_dev->has_fr)
4033f273ad4fSMax Gurtovoy 		dev_warn(&device->dev, "FR is not supported\n");
4034f273ad4fSMax Gurtovoy 	else if (!never_register &&
4035f273ad4fSMax Gurtovoy 		 attr->max_mr_size >= 2 * srp_dev->mr_page_size)
4036f273ad4fSMax Gurtovoy 		srp_dev->use_fast_reg = srp_dev->has_fr;
4037835ee624SBart Van Assche 
4038f273ad4fSMax Gurtovoy 	if (never_register || !register_always || !srp_dev->has_fr)
40395f071777SChristoph Hellwig 		flags |= IB_PD_UNSAFE_GLOBAL_RKEY;
40405f071777SChristoph Hellwig 
40415cfb1782SBart Van Assche 	if (srp_dev->use_fast_reg) {
40425cfb1782SBart Van Assche 		srp_dev->max_pages_per_mr =
40435cfb1782SBart Van Assche 			min_t(u32, srp_dev->max_pages_per_mr,
4044042dd765SBart Van Assche 			      attr->max_fast_reg_page_list_len);
40455cfb1782SBart Van Assche 	}
404652ede08fSBart Van Assche 	srp_dev->mr_max_size	= srp_dev->mr_page_size *
404752ede08fSBart Van Assche 				   srp_dev->max_pages_per_mr;
40484a061b28SOr 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",
40496c854111SJason Gunthorpe 		 dev_name(&device->dev), mr_page_shift, attr->max_mr_size,
4050042dd765SBart Van Assche 		 attr->max_fast_reg_page_list_len,
405152ede08fSBart Van Assche 		 srp_dev->max_pages_per_mr, srp_dev->mr_max_size);
4052f5358a17SRoland Dreier 
4053f5358a17SRoland Dreier 	INIT_LIST_HEAD(&srp_dev->dev_list);
4054f5358a17SRoland Dreier 
4055f5358a17SRoland Dreier 	srp_dev->dev = device;
40565f071777SChristoph Hellwig 	srp_dev->pd  = ib_alloc_pd(device, flags);
405711a0ae4cSJason Gunthorpe 	if (IS_ERR(srp_dev->pd)) {
405811a0ae4cSJason Gunthorpe 		int ret = PTR_ERR(srp_dev->pd);
405911a0ae4cSJason Gunthorpe 
406011a0ae4cSJason Gunthorpe 		kfree(srp_dev);
406111a0ae4cSJason Gunthorpe 		return ret;
406211a0ae4cSJason Gunthorpe 	}
4063f5358a17SRoland Dreier 
4064cee687b6SBart Van Assche 	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
4065cee687b6SBart Van Assche 		srp_dev->global_rkey = srp_dev->pd->unsafe_global_rkey;
4066cee687b6SBart Van Assche 		WARN_ON_ONCE(srp_dev->global_rkey == 0);
4067cee687b6SBart Van Assche 	}
4068f5358a17SRoland Dreier 
4069ea1075edSJason Gunthorpe 	rdma_for_each_port (device, p) {
4070f5358a17SRoland Dreier 		host = srp_add_port(srp_dev, p);
4071aef9ec39SRoland Dreier 		if (host)
4072f5358a17SRoland Dreier 			list_add_tail(&host->list, &srp_dev->dev_list);
4073aef9ec39SRoland Dreier 	}
4074aef9ec39SRoland Dreier 
4075f5358a17SRoland Dreier 	ib_set_client_data(device, &srp_client, srp_dev);
407611a0ae4cSJason Gunthorpe 	return 0;
4077aef9ec39SRoland Dreier }
4078aef9ec39SRoland Dreier 
srp_remove_one(struct ib_device * device,void * client_data)40797c1eb45aSHaggai Eran static void srp_remove_one(struct ib_device *device, void *client_data)
4080aef9ec39SRoland Dreier {
4081f5358a17SRoland Dreier 	struct srp_device *srp_dev;
4082aef9ec39SRoland Dreier 	struct srp_host *host, *tmp_host;
4083ef6c49d8SBart Van Assche 	struct srp_target_port *target;
4084aef9ec39SRoland Dreier 
40857c1eb45aSHaggai Eran 	srp_dev = client_data;
4086aef9ec39SRoland Dreier 
4087f5358a17SRoland Dreier 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
4088aef9ec39SRoland Dreier 		/*
40890766fcaaSBart Van Assche 		 * Remove the add_target sysfs entry so that no new target ports
40900766fcaaSBart Van Assche 		 * can be created.
4091aef9ec39SRoland Dreier 		 */
40920766fcaaSBart Van Assche 		device_del(&host->dev);
4093aef9ec39SRoland Dreier 
4094aef9ec39SRoland Dreier 		/*
4095ef6c49d8SBart Van Assche 		 * Remove all target ports.
4096aef9ec39SRoland Dreier 		 */
4097b3589fd4SMatthew Wilcox 		spin_lock(&host->target_lock);
4098ef6c49d8SBart Van Assche 		list_for_each_entry(target, &host->target_list, list)
4099ef6c49d8SBart Van Assche 			srp_queue_remove_work(target);
4100b3589fd4SMatthew Wilcox 		spin_unlock(&host->target_lock);
4101aef9ec39SRoland Dreier 
4102aef9ec39SRoland Dreier 		/*
4103081bdc9fSBart Van Assche 		 * srp_queue_remove_work() queues a call to
4104081bdc9fSBart Van Assche 		 * srp_remove_target(). The latter function cancels
4105081bdc9fSBart Van Assche 		 * target->tl_err_work so waiting for the remove works to
4106081bdc9fSBart Van Assche 		 * finish is sufficient.
4107aef9ec39SRoland Dreier 		 */
4108bcc05910SBart Van Assche 		flush_workqueue(srp_remove_wq);
4109aef9ec39SRoland Dreier 
41100766fcaaSBart Van Assche 		put_device(&host->dev);
4111aef9ec39SRoland Dreier 	}
4112aef9ec39SRoland Dreier 
4113f5358a17SRoland Dreier 	ib_dealloc_pd(srp_dev->pd);
4114f5358a17SRoland Dreier 
4115f5358a17SRoland Dreier 	kfree(srp_dev);
4116aef9ec39SRoland Dreier }
4117aef9ec39SRoland Dreier 
41183236822bSFUJITA Tomonori static struct srp_function_template ib_srp_transport_functions = {
4119ed9b2264SBart Van Assche 	.has_rport_state	 = true,
4120ed9b2264SBart Van Assche 	.reset_timer_if_blocked	 = true,
4121a95cadb9SBart Van Assche 	.reconnect_delay	 = &srp_reconnect_delay,
4122ed9b2264SBart Van Assche 	.fast_io_fail_tmo	 = &srp_fast_io_fail_tmo,
4123ed9b2264SBart Van Assche 	.dev_loss_tmo		 = &srp_dev_loss_tmo,
4124ed9b2264SBart Van Assche 	.reconnect		 = srp_rport_reconnect,
4125dc1bdbd9SBart Van Assche 	.rport_delete		 = srp_rport_delete,
4126ed9b2264SBart Van Assche 	.terminate_rport_io	 = srp_terminate_io,
41273236822bSFUJITA Tomonori };
41283236822bSFUJITA Tomonori 
srp_init_module(void)4129aef9ec39SRoland Dreier static int __init srp_init_module(void)
4130aef9ec39SRoland Dreier {
4131aef9ec39SRoland Dreier 	int ret;
4132aef9ec39SRoland Dreier 
4133c838de1aSBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_aer_req) != 36);
4134c838de1aSBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_cmd) != 48);
413516d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_imm_buf) != 4);
4136c838de1aSBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_indirect_buf) != 20);
413716d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req) != 64);
413816d14e01SBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_login_req_rdma) != 56);
4139c838de1aSBart Van Assche 	BUILD_BUG_ON(sizeof(struct srp_rsp) != 36);
414016d14e01SBart Van Assche 
414149248644SDavid Dillow 	if (srp_sg_tablesize) {
4142e0bda7d8SBart Van Assche 		pr_warn("srp_sg_tablesize is deprecated, please use cmd_sg_entries\n");
414349248644SDavid Dillow 		if (!cmd_sg_entries)
414449248644SDavid Dillow 			cmd_sg_entries = srp_sg_tablesize;
414549248644SDavid Dillow 	}
414649248644SDavid Dillow 
414749248644SDavid Dillow 	if (!cmd_sg_entries)
414849248644SDavid Dillow 		cmd_sg_entries = SRP_DEF_SG_TABLESIZE;
414949248644SDavid Dillow 
415049248644SDavid Dillow 	if (cmd_sg_entries > 255) {
4151e0bda7d8SBart Van Assche 		pr_warn("Clamping cmd_sg_entries to 255\n");
415249248644SDavid Dillow 		cmd_sg_entries = 255;
41531e89a194SDavid Dillow 	}
41541e89a194SDavid Dillow 
4155c07d424dSDavid Dillow 	if (!indirect_sg_entries)
4156c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4157c07d424dSDavid Dillow 	else if (indirect_sg_entries < cmd_sg_entries) {
4158e0bda7d8SBart Van Assche 		pr_warn("Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n",
4159e0bda7d8SBart Van Assche 			cmd_sg_entries);
4160c07d424dSDavid Dillow 		indirect_sg_entries = cmd_sg_entries;
4161c07d424dSDavid Dillow 	}
4162c07d424dSDavid Dillow 
41630a475ef4SIsrael Rukshin 	if (indirect_sg_entries > SG_MAX_SEGMENTS) {
41640a475ef4SIsrael Rukshin 		pr_warn("Clamping indirect_sg_entries to %u\n",
41650a475ef4SIsrael Rukshin 			SG_MAX_SEGMENTS);
41660a475ef4SIsrael Rukshin 		indirect_sg_entries = SG_MAX_SEGMENTS;
41670a475ef4SIsrael Rukshin 	}
41680a475ef4SIsrael Rukshin 
4169bcc05910SBart Van Assche 	srp_remove_wq = create_workqueue("srp_remove");
4170da05be29SWei Yongjun 	if (!srp_remove_wq) {
4171da05be29SWei Yongjun 		ret = -ENOMEM;
4172bcc05910SBart Van Assche 		goto out;
4173bcc05910SBart Van Assche 	}
4174bcc05910SBart Van Assche 
4175bcc05910SBart Van Assche 	ret = -ENOMEM;
41763236822bSFUJITA Tomonori 	ib_srp_transport_template =
41773236822bSFUJITA Tomonori 		srp_attach_transport(&ib_srp_transport_functions);
41783236822bSFUJITA Tomonori 	if (!ib_srp_transport_template)
4179bcc05910SBart Van Assche 		goto destroy_wq;
41803236822bSFUJITA Tomonori 
4181aef9ec39SRoland Dreier 	ret = class_register(&srp_class);
4182aef9ec39SRoland Dreier 	if (ret) {
4183e0bda7d8SBart Van Assche 		pr_err("couldn't register class infiniband_srp\n");
4184bcc05910SBart Van Assche 		goto release_tr;
4185aef9ec39SRoland Dreier 	}
4186aef9ec39SRoland Dreier 
4187c1a0b23bSMichael S. Tsirkin 	ib_sa_register_client(&srp_sa_client);
4188c1a0b23bSMichael S. Tsirkin 
4189aef9ec39SRoland Dreier 	ret = ib_register_client(&srp_client);
4190aef9ec39SRoland Dreier 	if (ret) {
4191e0bda7d8SBart Van Assche 		pr_err("couldn't register IB client\n");
4192bcc05910SBart Van Assche 		goto unreg_sa;
4193aef9ec39SRoland Dreier 	}
4194aef9ec39SRoland Dreier 
4195bcc05910SBart Van Assche out:
4196bcc05910SBart Van Assche 	return ret;
4197bcc05910SBart Van Assche 
4198bcc05910SBart Van Assche unreg_sa:
4199bcc05910SBart Van Assche 	ib_sa_unregister_client(&srp_sa_client);
4200bcc05910SBart Van Assche 	class_unregister(&srp_class);
4201bcc05910SBart Van Assche 
4202bcc05910SBart Van Assche release_tr:
4203bcc05910SBart Van Assche 	srp_release_transport(ib_srp_transport_template);
4204bcc05910SBart Van Assche 
4205bcc05910SBart Van Assche destroy_wq:
4206bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4207bcc05910SBart Van Assche 	goto out;
4208aef9ec39SRoland Dreier }
4209aef9ec39SRoland Dreier 
srp_cleanup_module(void)4210aef9ec39SRoland Dreier static void __exit srp_cleanup_module(void)
4211aef9ec39SRoland Dreier {
4212aef9ec39SRoland Dreier 	ib_unregister_client(&srp_client);
4213c1a0b23bSMichael S. Tsirkin 	ib_sa_unregister_client(&srp_sa_client);
4214aef9ec39SRoland Dreier 	class_unregister(&srp_class);
42153236822bSFUJITA Tomonori 	srp_release_transport(ib_srp_transport_template);
4216bcc05910SBart Van Assche 	destroy_workqueue(srp_remove_wq);
4217aef9ec39SRoland Dreier }
4218aef9ec39SRoland Dreier 
4219aef9ec39SRoland Dreier module_init(srp_init_module);
4220aef9ec39SRoland Dreier module_exit(srp_cleanup_module);
4221