162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2005 Cisco Systems.  All rights reserved.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * This software is available to you under a choice of one of two
562306a36Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
662306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
762306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the
862306a36Sopenharmony_ci * OpenIB.org BSD license below:
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
1162306a36Sopenharmony_ci *     without modification, are permitted provided that the following
1262306a36Sopenharmony_ci *     conditions are met:
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *      - Redistributions of source code must retain the above
1562306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
1662306a36Sopenharmony_ci *        disclaimer.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
1962306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
2062306a36Sopenharmony_ci *        disclaimer in the documentation and/or other materials
2162306a36Sopenharmony_ci *        provided with the distribution.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2462306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2562306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2662306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2762306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2862306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2962306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3062306a36Sopenharmony_ci * SOFTWARE.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include <linux/module.h>
3662306a36Sopenharmony_ci#include <linux/init.h>
3762306a36Sopenharmony_ci#include <linux/slab.h>
3862306a36Sopenharmony_ci#include <linux/err.h>
3962306a36Sopenharmony_ci#include <linux/string.h>
4062306a36Sopenharmony_ci#include <linux/parser.h>
4162306a36Sopenharmony_ci#include <linux/random.h>
4262306a36Sopenharmony_ci#include <linux/jiffies.h>
4362306a36Sopenharmony_ci#include <linux/lockdep.h>
4462306a36Sopenharmony_ci#include <linux/inet.h>
4562306a36Sopenharmony_ci#include <rdma/ib_cache.h>
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#include <linux/atomic.h>
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#include <scsi/scsi.h>
5062306a36Sopenharmony_ci#include <scsi/scsi_device.h>
5162306a36Sopenharmony_ci#include <scsi/scsi_dbg.h>
5262306a36Sopenharmony_ci#include <scsi/scsi_tcq.h>
5362306a36Sopenharmony_ci#include <scsi/srp.h>
5462306a36Sopenharmony_ci#include <scsi/scsi_transport_srp.h>
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#include "ib_srp.h"
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define DRV_NAME	"ib_srp"
5962306a36Sopenharmony_ci#define PFX		DRV_NAME ": "
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciMODULE_AUTHOR("Roland Dreier");
6262306a36Sopenharmony_ciMODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator");
6362306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic unsigned int srp_sg_tablesize;
6662306a36Sopenharmony_cistatic unsigned int cmd_sg_entries;
6762306a36Sopenharmony_cistatic unsigned int indirect_sg_entries;
6862306a36Sopenharmony_cistatic bool allow_ext_sg;
6962306a36Sopenharmony_cistatic bool register_always = true;
7062306a36Sopenharmony_cistatic bool never_register;
7162306a36Sopenharmony_cistatic int topspin_workarounds = 1;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cimodule_param(srp_sg_tablesize, uint, 0444);
7462306a36Sopenharmony_ciMODULE_PARM_DESC(srp_sg_tablesize, "Deprecated name for cmd_sg_entries");
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cimodule_param(cmd_sg_entries, uint, 0444);
7762306a36Sopenharmony_ciMODULE_PARM_DESC(cmd_sg_entries,
7862306a36Sopenharmony_ci		 "Default number of gather/scatter entries in the SRP command (default is 12, max 255)");
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cimodule_param(indirect_sg_entries, uint, 0444);
8162306a36Sopenharmony_ciMODULE_PARM_DESC(indirect_sg_entries,
8262306a36Sopenharmony_ci		 "Default max number of gather/scatter entries (default is 12, max is " __stringify(SG_MAX_SEGMENTS) ")");
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cimodule_param(allow_ext_sg, bool, 0444);
8562306a36Sopenharmony_ciMODULE_PARM_DESC(allow_ext_sg,
8662306a36Sopenharmony_ci		  "Default behavior when there are more than cmd_sg_entries S/G entries after mapping; fails the request when false (default false)");
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cimodule_param(topspin_workarounds, int, 0444);
8962306a36Sopenharmony_ciMODULE_PARM_DESC(topspin_workarounds,
9062306a36Sopenharmony_ci		 "Enable workarounds for Topspin/Cisco SRP target bugs if != 0");
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cimodule_param(register_always, bool, 0444);
9362306a36Sopenharmony_ciMODULE_PARM_DESC(register_always,
9462306a36Sopenharmony_ci		 "Use memory registration even for contiguous memory regions");
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cimodule_param(never_register, bool, 0444);
9762306a36Sopenharmony_ciMODULE_PARM_DESC(never_register, "Never register memory");
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic const struct kernel_param_ops srp_tmo_ops;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic int srp_reconnect_delay = 10;
10262306a36Sopenharmony_cimodule_param_cb(reconnect_delay, &srp_tmo_ops, &srp_reconnect_delay,
10362306a36Sopenharmony_ci		S_IRUGO | S_IWUSR);
10462306a36Sopenharmony_ciMODULE_PARM_DESC(reconnect_delay, "Time between successive reconnect attempts");
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic int srp_fast_io_fail_tmo = 15;
10762306a36Sopenharmony_cimodule_param_cb(fast_io_fail_tmo, &srp_tmo_ops, &srp_fast_io_fail_tmo,
10862306a36Sopenharmony_ci		S_IRUGO | S_IWUSR);
10962306a36Sopenharmony_ciMODULE_PARM_DESC(fast_io_fail_tmo,
11062306a36Sopenharmony_ci		 "Number of seconds between the observation of a transport"
11162306a36Sopenharmony_ci		 " layer error and failing all I/O. \"off\" means that this"
11262306a36Sopenharmony_ci		 " functionality is disabled.");
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic int srp_dev_loss_tmo = 600;
11562306a36Sopenharmony_cimodule_param_cb(dev_loss_tmo, &srp_tmo_ops, &srp_dev_loss_tmo,
11662306a36Sopenharmony_ci		S_IRUGO | S_IWUSR);
11762306a36Sopenharmony_ciMODULE_PARM_DESC(dev_loss_tmo,
11862306a36Sopenharmony_ci		 "Maximum number of seconds that the SRP transport should"
11962306a36Sopenharmony_ci		 " insulate transport layer errors. After this time has been"
12062306a36Sopenharmony_ci		 " exceeded the SCSI host is removed. Should be"
12162306a36Sopenharmony_ci		 " between 1 and " __stringify(SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
12262306a36Sopenharmony_ci		 " if fast_io_fail_tmo has not been set. \"off\" means that"
12362306a36Sopenharmony_ci		 " this functionality is disabled.");
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic bool srp_use_imm_data = true;
12662306a36Sopenharmony_cimodule_param_named(use_imm_data, srp_use_imm_data, bool, 0644);
12762306a36Sopenharmony_ciMODULE_PARM_DESC(use_imm_data,
12862306a36Sopenharmony_ci		 "Whether or not to request permission to use immediate data during SRP login.");
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic unsigned int srp_max_imm_data = 8 * 1024;
13162306a36Sopenharmony_cimodule_param_named(max_imm_data, srp_max_imm_data, uint, 0644);
13262306a36Sopenharmony_ciMODULE_PARM_DESC(max_imm_data, "Maximum immediate data size.");
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic unsigned ch_count;
13562306a36Sopenharmony_cimodule_param(ch_count, uint, 0444);
13662306a36Sopenharmony_ciMODULE_PARM_DESC(ch_count,
13762306a36Sopenharmony_ci		 "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.");
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic int srp_add_one(struct ib_device *device);
14062306a36Sopenharmony_cistatic void srp_remove_one(struct ib_device *device, void *client_data);
14162306a36Sopenharmony_cistatic void srp_rename_dev(struct ib_device *device, void *client_data);
14262306a36Sopenharmony_cistatic void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc);
14362306a36Sopenharmony_cistatic void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
14462306a36Sopenharmony_ci		const char *opname);
14562306a36Sopenharmony_cistatic int srp_ib_cm_handler(struct ib_cm_id *cm_id,
14662306a36Sopenharmony_ci			     const struct ib_cm_event *event);
14762306a36Sopenharmony_cistatic int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
14862306a36Sopenharmony_ci			       struct rdma_cm_event *event);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic struct scsi_transport_template *ib_srp_transport_template;
15162306a36Sopenharmony_cistatic struct workqueue_struct *srp_remove_wq;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic struct ib_client srp_client = {
15462306a36Sopenharmony_ci	.name   = "srp",
15562306a36Sopenharmony_ci	.add    = srp_add_one,
15662306a36Sopenharmony_ci	.remove = srp_remove_one,
15762306a36Sopenharmony_ci	.rename = srp_rename_dev
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic struct ib_sa_client srp_sa_client;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic int srp_tmo_get(char *buffer, const struct kernel_param *kp)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	int tmo = *(int *)kp->arg;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (tmo >= 0)
16762306a36Sopenharmony_ci		return sysfs_emit(buffer, "%d\n", tmo);
16862306a36Sopenharmony_ci	else
16962306a36Sopenharmony_ci		return sysfs_emit(buffer, "off\n");
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic int srp_tmo_set(const char *val, const struct kernel_param *kp)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	int tmo, res;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	res = srp_parse_tmo(&tmo, val);
17762306a36Sopenharmony_ci	if (res)
17862306a36Sopenharmony_ci		goto out;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	if (kp->arg == &srp_reconnect_delay)
18162306a36Sopenharmony_ci		res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo,
18262306a36Sopenharmony_ci				    srp_dev_loss_tmo);
18362306a36Sopenharmony_ci	else if (kp->arg == &srp_fast_io_fail_tmo)
18462306a36Sopenharmony_ci		res = srp_tmo_valid(srp_reconnect_delay, tmo, srp_dev_loss_tmo);
18562306a36Sopenharmony_ci	else
18662306a36Sopenharmony_ci		res = srp_tmo_valid(srp_reconnect_delay, srp_fast_io_fail_tmo,
18762306a36Sopenharmony_ci				    tmo);
18862306a36Sopenharmony_ci	if (res)
18962306a36Sopenharmony_ci		goto out;
19062306a36Sopenharmony_ci	*(int *)kp->arg = tmo;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ciout:
19362306a36Sopenharmony_ci	return res;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic const struct kernel_param_ops srp_tmo_ops = {
19762306a36Sopenharmony_ci	.get = srp_tmo_get,
19862306a36Sopenharmony_ci	.set = srp_tmo_set,
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	return (struct srp_target_port *) host->hostdata;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic const char *srp_target_info(struct Scsi_Host *host)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	return host_to_target(host)->target_name;
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic int srp_target_is_topspin(struct srp_target_port *target)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
21462306a36Sopenharmony_ci	static const u8 cisco_oui[3]   = { 0x00, 0x1b, 0x0d };
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	return topspin_workarounds &&
21762306a36Sopenharmony_ci		(!memcmp(&target->ioc_guid, topspin_oui, sizeof topspin_oui) ||
21862306a36Sopenharmony_ci		 !memcmp(&target->ioc_guid, cisco_oui, sizeof cisco_oui));
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
22262306a36Sopenharmony_ci				   gfp_t gfp_mask,
22362306a36Sopenharmony_ci				   enum dma_data_direction direction)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	struct srp_iu *iu;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	iu = kmalloc(sizeof *iu, gfp_mask);
22862306a36Sopenharmony_ci	if (!iu)
22962306a36Sopenharmony_ci		goto out;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	iu->buf = kzalloc(size, gfp_mask);
23262306a36Sopenharmony_ci	if (!iu->buf)
23362306a36Sopenharmony_ci		goto out_free_iu;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size,
23662306a36Sopenharmony_ci				    direction);
23762306a36Sopenharmony_ci	if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma))
23862306a36Sopenharmony_ci		goto out_free_buf;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	iu->size      = size;
24162306a36Sopenharmony_ci	iu->direction = direction;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	return iu;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ciout_free_buf:
24662306a36Sopenharmony_ci	kfree(iu->buf);
24762306a36Sopenharmony_ciout_free_iu:
24862306a36Sopenharmony_ci	kfree(iu);
24962306a36Sopenharmony_ciout:
25062306a36Sopenharmony_ci	return NULL;
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	if (!iu)
25662306a36Sopenharmony_ci		return;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size,
25962306a36Sopenharmony_ci			    iu->direction);
26062306a36Sopenharmony_ci	kfree(iu->buf);
26162306a36Sopenharmony_ci	kfree(iu);
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic void srp_qp_event(struct ib_event *event, void *context)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	pr_debug("QP event %s (%d)\n",
26762306a36Sopenharmony_ci		 ib_event_msg(event->event), event->event);
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic int srp_init_ib_qp(struct srp_target_port *target,
27162306a36Sopenharmony_ci			  struct ib_qp *qp)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	struct ib_qp_attr *attr;
27462306a36Sopenharmony_ci	int ret;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	attr = kmalloc(sizeof *attr, GFP_KERNEL);
27762306a36Sopenharmony_ci	if (!attr)
27862306a36Sopenharmony_ci		return -ENOMEM;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev,
28162306a36Sopenharmony_ci				  target->srp_host->port,
28262306a36Sopenharmony_ci				  be16_to_cpu(target->ib_cm.pkey),
28362306a36Sopenharmony_ci				  &attr->pkey_index);
28462306a36Sopenharmony_ci	if (ret)
28562306a36Sopenharmony_ci		goto out;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	attr->qp_state        = IB_QPS_INIT;
28862306a36Sopenharmony_ci	attr->qp_access_flags = (IB_ACCESS_REMOTE_READ |
28962306a36Sopenharmony_ci				    IB_ACCESS_REMOTE_WRITE);
29062306a36Sopenharmony_ci	attr->port_num        = target->srp_host->port;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	ret = ib_modify_qp(qp, attr,
29362306a36Sopenharmony_ci			   IB_QP_STATE		|
29462306a36Sopenharmony_ci			   IB_QP_PKEY_INDEX	|
29562306a36Sopenharmony_ci			   IB_QP_ACCESS_FLAGS	|
29662306a36Sopenharmony_ci			   IB_QP_PORT);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ciout:
29962306a36Sopenharmony_ci	kfree(attr);
30062306a36Sopenharmony_ci	return ret;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic int srp_new_ib_cm_id(struct srp_rdma_ch *ch)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
30662306a36Sopenharmony_ci	struct ib_cm_id *new_cm_id;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
30962306a36Sopenharmony_ci				    srp_ib_cm_handler, ch);
31062306a36Sopenharmony_ci	if (IS_ERR(new_cm_id))
31162306a36Sopenharmony_ci		return PTR_ERR(new_cm_id);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (ch->ib_cm.cm_id)
31462306a36Sopenharmony_ci		ib_destroy_cm_id(ch->ib_cm.cm_id);
31562306a36Sopenharmony_ci	ch->ib_cm.cm_id = new_cm_id;
31662306a36Sopenharmony_ci	if (rdma_cap_opa_ah(target->srp_host->srp_dev->dev,
31762306a36Sopenharmony_ci			    target->srp_host->port))
31862306a36Sopenharmony_ci		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_OPA;
31962306a36Sopenharmony_ci	else
32062306a36Sopenharmony_ci		ch->ib_cm.path.rec_type = SA_PATH_REC_TYPE_IB;
32162306a36Sopenharmony_ci	ch->ib_cm.path.sgid = target->sgid;
32262306a36Sopenharmony_ci	ch->ib_cm.path.dgid = target->ib_cm.orig_dgid;
32362306a36Sopenharmony_ci	ch->ib_cm.path.pkey = target->ib_cm.pkey;
32462306a36Sopenharmony_ci	ch->ib_cm.path.service_id = target->ib_cm.service_id;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	return 0;
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic int srp_new_rdma_cm_id(struct srp_rdma_ch *ch)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
33262306a36Sopenharmony_ci	struct rdma_cm_id *new_cm_id;
33362306a36Sopenharmony_ci	int ret;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	new_cm_id = rdma_create_id(target->net, srp_rdma_cm_handler, ch,
33662306a36Sopenharmony_ci				   RDMA_PS_TCP, IB_QPT_RC);
33762306a36Sopenharmony_ci	if (IS_ERR(new_cm_id)) {
33862306a36Sopenharmony_ci		ret = PTR_ERR(new_cm_id);
33962306a36Sopenharmony_ci		new_cm_id = NULL;
34062306a36Sopenharmony_ci		goto out;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	init_completion(&ch->done);
34462306a36Sopenharmony_ci	ret = rdma_resolve_addr(new_cm_id, target->rdma_cm.src_specified ?
34562306a36Sopenharmony_ci				&target->rdma_cm.src.sa : NULL,
34662306a36Sopenharmony_ci				&target->rdma_cm.dst.sa,
34762306a36Sopenharmony_ci				SRP_PATH_REC_TIMEOUT_MS);
34862306a36Sopenharmony_ci	if (ret) {
34962306a36Sopenharmony_ci		pr_err("No route available from %pISpsc to %pISpsc (%d)\n",
35062306a36Sopenharmony_ci		       &target->rdma_cm.src, &target->rdma_cm.dst, ret);
35162306a36Sopenharmony_ci		goto out;
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci	ret = wait_for_completion_interruptible(&ch->done);
35462306a36Sopenharmony_ci	if (ret < 0)
35562306a36Sopenharmony_ci		goto out;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	ret = ch->status;
35862306a36Sopenharmony_ci	if (ret) {
35962306a36Sopenharmony_ci		pr_err("Resolving address %pISpsc failed (%d)\n",
36062306a36Sopenharmony_ci		       &target->rdma_cm.dst, ret);
36162306a36Sopenharmony_ci		goto out;
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	swap(ch->rdma_cm.cm_id, new_cm_id);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ciout:
36762306a36Sopenharmony_ci	if (new_cm_id)
36862306a36Sopenharmony_ci		rdma_destroy_id(new_cm_id);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	return ret;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int srp_new_cm_id(struct srp_rdma_ch *ch)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	return target->using_rdma_cm ? srp_new_rdma_cm_id(ch) :
37862306a36Sopenharmony_ci		srp_new_ib_cm_id(ch);
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci/**
38262306a36Sopenharmony_ci * srp_destroy_fr_pool() - free the resources owned by a pool
38362306a36Sopenharmony_ci * @pool: Fast registration pool to be destroyed.
38462306a36Sopenharmony_ci */
38562306a36Sopenharmony_cistatic void srp_destroy_fr_pool(struct srp_fr_pool *pool)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	int i;
38862306a36Sopenharmony_ci	struct srp_fr_desc *d;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	if (!pool)
39162306a36Sopenharmony_ci		return;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
39462306a36Sopenharmony_ci		if (d->mr)
39562306a36Sopenharmony_ci			ib_dereg_mr(d->mr);
39662306a36Sopenharmony_ci	}
39762306a36Sopenharmony_ci	kfree(pool);
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci/**
40162306a36Sopenharmony_ci * srp_create_fr_pool() - allocate and initialize a pool for fast registration
40262306a36Sopenharmony_ci * @device:            IB device to allocate fast registration descriptors for.
40362306a36Sopenharmony_ci * @pd:                Protection domain associated with the FR descriptors.
40462306a36Sopenharmony_ci * @pool_size:         Number of descriptors to allocate.
40562306a36Sopenharmony_ci * @max_page_list_len: Maximum fast registration work request page list length.
40662306a36Sopenharmony_ci */
40762306a36Sopenharmony_cistatic struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
40862306a36Sopenharmony_ci					      struct ib_pd *pd, int pool_size,
40962306a36Sopenharmony_ci					      int max_page_list_len)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	struct srp_fr_pool *pool;
41262306a36Sopenharmony_ci	struct srp_fr_desc *d;
41362306a36Sopenharmony_ci	struct ib_mr *mr;
41462306a36Sopenharmony_ci	int i, ret = -EINVAL;
41562306a36Sopenharmony_ci	enum ib_mr_type mr_type;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	if (pool_size <= 0)
41862306a36Sopenharmony_ci		goto err;
41962306a36Sopenharmony_ci	ret = -ENOMEM;
42062306a36Sopenharmony_ci	pool = kzalloc(struct_size(pool, desc, pool_size), GFP_KERNEL);
42162306a36Sopenharmony_ci	if (!pool)
42262306a36Sopenharmony_ci		goto err;
42362306a36Sopenharmony_ci	pool->size = pool_size;
42462306a36Sopenharmony_ci	pool->max_page_list_len = max_page_list_len;
42562306a36Sopenharmony_ci	spin_lock_init(&pool->lock);
42662306a36Sopenharmony_ci	INIT_LIST_HEAD(&pool->free_list);
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	if (device->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
42962306a36Sopenharmony_ci		mr_type = IB_MR_TYPE_SG_GAPS;
43062306a36Sopenharmony_ci	else
43162306a36Sopenharmony_ci		mr_type = IB_MR_TYPE_MEM_REG;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
43462306a36Sopenharmony_ci		mr = ib_alloc_mr(pd, mr_type, max_page_list_len);
43562306a36Sopenharmony_ci		if (IS_ERR(mr)) {
43662306a36Sopenharmony_ci			ret = PTR_ERR(mr);
43762306a36Sopenharmony_ci			if (ret == -ENOMEM)
43862306a36Sopenharmony_ci				pr_info("%s: ib_alloc_mr() failed. Try to reduce max_cmd_per_lun, max_sect or ch_count\n",
43962306a36Sopenharmony_ci					dev_name(&device->dev));
44062306a36Sopenharmony_ci			goto destroy_pool;
44162306a36Sopenharmony_ci		}
44262306a36Sopenharmony_ci		d->mr = mr;
44362306a36Sopenharmony_ci		list_add_tail(&d->entry, &pool->free_list);
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ciout:
44762306a36Sopenharmony_ci	return pool;
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cidestroy_pool:
45062306a36Sopenharmony_ci	srp_destroy_fr_pool(pool);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cierr:
45362306a36Sopenharmony_ci	pool = ERR_PTR(ret);
45462306a36Sopenharmony_ci	goto out;
45562306a36Sopenharmony_ci}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci/**
45862306a36Sopenharmony_ci * srp_fr_pool_get() - obtain a descriptor suitable for fast registration
45962306a36Sopenharmony_ci * @pool: Pool to obtain descriptor from.
46062306a36Sopenharmony_ci */
46162306a36Sopenharmony_cistatic struct srp_fr_desc *srp_fr_pool_get(struct srp_fr_pool *pool)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	struct srp_fr_desc *d = NULL;
46462306a36Sopenharmony_ci	unsigned long flags;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	spin_lock_irqsave(&pool->lock, flags);
46762306a36Sopenharmony_ci	if (!list_empty(&pool->free_list)) {
46862306a36Sopenharmony_ci		d = list_first_entry(&pool->free_list, typeof(*d), entry);
46962306a36Sopenharmony_ci		list_del(&d->entry);
47062306a36Sopenharmony_ci	}
47162306a36Sopenharmony_ci	spin_unlock_irqrestore(&pool->lock, flags);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	return d;
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci/**
47762306a36Sopenharmony_ci * srp_fr_pool_put() - put an FR descriptor back in the free list
47862306a36Sopenharmony_ci * @pool: Pool the descriptor was allocated from.
47962306a36Sopenharmony_ci * @desc: Pointer to an array of fast registration descriptor pointers.
48062306a36Sopenharmony_ci * @n:    Number of descriptors to put back.
48162306a36Sopenharmony_ci *
48262306a36Sopenharmony_ci * Note: The caller must already have queued an invalidation request for
48362306a36Sopenharmony_ci * desc->mr->rkey before calling this function.
48462306a36Sopenharmony_ci */
48562306a36Sopenharmony_cistatic void srp_fr_pool_put(struct srp_fr_pool *pool, struct srp_fr_desc **desc,
48662306a36Sopenharmony_ci			    int n)
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci	unsigned long flags;
48962306a36Sopenharmony_ci	int i;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	spin_lock_irqsave(&pool->lock, flags);
49262306a36Sopenharmony_ci	for (i = 0; i < n; i++)
49362306a36Sopenharmony_ci		list_add(&desc[i]->entry, &pool->free_list);
49462306a36Sopenharmony_ci	spin_unlock_irqrestore(&pool->lock, flags);
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_cistatic struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	struct srp_device *dev = target->srp_host->srp_dev;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	return srp_create_fr_pool(dev->dev, dev->pd, target->mr_pool_size,
50262306a36Sopenharmony_ci				  dev->max_pages_per_mr);
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci/**
50662306a36Sopenharmony_ci * srp_destroy_qp() - destroy an RDMA queue pair
50762306a36Sopenharmony_ci * @ch: SRP RDMA channel.
50862306a36Sopenharmony_ci *
50962306a36Sopenharmony_ci * Drain the qp before destroying it.  This avoids that the receive
51062306a36Sopenharmony_ci * completion handler can access the queue pair while it is
51162306a36Sopenharmony_ci * being destroyed.
51262306a36Sopenharmony_ci */
51362306a36Sopenharmony_cistatic void srp_destroy_qp(struct srp_rdma_ch *ch)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	spin_lock_irq(&ch->lock);
51662306a36Sopenharmony_ci	ib_process_cq_direct(ch->send_cq, -1);
51762306a36Sopenharmony_ci	spin_unlock_irq(&ch->lock);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	ib_drain_qp(ch->qp);
52062306a36Sopenharmony_ci	ib_destroy_qp(ch->qp);
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic int srp_create_ch_ib(struct srp_rdma_ch *ch)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
52662306a36Sopenharmony_ci	struct srp_device *dev = target->srp_host->srp_dev;
52762306a36Sopenharmony_ci	const struct ib_device_attr *attr = &dev->dev->attrs;
52862306a36Sopenharmony_ci	struct ib_qp_init_attr *init_attr;
52962306a36Sopenharmony_ci	struct ib_cq *recv_cq, *send_cq;
53062306a36Sopenharmony_ci	struct ib_qp *qp;
53162306a36Sopenharmony_ci	struct srp_fr_pool *fr_pool = NULL;
53262306a36Sopenharmony_ci	const int m = 1 + dev->use_fast_reg * target->mr_per_cmd * 2;
53362306a36Sopenharmony_ci	int ret;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
53662306a36Sopenharmony_ci	if (!init_attr)
53762306a36Sopenharmony_ci		return -ENOMEM;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	/* queue_size + 1 for ib_drain_rq() */
54062306a36Sopenharmony_ci	recv_cq = ib_alloc_cq(dev->dev, ch, target->queue_size + 1,
54162306a36Sopenharmony_ci				ch->comp_vector, IB_POLL_SOFTIRQ);
54262306a36Sopenharmony_ci	if (IS_ERR(recv_cq)) {
54362306a36Sopenharmony_ci		ret = PTR_ERR(recv_cq);
54462306a36Sopenharmony_ci		goto err;
54562306a36Sopenharmony_ci	}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	send_cq = ib_alloc_cq(dev->dev, ch, m * target->queue_size,
54862306a36Sopenharmony_ci				ch->comp_vector, IB_POLL_DIRECT);
54962306a36Sopenharmony_ci	if (IS_ERR(send_cq)) {
55062306a36Sopenharmony_ci		ret = PTR_ERR(send_cq);
55162306a36Sopenharmony_ci		goto err_recv_cq;
55262306a36Sopenharmony_ci	}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	init_attr->event_handler       = srp_qp_event;
55562306a36Sopenharmony_ci	init_attr->cap.max_send_wr     = m * target->queue_size;
55662306a36Sopenharmony_ci	init_attr->cap.max_recv_wr     = target->queue_size + 1;
55762306a36Sopenharmony_ci	init_attr->cap.max_recv_sge    = 1;
55862306a36Sopenharmony_ci	init_attr->cap.max_send_sge    = min(SRP_MAX_SGE, attr->max_send_sge);
55962306a36Sopenharmony_ci	init_attr->sq_sig_type         = IB_SIGNAL_REQ_WR;
56062306a36Sopenharmony_ci	init_attr->qp_type             = IB_QPT_RC;
56162306a36Sopenharmony_ci	init_attr->send_cq             = send_cq;
56262306a36Sopenharmony_ci	init_attr->recv_cq             = recv_cq;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	ch->max_imm_sge = min(init_attr->cap.max_send_sge - 1U, 255U);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (target->using_rdma_cm) {
56762306a36Sopenharmony_ci		ret = rdma_create_qp(ch->rdma_cm.cm_id, dev->pd, init_attr);
56862306a36Sopenharmony_ci		qp = ch->rdma_cm.cm_id->qp;
56962306a36Sopenharmony_ci	} else {
57062306a36Sopenharmony_ci		qp = ib_create_qp(dev->pd, init_attr);
57162306a36Sopenharmony_ci		if (!IS_ERR(qp)) {
57262306a36Sopenharmony_ci			ret = srp_init_ib_qp(target, qp);
57362306a36Sopenharmony_ci			if (ret)
57462306a36Sopenharmony_ci				ib_destroy_qp(qp);
57562306a36Sopenharmony_ci		} else {
57662306a36Sopenharmony_ci			ret = PTR_ERR(qp);
57762306a36Sopenharmony_ci		}
57862306a36Sopenharmony_ci	}
57962306a36Sopenharmony_ci	if (ret) {
58062306a36Sopenharmony_ci		pr_err("QP creation failed for dev %s: %d\n",
58162306a36Sopenharmony_ci		       dev_name(&dev->dev->dev), ret);
58262306a36Sopenharmony_ci		goto err_send_cq;
58362306a36Sopenharmony_ci	}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	if (dev->use_fast_reg) {
58662306a36Sopenharmony_ci		fr_pool = srp_alloc_fr_pool(target);
58762306a36Sopenharmony_ci		if (IS_ERR(fr_pool)) {
58862306a36Sopenharmony_ci			ret = PTR_ERR(fr_pool);
58962306a36Sopenharmony_ci			shost_printk(KERN_WARNING, target->scsi_host, PFX
59062306a36Sopenharmony_ci				     "FR pool allocation failed (%d)\n", ret);
59162306a36Sopenharmony_ci			goto err_qp;
59262306a36Sopenharmony_ci		}
59362306a36Sopenharmony_ci	}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	if (ch->qp)
59662306a36Sopenharmony_ci		srp_destroy_qp(ch);
59762306a36Sopenharmony_ci	if (ch->recv_cq)
59862306a36Sopenharmony_ci		ib_free_cq(ch->recv_cq);
59962306a36Sopenharmony_ci	if (ch->send_cq)
60062306a36Sopenharmony_ci		ib_free_cq(ch->send_cq);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	ch->qp = qp;
60362306a36Sopenharmony_ci	ch->recv_cq = recv_cq;
60462306a36Sopenharmony_ci	ch->send_cq = send_cq;
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	if (dev->use_fast_reg) {
60762306a36Sopenharmony_ci		if (ch->fr_pool)
60862306a36Sopenharmony_ci			srp_destroy_fr_pool(ch->fr_pool);
60962306a36Sopenharmony_ci		ch->fr_pool = fr_pool;
61062306a36Sopenharmony_ci	}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	kfree(init_attr);
61362306a36Sopenharmony_ci	return 0;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_cierr_qp:
61662306a36Sopenharmony_ci	if (target->using_rdma_cm)
61762306a36Sopenharmony_ci		rdma_destroy_qp(ch->rdma_cm.cm_id);
61862306a36Sopenharmony_ci	else
61962306a36Sopenharmony_ci		ib_destroy_qp(qp);
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_cierr_send_cq:
62262306a36Sopenharmony_ci	ib_free_cq(send_cq);
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_cierr_recv_cq:
62562306a36Sopenharmony_ci	ib_free_cq(recv_cq);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_cierr:
62862306a36Sopenharmony_ci	kfree(init_attr);
62962306a36Sopenharmony_ci	return ret;
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci/*
63362306a36Sopenharmony_ci * Note: this function may be called without srp_alloc_iu_bufs() having been
63462306a36Sopenharmony_ci * invoked. Hence the ch->[rt]x_ring checks.
63562306a36Sopenharmony_ci */
63662306a36Sopenharmony_cistatic void srp_free_ch_ib(struct srp_target_port *target,
63762306a36Sopenharmony_ci			   struct srp_rdma_ch *ch)
63862306a36Sopenharmony_ci{
63962306a36Sopenharmony_ci	struct srp_device *dev = target->srp_host->srp_dev;
64062306a36Sopenharmony_ci	int i;
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	if (!ch->target)
64362306a36Sopenharmony_ci		return;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	if (target->using_rdma_cm) {
64662306a36Sopenharmony_ci		if (ch->rdma_cm.cm_id) {
64762306a36Sopenharmony_ci			rdma_destroy_id(ch->rdma_cm.cm_id);
64862306a36Sopenharmony_ci			ch->rdma_cm.cm_id = NULL;
64962306a36Sopenharmony_ci		}
65062306a36Sopenharmony_ci	} else {
65162306a36Sopenharmony_ci		if (ch->ib_cm.cm_id) {
65262306a36Sopenharmony_ci			ib_destroy_cm_id(ch->ib_cm.cm_id);
65362306a36Sopenharmony_ci			ch->ib_cm.cm_id = NULL;
65462306a36Sopenharmony_ci		}
65562306a36Sopenharmony_ci	}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	/* If srp_new_cm_id() succeeded but srp_create_ch_ib() not, return. */
65862306a36Sopenharmony_ci	if (!ch->qp)
65962306a36Sopenharmony_ci		return;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if (dev->use_fast_reg) {
66262306a36Sopenharmony_ci		if (ch->fr_pool)
66362306a36Sopenharmony_ci			srp_destroy_fr_pool(ch->fr_pool);
66462306a36Sopenharmony_ci	}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	srp_destroy_qp(ch);
66762306a36Sopenharmony_ci	ib_free_cq(ch->send_cq);
66862306a36Sopenharmony_ci	ib_free_cq(ch->recv_cq);
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	/*
67162306a36Sopenharmony_ci	 * Avoid that the SCSI error handler tries to use this channel after
67262306a36Sopenharmony_ci	 * it has been freed. The SCSI error handler can namely continue
67362306a36Sopenharmony_ci	 * trying to perform recovery actions after scsi_remove_host()
67462306a36Sopenharmony_ci	 * returned.
67562306a36Sopenharmony_ci	 */
67662306a36Sopenharmony_ci	ch->target = NULL;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	ch->qp = NULL;
67962306a36Sopenharmony_ci	ch->send_cq = ch->recv_cq = NULL;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	if (ch->rx_ring) {
68262306a36Sopenharmony_ci		for (i = 0; i < target->queue_size; ++i)
68362306a36Sopenharmony_ci			srp_free_iu(target->srp_host, ch->rx_ring[i]);
68462306a36Sopenharmony_ci		kfree(ch->rx_ring);
68562306a36Sopenharmony_ci		ch->rx_ring = NULL;
68662306a36Sopenharmony_ci	}
68762306a36Sopenharmony_ci	if (ch->tx_ring) {
68862306a36Sopenharmony_ci		for (i = 0; i < target->queue_size; ++i)
68962306a36Sopenharmony_ci			srp_free_iu(target->srp_host, ch->tx_ring[i]);
69062306a36Sopenharmony_ci		kfree(ch->tx_ring);
69162306a36Sopenharmony_ci		ch->tx_ring = NULL;
69262306a36Sopenharmony_ci	}
69362306a36Sopenharmony_ci}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_cistatic void srp_path_rec_completion(int status,
69662306a36Sopenharmony_ci				    struct sa_path_rec *pathrec,
69762306a36Sopenharmony_ci				    unsigned int num_paths, void *ch_ptr)
69862306a36Sopenharmony_ci{
69962306a36Sopenharmony_ci	struct srp_rdma_ch *ch = ch_ptr;
70062306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	ch->status = status;
70362306a36Sopenharmony_ci	if (status)
70462306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
70562306a36Sopenharmony_ci			     PFX "Got failed path rec status %d\n", status);
70662306a36Sopenharmony_ci	else
70762306a36Sopenharmony_ci		ch->ib_cm.path = *pathrec;
70862306a36Sopenharmony_ci	complete(&ch->done);
70962306a36Sopenharmony_ci}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_cistatic int srp_ib_lookup_path(struct srp_rdma_ch *ch)
71262306a36Sopenharmony_ci{
71362306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
71462306a36Sopenharmony_ci	int ret;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	ch->ib_cm.path.numb_path = 1;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	init_completion(&ch->done);
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	ch->ib_cm.path_query_id = ib_sa_path_rec_get(&srp_sa_client,
72162306a36Sopenharmony_ci					       target->srp_host->srp_dev->dev,
72262306a36Sopenharmony_ci					       target->srp_host->port,
72362306a36Sopenharmony_ci					       &ch->ib_cm.path,
72462306a36Sopenharmony_ci					       IB_SA_PATH_REC_SERVICE_ID |
72562306a36Sopenharmony_ci					       IB_SA_PATH_REC_DGID	 |
72662306a36Sopenharmony_ci					       IB_SA_PATH_REC_SGID	 |
72762306a36Sopenharmony_ci					       IB_SA_PATH_REC_NUMB_PATH	 |
72862306a36Sopenharmony_ci					       IB_SA_PATH_REC_PKEY,
72962306a36Sopenharmony_ci					       SRP_PATH_REC_TIMEOUT_MS,
73062306a36Sopenharmony_ci					       GFP_KERNEL,
73162306a36Sopenharmony_ci					       srp_path_rec_completion,
73262306a36Sopenharmony_ci					       ch, &ch->ib_cm.path_query);
73362306a36Sopenharmony_ci	if (ch->ib_cm.path_query_id < 0)
73462306a36Sopenharmony_ci		return ch->ib_cm.path_query_id;
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	ret = wait_for_completion_interruptible(&ch->done);
73762306a36Sopenharmony_ci	if (ret < 0)
73862306a36Sopenharmony_ci		return ret;
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	if (ch->status < 0)
74162306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
74262306a36Sopenharmony_ci			     PFX "Path record query failed: sgid %pI6, dgid %pI6, pkey %#04x, service_id %#16llx\n",
74362306a36Sopenharmony_ci			     ch->ib_cm.path.sgid.raw, ch->ib_cm.path.dgid.raw,
74462306a36Sopenharmony_ci			     be16_to_cpu(target->ib_cm.pkey),
74562306a36Sopenharmony_ci			     be64_to_cpu(target->ib_cm.service_id));
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	return ch->status;
74862306a36Sopenharmony_ci}
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cistatic int srp_rdma_lookup_path(struct srp_rdma_ch *ch)
75162306a36Sopenharmony_ci{
75262306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
75362306a36Sopenharmony_ci	int ret;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	init_completion(&ch->done);
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	ret = rdma_resolve_route(ch->rdma_cm.cm_id, SRP_PATH_REC_TIMEOUT_MS);
75862306a36Sopenharmony_ci	if (ret)
75962306a36Sopenharmony_ci		return ret;
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	wait_for_completion_interruptible(&ch->done);
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	if (ch->status != 0)
76462306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
76562306a36Sopenharmony_ci			     PFX "Path resolution failed\n");
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	return ch->status;
76862306a36Sopenharmony_ci}
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_cistatic int srp_lookup_path(struct srp_rdma_ch *ch)
77162306a36Sopenharmony_ci{
77262306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	return target->using_rdma_cm ? srp_rdma_lookup_path(ch) :
77562306a36Sopenharmony_ci		srp_ib_lookup_path(ch);
77662306a36Sopenharmony_ci}
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_cistatic u8 srp_get_subnet_timeout(struct srp_host *host)
77962306a36Sopenharmony_ci{
78062306a36Sopenharmony_ci	struct ib_port_attr attr;
78162306a36Sopenharmony_ci	int ret;
78262306a36Sopenharmony_ci	u8 subnet_timeout = 18;
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	ret = ib_query_port(host->srp_dev->dev, host->port, &attr);
78562306a36Sopenharmony_ci	if (ret == 0)
78662306a36Sopenharmony_ci		subnet_timeout = attr.subnet_timeout;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	if (unlikely(subnet_timeout < 15))
78962306a36Sopenharmony_ci		pr_warn("%s: subnet timeout %d may cause SRP login to fail.\n",
79062306a36Sopenharmony_ci			dev_name(&host->srp_dev->dev->dev), subnet_timeout);
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	return subnet_timeout;
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_cistatic int srp_send_req(struct srp_rdma_ch *ch, uint32_t max_iu_len,
79662306a36Sopenharmony_ci			bool multich)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
79962306a36Sopenharmony_ci	struct {
80062306a36Sopenharmony_ci		struct rdma_conn_param	  rdma_param;
80162306a36Sopenharmony_ci		struct srp_login_req_rdma rdma_req;
80262306a36Sopenharmony_ci		struct ib_cm_req_param	  ib_param;
80362306a36Sopenharmony_ci		struct srp_login_req	  ib_req;
80462306a36Sopenharmony_ci	} *req = NULL;
80562306a36Sopenharmony_ci	char *ipi, *tpi;
80662306a36Sopenharmony_ci	int status;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	req = kzalloc(sizeof *req, GFP_KERNEL);
80962306a36Sopenharmony_ci	if (!req)
81062306a36Sopenharmony_ci		return -ENOMEM;
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	req->ib_param.flow_control = 1;
81362306a36Sopenharmony_ci	req->ib_param.retry_count = target->tl_retry_count;
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	/*
81662306a36Sopenharmony_ci	 * Pick some arbitrary defaults here; we could make these
81762306a36Sopenharmony_ci	 * module parameters if anyone cared about setting them.
81862306a36Sopenharmony_ci	 */
81962306a36Sopenharmony_ci	req->ib_param.responder_resources = 4;
82062306a36Sopenharmony_ci	req->ib_param.rnr_retry_count = 7;
82162306a36Sopenharmony_ci	req->ib_param.max_cm_retries = 15;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	req->ib_req.opcode = SRP_LOGIN_REQ;
82462306a36Sopenharmony_ci	req->ib_req.tag = 0;
82562306a36Sopenharmony_ci	req->ib_req.req_it_iu_len = cpu_to_be32(max_iu_len);
82662306a36Sopenharmony_ci	req->ib_req.req_buf_fmt	= cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
82762306a36Sopenharmony_ci					      SRP_BUF_FORMAT_INDIRECT);
82862306a36Sopenharmony_ci	req->ib_req.req_flags = (multich ? SRP_MULTICHAN_MULTI :
82962306a36Sopenharmony_ci				 SRP_MULTICHAN_SINGLE);
83062306a36Sopenharmony_ci	if (srp_use_imm_data) {
83162306a36Sopenharmony_ci		req->ib_req.req_flags |= SRP_IMMED_REQUESTED;
83262306a36Sopenharmony_ci		req->ib_req.imm_data_offset = cpu_to_be16(SRP_IMM_DATA_OFFSET);
83362306a36Sopenharmony_ci	}
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	if (target->using_rdma_cm) {
83662306a36Sopenharmony_ci		req->rdma_param.flow_control = req->ib_param.flow_control;
83762306a36Sopenharmony_ci		req->rdma_param.responder_resources =
83862306a36Sopenharmony_ci			req->ib_param.responder_resources;
83962306a36Sopenharmony_ci		req->rdma_param.initiator_depth = req->ib_param.initiator_depth;
84062306a36Sopenharmony_ci		req->rdma_param.retry_count = req->ib_param.retry_count;
84162306a36Sopenharmony_ci		req->rdma_param.rnr_retry_count = req->ib_param.rnr_retry_count;
84262306a36Sopenharmony_ci		req->rdma_param.private_data = &req->rdma_req;
84362306a36Sopenharmony_ci		req->rdma_param.private_data_len = sizeof(req->rdma_req);
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci		req->rdma_req.opcode = req->ib_req.opcode;
84662306a36Sopenharmony_ci		req->rdma_req.tag = req->ib_req.tag;
84762306a36Sopenharmony_ci		req->rdma_req.req_it_iu_len = req->ib_req.req_it_iu_len;
84862306a36Sopenharmony_ci		req->rdma_req.req_buf_fmt = req->ib_req.req_buf_fmt;
84962306a36Sopenharmony_ci		req->rdma_req.req_flags	= req->ib_req.req_flags;
85062306a36Sopenharmony_ci		req->rdma_req.imm_data_offset = req->ib_req.imm_data_offset;
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci		ipi = req->rdma_req.initiator_port_id;
85362306a36Sopenharmony_ci		tpi = req->rdma_req.target_port_id;
85462306a36Sopenharmony_ci	} else {
85562306a36Sopenharmony_ci		u8 subnet_timeout;
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci		subnet_timeout = srp_get_subnet_timeout(target->srp_host);
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci		req->ib_param.primary_path = &ch->ib_cm.path;
86062306a36Sopenharmony_ci		req->ib_param.alternate_path = NULL;
86162306a36Sopenharmony_ci		req->ib_param.service_id = target->ib_cm.service_id;
86262306a36Sopenharmony_ci		get_random_bytes(&req->ib_param.starting_psn, 4);
86362306a36Sopenharmony_ci		req->ib_param.starting_psn &= 0xffffff;
86462306a36Sopenharmony_ci		req->ib_param.qp_num = ch->qp->qp_num;
86562306a36Sopenharmony_ci		req->ib_param.qp_type = ch->qp->qp_type;
86662306a36Sopenharmony_ci		req->ib_param.local_cm_response_timeout = subnet_timeout + 2;
86762306a36Sopenharmony_ci		req->ib_param.remote_cm_response_timeout = subnet_timeout + 2;
86862306a36Sopenharmony_ci		req->ib_param.private_data = &req->ib_req;
86962306a36Sopenharmony_ci		req->ib_param.private_data_len = sizeof(req->ib_req);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci		ipi = req->ib_req.initiator_port_id;
87262306a36Sopenharmony_ci		tpi = req->ib_req.target_port_id;
87362306a36Sopenharmony_ci	}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	/*
87662306a36Sopenharmony_ci	 * In the published SRP specification (draft rev. 16a), the
87762306a36Sopenharmony_ci	 * port identifier format is 8 bytes of ID extension followed
87862306a36Sopenharmony_ci	 * by 8 bytes of GUID.  Older drafts put the two halves in the
87962306a36Sopenharmony_ci	 * opposite order, so that the GUID comes first.
88062306a36Sopenharmony_ci	 *
88162306a36Sopenharmony_ci	 * Targets conforming to these obsolete drafts can be
88262306a36Sopenharmony_ci	 * recognized by the I/O Class they report.
88362306a36Sopenharmony_ci	 */
88462306a36Sopenharmony_ci	if (target->io_class == SRP_REV10_IB_IO_CLASS) {
88562306a36Sopenharmony_ci		memcpy(ipi,     &target->sgid.global.interface_id, 8);
88662306a36Sopenharmony_ci		memcpy(ipi + 8, &target->initiator_ext, 8);
88762306a36Sopenharmony_ci		memcpy(tpi,     &target->ioc_guid, 8);
88862306a36Sopenharmony_ci		memcpy(tpi + 8, &target->id_ext, 8);
88962306a36Sopenharmony_ci	} else {
89062306a36Sopenharmony_ci		memcpy(ipi,     &target->initiator_ext, 8);
89162306a36Sopenharmony_ci		memcpy(ipi + 8, &target->sgid.global.interface_id, 8);
89262306a36Sopenharmony_ci		memcpy(tpi,     &target->id_ext, 8);
89362306a36Sopenharmony_ci		memcpy(tpi + 8, &target->ioc_guid, 8);
89462306a36Sopenharmony_ci	}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	/*
89762306a36Sopenharmony_ci	 * Topspin/Cisco SRP targets will reject our login unless we
89862306a36Sopenharmony_ci	 * zero out the first 8 bytes of our initiator port ID and set
89962306a36Sopenharmony_ci	 * the second 8 bytes to the local node GUID.
90062306a36Sopenharmony_ci	 */
90162306a36Sopenharmony_ci	if (srp_target_is_topspin(target)) {
90262306a36Sopenharmony_ci		shost_printk(KERN_DEBUG, target->scsi_host,
90362306a36Sopenharmony_ci			     PFX "Topspin/Cisco initiator port ID workaround "
90462306a36Sopenharmony_ci			     "activated for target GUID %016llx\n",
90562306a36Sopenharmony_ci			     be64_to_cpu(target->ioc_guid));
90662306a36Sopenharmony_ci		memset(ipi, 0, 8);
90762306a36Sopenharmony_ci		memcpy(ipi + 8, &target->srp_host->srp_dev->dev->node_guid, 8);
90862306a36Sopenharmony_ci	}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	if (target->using_rdma_cm)
91162306a36Sopenharmony_ci		status = rdma_connect(ch->rdma_cm.cm_id, &req->rdma_param);
91262306a36Sopenharmony_ci	else
91362306a36Sopenharmony_ci		status = ib_send_cm_req(ch->ib_cm.cm_id, &req->ib_param);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	kfree(req);
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	return status;
91862306a36Sopenharmony_ci}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_cistatic bool srp_queue_remove_work(struct srp_target_port *target)
92162306a36Sopenharmony_ci{
92262306a36Sopenharmony_ci	bool changed = false;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	spin_lock_irq(&target->lock);
92562306a36Sopenharmony_ci	if (target->state != SRP_TARGET_REMOVED) {
92662306a36Sopenharmony_ci		target->state = SRP_TARGET_REMOVED;
92762306a36Sopenharmony_ci		changed = true;
92862306a36Sopenharmony_ci	}
92962306a36Sopenharmony_ci	spin_unlock_irq(&target->lock);
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	if (changed)
93262306a36Sopenharmony_ci		queue_work(srp_remove_wq, &target->remove_work);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	return changed;
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic void srp_disconnect_target(struct srp_target_port *target)
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
94062306a36Sopenharmony_ci	int i, ret;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	/* XXX should send SRP_I_LOGOUT request */
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++) {
94562306a36Sopenharmony_ci		ch = &target->ch[i];
94662306a36Sopenharmony_ci		ch->connected = false;
94762306a36Sopenharmony_ci		ret = 0;
94862306a36Sopenharmony_ci		if (target->using_rdma_cm) {
94962306a36Sopenharmony_ci			if (ch->rdma_cm.cm_id)
95062306a36Sopenharmony_ci				rdma_disconnect(ch->rdma_cm.cm_id);
95162306a36Sopenharmony_ci		} else {
95262306a36Sopenharmony_ci			if (ch->ib_cm.cm_id)
95362306a36Sopenharmony_ci				ret = ib_send_cm_dreq(ch->ib_cm.cm_id,
95462306a36Sopenharmony_ci						      NULL, 0);
95562306a36Sopenharmony_ci		}
95662306a36Sopenharmony_ci		if (ret < 0) {
95762306a36Sopenharmony_ci			shost_printk(KERN_DEBUG, target->scsi_host,
95862306a36Sopenharmony_ci				     PFX "Sending CM DREQ failed\n");
95962306a36Sopenharmony_ci		}
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci}
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_cistatic int srp_exit_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
96462306a36Sopenharmony_ci{
96562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(shost);
96662306a36Sopenharmony_ci	struct srp_device *dev = target->srp_host->srp_dev;
96762306a36Sopenharmony_ci	struct ib_device *ibdev = dev->dev;
96862306a36Sopenharmony_ci	struct srp_request *req = scsi_cmd_priv(cmd);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	kfree(req->fr_list);
97162306a36Sopenharmony_ci	if (req->indirect_dma_addr) {
97262306a36Sopenharmony_ci		ib_dma_unmap_single(ibdev, req->indirect_dma_addr,
97362306a36Sopenharmony_ci				    target->indirect_size,
97462306a36Sopenharmony_ci				    DMA_TO_DEVICE);
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci	kfree(req->indirect_desc);
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	return 0;
97962306a36Sopenharmony_ci}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_cistatic int srp_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
98262306a36Sopenharmony_ci{
98362306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(shost);
98462306a36Sopenharmony_ci	struct srp_device *srp_dev = target->srp_host->srp_dev;
98562306a36Sopenharmony_ci	struct ib_device *ibdev = srp_dev->dev;
98662306a36Sopenharmony_ci	struct srp_request *req = scsi_cmd_priv(cmd);
98762306a36Sopenharmony_ci	dma_addr_t dma_addr;
98862306a36Sopenharmony_ci	int ret = -ENOMEM;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	if (srp_dev->use_fast_reg) {
99162306a36Sopenharmony_ci		req->fr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *),
99262306a36Sopenharmony_ci					GFP_KERNEL);
99362306a36Sopenharmony_ci		if (!req->fr_list)
99462306a36Sopenharmony_ci			goto out;
99562306a36Sopenharmony_ci	}
99662306a36Sopenharmony_ci	req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
99762306a36Sopenharmony_ci	if (!req->indirect_desc)
99862306a36Sopenharmony_ci		goto out;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	dma_addr = ib_dma_map_single(ibdev, req->indirect_desc,
100162306a36Sopenharmony_ci				     target->indirect_size,
100262306a36Sopenharmony_ci				     DMA_TO_DEVICE);
100362306a36Sopenharmony_ci	if (ib_dma_mapping_error(ibdev, dma_addr)) {
100462306a36Sopenharmony_ci		srp_exit_cmd_priv(shost, cmd);
100562306a36Sopenharmony_ci		goto out;
100662306a36Sopenharmony_ci	}
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	req->indirect_dma_addr = dma_addr;
100962306a36Sopenharmony_ci	ret = 0;
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ciout:
101262306a36Sopenharmony_ci	return ret;
101362306a36Sopenharmony_ci}
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci/**
101662306a36Sopenharmony_ci * srp_del_scsi_host_attr() - Remove attributes defined in the host template.
101762306a36Sopenharmony_ci * @shost: SCSI host whose attributes to remove from sysfs.
101862306a36Sopenharmony_ci *
101962306a36Sopenharmony_ci * Note: Any attributes defined in the host template and that did not exist
102062306a36Sopenharmony_ci * before invocation of this function will be ignored.
102162306a36Sopenharmony_ci */
102262306a36Sopenharmony_cistatic void srp_del_scsi_host_attr(struct Scsi_Host *shost)
102362306a36Sopenharmony_ci{
102462306a36Sopenharmony_ci	const struct attribute_group **g;
102562306a36Sopenharmony_ci	struct attribute **attr;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	for (g = shost->hostt->shost_groups; *g; ++g) {
102862306a36Sopenharmony_ci		for (attr = (*g)->attrs; *attr; ++attr) {
102962306a36Sopenharmony_ci			struct device_attribute *dev_attr =
103062306a36Sopenharmony_ci				container_of(*attr, typeof(*dev_attr), attr);
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci			device_remove_file(&shost->shost_dev, dev_attr);
103362306a36Sopenharmony_ci		}
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_cistatic void srp_remove_target(struct srp_target_port *target)
103862306a36Sopenharmony_ci{
103962306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
104062306a36Sopenharmony_ci	int i;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	srp_del_scsi_host_attr(target->scsi_host);
104562306a36Sopenharmony_ci	srp_rport_get(target->rport);
104662306a36Sopenharmony_ci	srp_remove_host(target->scsi_host);
104762306a36Sopenharmony_ci	scsi_remove_host(target->scsi_host);
104862306a36Sopenharmony_ci	srp_stop_rport_timers(target->rport);
104962306a36Sopenharmony_ci	srp_disconnect_target(target);
105062306a36Sopenharmony_ci	kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
105162306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++) {
105262306a36Sopenharmony_ci		ch = &target->ch[i];
105362306a36Sopenharmony_ci		srp_free_ch_ib(target, ch);
105462306a36Sopenharmony_ci	}
105562306a36Sopenharmony_ci	cancel_work_sync(&target->tl_err_work);
105662306a36Sopenharmony_ci	srp_rport_put(target->rport);
105762306a36Sopenharmony_ci	kfree(target->ch);
105862306a36Sopenharmony_ci	target->ch = NULL;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	spin_lock(&target->srp_host->target_lock);
106162306a36Sopenharmony_ci	list_del(&target->list);
106262306a36Sopenharmony_ci	spin_unlock(&target->srp_host->target_lock);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	scsi_host_put(target->scsi_host);
106562306a36Sopenharmony_ci}
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_cistatic void srp_remove_work(struct work_struct *work)
106862306a36Sopenharmony_ci{
106962306a36Sopenharmony_ci	struct srp_target_port *target =
107062306a36Sopenharmony_ci		container_of(work, struct srp_target_port, remove_work);
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	srp_remove_target(target);
107562306a36Sopenharmony_ci}
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_cistatic void srp_rport_delete(struct srp_rport *rport)
107862306a36Sopenharmony_ci{
107962306a36Sopenharmony_ci	struct srp_target_port *target = rport->lld_data;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	srp_queue_remove_work(target);
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci/**
108562306a36Sopenharmony_ci * srp_connected_ch() - number of connected channels
108662306a36Sopenharmony_ci * @target: SRP target port.
108762306a36Sopenharmony_ci */
108862306a36Sopenharmony_cistatic int srp_connected_ch(struct srp_target_port *target)
108962306a36Sopenharmony_ci{
109062306a36Sopenharmony_ci	int i, c = 0;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++)
109362306a36Sopenharmony_ci		c += target->ch[i].connected;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	return c;
109662306a36Sopenharmony_ci}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_cistatic int srp_connect_ch(struct srp_rdma_ch *ch, uint32_t max_iu_len,
109962306a36Sopenharmony_ci			  bool multich)
110062306a36Sopenharmony_ci{
110162306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
110262306a36Sopenharmony_ci	int ret;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0);
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	ret = srp_lookup_path(ch);
110762306a36Sopenharmony_ci	if (ret)
110862306a36Sopenharmony_ci		goto out;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	while (1) {
111162306a36Sopenharmony_ci		init_completion(&ch->done);
111262306a36Sopenharmony_ci		ret = srp_send_req(ch, max_iu_len, multich);
111362306a36Sopenharmony_ci		if (ret)
111462306a36Sopenharmony_ci			goto out;
111562306a36Sopenharmony_ci		ret = wait_for_completion_interruptible(&ch->done);
111662306a36Sopenharmony_ci		if (ret < 0)
111762306a36Sopenharmony_ci			goto out;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci		/*
112062306a36Sopenharmony_ci		 * The CM event handling code will set status to
112162306a36Sopenharmony_ci		 * SRP_PORT_REDIRECT if we get a port redirect REJ
112262306a36Sopenharmony_ci		 * back, or SRP_DLID_REDIRECT if we get a lid/qp
112362306a36Sopenharmony_ci		 * redirect REJ back.
112462306a36Sopenharmony_ci		 */
112562306a36Sopenharmony_ci		ret = ch->status;
112662306a36Sopenharmony_ci		switch (ret) {
112762306a36Sopenharmony_ci		case 0:
112862306a36Sopenharmony_ci			ch->connected = true;
112962306a36Sopenharmony_ci			goto out;
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci		case SRP_PORT_REDIRECT:
113262306a36Sopenharmony_ci			ret = srp_lookup_path(ch);
113362306a36Sopenharmony_ci			if (ret)
113462306a36Sopenharmony_ci				goto out;
113562306a36Sopenharmony_ci			break;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci		case SRP_DLID_REDIRECT:
113862306a36Sopenharmony_ci			break;
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci		case SRP_STALE_CONN:
114162306a36Sopenharmony_ci			shost_printk(KERN_ERR, target->scsi_host, PFX
114262306a36Sopenharmony_ci				     "giving up on stale connection\n");
114362306a36Sopenharmony_ci			ret = -ECONNRESET;
114462306a36Sopenharmony_ci			goto out;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci		default:
114762306a36Sopenharmony_ci			goto out;
114862306a36Sopenharmony_ci		}
114962306a36Sopenharmony_ci	}
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ciout:
115262306a36Sopenharmony_ci	return ret <= 0 ? ret : -ENODEV;
115362306a36Sopenharmony_ci}
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_cistatic void srp_inv_rkey_err_done(struct ib_cq *cq, struct ib_wc *wc)
115662306a36Sopenharmony_ci{
115762306a36Sopenharmony_ci	srp_handle_qp_err(cq, wc, "INV RKEY");
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_cistatic int srp_inv_rkey(struct srp_request *req, struct srp_rdma_ch *ch,
116162306a36Sopenharmony_ci		u32 rkey)
116262306a36Sopenharmony_ci{
116362306a36Sopenharmony_ci	struct ib_send_wr wr = {
116462306a36Sopenharmony_ci		.opcode		    = IB_WR_LOCAL_INV,
116562306a36Sopenharmony_ci		.next		    = NULL,
116662306a36Sopenharmony_ci		.num_sge	    = 0,
116762306a36Sopenharmony_ci		.send_flags	    = 0,
116862306a36Sopenharmony_ci		.ex.invalidate_rkey = rkey,
116962306a36Sopenharmony_ci	};
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	wr.wr_cqe = &req->reg_cqe;
117262306a36Sopenharmony_ci	req->reg_cqe.done = srp_inv_rkey_err_done;
117362306a36Sopenharmony_ci	return ib_post_send(ch->qp, &wr, NULL);
117462306a36Sopenharmony_ci}
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_cistatic void srp_unmap_data(struct scsi_cmnd *scmnd,
117762306a36Sopenharmony_ci			   struct srp_rdma_ch *ch,
117862306a36Sopenharmony_ci			   struct srp_request *req)
117962306a36Sopenharmony_ci{
118062306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
118162306a36Sopenharmony_ci	struct srp_device *dev = target->srp_host->srp_dev;
118262306a36Sopenharmony_ci	struct ib_device *ibdev = dev->dev;
118362306a36Sopenharmony_ci	int i, res;
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	if (!scsi_sglist(scmnd) ||
118662306a36Sopenharmony_ci	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
118762306a36Sopenharmony_ci	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
118862306a36Sopenharmony_ci		return;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	if (dev->use_fast_reg) {
119162306a36Sopenharmony_ci		struct srp_fr_desc **pfr;
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci		for (i = req->nmdesc, pfr = req->fr_list; i > 0; i--, pfr++) {
119462306a36Sopenharmony_ci			res = srp_inv_rkey(req, ch, (*pfr)->mr->rkey);
119562306a36Sopenharmony_ci			if (res < 0) {
119662306a36Sopenharmony_ci				shost_printk(KERN_ERR, target->scsi_host, PFX
119762306a36Sopenharmony_ci				  "Queueing INV WR for rkey %#x failed (%d)\n",
119862306a36Sopenharmony_ci				  (*pfr)->mr->rkey, res);
119962306a36Sopenharmony_ci				queue_work(system_long_wq,
120062306a36Sopenharmony_ci					   &target->tl_err_work);
120162306a36Sopenharmony_ci			}
120262306a36Sopenharmony_ci		}
120362306a36Sopenharmony_ci		if (req->nmdesc)
120462306a36Sopenharmony_ci			srp_fr_pool_put(ch->fr_pool, req->fr_list,
120562306a36Sopenharmony_ci					req->nmdesc);
120662306a36Sopenharmony_ci	}
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	ib_dma_unmap_sg(ibdev, scsi_sglist(scmnd), scsi_sg_count(scmnd),
120962306a36Sopenharmony_ci			scmnd->sc_data_direction);
121062306a36Sopenharmony_ci}
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci/**
121362306a36Sopenharmony_ci * srp_claim_req - Take ownership of the scmnd associated with a request.
121462306a36Sopenharmony_ci * @ch: SRP RDMA channel.
121562306a36Sopenharmony_ci * @req: SRP request.
121662306a36Sopenharmony_ci * @sdev: If not NULL, only take ownership for this SCSI device.
121762306a36Sopenharmony_ci * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
121862306a36Sopenharmony_ci *         ownership of @req->scmnd if it equals @scmnd.
121962306a36Sopenharmony_ci *
122062306a36Sopenharmony_ci * Return value:
122162306a36Sopenharmony_ci * Either NULL or a pointer to the SCSI command the caller became owner of.
122262306a36Sopenharmony_ci */
122362306a36Sopenharmony_cistatic struct scsi_cmnd *srp_claim_req(struct srp_rdma_ch *ch,
122462306a36Sopenharmony_ci				       struct srp_request *req,
122562306a36Sopenharmony_ci				       struct scsi_device *sdev,
122662306a36Sopenharmony_ci				       struct scsi_cmnd *scmnd)
122762306a36Sopenharmony_ci{
122862306a36Sopenharmony_ci	unsigned long flags;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	spin_lock_irqsave(&ch->lock, flags);
123162306a36Sopenharmony_ci	if (req->scmnd &&
123262306a36Sopenharmony_ci	    (!sdev || req->scmnd->device == sdev) &&
123362306a36Sopenharmony_ci	    (!scmnd || req->scmnd == scmnd)) {
123462306a36Sopenharmony_ci		scmnd = req->scmnd;
123562306a36Sopenharmony_ci		req->scmnd = NULL;
123662306a36Sopenharmony_ci	} else {
123762306a36Sopenharmony_ci		scmnd = NULL;
123862306a36Sopenharmony_ci	}
123962306a36Sopenharmony_ci	spin_unlock_irqrestore(&ch->lock, flags);
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	return scmnd;
124262306a36Sopenharmony_ci}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci/**
124562306a36Sopenharmony_ci * srp_free_req() - Unmap data and adjust ch->req_lim.
124662306a36Sopenharmony_ci * @ch:     SRP RDMA channel.
124762306a36Sopenharmony_ci * @req:    Request to be freed.
124862306a36Sopenharmony_ci * @scmnd:  SCSI command associated with @req.
124962306a36Sopenharmony_ci * @req_lim_delta: Amount to be added to @target->req_lim.
125062306a36Sopenharmony_ci */
125162306a36Sopenharmony_cistatic void srp_free_req(struct srp_rdma_ch *ch, struct srp_request *req,
125262306a36Sopenharmony_ci			 struct scsi_cmnd *scmnd, s32 req_lim_delta)
125362306a36Sopenharmony_ci{
125462306a36Sopenharmony_ci	unsigned long flags;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	srp_unmap_data(scmnd, ch, req);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	spin_lock_irqsave(&ch->lock, flags);
125962306a36Sopenharmony_ci	ch->req_lim += req_lim_delta;
126062306a36Sopenharmony_ci	spin_unlock_irqrestore(&ch->lock, flags);
126162306a36Sopenharmony_ci}
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_cistatic void srp_finish_req(struct srp_rdma_ch *ch, struct srp_request *req,
126462306a36Sopenharmony_ci			   struct scsi_device *sdev, int result)
126562306a36Sopenharmony_ci{
126662306a36Sopenharmony_ci	struct scsi_cmnd *scmnd = srp_claim_req(ch, req, sdev, NULL);
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	if (scmnd) {
126962306a36Sopenharmony_ci		srp_free_req(ch, req, scmnd, 0);
127062306a36Sopenharmony_ci		scmnd->result = result;
127162306a36Sopenharmony_ci		scsi_done(scmnd);
127262306a36Sopenharmony_ci	}
127362306a36Sopenharmony_ci}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_cistruct srp_terminate_context {
127662306a36Sopenharmony_ci	struct srp_target_port *srp_target;
127762306a36Sopenharmony_ci	int scsi_result;
127862306a36Sopenharmony_ci};
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_cistatic bool srp_terminate_cmd(struct scsi_cmnd *scmnd, void *context_ptr)
128162306a36Sopenharmony_ci{
128262306a36Sopenharmony_ci	struct srp_terminate_context *context = context_ptr;
128362306a36Sopenharmony_ci	struct srp_target_port *target = context->srp_target;
128462306a36Sopenharmony_ci	u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmnd));
128562306a36Sopenharmony_ci	struct srp_rdma_ch *ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
128662306a36Sopenharmony_ci	struct srp_request *req = scsi_cmd_priv(scmnd);
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	srp_finish_req(ch, req, NULL, context->scsi_result);
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	return true;
129162306a36Sopenharmony_ci}
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_cistatic void srp_terminate_io(struct srp_rport *rport)
129462306a36Sopenharmony_ci{
129562306a36Sopenharmony_ci	struct srp_target_port *target = rport->lld_data;
129662306a36Sopenharmony_ci	struct srp_terminate_context context = { .srp_target = target,
129762306a36Sopenharmony_ci		.scsi_result = DID_TRANSPORT_FAILFAST << 16 };
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	scsi_host_busy_iter(target->scsi_host, srp_terminate_cmd, &context);
130062306a36Sopenharmony_ci}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci/* Calculate maximum initiator to target information unit length. */
130362306a36Sopenharmony_cistatic uint32_t srp_max_it_iu_len(int cmd_sg_cnt, bool use_imm_data,
130462306a36Sopenharmony_ci				  uint32_t max_it_iu_size)
130562306a36Sopenharmony_ci{
130662306a36Sopenharmony_ci	uint32_t max_iu_len = sizeof(struct srp_cmd) + SRP_MAX_ADD_CDB_LEN +
130762306a36Sopenharmony_ci		sizeof(struct srp_indirect_buf) +
130862306a36Sopenharmony_ci		cmd_sg_cnt * sizeof(struct srp_direct_buf);
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci	if (use_imm_data)
131162306a36Sopenharmony_ci		max_iu_len = max(max_iu_len, SRP_IMM_DATA_OFFSET +
131262306a36Sopenharmony_ci				 srp_max_imm_data);
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	if (max_it_iu_size)
131562306a36Sopenharmony_ci		max_iu_len = min(max_iu_len, max_it_iu_size);
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	pr_debug("max_iu_len = %d\n", max_iu_len);
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	return max_iu_len;
132062306a36Sopenharmony_ci}
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci/*
132362306a36Sopenharmony_ci * It is up to the caller to ensure that srp_rport_reconnect() calls are
132462306a36Sopenharmony_ci * serialized and that no concurrent srp_queuecommand(), srp_abort(),
132562306a36Sopenharmony_ci * srp_reset_device() or srp_reset_host() calls will occur while this function
132662306a36Sopenharmony_ci * is in progress. One way to realize that is not to call this function
132762306a36Sopenharmony_ci * directly but to call srp_reconnect_rport() instead since that last function
132862306a36Sopenharmony_ci * serializes calls of this function via rport->mutex and also blocks
132962306a36Sopenharmony_ci * srp_queuecommand() calls before invoking this function.
133062306a36Sopenharmony_ci */
133162306a36Sopenharmony_cistatic int srp_rport_reconnect(struct srp_rport *rport)
133262306a36Sopenharmony_ci{
133362306a36Sopenharmony_ci	struct srp_target_port *target = rport->lld_data;
133462306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
133562306a36Sopenharmony_ci	uint32_t max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
133662306a36Sopenharmony_ci						srp_use_imm_data,
133762306a36Sopenharmony_ci						target->max_it_iu_size);
133862306a36Sopenharmony_ci	int i, j, ret = 0;
133962306a36Sopenharmony_ci	bool multich = false;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	srp_disconnect_target(target);
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	if (target->state == SRP_TARGET_SCANNING)
134462306a36Sopenharmony_ci		return -ENODEV;
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	/*
134762306a36Sopenharmony_ci	 * Now get a new local CM ID so that we avoid confusing the target in
134862306a36Sopenharmony_ci	 * case things are really fouled up. Doing so also ensures that all CM
134962306a36Sopenharmony_ci	 * callbacks will have finished before a new QP is allocated.
135062306a36Sopenharmony_ci	 */
135162306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++) {
135262306a36Sopenharmony_ci		ch = &target->ch[i];
135362306a36Sopenharmony_ci		ret += srp_new_cm_id(ch);
135462306a36Sopenharmony_ci	}
135562306a36Sopenharmony_ci	{
135662306a36Sopenharmony_ci		struct srp_terminate_context context = {
135762306a36Sopenharmony_ci			.srp_target = target, .scsi_result = DID_RESET << 16};
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci		scsi_host_busy_iter(target->scsi_host, srp_terminate_cmd,
136062306a36Sopenharmony_ci				    &context);
136162306a36Sopenharmony_ci	}
136262306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++) {
136362306a36Sopenharmony_ci		ch = &target->ch[i];
136462306a36Sopenharmony_ci		/*
136562306a36Sopenharmony_ci		 * Whether or not creating a new CM ID succeeded, create a new
136662306a36Sopenharmony_ci		 * QP. This guarantees that all completion callback function
136762306a36Sopenharmony_ci		 * invocations have finished before request resetting starts.
136862306a36Sopenharmony_ci		 */
136962306a36Sopenharmony_ci		ret += srp_create_ch_ib(ch);
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci		INIT_LIST_HEAD(&ch->free_tx);
137262306a36Sopenharmony_ci		for (j = 0; j < target->queue_size; ++j)
137362306a36Sopenharmony_ci			list_add(&ch->tx_ring[j]->list, &ch->free_tx);
137462306a36Sopenharmony_ci	}
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci	target->qp_in_error = false;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++) {
137962306a36Sopenharmony_ci		ch = &target->ch[i];
138062306a36Sopenharmony_ci		if (ret)
138162306a36Sopenharmony_ci			break;
138262306a36Sopenharmony_ci		ret = srp_connect_ch(ch, max_iu_len, multich);
138362306a36Sopenharmony_ci		multich = true;
138462306a36Sopenharmony_ci	}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	if (ret == 0)
138762306a36Sopenharmony_ci		shost_printk(KERN_INFO, target->scsi_host,
138862306a36Sopenharmony_ci			     PFX "reconnect succeeded\n");
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	return ret;
139162306a36Sopenharmony_ci}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_cistatic void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr,
139462306a36Sopenharmony_ci			 unsigned int dma_len, u32 rkey)
139562306a36Sopenharmony_ci{
139662306a36Sopenharmony_ci	struct srp_direct_buf *desc = state->desc;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	WARN_ON_ONCE(!dma_len);
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	desc->va = cpu_to_be64(dma_addr);
140162306a36Sopenharmony_ci	desc->key = cpu_to_be32(rkey);
140262306a36Sopenharmony_ci	desc->len = cpu_to_be32(dma_len);
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	state->total_len += dma_len;
140562306a36Sopenharmony_ci	state->desc++;
140662306a36Sopenharmony_ci	state->ndesc++;
140762306a36Sopenharmony_ci}
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_cistatic void srp_reg_mr_err_done(struct ib_cq *cq, struct ib_wc *wc)
141062306a36Sopenharmony_ci{
141162306a36Sopenharmony_ci	srp_handle_qp_err(cq, wc, "FAST REG");
141262306a36Sopenharmony_ci}
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci/*
141562306a36Sopenharmony_ci * Map up to sg_nents elements of state->sg where *sg_offset_p is the offset
141662306a36Sopenharmony_ci * where to start in the first element. If sg_offset_p != NULL then
141762306a36Sopenharmony_ci * *sg_offset_p is updated to the offset in state->sg[retval] of the first
141862306a36Sopenharmony_ci * byte that has not yet been mapped.
141962306a36Sopenharmony_ci */
142062306a36Sopenharmony_cistatic int srp_map_finish_fr(struct srp_map_state *state,
142162306a36Sopenharmony_ci			     struct srp_request *req,
142262306a36Sopenharmony_ci			     struct srp_rdma_ch *ch, int sg_nents,
142362306a36Sopenharmony_ci			     unsigned int *sg_offset_p)
142462306a36Sopenharmony_ci{
142562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
142662306a36Sopenharmony_ci	struct srp_device *dev = target->srp_host->srp_dev;
142762306a36Sopenharmony_ci	struct ib_reg_wr wr;
142862306a36Sopenharmony_ci	struct srp_fr_desc *desc;
142962306a36Sopenharmony_ci	u32 rkey;
143062306a36Sopenharmony_ci	int n, err;
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	if (state->fr.next >= state->fr.end) {
143362306a36Sopenharmony_ci		shost_printk(KERN_ERR, ch->target->scsi_host,
143462306a36Sopenharmony_ci			     PFX "Out of MRs (mr_per_cmd = %d)\n",
143562306a36Sopenharmony_ci			     ch->target->mr_per_cmd);
143662306a36Sopenharmony_ci		return -ENOMEM;
143762306a36Sopenharmony_ci	}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	WARN_ON_ONCE(!dev->use_fast_reg);
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	if (sg_nents == 1 && target->global_rkey) {
144262306a36Sopenharmony_ci		unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci		srp_map_desc(state, sg_dma_address(state->sg) + sg_offset,
144562306a36Sopenharmony_ci			     sg_dma_len(state->sg) - sg_offset,
144662306a36Sopenharmony_ci			     target->global_rkey);
144762306a36Sopenharmony_ci		if (sg_offset_p)
144862306a36Sopenharmony_ci			*sg_offset_p = 0;
144962306a36Sopenharmony_ci		return 1;
145062306a36Sopenharmony_ci	}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci	desc = srp_fr_pool_get(ch->fr_pool);
145362306a36Sopenharmony_ci	if (!desc)
145462306a36Sopenharmony_ci		return -ENOMEM;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	rkey = ib_inc_rkey(desc->mr->rkey);
145762306a36Sopenharmony_ci	ib_update_fast_reg_key(desc->mr, rkey);
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci	n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, sg_offset_p,
146062306a36Sopenharmony_ci			 dev->mr_page_size);
146162306a36Sopenharmony_ci	if (unlikely(n < 0)) {
146262306a36Sopenharmony_ci		srp_fr_pool_put(ch->fr_pool, &desc, 1);
146362306a36Sopenharmony_ci		pr_debug("%s: ib_map_mr_sg(%d, %d) returned %d.\n",
146462306a36Sopenharmony_ci			 dev_name(&req->scmnd->device->sdev_gendev), sg_nents,
146562306a36Sopenharmony_ci			 sg_offset_p ? *sg_offset_p : -1, n);
146662306a36Sopenharmony_ci		return n;
146762306a36Sopenharmony_ci	}
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	WARN_ON_ONCE(desc->mr->length == 0);
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	req->reg_cqe.done = srp_reg_mr_err_done;
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	wr.wr.next = NULL;
147462306a36Sopenharmony_ci	wr.wr.opcode = IB_WR_REG_MR;
147562306a36Sopenharmony_ci	wr.wr.wr_cqe = &req->reg_cqe;
147662306a36Sopenharmony_ci	wr.wr.num_sge = 0;
147762306a36Sopenharmony_ci	wr.wr.send_flags = 0;
147862306a36Sopenharmony_ci	wr.mr = desc->mr;
147962306a36Sopenharmony_ci	wr.key = desc->mr->rkey;
148062306a36Sopenharmony_ci	wr.access = (IB_ACCESS_LOCAL_WRITE |
148162306a36Sopenharmony_ci		     IB_ACCESS_REMOTE_READ |
148262306a36Sopenharmony_ci		     IB_ACCESS_REMOTE_WRITE);
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	*state->fr.next++ = desc;
148562306a36Sopenharmony_ci	state->nmdesc++;
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	srp_map_desc(state, desc->mr->iova,
148862306a36Sopenharmony_ci		     desc->mr->length, desc->mr->rkey);
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	err = ib_post_send(ch->qp, &wr.wr, NULL);
149162306a36Sopenharmony_ci	if (unlikely(err)) {
149262306a36Sopenharmony_ci		WARN_ON_ONCE(err == -ENOMEM);
149362306a36Sopenharmony_ci		return err;
149462306a36Sopenharmony_ci	}
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	return n;
149762306a36Sopenharmony_ci}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_cistatic int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
150062306a36Sopenharmony_ci			 struct srp_request *req, struct scatterlist *scat,
150162306a36Sopenharmony_ci			 int count)
150262306a36Sopenharmony_ci{
150362306a36Sopenharmony_ci	unsigned int sg_offset = 0;
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	state->fr.next = req->fr_list;
150662306a36Sopenharmony_ci	state->fr.end = req->fr_list + ch->target->mr_per_cmd;
150762306a36Sopenharmony_ci	state->sg = scat;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	if (count == 0)
151062306a36Sopenharmony_ci		return 0;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	while (count) {
151362306a36Sopenharmony_ci		int i, n;
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci		n = srp_map_finish_fr(state, req, ch, count, &sg_offset);
151662306a36Sopenharmony_ci		if (unlikely(n < 0))
151762306a36Sopenharmony_ci			return n;
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci		count -= n;
152062306a36Sopenharmony_ci		for (i = 0; i < n; i++)
152162306a36Sopenharmony_ci			state->sg = sg_next(state->sg);
152262306a36Sopenharmony_ci	}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	return 0;
152562306a36Sopenharmony_ci}
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_cistatic int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
152862306a36Sopenharmony_ci			  struct srp_request *req, struct scatterlist *scat,
152962306a36Sopenharmony_ci			  int count)
153062306a36Sopenharmony_ci{
153162306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
153262306a36Sopenharmony_ci	struct scatterlist *sg;
153362306a36Sopenharmony_ci	int i;
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	for_each_sg(scat, sg, count, i) {
153662306a36Sopenharmony_ci		srp_map_desc(state, sg_dma_address(sg), sg_dma_len(sg),
153762306a36Sopenharmony_ci			     target->global_rkey);
153862306a36Sopenharmony_ci	}
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	return 0;
154162306a36Sopenharmony_ci}
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci/*
154462306a36Sopenharmony_ci * Register the indirect data buffer descriptor with the HCA.
154562306a36Sopenharmony_ci *
154662306a36Sopenharmony_ci * Note: since the indirect data buffer descriptor has been allocated with
154762306a36Sopenharmony_ci * kmalloc() it is guaranteed that this buffer is a physically contiguous
154862306a36Sopenharmony_ci * memory buffer.
154962306a36Sopenharmony_ci */
155062306a36Sopenharmony_cistatic int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
155162306a36Sopenharmony_ci		       void **next_mr, void **end_mr, u32 idb_len,
155262306a36Sopenharmony_ci		       __be32 *idb_rkey)
155362306a36Sopenharmony_ci{
155462306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
155562306a36Sopenharmony_ci	struct srp_device *dev = target->srp_host->srp_dev;
155662306a36Sopenharmony_ci	struct srp_map_state state;
155762306a36Sopenharmony_ci	struct srp_direct_buf idb_desc;
155862306a36Sopenharmony_ci	struct scatterlist idb_sg[1];
155962306a36Sopenharmony_ci	int ret;
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	memset(&state, 0, sizeof(state));
156262306a36Sopenharmony_ci	memset(&idb_desc, 0, sizeof(idb_desc));
156362306a36Sopenharmony_ci	state.gen.next = next_mr;
156462306a36Sopenharmony_ci	state.gen.end = end_mr;
156562306a36Sopenharmony_ci	state.desc = &idb_desc;
156662306a36Sopenharmony_ci	state.base_dma_addr = req->indirect_dma_addr;
156762306a36Sopenharmony_ci	state.dma_len = idb_len;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	if (dev->use_fast_reg) {
157062306a36Sopenharmony_ci		state.sg = idb_sg;
157162306a36Sopenharmony_ci		sg_init_one(idb_sg, req->indirect_desc, idb_len);
157262306a36Sopenharmony_ci		idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
157362306a36Sopenharmony_ci#ifdef CONFIG_NEED_SG_DMA_LENGTH
157462306a36Sopenharmony_ci		idb_sg->dma_length = idb_sg->length;	      /* hack^2 */
157562306a36Sopenharmony_ci#endif
157662306a36Sopenharmony_ci		ret = srp_map_finish_fr(&state, req, ch, 1, NULL);
157762306a36Sopenharmony_ci		if (ret < 0)
157862306a36Sopenharmony_ci			return ret;
157962306a36Sopenharmony_ci		WARN_ON_ONCE(ret < 1);
158062306a36Sopenharmony_ci	} else {
158162306a36Sopenharmony_ci		return -EINVAL;
158262306a36Sopenharmony_ci	}
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	*idb_rkey = idb_desc.key;
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	return 0;
158762306a36Sopenharmony_ci}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_cistatic void srp_check_mapping(struct srp_map_state *state,
159062306a36Sopenharmony_ci			      struct srp_rdma_ch *ch, struct srp_request *req,
159162306a36Sopenharmony_ci			      struct scatterlist *scat, int count)
159262306a36Sopenharmony_ci{
159362306a36Sopenharmony_ci	struct srp_device *dev = ch->target->srp_host->srp_dev;
159462306a36Sopenharmony_ci	struct srp_fr_desc **pfr;
159562306a36Sopenharmony_ci	u64 desc_len = 0, mr_len = 0;
159662306a36Sopenharmony_ci	int i;
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	for (i = 0; i < state->ndesc; i++)
159962306a36Sopenharmony_ci		desc_len += be32_to_cpu(req->indirect_desc[i].len);
160062306a36Sopenharmony_ci	if (dev->use_fast_reg)
160162306a36Sopenharmony_ci		for (i = 0, pfr = req->fr_list; i < state->nmdesc; i++, pfr++)
160262306a36Sopenharmony_ci			mr_len += (*pfr)->mr->length;
160362306a36Sopenharmony_ci	if (desc_len != scsi_bufflen(req->scmnd) ||
160462306a36Sopenharmony_ci	    mr_len > scsi_bufflen(req->scmnd))
160562306a36Sopenharmony_ci		pr_err("Inconsistent: scsi len %d <> desc len %lld <> mr len %lld; ndesc %d; nmdesc = %d\n",
160662306a36Sopenharmony_ci		       scsi_bufflen(req->scmnd), desc_len, mr_len,
160762306a36Sopenharmony_ci		       state->ndesc, state->nmdesc);
160862306a36Sopenharmony_ci}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci/**
161162306a36Sopenharmony_ci * srp_map_data() - map SCSI data buffer onto an SRP request
161262306a36Sopenharmony_ci * @scmnd: SCSI command to map
161362306a36Sopenharmony_ci * @ch: SRP RDMA channel
161462306a36Sopenharmony_ci * @req: SRP request
161562306a36Sopenharmony_ci *
161662306a36Sopenharmony_ci * Returns the length in bytes of the SRP_CMD IU or a negative value if
161762306a36Sopenharmony_ci * mapping failed. The size of any immediate data is not included in the
161862306a36Sopenharmony_ci * return value.
161962306a36Sopenharmony_ci */
162062306a36Sopenharmony_cistatic int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
162162306a36Sopenharmony_ci			struct srp_request *req)
162262306a36Sopenharmony_ci{
162362306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
162462306a36Sopenharmony_ci	struct scatterlist *scat, *sg;
162562306a36Sopenharmony_ci	struct srp_cmd *cmd = req->cmd->buf;
162662306a36Sopenharmony_ci	int i, len, nents, count, ret;
162762306a36Sopenharmony_ci	struct srp_device *dev;
162862306a36Sopenharmony_ci	struct ib_device *ibdev;
162962306a36Sopenharmony_ci	struct srp_map_state state;
163062306a36Sopenharmony_ci	struct srp_indirect_buf *indirect_hdr;
163162306a36Sopenharmony_ci	u64 data_len;
163262306a36Sopenharmony_ci	u32 idb_len, table_len;
163362306a36Sopenharmony_ci	__be32 idb_rkey;
163462306a36Sopenharmony_ci	u8 fmt;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	req->cmd->num_sge = 1;
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
163962306a36Sopenharmony_ci		return sizeof(struct srp_cmd) + cmd->add_cdb_len;
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
164262306a36Sopenharmony_ci	    scmnd->sc_data_direction != DMA_TO_DEVICE) {
164362306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
164462306a36Sopenharmony_ci			     PFX "Unhandled data direction %d\n",
164562306a36Sopenharmony_ci			     scmnd->sc_data_direction);
164662306a36Sopenharmony_ci		return -EINVAL;
164762306a36Sopenharmony_ci	}
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	nents = scsi_sg_count(scmnd);
165062306a36Sopenharmony_ci	scat  = scsi_sglist(scmnd);
165162306a36Sopenharmony_ci	data_len = scsi_bufflen(scmnd);
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	dev = target->srp_host->srp_dev;
165462306a36Sopenharmony_ci	ibdev = dev->dev;
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
165762306a36Sopenharmony_ci	if (unlikely(count == 0))
165862306a36Sopenharmony_ci		return -EIO;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	if (ch->use_imm_data &&
166162306a36Sopenharmony_ci	    count <= ch->max_imm_sge &&
166262306a36Sopenharmony_ci	    SRP_IMM_DATA_OFFSET + data_len <= ch->max_it_iu_len &&
166362306a36Sopenharmony_ci	    scmnd->sc_data_direction == DMA_TO_DEVICE) {
166462306a36Sopenharmony_ci		struct srp_imm_buf *buf;
166562306a36Sopenharmony_ci		struct ib_sge *sge = &req->cmd->sge[1];
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci		fmt = SRP_DATA_DESC_IMM;
166862306a36Sopenharmony_ci		len = SRP_IMM_DATA_OFFSET;
166962306a36Sopenharmony_ci		req->nmdesc = 0;
167062306a36Sopenharmony_ci		buf = (void *)cmd->add_data + cmd->add_cdb_len;
167162306a36Sopenharmony_ci		buf->len = cpu_to_be32(data_len);
167262306a36Sopenharmony_ci		WARN_ON_ONCE((void *)(buf + 1) > (void *)cmd + len);
167362306a36Sopenharmony_ci		for_each_sg(scat, sg, count, i) {
167462306a36Sopenharmony_ci			sge[i].addr   = sg_dma_address(sg);
167562306a36Sopenharmony_ci			sge[i].length = sg_dma_len(sg);
167662306a36Sopenharmony_ci			sge[i].lkey   = target->lkey;
167762306a36Sopenharmony_ci		}
167862306a36Sopenharmony_ci		req->cmd->num_sge += count;
167962306a36Sopenharmony_ci		goto map_complete;
168062306a36Sopenharmony_ci	}
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	fmt = SRP_DATA_DESC_DIRECT;
168362306a36Sopenharmony_ci	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
168462306a36Sopenharmony_ci		sizeof(struct srp_direct_buf);
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	if (count == 1 && target->global_rkey) {
168762306a36Sopenharmony_ci		/*
168862306a36Sopenharmony_ci		 * The midlayer only generated a single gather/scatter
168962306a36Sopenharmony_ci		 * entry, or DMA mapping coalesced everything to a
169062306a36Sopenharmony_ci		 * single entry.  So a direct descriptor along with
169162306a36Sopenharmony_ci		 * the DMA MR suffices.
169262306a36Sopenharmony_ci		 */
169362306a36Sopenharmony_ci		struct srp_direct_buf *buf;
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci		buf = (void *)cmd->add_data + cmd->add_cdb_len;
169662306a36Sopenharmony_ci		buf->va  = cpu_to_be64(sg_dma_address(scat));
169762306a36Sopenharmony_ci		buf->key = cpu_to_be32(target->global_rkey);
169862306a36Sopenharmony_ci		buf->len = cpu_to_be32(sg_dma_len(scat));
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci		req->nmdesc = 0;
170162306a36Sopenharmony_ci		goto map_complete;
170262306a36Sopenharmony_ci	}
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci	/*
170562306a36Sopenharmony_ci	 * We have more than one scatter/gather entry, so build our indirect
170662306a36Sopenharmony_ci	 * descriptor table, trying to merge as many entries as we can.
170762306a36Sopenharmony_ci	 */
170862306a36Sopenharmony_ci	indirect_hdr = (void *)cmd->add_data + cmd->add_cdb_len;
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
171162306a36Sopenharmony_ci				   target->indirect_size, DMA_TO_DEVICE);
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	memset(&state, 0, sizeof(state));
171462306a36Sopenharmony_ci	state.desc = req->indirect_desc;
171562306a36Sopenharmony_ci	if (dev->use_fast_reg)
171662306a36Sopenharmony_ci		ret = srp_map_sg_fr(&state, ch, req, scat, count);
171762306a36Sopenharmony_ci	else
171862306a36Sopenharmony_ci		ret = srp_map_sg_dma(&state, ch, req, scat, count);
171962306a36Sopenharmony_ci	req->nmdesc = state.nmdesc;
172062306a36Sopenharmony_ci	if (ret < 0)
172162306a36Sopenharmony_ci		goto unmap;
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	{
172462306a36Sopenharmony_ci		DEFINE_DYNAMIC_DEBUG_METADATA(ddm,
172562306a36Sopenharmony_ci			"Memory mapping consistency check");
172662306a36Sopenharmony_ci		if (DYNAMIC_DEBUG_BRANCH(ddm))
172762306a36Sopenharmony_ci			srp_check_mapping(&state, ch, req, scat, count);
172862306a36Sopenharmony_ci	}
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	/* We've mapped the request, now pull as much of the indirect
173162306a36Sopenharmony_ci	 * descriptor table as we can into the command buffer. If this
173262306a36Sopenharmony_ci	 * target is not using an external indirect table, we are
173362306a36Sopenharmony_ci	 * guaranteed to fit into the command, as the SCSI layer won't
173462306a36Sopenharmony_ci	 * give us more S/G entries than we allow.
173562306a36Sopenharmony_ci	 */
173662306a36Sopenharmony_ci	if (state.ndesc == 1) {
173762306a36Sopenharmony_ci		/*
173862306a36Sopenharmony_ci		 * Memory registration collapsed the sg-list into one entry,
173962306a36Sopenharmony_ci		 * so use a direct descriptor.
174062306a36Sopenharmony_ci		 */
174162306a36Sopenharmony_ci		struct srp_direct_buf *buf;
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci		buf = (void *)cmd->add_data + cmd->add_cdb_len;
174462306a36Sopenharmony_ci		*buf = req->indirect_desc[0];
174562306a36Sopenharmony_ci		goto map_complete;
174662306a36Sopenharmony_ci	}
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_ci	if (unlikely(target->cmd_sg_cnt < state.ndesc &&
174962306a36Sopenharmony_ci						!target->allow_ext_sg)) {
175062306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
175162306a36Sopenharmony_ci			     "Could not fit S/G list into SRP_CMD\n");
175262306a36Sopenharmony_ci		ret = -EIO;
175362306a36Sopenharmony_ci		goto unmap;
175462306a36Sopenharmony_ci	}
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	count = min(state.ndesc, target->cmd_sg_cnt);
175762306a36Sopenharmony_ci	table_len = state.ndesc * sizeof (struct srp_direct_buf);
175862306a36Sopenharmony_ci	idb_len = sizeof(struct srp_indirect_buf) + table_len;
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	fmt = SRP_DATA_DESC_INDIRECT;
176162306a36Sopenharmony_ci	len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
176262306a36Sopenharmony_ci		sizeof(struct srp_indirect_buf);
176362306a36Sopenharmony_ci	len += count * sizeof (struct srp_direct_buf);
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	memcpy(indirect_hdr->desc_list, req->indirect_desc,
176662306a36Sopenharmony_ci	       count * sizeof (struct srp_direct_buf));
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci	if (!target->global_rkey) {
176962306a36Sopenharmony_ci		ret = srp_map_idb(ch, req, state.gen.next, state.gen.end,
177062306a36Sopenharmony_ci				  idb_len, &idb_rkey);
177162306a36Sopenharmony_ci		if (ret < 0)
177262306a36Sopenharmony_ci			goto unmap;
177362306a36Sopenharmony_ci		req->nmdesc++;
177462306a36Sopenharmony_ci	} else {
177562306a36Sopenharmony_ci		idb_rkey = cpu_to_be32(target->global_rkey);
177662306a36Sopenharmony_ci	}
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
177962306a36Sopenharmony_ci	indirect_hdr->table_desc.key = idb_rkey;
178062306a36Sopenharmony_ci	indirect_hdr->table_desc.len = cpu_to_be32(table_len);
178162306a36Sopenharmony_ci	indirect_hdr->len = cpu_to_be32(state.total_len);
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
178462306a36Sopenharmony_ci		cmd->data_out_desc_cnt = count;
178562306a36Sopenharmony_ci	else
178662306a36Sopenharmony_ci		cmd->data_in_desc_cnt = count;
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	ib_dma_sync_single_for_device(ibdev, req->indirect_dma_addr, table_len,
178962306a36Sopenharmony_ci				      DMA_TO_DEVICE);
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_cimap_complete:
179262306a36Sopenharmony_ci	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
179362306a36Sopenharmony_ci		cmd->buf_fmt = fmt << 4;
179462306a36Sopenharmony_ci	else
179562306a36Sopenharmony_ci		cmd->buf_fmt = fmt;
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	return len;
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ciunmap:
180062306a36Sopenharmony_ci	srp_unmap_data(scmnd, ch, req);
180162306a36Sopenharmony_ci	if (ret == -ENOMEM && req->nmdesc >= target->mr_pool_size)
180262306a36Sopenharmony_ci		ret = -E2BIG;
180362306a36Sopenharmony_ci	return ret;
180462306a36Sopenharmony_ci}
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci/*
180762306a36Sopenharmony_ci * Return an IU and possible credit to the free pool
180862306a36Sopenharmony_ci */
180962306a36Sopenharmony_cistatic void srp_put_tx_iu(struct srp_rdma_ch *ch, struct srp_iu *iu,
181062306a36Sopenharmony_ci			  enum srp_iu_type iu_type)
181162306a36Sopenharmony_ci{
181262306a36Sopenharmony_ci	unsigned long flags;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	spin_lock_irqsave(&ch->lock, flags);
181562306a36Sopenharmony_ci	list_add(&iu->list, &ch->free_tx);
181662306a36Sopenharmony_ci	if (iu_type != SRP_IU_RSP)
181762306a36Sopenharmony_ci		++ch->req_lim;
181862306a36Sopenharmony_ci	spin_unlock_irqrestore(&ch->lock, flags);
181962306a36Sopenharmony_ci}
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci/*
182262306a36Sopenharmony_ci * Must be called with ch->lock held to protect req_lim and free_tx.
182362306a36Sopenharmony_ci * If IU is not sent, it must be returned using srp_put_tx_iu().
182462306a36Sopenharmony_ci *
182562306a36Sopenharmony_ci * Note:
182662306a36Sopenharmony_ci * An upper limit for the number of allocated information units for each
182762306a36Sopenharmony_ci * request type is:
182862306a36Sopenharmony_ci * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
182962306a36Sopenharmony_ci *   more than Scsi_Host.can_queue requests.
183062306a36Sopenharmony_ci * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
183162306a36Sopenharmony_ci * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
183262306a36Sopenharmony_ci *   one unanswered SRP request to an initiator.
183362306a36Sopenharmony_ci */
183462306a36Sopenharmony_cistatic struct srp_iu *__srp_get_tx_iu(struct srp_rdma_ch *ch,
183562306a36Sopenharmony_ci				      enum srp_iu_type iu_type)
183662306a36Sopenharmony_ci{
183762306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
183862306a36Sopenharmony_ci	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
183962306a36Sopenharmony_ci	struct srp_iu *iu;
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	lockdep_assert_held(&ch->lock);
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci	ib_process_cq_direct(ch->send_cq, -1);
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	if (list_empty(&ch->free_tx))
184662306a36Sopenharmony_ci		return NULL;
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci	/* Initiator responses to target requests do not consume credits */
184962306a36Sopenharmony_ci	if (iu_type != SRP_IU_RSP) {
185062306a36Sopenharmony_ci		if (ch->req_lim <= rsv) {
185162306a36Sopenharmony_ci			++target->zero_req_lim;
185262306a36Sopenharmony_ci			return NULL;
185362306a36Sopenharmony_ci		}
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci		--ch->req_lim;
185662306a36Sopenharmony_ci	}
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	iu = list_first_entry(&ch->free_tx, struct srp_iu, list);
185962306a36Sopenharmony_ci	list_del(&iu->list);
186062306a36Sopenharmony_ci	return iu;
186162306a36Sopenharmony_ci}
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci/*
186462306a36Sopenharmony_ci * Note: if this function is called from inside ib_drain_sq() then it will
186562306a36Sopenharmony_ci * be called without ch->lock being held. If ib_drain_sq() dequeues a WQE
186662306a36Sopenharmony_ci * with status IB_WC_SUCCESS then that's a bug.
186762306a36Sopenharmony_ci */
186862306a36Sopenharmony_cistatic void srp_send_done(struct ib_cq *cq, struct ib_wc *wc)
186962306a36Sopenharmony_ci{
187062306a36Sopenharmony_ci	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
187162306a36Sopenharmony_ci	struct srp_rdma_ch *ch = cq->cq_context;
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci	if (unlikely(wc->status != IB_WC_SUCCESS)) {
187462306a36Sopenharmony_ci		srp_handle_qp_err(cq, wc, "SEND");
187562306a36Sopenharmony_ci		return;
187662306a36Sopenharmony_ci	}
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci	lockdep_assert_held(&ch->lock);
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	list_add(&iu->list, &ch->free_tx);
188162306a36Sopenharmony_ci}
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci/**
188462306a36Sopenharmony_ci * srp_post_send() - send an SRP information unit
188562306a36Sopenharmony_ci * @ch: RDMA channel over which to send the information unit.
188662306a36Sopenharmony_ci * @iu: Information unit to send.
188762306a36Sopenharmony_ci * @len: Length of the information unit excluding immediate data.
188862306a36Sopenharmony_ci */
188962306a36Sopenharmony_cistatic int srp_post_send(struct srp_rdma_ch *ch, struct srp_iu *iu, int len)
189062306a36Sopenharmony_ci{
189162306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
189262306a36Sopenharmony_ci	struct ib_send_wr wr;
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	if (WARN_ON_ONCE(iu->num_sge > SRP_MAX_SGE))
189562306a36Sopenharmony_ci		return -EINVAL;
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci	iu->sge[0].addr   = iu->dma;
189862306a36Sopenharmony_ci	iu->sge[0].length = len;
189962306a36Sopenharmony_ci	iu->sge[0].lkey   = target->lkey;
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	iu->cqe.done = srp_send_done;
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	wr.next       = NULL;
190462306a36Sopenharmony_ci	wr.wr_cqe     = &iu->cqe;
190562306a36Sopenharmony_ci	wr.sg_list    = &iu->sge[0];
190662306a36Sopenharmony_ci	wr.num_sge    = iu->num_sge;
190762306a36Sopenharmony_ci	wr.opcode     = IB_WR_SEND;
190862306a36Sopenharmony_ci	wr.send_flags = IB_SEND_SIGNALED;
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	return ib_post_send(ch->qp, &wr, NULL);
191162306a36Sopenharmony_ci}
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_cistatic int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
191462306a36Sopenharmony_ci{
191562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
191662306a36Sopenharmony_ci	struct ib_recv_wr wr;
191762306a36Sopenharmony_ci	struct ib_sge list;
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	list.addr   = iu->dma;
192062306a36Sopenharmony_ci	list.length = iu->size;
192162306a36Sopenharmony_ci	list.lkey   = target->lkey;
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	iu->cqe.done = srp_recv_done;
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	wr.next     = NULL;
192662306a36Sopenharmony_ci	wr.wr_cqe   = &iu->cqe;
192762306a36Sopenharmony_ci	wr.sg_list  = &list;
192862306a36Sopenharmony_ci	wr.num_sge  = 1;
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci	return ib_post_recv(ch->qp, &wr, NULL);
193162306a36Sopenharmony_ci}
193262306a36Sopenharmony_ci
193362306a36Sopenharmony_cistatic void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
193462306a36Sopenharmony_ci{
193562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
193662306a36Sopenharmony_ci	struct srp_request *req;
193762306a36Sopenharmony_ci	struct scsi_cmnd *scmnd;
193862306a36Sopenharmony_ci	unsigned long flags;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
194162306a36Sopenharmony_ci		spin_lock_irqsave(&ch->lock, flags);
194262306a36Sopenharmony_ci		ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
194362306a36Sopenharmony_ci		if (rsp->tag == ch->tsk_mgmt_tag) {
194462306a36Sopenharmony_ci			ch->tsk_mgmt_status = -1;
194562306a36Sopenharmony_ci			if (be32_to_cpu(rsp->resp_data_len) >= 4)
194662306a36Sopenharmony_ci				ch->tsk_mgmt_status = rsp->data[3];
194762306a36Sopenharmony_ci			complete(&ch->tsk_mgmt_done);
194862306a36Sopenharmony_ci		} else {
194962306a36Sopenharmony_ci			shost_printk(KERN_ERR, target->scsi_host,
195062306a36Sopenharmony_ci				     "Received tsk mgmt response too late for tag %#llx\n",
195162306a36Sopenharmony_ci				     rsp->tag);
195262306a36Sopenharmony_ci		}
195362306a36Sopenharmony_ci		spin_unlock_irqrestore(&ch->lock, flags);
195462306a36Sopenharmony_ci	} else {
195562306a36Sopenharmony_ci		scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
195662306a36Sopenharmony_ci		if (scmnd) {
195762306a36Sopenharmony_ci			req = scsi_cmd_priv(scmnd);
195862306a36Sopenharmony_ci			scmnd = srp_claim_req(ch, req, NULL, scmnd);
195962306a36Sopenharmony_ci		}
196062306a36Sopenharmony_ci		if (!scmnd) {
196162306a36Sopenharmony_ci			shost_printk(KERN_ERR, target->scsi_host,
196262306a36Sopenharmony_ci				     "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
196362306a36Sopenharmony_ci				     rsp->tag, ch - target->ch, ch->qp->qp_num);
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci			spin_lock_irqsave(&ch->lock, flags);
196662306a36Sopenharmony_ci			ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
196762306a36Sopenharmony_ci			spin_unlock_irqrestore(&ch->lock, flags);
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci			return;
197062306a36Sopenharmony_ci		}
197162306a36Sopenharmony_ci		scmnd->result = rsp->status;
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci		if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
197462306a36Sopenharmony_ci			memcpy(scmnd->sense_buffer, rsp->data +
197562306a36Sopenharmony_ci			       be32_to_cpu(rsp->resp_data_len),
197662306a36Sopenharmony_ci			       min_t(int, be32_to_cpu(rsp->sense_data_len),
197762306a36Sopenharmony_ci				     SCSI_SENSE_BUFFERSIZE));
197862306a36Sopenharmony_ci		}
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_ci		if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
198162306a36Sopenharmony_ci			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
198262306a36Sopenharmony_ci		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOUNDER))
198362306a36Sopenharmony_ci			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci		srp_free_req(ch, req, scmnd,
198662306a36Sopenharmony_ci			     be32_to_cpu(rsp->req_lim_delta));
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci		scsi_done(scmnd);
198962306a36Sopenharmony_ci	}
199062306a36Sopenharmony_ci}
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_cistatic int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
199362306a36Sopenharmony_ci			       void *rsp, int len)
199462306a36Sopenharmony_ci{
199562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
199662306a36Sopenharmony_ci	struct ib_device *dev = target->srp_host->srp_dev->dev;
199762306a36Sopenharmony_ci	unsigned long flags;
199862306a36Sopenharmony_ci	struct srp_iu *iu;
199962306a36Sopenharmony_ci	int err;
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci	spin_lock_irqsave(&ch->lock, flags);
200262306a36Sopenharmony_ci	ch->req_lim += req_delta;
200362306a36Sopenharmony_ci	iu = __srp_get_tx_iu(ch, SRP_IU_RSP);
200462306a36Sopenharmony_ci	spin_unlock_irqrestore(&ch->lock, flags);
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci	if (!iu) {
200762306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host, PFX
200862306a36Sopenharmony_ci			     "no IU available to send response\n");
200962306a36Sopenharmony_ci		return 1;
201062306a36Sopenharmony_ci	}
201162306a36Sopenharmony_ci
201262306a36Sopenharmony_ci	iu->num_sge = 1;
201362306a36Sopenharmony_ci	ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
201462306a36Sopenharmony_ci	memcpy(iu->buf, rsp, len);
201562306a36Sopenharmony_ci	ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	err = srp_post_send(ch, iu, len);
201862306a36Sopenharmony_ci	if (err) {
201962306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host, PFX
202062306a36Sopenharmony_ci			     "unable to post response: %d\n", err);
202162306a36Sopenharmony_ci		srp_put_tx_iu(ch, iu, SRP_IU_RSP);
202262306a36Sopenharmony_ci	}
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci	return err;
202562306a36Sopenharmony_ci}
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_cistatic void srp_process_cred_req(struct srp_rdma_ch *ch,
202862306a36Sopenharmony_ci				 struct srp_cred_req *req)
202962306a36Sopenharmony_ci{
203062306a36Sopenharmony_ci	struct srp_cred_rsp rsp = {
203162306a36Sopenharmony_ci		.opcode = SRP_CRED_RSP,
203262306a36Sopenharmony_ci		.tag = req->tag,
203362306a36Sopenharmony_ci	};
203462306a36Sopenharmony_ci	s32 delta = be32_to_cpu(req->req_lim_delta);
203562306a36Sopenharmony_ci
203662306a36Sopenharmony_ci	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
203762306a36Sopenharmony_ci		shost_printk(KERN_ERR, ch->target->scsi_host, PFX
203862306a36Sopenharmony_ci			     "problems processing SRP_CRED_REQ\n");
203962306a36Sopenharmony_ci}
204062306a36Sopenharmony_ci
204162306a36Sopenharmony_cistatic void srp_process_aer_req(struct srp_rdma_ch *ch,
204262306a36Sopenharmony_ci				struct srp_aer_req *req)
204362306a36Sopenharmony_ci{
204462306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
204562306a36Sopenharmony_ci	struct srp_aer_rsp rsp = {
204662306a36Sopenharmony_ci		.opcode = SRP_AER_RSP,
204762306a36Sopenharmony_ci		.tag = req->tag,
204862306a36Sopenharmony_ci	};
204962306a36Sopenharmony_ci	s32 delta = be32_to_cpu(req->req_lim_delta);
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	shost_printk(KERN_ERR, target->scsi_host, PFX
205262306a36Sopenharmony_ci		     "ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci	if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
205562306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host, PFX
205662306a36Sopenharmony_ci			     "problems processing SRP_AER_REQ\n");
205762306a36Sopenharmony_ci}
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_cistatic void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
206062306a36Sopenharmony_ci{
206162306a36Sopenharmony_ci	struct srp_iu *iu = container_of(wc->wr_cqe, struct srp_iu, cqe);
206262306a36Sopenharmony_ci	struct srp_rdma_ch *ch = cq->cq_context;
206362306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
206462306a36Sopenharmony_ci	struct ib_device *dev = target->srp_host->srp_dev->dev;
206562306a36Sopenharmony_ci	int res;
206662306a36Sopenharmony_ci	u8 opcode;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci	if (unlikely(wc->status != IB_WC_SUCCESS)) {
206962306a36Sopenharmony_ci		srp_handle_qp_err(cq, wc, "RECV");
207062306a36Sopenharmony_ci		return;
207162306a36Sopenharmony_ci	}
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_ti_iu_len,
207462306a36Sopenharmony_ci				   DMA_FROM_DEVICE);
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	opcode = *(u8 *) iu->buf;
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_ci	if (0) {
207962306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
208062306a36Sopenharmony_ci			     PFX "recv completion, opcode 0x%02x\n", opcode);
208162306a36Sopenharmony_ci		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 8, 1,
208262306a36Sopenharmony_ci			       iu->buf, wc->byte_len, true);
208362306a36Sopenharmony_ci	}
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	switch (opcode) {
208662306a36Sopenharmony_ci	case SRP_RSP:
208762306a36Sopenharmony_ci		srp_process_rsp(ch, iu->buf);
208862306a36Sopenharmony_ci		break;
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	case SRP_CRED_REQ:
209162306a36Sopenharmony_ci		srp_process_cred_req(ch, iu->buf);
209262306a36Sopenharmony_ci		break;
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	case SRP_AER_REQ:
209562306a36Sopenharmony_ci		srp_process_aer_req(ch, iu->buf);
209662306a36Sopenharmony_ci		break;
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci	case SRP_T_LOGOUT:
209962306a36Sopenharmony_ci		/* XXX Handle target logout */
210062306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
210162306a36Sopenharmony_ci			     PFX "Got target logout request\n");
210262306a36Sopenharmony_ci		break;
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_ci	default:
210562306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
210662306a36Sopenharmony_ci			     PFX "Unhandled SRP opcode 0x%02x\n", opcode);
210762306a36Sopenharmony_ci		break;
210862306a36Sopenharmony_ci	}
210962306a36Sopenharmony_ci
211062306a36Sopenharmony_ci	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_ti_iu_len,
211162306a36Sopenharmony_ci				      DMA_FROM_DEVICE);
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_ci	res = srp_post_recv(ch, iu);
211462306a36Sopenharmony_ci	if (res != 0)
211562306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
211662306a36Sopenharmony_ci			     PFX "Recv failed with error code %d\n", res);
211762306a36Sopenharmony_ci}
211862306a36Sopenharmony_ci
211962306a36Sopenharmony_ci/**
212062306a36Sopenharmony_ci * srp_tl_err_work() - handle a transport layer error
212162306a36Sopenharmony_ci * @work: Work structure embedded in an SRP target port.
212262306a36Sopenharmony_ci *
212362306a36Sopenharmony_ci * Note: This function may get invoked before the rport has been created,
212462306a36Sopenharmony_ci * hence the target->rport test.
212562306a36Sopenharmony_ci */
212662306a36Sopenharmony_cistatic void srp_tl_err_work(struct work_struct *work)
212762306a36Sopenharmony_ci{
212862306a36Sopenharmony_ci	struct srp_target_port *target;
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	target = container_of(work, struct srp_target_port, tl_err_work);
213162306a36Sopenharmony_ci	if (target->rport)
213262306a36Sopenharmony_ci		srp_start_tl_fail_timers(target->rport);
213362306a36Sopenharmony_ci}
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_cistatic void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
213662306a36Sopenharmony_ci		const char *opname)
213762306a36Sopenharmony_ci{
213862306a36Sopenharmony_ci	struct srp_rdma_ch *ch = cq->cq_context;
213962306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	if (ch->connected && !target->qp_in_error) {
214262306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
214362306a36Sopenharmony_ci			     PFX "failed %s status %s (%d) for CQE %p\n",
214462306a36Sopenharmony_ci			     opname, ib_wc_status_msg(wc->status), wc->status,
214562306a36Sopenharmony_ci			     wc->wr_cqe);
214662306a36Sopenharmony_ci		queue_work(system_long_wq, &target->tl_err_work);
214762306a36Sopenharmony_ci	}
214862306a36Sopenharmony_ci	target->qp_in_error = true;
214962306a36Sopenharmony_ci}
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_cistatic int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
215262306a36Sopenharmony_ci{
215362306a36Sopenharmony_ci	struct request *rq = scsi_cmd_to_rq(scmnd);
215462306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(shost);
215562306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
215662306a36Sopenharmony_ci	struct srp_request *req = scsi_cmd_priv(scmnd);
215762306a36Sopenharmony_ci	struct srp_iu *iu;
215862306a36Sopenharmony_ci	struct srp_cmd *cmd;
215962306a36Sopenharmony_ci	struct ib_device *dev;
216062306a36Sopenharmony_ci	unsigned long flags;
216162306a36Sopenharmony_ci	u32 tag;
216262306a36Sopenharmony_ci	int len, ret;
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci	scmnd->result = srp_chkready(target->rport);
216562306a36Sopenharmony_ci	if (unlikely(scmnd->result))
216662306a36Sopenharmony_ci		goto err;
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci	WARN_ON_ONCE(rq->tag < 0);
216962306a36Sopenharmony_ci	tag = blk_mq_unique_tag(rq);
217062306a36Sopenharmony_ci	ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci	spin_lock_irqsave(&ch->lock, flags);
217362306a36Sopenharmony_ci	iu = __srp_get_tx_iu(ch, SRP_IU_CMD);
217462306a36Sopenharmony_ci	spin_unlock_irqrestore(&ch->lock, flags);
217562306a36Sopenharmony_ci
217662306a36Sopenharmony_ci	if (!iu)
217762306a36Sopenharmony_ci		goto err;
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	dev = target->srp_host->srp_dev->dev;
218062306a36Sopenharmony_ci	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_it_iu_len,
218162306a36Sopenharmony_ci				   DMA_TO_DEVICE);
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci	cmd = iu->buf;
218462306a36Sopenharmony_ci	memset(cmd, 0, sizeof *cmd);
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_ci	cmd->opcode = SRP_CMD;
218762306a36Sopenharmony_ci	int_to_scsilun(scmnd->device->lun, &cmd->lun);
218862306a36Sopenharmony_ci	cmd->tag    = tag;
218962306a36Sopenharmony_ci	memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
219062306a36Sopenharmony_ci	if (unlikely(scmnd->cmd_len > sizeof(cmd->cdb))) {
219162306a36Sopenharmony_ci		cmd->add_cdb_len = round_up(scmnd->cmd_len - sizeof(cmd->cdb),
219262306a36Sopenharmony_ci					    4);
219362306a36Sopenharmony_ci		if (WARN_ON_ONCE(cmd->add_cdb_len > SRP_MAX_ADD_CDB_LEN))
219462306a36Sopenharmony_ci			goto err_iu;
219562306a36Sopenharmony_ci	}
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	req->scmnd    = scmnd;
219862306a36Sopenharmony_ci	req->cmd      = iu;
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci	len = srp_map_data(scmnd, ch, req);
220162306a36Sopenharmony_ci	if (len < 0) {
220262306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
220362306a36Sopenharmony_ci			     PFX "Failed to map data (%d)\n", len);
220462306a36Sopenharmony_ci		/*
220562306a36Sopenharmony_ci		 * If we ran out of memory descriptors (-ENOMEM) because an
220662306a36Sopenharmony_ci		 * application is queuing many requests with more than
220762306a36Sopenharmony_ci		 * max_pages_per_mr sg-list elements, tell the SCSI mid-layer
220862306a36Sopenharmony_ci		 * to reduce queue depth temporarily.
220962306a36Sopenharmony_ci		 */
221062306a36Sopenharmony_ci		scmnd->result = len == -ENOMEM ?
221162306a36Sopenharmony_ci			DID_OK << 16 | SAM_STAT_TASK_SET_FULL : DID_ERROR << 16;
221262306a36Sopenharmony_ci		goto err_iu;
221362306a36Sopenharmony_ci	}
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_it_iu_len,
221662306a36Sopenharmony_ci				      DMA_TO_DEVICE);
221762306a36Sopenharmony_ci
221862306a36Sopenharmony_ci	if (srp_post_send(ch, iu, len)) {
221962306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
222062306a36Sopenharmony_ci		scmnd->result = DID_ERROR << 16;
222162306a36Sopenharmony_ci		goto err_unmap;
222262306a36Sopenharmony_ci	}
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ci	return 0;
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_cierr_unmap:
222762306a36Sopenharmony_ci	srp_unmap_data(scmnd, ch, req);
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_cierr_iu:
223062306a36Sopenharmony_ci	srp_put_tx_iu(ch, iu, SRP_IU_CMD);
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_ci	/*
223362306a36Sopenharmony_ci	 * Avoid that the loops that iterate over the request ring can
223462306a36Sopenharmony_ci	 * encounter a dangling SCSI command pointer.
223562306a36Sopenharmony_ci	 */
223662306a36Sopenharmony_ci	req->scmnd = NULL;
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_cierr:
223962306a36Sopenharmony_ci	if (scmnd->result) {
224062306a36Sopenharmony_ci		scsi_done(scmnd);
224162306a36Sopenharmony_ci		ret = 0;
224262306a36Sopenharmony_ci	} else {
224362306a36Sopenharmony_ci		ret = SCSI_MLQUEUE_HOST_BUSY;
224462306a36Sopenharmony_ci	}
224562306a36Sopenharmony_ci
224662306a36Sopenharmony_ci	return ret;
224762306a36Sopenharmony_ci}
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci/*
225062306a36Sopenharmony_ci * Note: the resources allocated in this function are freed in
225162306a36Sopenharmony_ci * srp_free_ch_ib().
225262306a36Sopenharmony_ci */
225362306a36Sopenharmony_cistatic int srp_alloc_iu_bufs(struct srp_rdma_ch *ch)
225462306a36Sopenharmony_ci{
225562306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
225662306a36Sopenharmony_ci	int i;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	ch->rx_ring = kcalloc(target->queue_size, sizeof(*ch->rx_ring),
225962306a36Sopenharmony_ci			      GFP_KERNEL);
226062306a36Sopenharmony_ci	if (!ch->rx_ring)
226162306a36Sopenharmony_ci		goto err_no_ring;
226262306a36Sopenharmony_ci	ch->tx_ring = kcalloc(target->queue_size, sizeof(*ch->tx_ring),
226362306a36Sopenharmony_ci			      GFP_KERNEL);
226462306a36Sopenharmony_ci	if (!ch->tx_ring)
226562306a36Sopenharmony_ci		goto err_no_ring;
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	for (i = 0; i < target->queue_size; ++i) {
226862306a36Sopenharmony_ci		ch->rx_ring[i] = srp_alloc_iu(target->srp_host,
226962306a36Sopenharmony_ci					      ch->max_ti_iu_len,
227062306a36Sopenharmony_ci					      GFP_KERNEL, DMA_FROM_DEVICE);
227162306a36Sopenharmony_ci		if (!ch->rx_ring[i])
227262306a36Sopenharmony_ci			goto err;
227362306a36Sopenharmony_ci	}
227462306a36Sopenharmony_ci
227562306a36Sopenharmony_ci	for (i = 0; i < target->queue_size; ++i) {
227662306a36Sopenharmony_ci		ch->tx_ring[i] = srp_alloc_iu(target->srp_host,
227762306a36Sopenharmony_ci					      ch->max_it_iu_len,
227862306a36Sopenharmony_ci					      GFP_KERNEL, DMA_TO_DEVICE);
227962306a36Sopenharmony_ci		if (!ch->tx_ring[i])
228062306a36Sopenharmony_ci			goto err;
228162306a36Sopenharmony_ci
228262306a36Sopenharmony_ci		list_add(&ch->tx_ring[i]->list, &ch->free_tx);
228362306a36Sopenharmony_ci	}
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	return 0;
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_cierr:
228862306a36Sopenharmony_ci	for (i = 0; i < target->queue_size; ++i) {
228962306a36Sopenharmony_ci		srp_free_iu(target->srp_host, ch->rx_ring[i]);
229062306a36Sopenharmony_ci		srp_free_iu(target->srp_host, ch->tx_ring[i]);
229162306a36Sopenharmony_ci	}
229262306a36Sopenharmony_ci
229362306a36Sopenharmony_ci
229462306a36Sopenharmony_cierr_no_ring:
229562306a36Sopenharmony_ci	kfree(ch->tx_ring);
229662306a36Sopenharmony_ci	ch->tx_ring = NULL;
229762306a36Sopenharmony_ci	kfree(ch->rx_ring);
229862306a36Sopenharmony_ci	ch->rx_ring = NULL;
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_ci	return -ENOMEM;
230162306a36Sopenharmony_ci}
230262306a36Sopenharmony_ci
230362306a36Sopenharmony_cistatic uint32_t srp_compute_rq_tmo(struct ib_qp_attr *qp_attr, int attr_mask)
230462306a36Sopenharmony_ci{
230562306a36Sopenharmony_ci	uint64_t T_tr_ns, max_compl_time_ms;
230662306a36Sopenharmony_ci	uint32_t rq_tmo_jiffies;
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	/*
230962306a36Sopenharmony_ci	 * According to section 11.2.4.2 in the IBTA spec (Modify Queue Pair,
231062306a36Sopenharmony_ci	 * table 91), both the QP timeout and the retry count have to be set
231162306a36Sopenharmony_ci	 * for RC QP's during the RTR to RTS transition.
231262306a36Sopenharmony_ci	 */
231362306a36Sopenharmony_ci	WARN_ON_ONCE((attr_mask & (IB_QP_TIMEOUT | IB_QP_RETRY_CNT)) !=
231462306a36Sopenharmony_ci		     (IB_QP_TIMEOUT | IB_QP_RETRY_CNT));
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_ci	/*
231762306a36Sopenharmony_ci	 * Set target->rq_tmo_jiffies to one second more than the largest time
231862306a36Sopenharmony_ci	 * it can take before an error completion is generated. See also
231962306a36Sopenharmony_ci	 * C9-140..142 in the IBTA spec for more information about how to
232062306a36Sopenharmony_ci	 * convert the QP Local ACK Timeout value to nanoseconds.
232162306a36Sopenharmony_ci	 */
232262306a36Sopenharmony_ci	T_tr_ns = 4096 * (1ULL << qp_attr->timeout);
232362306a36Sopenharmony_ci	max_compl_time_ms = qp_attr->retry_cnt * 4 * T_tr_ns;
232462306a36Sopenharmony_ci	do_div(max_compl_time_ms, NSEC_PER_MSEC);
232562306a36Sopenharmony_ci	rq_tmo_jiffies = msecs_to_jiffies(max_compl_time_ms + 1000);
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_ci	return rq_tmo_jiffies;
232862306a36Sopenharmony_ci}
232962306a36Sopenharmony_ci
233062306a36Sopenharmony_cistatic void srp_cm_rep_handler(struct ib_cm_id *cm_id,
233162306a36Sopenharmony_ci			       const struct srp_login_rsp *lrsp,
233262306a36Sopenharmony_ci			       struct srp_rdma_ch *ch)
233362306a36Sopenharmony_ci{
233462306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
233562306a36Sopenharmony_ci	struct ib_qp_attr *qp_attr = NULL;
233662306a36Sopenharmony_ci	int attr_mask = 0;
233762306a36Sopenharmony_ci	int ret = 0;
233862306a36Sopenharmony_ci	int i;
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_ci	if (lrsp->opcode == SRP_LOGIN_RSP) {
234162306a36Sopenharmony_ci		ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
234262306a36Sopenharmony_ci		ch->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
234362306a36Sopenharmony_ci		ch->use_imm_data  = srp_use_imm_data &&
234462306a36Sopenharmony_ci			(lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP);
234562306a36Sopenharmony_ci		ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
234662306a36Sopenharmony_ci						      ch->use_imm_data,
234762306a36Sopenharmony_ci						      target->max_it_iu_size);
234862306a36Sopenharmony_ci		WARN_ON_ONCE(ch->max_it_iu_len >
234962306a36Sopenharmony_ci			     be32_to_cpu(lrsp->max_it_iu_len));
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ci		if (ch->use_imm_data)
235262306a36Sopenharmony_ci			shost_printk(KERN_DEBUG, target->scsi_host,
235362306a36Sopenharmony_ci				     PFX "using immediate data\n");
235462306a36Sopenharmony_ci
235562306a36Sopenharmony_ci		/*
235662306a36Sopenharmony_ci		 * Reserve credits for task management so we don't
235762306a36Sopenharmony_ci		 * bounce requests back to the SCSI mid-layer.
235862306a36Sopenharmony_ci		 */
235962306a36Sopenharmony_ci		target->scsi_host->can_queue
236062306a36Sopenharmony_ci			= min(ch->req_lim - SRP_TSK_MGMT_SQ_SIZE,
236162306a36Sopenharmony_ci			      target->scsi_host->can_queue);
236262306a36Sopenharmony_ci		target->scsi_host->cmd_per_lun
236362306a36Sopenharmony_ci			= min_t(int, target->scsi_host->can_queue,
236462306a36Sopenharmony_ci				target->scsi_host->cmd_per_lun);
236562306a36Sopenharmony_ci	} else {
236662306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
236762306a36Sopenharmony_ci			     PFX "Unhandled RSP opcode %#x\n", lrsp->opcode);
236862306a36Sopenharmony_ci		ret = -ECONNRESET;
236962306a36Sopenharmony_ci		goto error;
237062306a36Sopenharmony_ci	}
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	if (!ch->rx_ring) {
237362306a36Sopenharmony_ci		ret = srp_alloc_iu_bufs(ch);
237462306a36Sopenharmony_ci		if (ret)
237562306a36Sopenharmony_ci			goto error;
237662306a36Sopenharmony_ci	}
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	for (i = 0; i < target->queue_size; i++) {
237962306a36Sopenharmony_ci		struct srp_iu *iu = ch->rx_ring[i];
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci		ret = srp_post_recv(ch, iu);
238262306a36Sopenharmony_ci		if (ret)
238362306a36Sopenharmony_ci			goto error;
238462306a36Sopenharmony_ci	}
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	if (!target->using_rdma_cm) {
238762306a36Sopenharmony_ci		ret = -ENOMEM;
238862306a36Sopenharmony_ci		qp_attr = kmalloc(sizeof(*qp_attr), GFP_KERNEL);
238962306a36Sopenharmony_ci		if (!qp_attr)
239062306a36Sopenharmony_ci			goto error;
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci		qp_attr->qp_state = IB_QPS_RTR;
239362306a36Sopenharmony_ci		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
239462306a36Sopenharmony_ci		if (ret)
239562306a36Sopenharmony_ci			goto error_free;
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
239862306a36Sopenharmony_ci		if (ret)
239962306a36Sopenharmony_ci			goto error_free;
240062306a36Sopenharmony_ci
240162306a36Sopenharmony_ci		qp_attr->qp_state = IB_QPS_RTS;
240262306a36Sopenharmony_ci		ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
240362306a36Sopenharmony_ci		if (ret)
240462306a36Sopenharmony_ci			goto error_free;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci		target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_ci		ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
240962306a36Sopenharmony_ci		if (ret)
241062306a36Sopenharmony_ci			goto error_free;
241162306a36Sopenharmony_ci
241262306a36Sopenharmony_ci		ret = ib_send_cm_rtu(cm_id, NULL, 0);
241362306a36Sopenharmony_ci	}
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_cierror_free:
241662306a36Sopenharmony_ci	kfree(qp_attr);
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_cierror:
241962306a36Sopenharmony_ci	ch->status = ret;
242062306a36Sopenharmony_ci}
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_cistatic void srp_ib_cm_rej_handler(struct ib_cm_id *cm_id,
242362306a36Sopenharmony_ci				  const struct ib_cm_event *event,
242462306a36Sopenharmony_ci				  struct srp_rdma_ch *ch)
242562306a36Sopenharmony_ci{
242662306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
242762306a36Sopenharmony_ci	struct Scsi_Host *shost = target->scsi_host;
242862306a36Sopenharmony_ci	struct ib_class_port_info *cpi;
242962306a36Sopenharmony_ci	int opcode;
243062306a36Sopenharmony_ci	u16 dlid;
243162306a36Sopenharmony_ci
243262306a36Sopenharmony_ci	switch (event->param.rej_rcvd.reason) {
243362306a36Sopenharmony_ci	case IB_CM_REJ_PORT_CM_REDIRECT:
243462306a36Sopenharmony_ci		cpi = event->param.rej_rcvd.ari;
243562306a36Sopenharmony_ci		dlid = be16_to_cpu(cpi->redirect_lid);
243662306a36Sopenharmony_ci		sa_path_set_dlid(&ch->ib_cm.path, dlid);
243762306a36Sopenharmony_ci		ch->ib_cm.path.pkey = cpi->redirect_pkey;
243862306a36Sopenharmony_ci		cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
243962306a36Sopenharmony_ci		memcpy(ch->ib_cm.path.dgid.raw, cpi->redirect_gid, 16);
244062306a36Sopenharmony_ci
244162306a36Sopenharmony_ci		ch->status = dlid ? SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
244262306a36Sopenharmony_ci		break;
244362306a36Sopenharmony_ci
244462306a36Sopenharmony_ci	case IB_CM_REJ_PORT_REDIRECT:
244562306a36Sopenharmony_ci		if (srp_target_is_topspin(target)) {
244662306a36Sopenharmony_ci			union ib_gid *dgid = &ch->ib_cm.path.dgid;
244762306a36Sopenharmony_ci
244862306a36Sopenharmony_ci			/*
244962306a36Sopenharmony_ci			 * Topspin/Cisco SRP gateways incorrectly send
245062306a36Sopenharmony_ci			 * reject reason code 25 when they mean 24
245162306a36Sopenharmony_ci			 * (port redirect).
245262306a36Sopenharmony_ci			 */
245362306a36Sopenharmony_ci			memcpy(dgid->raw, event->param.rej_rcvd.ari, 16);
245462306a36Sopenharmony_ci
245562306a36Sopenharmony_ci			shost_printk(KERN_DEBUG, shost,
245662306a36Sopenharmony_ci				     PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
245762306a36Sopenharmony_ci				     be64_to_cpu(dgid->global.subnet_prefix),
245862306a36Sopenharmony_ci				     be64_to_cpu(dgid->global.interface_id));
245962306a36Sopenharmony_ci
246062306a36Sopenharmony_ci			ch->status = SRP_PORT_REDIRECT;
246162306a36Sopenharmony_ci		} else {
246262306a36Sopenharmony_ci			shost_printk(KERN_WARNING, shost,
246362306a36Sopenharmony_ci				     "  REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
246462306a36Sopenharmony_ci			ch->status = -ECONNRESET;
246562306a36Sopenharmony_ci		}
246662306a36Sopenharmony_ci		break;
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
246962306a36Sopenharmony_ci		shost_printk(KERN_WARNING, shost,
247062306a36Sopenharmony_ci			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
247162306a36Sopenharmony_ci		ch->status = -ECONNRESET;
247262306a36Sopenharmony_ci		break;
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	case IB_CM_REJ_CONSUMER_DEFINED:
247562306a36Sopenharmony_ci		opcode = *(u8 *) event->private_data;
247662306a36Sopenharmony_ci		if (opcode == SRP_LOGIN_REJ) {
247762306a36Sopenharmony_ci			struct srp_login_rej *rej = event->private_data;
247862306a36Sopenharmony_ci			u32 reason = be32_to_cpu(rej->reason);
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_ci			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
248162306a36Sopenharmony_ci				shost_printk(KERN_WARNING, shost,
248262306a36Sopenharmony_ci					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
248362306a36Sopenharmony_ci			else
248462306a36Sopenharmony_ci				shost_printk(KERN_WARNING, shost, PFX
248562306a36Sopenharmony_ci					     "SRP LOGIN from %pI6 to %pI6 REJECTED, reason 0x%08x\n",
248662306a36Sopenharmony_ci					     target->sgid.raw,
248762306a36Sopenharmony_ci					     target->ib_cm.orig_dgid.raw,
248862306a36Sopenharmony_ci					     reason);
248962306a36Sopenharmony_ci		} else
249062306a36Sopenharmony_ci			shost_printk(KERN_WARNING, shost,
249162306a36Sopenharmony_ci				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
249262306a36Sopenharmony_ci				     " opcode 0x%02x\n", opcode);
249362306a36Sopenharmony_ci		ch->status = -ECONNRESET;
249462306a36Sopenharmony_ci		break;
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_ci	case IB_CM_REJ_STALE_CONN:
249762306a36Sopenharmony_ci		shost_printk(KERN_WARNING, shost, "  REJ reason: stale connection\n");
249862306a36Sopenharmony_ci		ch->status = SRP_STALE_CONN;
249962306a36Sopenharmony_ci		break;
250062306a36Sopenharmony_ci
250162306a36Sopenharmony_ci	default:
250262306a36Sopenharmony_ci		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
250362306a36Sopenharmony_ci			     event->param.rej_rcvd.reason);
250462306a36Sopenharmony_ci		ch->status = -ECONNRESET;
250562306a36Sopenharmony_ci	}
250662306a36Sopenharmony_ci}
250762306a36Sopenharmony_ci
250862306a36Sopenharmony_cistatic int srp_ib_cm_handler(struct ib_cm_id *cm_id,
250962306a36Sopenharmony_ci			     const struct ib_cm_event *event)
251062306a36Sopenharmony_ci{
251162306a36Sopenharmony_ci	struct srp_rdma_ch *ch = cm_id->context;
251262306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
251362306a36Sopenharmony_ci	int comp = 0;
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci	switch (event->event) {
251662306a36Sopenharmony_ci	case IB_CM_REQ_ERROR:
251762306a36Sopenharmony_ci		shost_printk(KERN_DEBUG, target->scsi_host,
251862306a36Sopenharmony_ci			     PFX "Sending CM REQ failed\n");
251962306a36Sopenharmony_ci		comp = 1;
252062306a36Sopenharmony_ci		ch->status = -ECONNRESET;
252162306a36Sopenharmony_ci		break;
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_ci	case IB_CM_REP_RECEIVED:
252462306a36Sopenharmony_ci		comp = 1;
252562306a36Sopenharmony_ci		srp_cm_rep_handler(cm_id, event->private_data, ch);
252662306a36Sopenharmony_ci		break;
252762306a36Sopenharmony_ci
252862306a36Sopenharmony_ci	case IB_CM_REJ_RECEIVED:
252962306a36Sopenharmony_ci		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
253062306a36Sopenharmony_ci		comp = 1;
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci		srp_ib_cm_rej_handler(cm_id, event, ch);
253362306a36Sopenharmony_ci		break;
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_ci	case IB_CM_DREQ_RECEIVED:
253662306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
253762306a36Sopenharmony_ci			     PFX "DREQ received - connection closed\n");
253862306a36Sopenharmony_ci		ch->connected = false;
253962306a36Sopenharmony_ci		if (ib_send_cm_drep(cm_id, NULL, 0))
254062306a36Sopenharmony_ci			shost_printk(KERN_ERR, target->scsi_host,
254162306a36Sopenharmony_ci				     PFX "Sending CM DREP failed\n");
254262306a36Sopenharmony_ci		queue_work(system_long_wq, &target->tl_err_work);
254362306a36Sopenharmony_ci		break;
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci	case IB_CM_TIMEWAIT_EXIT:
254662306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
254762306a36Sopenharmony_ci			     PFX "connection closed\n");
254862306a36Sopenharmony_ci		comp = 1;
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci		ch->status = 0;
255162306a36Sopenharmony_ci		break;
255262306a36Sopenharmony_ci
255362306a36Sopenharmony_ci	case IB_CM_MRA_RECEIVED:
255462306a36Sopenharmony_ci	case IB_CM_DREQ_ERROR:
255562306a36Sopenharmony_ci	case IB_CM_DREP_RECEIVED:
255662306a36Sopenharmony_ci		break;
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	default:
255962306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
256062306a36Sopenharmony_ci			     PFX "Unhandled CM event %d\n", event->event);
256162306a36Sopenharmony_ci		break;
256262306a36Sopenharmony_ci	}
256362306a36Sopenharmony_ci
256462306a36Sopenharmony_ci	if (comp)
256562306a36Sopenharmony_ci		complete(&ch->done);
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	return 0;
256862306a36Sopenharmony_ci}
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_cistatic void srp_rdma_cm_rej_handler(struct srp_rdma_ch *ch,
257162306a36Sopenharmony_ci				    struct rdma_cm_event *event)
257262306a36Sopenharmony_ci{
257362306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
257462306a36Sopenharmony_ci	struct Scsi_Host *shost = target->scsi_host;
257562306a36Sopenharmony_ci	int opcode;
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	switch (event->status) {
257862306a36Sopenharmony_ci	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
257962306a36Sopenharmony_ci		shost_printk(KERN_WARNING, shost,
258062306a36Sopenharmony_ci			    "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
258162306a36Sopenharmony_ci		ch->status = -ECONNRESET;
258262306a36Sopenharmony_ci		break;
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci	case IB_CM_REJ_CONSUMER_DEFINED:
258562306a36Sopenharmony_ci		opcode = *(u8 *) event->param.conn.private_data;
258662306a36Sopenharmony_ci		if (opcode == SRP_LOGIN_REJ) {
258762306a36Sopenharmony_ci			struct srp_login_rej *rej =
258862306a36Sopenharmony_ci				(struct srp_login_rej *)
258962306a36Sopenharmony_ci				event->param.conn.private_data;
259062306a36Sopenharmony_ci			u32 reason = be32_to_cpu(rej->reason);
259162306a36Sopenharmony_ci
259262306a36Sopenharmony_ci			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
259362306a36Sopenharmony_ci				shost_printk(KERN_WARNING, shost,
259462306a36Sopenharmony_ci					     PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
259562306a36Sopenharmony_ci			else
259662306a36Sopenharmony_ci				shost_printk(KERN_WARNING, shost,
259762306a36Sopenharmony_ci					    PFX "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
259862306a36Sopenharmony_ci		} else {
259962306a36Sopenharmony_ci			shost_printk(KERN_WARNING, shost,
260062306a36Sopenharmony_ci				     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED, opcode 0x%02x\n",
260162306a36Sopenharmony_ci				     opcode);
260262306a36Sopenharmony_ci		}
260362306a36Sopenharmony_ci		ch->status = -ECONNRESET;
260462306a36Sopenharmony_ci		break;
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_ci	case IB_CM_REJ_STALE_CONN:
260762306a36Sopenharmony_ci		shost_printk(KERN_WARNING, shost,
260862306a36Sopenharmony_ci			     "  REJ reason: stale connection\n");
260962306a36Sopenharmony_ci		ch->status = SRP_STALE_CONN;
261062306a36Sopenharmony_ci		break;
261162306a36Sopenharmony_ci
261262306a36Sopenharmony_ci	default:
261362306a36Sopenharmony_ci		shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
261462306a36Sopenharmony_ci			     event->status);
261562306a36Sopenharmony_ci		ch->status = -ECONNRESET;
261662306a36Sopenharmony_ci		break;
261762306a36Sopenharmony_ci	}
261862306a36Sopenharmony_ci}
261962306a36Sopenharmony_ci
262062306a36Sopenharmony_cistatic int srp_rdma_cm_handler(struct rdma_cm_id *cm_id,
262162306a36Sopenharmony_ci			       struct rdma_cm_event *event)
262262306a36Sopenharmony_ci{
262362306a36Sopenharmony_ci	struct srp_rdma_ch *ch = cm_id->context;
262462306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
262562306a36Sopenharmony_ci	int comp = 0;
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci	switch (event->event) {
262862306a36Sopenharmony_ci	case RDMA_CM_EVENT_ADDR_RESOLVED:
262962306a36Sopenharmony_ci		ch->status = 0;
263062306a36Sopenharmony_ci		comp = 1;
263162306a36Sopenharmony_ci		break;
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_ci	case RDMA_CM_EVENT_ADDR_ERROR:
263462306a36Sopenharmony_ci		ch->status = -ENXIO;
263562306a36Sopenharmony_ci		comp = 1;
263662306a36Sopenharmony_ci		break;
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	case RDMA_CM_EVENT_ROUTE_RESOLVED:
263962306a36Sopenharmony_ci		ch->status = 0;
264062306a36Sopenharmony_ci		comp = 1;
264162306a36Sopenharmony_ci		break;
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_ci	case RDMA_CM_EVENT_ROUTE_ERROR:
264462306a36Sopenharmony_ci	case RDMA_CM_EVENT_UNREACHABLE:
264562306a36Sopenharmony_ci		ch->status = -EHOSTUNREACH;
264662306a36Sopenharmony_ci		comp = 1;
264762306a36Sopenharmony_ci		break;
264862306a36Sopenharmony_ci
264962306a36Sopenharmony_ci	case RDMA_CM_EVENT_CONNECT_ERROR:
265062306a36Sopenharmony_ci		shost_printk(KERN_DEBUG, target->scsi_host,
265162306a36Sopenharmony_ci			     PFX "Sending CM REQ failed\n");
265262306a36Sopenharmony_ci		comp = 1;
265362306a36Sopenharmony_ci		ch->status = -ECONNRESET;
265462306a36Sopenharmony_ci		break;
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci	case RDMA_CM_EVENT_ESTABLISHED:
265762306a36Sopenharmony_ci		comp = 1;
265862306a36Sopenharmony_ci		srp_cm_rep_handler(NULL, event->param.conn.private_data, ch);
265962306a36Sopenharmony_ci		break;
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci	case RDMA_CM_EVENT_REJECTED:
266262306a36Sopenharmony_ci		shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
266362306a36Sopenharmony_ci		comp = 1;
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_ci		srp_rdma_cm_rej_handler(ch, event);
266662306a36Sopenharmony_ci		break;
266762306a36Sopenharmony_ci
266862306a36Sopenharmony_ci	case RDMA_CM_EVENT_DISCONNECTED:
266962306a36Sopenharmony_ci		if (ch->connected) {
267062306a36Sopenharmony_ci			shost_printk(KERN_WARNING, target->scsi_host,
267162306a36Sopenharmony_ci				     PFX "received DREQ\n");
267262306a36Sopenharmony_ci			rdma_disconnect(ch->rdma_cm.cm_id);
267362306a36Sopenharmony_ci			comp = 1;
267462306a36Sopenharmony_ci			ch->status = 0;
267562306a36Sopenharmony_ci			queue_work(system_long_wq, &target->tl_err_work);
267662306a36Sopenharmony_ci		}
267762306a36Sopenharmony_ci		break;
267862306a36Sopenharmony_ci
267962306a36Sopenharmony_ci	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
268062306a36Sopenharmony_ci		shost_printk(KERN_ERR, target->scsi_host,
268162306a36Sopenharmony_ci			     PFX "connection closed\n");
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_ci		comp = 1;
268462306a36Sopenharmony_ci		ch->status = 0;
268562306a36Sopenharmony_ci		break;
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci	default:
268862306a36Sopenharmony_ci		shost_printk(KERN_WARNING, target->scsi_host,
268962306a36Sopenharmony_ci			     PFX "Unhandled CM event %d\n", event->event);
269062306a36Sopenharmony_ci		break;
269162306a36Sopenharmony_ci	}
269262306a36Sopenharmony_ci
269362306a36Sopenharmony_ci	if (comp)
269462306a36Sopenharmony_ci		complete(&ch->done);
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	return 0;
269762306a36Sopenharmony_ci}
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci/**
270062306a36Sopenharmony_ci * srp_change_queue_depth - setting device queue depth
270162306a36Sopenharmony_ci * @sdev: scsi device struct
270262306a36Sopenharmony_ci * @qdepth: requested queue depth
270362306a36Sopenharmony_ci *
270462306a36Sopenharmony_ci * Returns queue depth.
270562306a36Sopenharmony_ci */
270662306a36Sopenharmony_cistatic int
270762306a36Sopenharmony_cisrp_change_queue_depth(struct scsi_device *sdev, int qdepth)
270862306a36Sopenharmony_ci{
270962306a36Sopenharmony_ci	if (!sdev->tagged_supported)
271062306a36Sopenharmony_ci		qdepth = 1;
271162306a36Sopenharmony_ci	return scsi_change_queue_depth(sdev, qdepth);
271262306a36Sopenharmony_ci}
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_cistatic int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
271562306a36Sopenharmony_ci			     u8 func, u8 *status)
271662306a36Sopenharmony_ci{
271762306a36Sopenharmony_ci	struct srp_target_port *target = ch->target;
271862306a36Sopenharmony_ci	struct srp_rport *rport = target->rport;
271962306a36Sopenharmony_ci	struct ib_device *dev = target->srp_host->srp_dev->dev;
272062306a36Sopenharmony_ci	struct srp_iu *iu;
272162306a36Sopenharmony_ci	struct srp_tsk_mgmt *tsk_mgmt;
272262306a36Sopenharmony_ci	int res;
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_ci	if (!ch->connected || target->qp_in_error)
272562306a36Sopenharmony_ci		return -1;
272662306a36Sopenharmony_ci
272762306a36Sopenharmony_ci	/*
272862306a36Sopenharmony_ci	 * Lock the rport mutex to avoid that srp_create_ch_ib() is
272962306a36Sopenharmony_ci	 * invoked while a task management function is being sent.
273062306a36Sopenharmony_ci	 */
273162306a36Sopenharmony_ci	mutex_lock(&rport->mutex);
273262306a36Sopenharmony_ci	spin_lock_irq(&ch->lock);
273362306a36Sopenharmony_ci	iu = __srp_get_tx_iu(ch, SRP_IU_TSK_MGMT);
273462306a36Sopenharmony_ci	spin_unlock_irq(&ch->lock);
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	if (!iu) {
273762306a36Sopenharmony_ci		mutex_unlock(&rport->mutex);
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci		return -1;
274062306a36Sopenharmony_ci	}
274162306a36Sopenharmony_ci
274262306a36Sopenharmony_ci	iu->num_sge = 1;
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_ci	ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
274562306a36Sopenharmony_ci				   DMA_TO_DEVICE);
274662306a36Sopenharmony_ci	tsk_mgmt = iu->buf;
274762306a36Sopenharmony_ci	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_ci	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
275062306a36Sopenharmony_ci	int_to_scsilun(lun, &tsk_mgmt->lun);
275162306a36Sopenharmony_ci	tsk_mgmt->tsk_mgmt_func = func;
275262306a36Sopenharmony_ci	tsk_mgmt->task_tag	= req_tag;
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci	spin_lock_irq(&ch->lock);
275562306a36Sopenharmony_ci	ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT;
275662306a36Sopenharmony_ci	tsk_mgmt->tag = ch->tsk_mgmt_tag;
275762306a36Sopenharmony_ci	spin_unlock_irq(&ch->lock);
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	init_completion(&ch->tsk_mgmt_done);
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
276262306a36Sopenharmony_ci				      DMA_TO_DEVICE);
276362306a36Sopenharmony_ci	if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
276462306a36Sopenharmony_ci		srp_put_tx_iu(ch, iu, SRP_IU_TSK_MGMT);
276562306a36Sopenharmony_ci		mutex_unlock(&rport->mutex);
276662306a36Sopenharmony_ci
276762306a36Sopenharmony_ci		return -1;
276862306a36Sopenharmony_ci	}
276962306a36Sopenharmony_ci	res = wait_for_completion_timeout(&ch->tsk_mgmt_done,
277062306a36Sopenharmony_ci					msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS));
277162306a36Sopenharmony_ci	if (res > 0 && status)
277262306a36Sopenharmony_ci		*status = ch->tsk_mgmt_status;
277362306a36Sopenharmony_ci	mutex_unlock(&rport->mutex);
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	WARN_ON_ONCE(res < 0);
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci	return res > 0 ? 0 : -1;
277862306a36Sopenharmony_ci}
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_cistatic int srp_abort(struct scsi_cmnd *scmnd)
278162306a36Sopenharmony_ci{
278262306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(scmnd->device->host);
278362306a36Sopenharmony_ci	struct srp_request *req = scsi_cmd_priv(scmnd);
278462306a36Sopenharmony_ci	u32 tag;
278562306a36Sopenharmony_ci	u16 ch_idx;
278662306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_ci	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci	tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmnd));
279162306a36Sopenharmony_ci	ch_idx = blk_mq_unique_tag_to_hwq(tag);
279262306a36Sopenharmony_ci	if (WARN_ON_ONCE(ch_idx >= target->ch_count))
279362306a36Sopenharmony_ci		return SUCCESS;
279462306a36Sopenharmony_ci	ch = &target->ch[ch_idx];
279562306a36Sopenharmony_ci	if (!srp_claim_req(ch, req, NULL, scmnd))
279662306a36Sopenharmony_ci		return SUCCESS;
279762306a36Sopenharmony_ci	shost_printk(KERN_ERR, target->scsi_host,
279862306a36Sopenharmony_ci		     "Sending SRP abort for tag %#x\n", tag);
279962306a36Sopenharmony_ci	if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
280062306a36Sopenharmony_ci			      SRP_TSK_ABORT_TASK, NULL) == 0) {
280162306a36Sopenharmony_ci		srp_free_req(ch, req, scmnd, 0);
280262306a36Sopenharmony_ci		return SUCCESS;
280362306a36Sopenharmony_ci	}
280462306a36Sopenharmony_ci	if (target->rport->state == SRP_RPORT_LOST)
280562306a36Sopenharmony_ci		return FAST_IO_FAIL;
280662306a36Sopenharmony_ci
280762306a36Sopenharmony_ci	return FAILED;
280862306a36Sopenharmony_ci}
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_cistatic int srp_reset_device(struct scsi_cmnd *scmnd)
281162306a36Sopenharmony_ci{
281262306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(scmnd->device->host);
281362306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
281462306a36Sopenharmony_ci	u8 status;
281562306a36Sopenharmony_ci
281662306a36Sopenharmony_ci	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
281762306a36Sopenharmony_ci
281862306a36Sopenharmony_ci	ch = &target->ch[0];
281962306a36Sopenharmony_ci	if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
282062306a36Sopenharmony_ci			      SRP_TSK_LUN_RESET, &status))
282162306a36Sopenharmony_ci		return FAILED;
282262306a36Sopenharmony_ci	if (status)
282362306a36Sopenharmony_ci		return FAILED;
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	return SUCCESS;
282662306a36Sopenharmony_ci}
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_cistatic int srp_reset_host(struct scsi_cmnd *scmnd)
282962306a36Sopenharmony_ci{
283062306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(scmnd->device->host);
283162306a36Sopenharmony_ci
283262306a36Sopenharmony_ci	shost_printk(KERN_ERR, target->scsi_host, PFX "SRP reset_host called\n");
283362306a36Sopenharmony_ci
283462306a36Sopenharmony_ci	return srp_reconnect_rport(target->rport) == 0 ? SUCCESS : FAILED;
283562306a36Sopenharmony_ci}
283662306a36Sopenharmony_ci
283762306a36Sopenharmony_cistatic int srp_target_alloc(struct scsi_target *starget)
283862306a36Sopenharmony_ci{
283962306a36Sopenharmony_ci	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
284062306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(shost);
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci	if (target->target_can_queue)
284362306a36Sopenharmony_ci		starget->can_queue = target->target_can_queue;
284462306a36Sopenharmony_ci	return 0;
284562306a36Sopenharmony_ci}
284662306a36Sopenharmony_ci
284762306a36Sopenharmony_cistatic int srp_slave_configure(struct scsi_device *sdev)
284862306a36Sopenharmony_ci{
284962306a36Sopenharmony_ci	struct Scsi_Host *shost = sdev->host;
285062306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(shost);
285162306a36Sopenharmony_ci	struct request_queue *q = sdev->request_queue;
285262306a36Sopenharmony_ci	unsigned long timeout;
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_ci	if (sdev->type == TYPE_DISK) {
285562306a36Sopenharmony_ci		timeout = max_t(unsigned, 30 * HZ, target->rq_tmo_jiffies);
285662306a36Sopenharmony_ci		blk_queue_rq_timeout(q, timeout);
285762306a36Sopenharmony_ci	}
285862306a36Sopenharmony_ci
285962306a36Sopenharmony_ci	return 0;
286062306a36Sopenharmony_ci}
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_cistatic ssize_t id_ext_show(struct device *dev, struct device_attribute *attr,
286362306a36Sopenharmony_ci			   char *buf)
286462306a36Sopenharmony_ci{
286562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	return sysfs_emit(buf, "0x%016llx\n", be64_to_cpu(target->id_ext));
286862306a36Sopenharmony_ci}
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(id_ext);
287162306a36Sopenharmony_ci
287262306a36Sopenharmony_cistatic ssize_t ioc_guid_show(struct device *dev, struct device_attribute *attr,
287362306a36Sopenharmony_ci			     char *buf)
287462306a36Sopenharmony_ci{
287562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci	return sysfs_emit(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid));
287862306a36Sopenharmony_ci}
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(ioc_guid);
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_cistatic ssize_t service_id_show(struct device *dev,
288362306a36Sopenharmony_ci			       struct device_attribute *attr, char *buf)
288462306a36Sopenharmony_ci{
288562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_ci	if (target->using_rdma_cm)
288862306a36Sopenharmony_ci		return -ENOENT;
288962306a36Sopenharmony_ci	return sysfs_emit(buf, "0x%016llx\n",
289062306a36Sopenharmony_ci			  be64_to_cpu(target->ib_cm.service_id));
289162306a36Sopenharmony_ci}
289262306a36Sopenharmony_ci
289362306a36Sopenharmony_cistatic DEVICE_ATTR_RO(service_id);
289462306a36Sopenharmony_ci
289562306a36Sopenharmony_cistatic ssize_t pkey_show(struct device *dev, struct device_attribute *attr,
289662306a36Sopenharmony_ci			 char *buf)
289762306a36Sopenharmony_ci{
289862306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci	if (target->using_rdma_cm)
290162306a36Sopenharmony_ci		return -ENOENT;
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ci	return sysfs_emit(buf, "0x%04x\n", be16_to_cpu(target->ib_cm.pkey));
290462306a36Sopenharmony_ci}
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(pkey);
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_cistatic ssize_t sgid_show(struct device *dev, struct device_attribute *attr,
290962306a36Sopenharmony_ci			 char *buf)
291062306a36Sopenharmony_ci{
291162306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
291262306a36Sopenharmony_ci
291362306a36Sopenharmony_ci	return sysfs_emit(buf, "%pI6\n", target->sgid.raw);
291462306a36Sopenharmony_ci}
291562306a36Sopenharmony_ci
291662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(sgid);
291762306a36Sopenharmony_ci
291862306a36Sopenharmony_cistatic ssize_t dgid_show(struct device *dev, struct device_attribute *attr,
291962306a36Sopenharmony_ci			 char *buf)
292062306a36Sopenharmony_ci{
292162306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
292262306a36Sopenharmony_ci	struct srp_rdma_ch *ch = &target->ch[0];
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci	if (target->using_rdma_cm)
292562306a36Sopenharmony_ci		return -ENOENT;
292662306a36Sopenharmony_ci
292762306a36Sopenharmony_ci	return sysfs_emit(buf, "%pI6\n", ch->ib_cm.path.dgid.raw);
292862306a36Sopenharmony_ci}
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(dgid);
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_cistatic ssize_t orig_dgid_show(struct device *dev, struct device_attribute *attr,
293362306a36Sopenharmony_ci			      char *buf)
293462306a36Sopenharmony_ci{
293562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci	if (target->using_rdma_cm)
293862306a36Sopenharmony_ci		return -ENOENT;
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	return sysfs_emit(buf, "%pI6\n", target->ib_cm.orig_dgid.raw);
294162306a36Sopenharmony_ci}
294262306a36Sopenharmony_ci
294362306a36Sopenharmony_cistatic DEVICE_ATTR_RO(orig_dgid);
294462306a36Sopenharmony_ci
294562306a36Sopenharmony_cistatic ssize_t req_lim_show(struct device *dev, struct device_attribute *attr,
294662306a36Sopenharmony_ci			    char *buf)
294762306a36Sopenharmony_ci{
294862306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
294962306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
295062306a36Sopenharmony_ci	int i, req_lim = INT_MAX;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++) {
295362306a36Sopenharmony_ci		ch = &target->ch[i];
295462306a36Sopenharmony_ci		req_lim = min(req_lim, ch->req_lim);
295562306a36Sopenharmony_ci	}
295662306a36Sopenharmony_ci
295762306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", req_lim);
295862306a36Sopenharmony_ci}
295962306a36Sopenharmony_ci
296062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(req_lim);
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_cistatic ssize_t zero_req_lim_show(struct device *dev,
296362306a36Sopenharmony_ci				 struct device_attribute *attr, char *buf)
296462306a36Sopenharmony_ci{
296562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
296662306a36Sopenharmony_ci
296762306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", target->zero_req_lim);
296862306a36Sopenharmony_ci}
296962306a36Sopenharmony_ci
297062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(zero_req_lim);
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_cistatic ssize_t local_ib_port_show(struct device *dev,
297362306a36Sopenharmony_ci				  struct device_attribute *attr, char *buf)
297462306a36Sopenharmony_ci{
297562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	return sysfs_emit(buf, "%u\n", target->srp_host->port);
297862306a36Sopenharmony_ci}
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(local_ib_port);
298162306a36Sopenharmony_ci
298262306a36Sopenharmony_cistatic ssize_t local_ib_device_show(struct device *dev,
298362306a36Sopenharmony_ci				    struct device_attribute *attr, char *buf)
298462306a36Sopenharmony_ci{
298562306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci	return sysfs_emit(buf, "%s\n",
298862306a36Sopenharmony_ci			  dev_name(&target->srp_host->srp_dev->dev->dev));
298962306a36Sopenharmony_ci}
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(local_ib_device);
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_cistatic ssize_t ch_count_show(struct device *dev, struct device_attribute *attr,
299462306a36Sopenharmony_ci			     char *buf)
299562306a36Sopenharmony_ci{
299662306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", target->ch_count);
299962306a36Sopenharmony_ci}
300062306a36Sopenharmony_ci
300162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(ch_count);
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_cistatic ssize_t comp_vector_show(struct device *dev,
300462306a36Sopenharmony_ci				struct device_attribute *attr, char *buf)
300562306a36Sopenharmony_ci{
300662306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", target->comp_vector);
300962306a36Sopenharmony_ci}
301062306a36Sopenharmony_ci
301162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(comp_vector);
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_cistatic ssize_t tl_retry_count_show(struct device *dev,
301462306a36Sopenharmony_ci				   struct device_attribute *attr, char *buf)
301562306a36Sopenharmony_ci{
301662306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", target->tl_retry_count);
301962306a36Sopenharmony_ci}
302062306a36Sopenharmony_ci
302162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(tl_retry_count);
302262306a36Sopenharmony_ci
302362306a36Sopenharmony_cistatic ssize_t cmd_sg_entries_show(struct device *dev,
302462306a36Sopenharmony_ci				   struct device_attribute *attr, char *buf)
302562306a36Sopenharmony_ci{
302662306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
302762306a36Sopenharmony_ci
302862306a36Sopenharmony_ci	return sysfs_emit(buf, "%u\n", target->cmd_sg_cnt);
302962306a36Sopenharmony_ci}
303062306a36Sopenharmony_ci
303162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(cmd_sg_entries);
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_cistatic ssize_t allow_ext_sg_show(struct device *dev,
303462306a36Sopenharmony_ci				 struct device_attribute *attr, char *buf)
303562306a36Sopenharmony_ci{
303662306a36Sopenharmony_ci	struct srp_target_port *target = host_to_target(class_to_shost(dev));
303762306a36Sopenharmony_ci
303862306a36Sopenharmony_ci	return sysfs_emit(buf, "%s\n", target->allow_ext_sg ? "true" : "false");
303962306a36Sopenharmony_ci}
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(allow_ext_sg);
304262306a36Sopenharmony_ci
304362306a36Sopenharmony_cistatic struct attribute *srp_host_attrs[] = {
304462306a36Sopenharmony_ci	&dev_attr_id_ext.attr,
304562306a36Sopenharmony_ci	&dev_attr_ioc_guid.attr,
304662306a36Sopenharmony_ci	&dev_attr_service_id.attr,
304762306a36Sopenharmony_ci	&dev_attr_pkey.attr,
304862306a36Sopenharmony_ci	&dev_attr_sgid.attr,
304962306a36Sopenharmony_ci	&dev_attr_dgid.attr,
305062306a36Sopenharmony_ci	&dev_attr_orig_dgid.attr,
305162306a36Sopenharmony_ci	&dev_attr_req_lim.attr,
305262306a36Sopenharmony_ci	&dev_attr_zero_req_lim.attr,
305362306a36Sopenharmony_ci	&dev_attr_local_ib_port.attr,
305462306a36Sopenharmony_ci	&dev_attr_local_ib_device.attr,
305562306a36Sopenharmony_ci	&dev_attr_ch_count.attr,
305662306a36Sopenharmony_ci	&dev_attr_comp_vector.attr,
305762306a36Sopenharmony_ci	&dev_attr_tl_retry_count.attr,
305862306a36Sopenharmony_ci	&dev_attr_cmd_sg_entries.attr,
305962306a36Sopenharmony_ci	&dev_attr_allow_ext_sg.attr,
306062306a36Sopenharmony_ci	NULL
306162306a36Sopenharmony_ci};
306262306a36Sopenharmony_ci
306362306a36Sopenharmony_ciATTRIBUTE_GROUPS(srp_host);
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_cistatic const struct scsi_host_template srp_template = {
306662306a36Sopenharmony_ci	.module				= THIS_MODULE,
306762306a36Sopenharmony_ci	.name				= "InfiniBand SRP initiator",
306862306a36Sopenharmony_ci	.proc_name			= DRV_NAME,
306962306a36Sopenharmony_ci	.target_alloc			= srp_target_alloc,
307062306a36Sopenharmony_ci	.slave_configure		= srp_slave_configure,
307162306a36Sopenharmony_ci	.info				= srp_target_info,
307262306a36Sopenharmony_ci	.init_cmd_priv			= srp_init_cmd_priv,
307362306a36Sopenharmony_ci	.exit_cmd_priv			= srp_exit_cmd_priv,
307462306a36Sopenharmony_ci	.queuecommand			= srp_queuecommand,
307562306a36Sopenharmony_ci	.change_queue_depth             = srp_change_queue_depth,
307662306a36Sopenharmony_ci	.eh_timed_out			= srp_timed_out,
307762306a36Sopenharmony_ci	.eh_abort_handler		= srp_abort,
307862306a36Sopenharmony_ci	.eh_device_reset_handler	= srp_reset_device,
307962306a36Sopenharmony_ci	.eh_host_reset_handler		= srp_reset_host,
308062306a36Sopenharmony_ci	.skip_settle_delay		= true,
308162306a36Sopenharmony_ci	.sg_tablesize			= SRP_DEF_SG_TABLESIZE,
308262306a36Sopenharmony_ci	.can_queue			= SRP_DEFAULT_CMD_SQ_SIZE,
308362306a36Sopenharmony_ci	.this_id			= -1,
308462306a36Sopenharmony_ci	.cmd_per_lun			= SRP_DEFAULT_CMD_SQ_SIZE,
308562306a36Sopenharmony_ci	.shost_groups			= srp_host_groups,
308662306a36Sopenharmony_ci	.track_queue_depth		= 1,
308762306a36Sopenharmony_ci	.cmd_size			= sizeof(struct srp_request),
308862306a36Sopenharmony_ci};
308962306a36Sopenharmony_ci
309062306a36Sopenharmony_cistatic int srp_sdev_count(struct Scsi_Host *host)
309162306a36Sopenharmony_ci{
309262306a36Sopenharmony_ci	struct scsi_device *sdev;
309362306a36Sopenharmony_ci	int c = 0;
309462306a36Sopenharmony_ci
309562306a36Sopenharmony_ci	shost_for_each_device(sdev, host)
309662306a36Sopenharmony_ci		c++;
309762306a36Sopenharmony_ci
309862306a36Sopenharmony_ci	return c;
309962306a36Sopenharmony_ci}
310062306a36Sopenharmony_ci
310162306a36Sopenharmony_ci/*
310262306a36Sopenharmony_ci * Return values:
310362306a36Sopenharmony_ci * < 0 upon failure. Caller is responsible for SRP target port cleanup.
310462306a36Sopenharmony_ci * 0 and target->state == SRP_TARGET_REMOVED if asynchronous target port
310562306a36Sopenharmony_ci *    removal has been scheduled.
310662306a36Sopenharmony_ci * 0 and target->state != SRP_TARGET_REMOVED upon success.
310762306a36Sopenharmony_ci */
310862306a36Sopenharmony_cistatic int srp_add_target(struct srp_host *host, struct srp_target_port *target)
310962306a36Sopenharmony_ci{
311062306a36Sopenharmony_ci	struct srp_rport_identifiers ids;
311162306a36Sopenharmony_ci	struct srp_rport *rport;
311262306a36Sopenharmony_ci
311362306a36Sopenharmony_ci	target->state = SRP_TARGET_SCANNING;
311462306a36Sopenharmony_ci	sprintf(target->target_name, "SRP.T10:%016llX",
311562306a36Sopenharmony_ci		be64_to_cpu(target->id_ext));
311662306a36Sopenharmony_ci
311762306a36Sopenharmony_ci	if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dev.parent))
311862306a36Sopenharmony_ci		return -ENODEV;
311962306a36Sopenharmony_ci
312062306a36Sopenharmony_ci	memcpy(ids.port_id, &target->id_ext, 8);
312162306a36Sopenharmony_ci	memcpy(ids.port_id + 8, &target->ioc_guid, 8);
312262306a36Sopenharmony_ci	ids.roles = SRP_RPORT_ROLE_TARGET;
312362306a36Sopenharmony_ci	rport = srp_rport_add(target->scsi_host, &ids);
312462306a36Sopenharmony_ci	if (IS_ERR(rport)) {
312562306a36Sopenharmony_ci		scsi_remove_host(target->scsi_host);
312662306a36Sopenharmony_ci		return PTR_ERR(rport);
312762306a36Sopenharmony_ci	}
312862306a36Sopenharmony_ci
312962306a36Sopenharmony_ci	rport->lld_data = target;
313062306a36Sopenharmony_ci	target->rport = rport;
313162306a36Sopenharmony_ci
313262306a36Sopenharmony_ci	spin_lock(&host->target_lock);
313362306a36Sopenharmony_ci	list_add_tail(&target->list, &host->target_list);
313462306a36Sopenharmony_ci	spin_unlock(&host->target_lock);
313562306a36Sopenharmony_ci
313662306a36Sopenharmony_ci	scsi_scan_target(&target->scsi_host->shost_gendev,
313762306a36Sopenharmony_ci			 0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
313862306a36Sopenharmony_ci
313962306a36Sopenharmony_ci	if (srp_connected_ch(target) < target->ch_count ||
314062306a36Sopenharmony_ci	    target->qp_in_error) {
314162306a36Sopenharmony_ci		shost_printk(KERN_INFO, target->scsi_host,
314262306a36Sopenharmony_ci			     PFX "SCSI scan failed - removing SCSI host\n");
314362306a36Sopenharmony_ci		srp_queue_remove_work(target);
314462306a36Sopenharmony_ci		goto out;
314562306a36Sopenharmony_ci	}
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci	pr_debug("%s: SCSI scan succeeded - detected %d LUNs\n",
314862306a36Sopenharmony_ci		 dev_name(&target->scsi_host->shost_gendev),
314962306a36Sopenharmony_ci		 srp_sdev_count(target->scsi_host));
315062306a36Sopenharmony_ci
315162306a36Sopenharmony_ci	spin_lock_irq(&target->lock);
315262306a36Sopenharmony_ci	if (target->state == SRP_TARGET_SCANNING)
315362306a36Sopenharmony_ci		target->state = SRP_TARGET_LIVE;
315462306a36Sopenharmony_ci	spin_unlock_irq(&target->lock);
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_ciout:
315762306a36Sopenharmony_ci	return 0;
315862306a36Sopenharmony_ci}
315962306a36Sopenharmony_ci
316062306a36Sopenharmony_cistatic void srp_release_dev(struct device *dev)
316162306a36Sopenharmony_ci{
316262306a36Sopenharmony_ci	struct srp_host *host =
316362306a36Sopenharmony_ci		container_of(dev, struct srp_host, dev);
316462306a36Sopenharmony_ci
316562306a36Sopenharmony_ci	kfree(host);
316662306a36Sopenharmony_ci}
316762306a36Sopenharmony_ci
316862306a36Sopenharmony_cistatic struct attribute *srp_class_attrs[];
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ciATTRIBUTE_GROUPS(srp_class);
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_cistatic struct class srp_class = {
317362306a36Sopenharmony_ci	.name    = "infiniband_srp",
317462306a36Sopenharmony_ci	.dev_groups = srp_class_groups,
317562306a36Sopenharmony_ci	.dev_release = srp_release_dev
317662306a36Sopenharmony_ci};
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci/**
317962306a36Sopenharmony_ci * srp_conn_unique() - check whether the connection to a target is unique
318062306a36Sopenharmony_ci * @host:   SRP host.
318162306a36Sopenharmony_ci * @target: SRP target port.
318262306a36Sopenharmony_ci */
318362306a36Sopenharmony_cistatic bool srp_conn_unique(struct srp_host *host,
318462306a36Sopenharmony_ci			    struct srp_target_port *target)
318562306a36Sopenharmony_ci{
318662306a36Sopenharmony_ci	struct srp_target_port *t;
318762306a36Sopenharmony_ci	bool ret = false;
318862306a36Sopenharmony_ci
318962306a36Sopenharmony_ci	if (target->state == SRP_TARGET_REMOVED)
319062306a36Sopenharmony_ci		goto out;
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci	ret = true;
319362306a36Sopenharmony_ci
319462306a36Sopenharmony_ci	spin_lock(&host->target_lock);
319562306a36Sopenharmony_ci	list_for_each_entry(t, &host->target_list, list) {
319662306a36Sopenharmony_ci		if (t != target &&
319762306a36Sopenharmony_ci		    target->id_ext == t->id_ext &&
319862306a36Sopenharmony_ci		    target->ioc_guid == t->ioc_guid &&
319962306a36Sopenharmony_ci		    target->initiator_ext == t->initiator_ext) {
320062306a36Sopenharmony_ci			ret = false;
320162306a36Sopenharmony_ci			break;
320262306a36Sopenharmony_ci		}
320362306a36Sopenharmony_ci	}
320462306a36Sopenharmony_ci	spin_unlock(&host->target_lock);
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_ciout:
320762306a36Sopenharmony_ci	return ret;
320862306a36Sopenharmony_ci}
320962306a36Sopenharmony_ci
321062306a36Sopenharmony_ci/*
321162306a36Sopenharmony_ci * Target ports are added by writing
321262306a36Sopenharmony_ci *
321362306a36Sopenharmony_ci *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>,
321462306a36Sopenharmony_ci *     pkey=<P_Key>,service_id=<service ID>
321562306a36Sopenharmony_ci * or
321662306a36Sopenharmony_ci *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,
321762306a36Sopenharmony_ci *     [src=<IPv4 address>,]dest=<IPv4 address>:<port number>
321862306a36Sopenharmony_ci *
321962306a36Sopenharmony_ci * to the add_target sysfs attribute.
322062306a36Sopenharmony_ci */
322162306a36Sopenharmony_cienum {
322262306a36Sopenharmony_ci	SRP_OPT_ERR		= 0,
322362306a36Sopenharmony_ci	SRP_OPT_ID_EXT		= 1 << 0,
322462306a36Sopenharmony_ci	SRP_OPT_IOC_GUID	= 1 << 1,
322562306a36Sopenharmony_ci	SRP_OPT_DGID		= 1 << 2,
322662306a36Sopenharmony_ci	SRP_OPT_PKEY		= 1 << 3,
322762306a36Sopenharmony_ci	SRP_OPT_SERVICE_ID	= 1 << 4,
322862306a36Sopenharmony_ci	SRP_OPT_MAX_SECT	= 1 << 5,
322962306a36Sopenharmony_ci	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
323062306a36Sopenharmony_ci	SRP_OPT_IO_CLASS	= 1 << 7,
323162306a36Sopenharmony_ci	SRP_OPT_INITIATOR_EXT	= 1 << 8,
323262306a36Sopenharmony_ci	SRP_OPT_CMD_SG_ENTRIES	= 1 << 9,
323362306a36Sopenharmony_ci	SRP_OPT_ALLOW_EXT_SG	= 1 << 10,
323462306a36Sopenharmony_ci	SRP_OPT_SG_TABLESIZE	= 1 << 11,
323562306a36Sopenharmony_ci	SRP_OPT_COMP_VECTOR	= 1 << 12,
323662306a36Sopenharmony_ci	SRP_OPT_TL_RETRY_COUNT	= 1 << 13,
323762306a36Sopenharmony_ci	SRP_OPT_QUEUE_SIZE	= 1 << 14,
323862306a36Sopenharmony_ci	SRP_OPT_IP_SRC		= 1 << 15,
323962306a36Sopenharmony_ci	SRP_OPT_IP_DEST		= 1 << 16,
324062306a36Sopenharmony_ci	SRP_OPT_TARGET_CAN_QUEUE= 1 << 17,
324162306a36Sopenharmony_ci	SRP_OPT_MAX_IT_IU_SIZE  = 1 << 18,
324262306a36Sopenharmony_ci	SRP_OPT_CH_COUNT	= 1 << 19,
324362306a36Sopenharmony_ci};
324462306a36Sopenharmony_ci
324562306a36Sopenharmony_cistatic unsigned int srp_opt_mandatory[] = {
324662306a36Sopenharmony_ci	SRP_OPT_ID_EXT		|
324762306a36Sopenharmony_ci	SRP_OPT_IOC_GUID	|
324862306a36Sopenharmony_ci	SRP_OPT_DGID		|
324962306a36Sopenharmony_ci	SRP_OPT_PKEY		|
325062306a36Sopenharmony_ci	SRP_OPT_SERVICE_ID,
325162306a36Sopenharmony_ci	SRP_OPT_ID_EXT		|
325262306a36Sopenharmony_ci	SRP_OPT_IOC_GUID	|
325362306a36Sopenharmony_ci	SRP_OPT_IP_DEST,
325462306a36Sopenharmony_ci};
325562306a36Sopenharmony_ci
325662306a36Sopenharmony_cistatic const match_table_t srp_opt_tokens = {
325762306a36Sopenharmony_ci	{ SRP_OPT_ID_EXT,		"id_ext=%s" 		},
325862306a36Sopenharmony_ci	{ SRP_OPT_IOC_GUID,		"ioc_guid=%s" 		},
325962306a36Sopenharmony_ci	{ SRP_OPT_DGID,			"dgid=%s" 		},
326062306a36Sopenharmony_ci	{ SRP_OPT_PKEY,			"pkey=%x" 		},
326162306a36Sopenharmony_ci	{ SRP_OPT_SERVICE_ID,		"service_id=%s"		},
326262306a36Sopenharmony_ci	{ SRP_OPT_MAX_SECT,		"max_sect=%d" 		},
326362306a36Sopenharmony_ci	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
326462306a36Sopenharmony_ci	{ SRP_OPT_TARGET_CAN_QUEUE,	"target_can_queue=%d"	},
326562306a36Sopenharmony_ci	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
326662306a36Sopenharmony_ci	{ SRP_OPT_INITIATOR_EXT,	"initiator_ext=%s"	},
326762306a36Sopenharmony_ci	{ SRP_OPT_CMD_SG_ENTRIES,	"cmd_sg_entries=%u"	},
326862306a36Sopenharmony_ci	{ SRP_OPT_ALLOW_EXT_SG,		"allow_ext_sg=%u"	},
326962306a36Sopenharmony_ci	{ SRP_OPT_SG_TABLESIZE,		"sg_tablesize=%u"	},
327062306a36Sopenharmony_ci	{ SRP_OPT_COMP_VECTOR,		"comp_vector=%u"	},
327162306a36Sopenharmony_ci	{ SRP_OPT_TL_RETRY_COUNT,	"tl_retry_count=%u"	},
327262306a36Sopenharmony_ci	{ SRP_OPT_QUEUE_SIZE,		"queue_size=%d"		},
327362306a36Sopenharmony_ci	{ SRP_OPT_IP_SRC,		"src=%s"		},
327462306a36Sopenharmony_ci	{ SRP_OPT_IP_DEST,		"dest=%s"		},
327562306a36Sopenharmony_ci	{ SRP_OPT_MAX_IT_IU_SIZE,	"max_it_iu_size=%d"	},
327662306a36Sopenharmony_ci	{ SRP_OPT_CH_COUNT,		"ch_count=%u",		},
327762306a36Sopenharmony_ci	{ SRP_OPT_ERR,			NULL 			}
327862306a36Sopenharmony_ci};
327962306a36Sopenharmony_ci
328062306a36Sopenharmony_ci/**
328162306a36Sopenharmony_ci * srp_parse_in - parse an IP address and port number combination
328262306a36Sopenharmony_ci * @net:	   [in]  Network namespace.
328362306a36Sopenharmony_ci * @sa:		   [out] Address family, IP address and port number.
328462306a36Sopenharmony_ci * @addr_port_str: [in]  IP address and port number.
328562306a36Sopenharmony_ci * @has_port:	   [out] Whether or not @addr_port_str includes a port number.
328662306a36Sopenharmony_ci *
328762306a36Sopenharmony_ci * Parse the following address formats:
328862306a36Sopenharmony_ci * - IPv4: <ip_address>:<port>, e.g. 1.2.3.4:5.
328962306a36Sopenharmony_ci * - IPv6: \[<ipv6_address>\]:<port>, e.g. [1::2:3%4]:5.
329062306a36Sopenharmony_ci */
329162306a36Sopenharmony_cistatic int srp_parse_in(struct net *net, struct sockaddr_storage *sa,
329262306a36Sopenharmony_ci			const char *addr_port_str, bool *has_port)
329362306a36Sopenharmony_ci{
329462306a36Sopenharmony_ci	char *addr_end, *addr = kstrdup(addr_port_str, GFP_KERNEL);
329562306a36Sopenharmony_ci	char *port_str;
329662306a36Sopenharmony_ci	int ret;
329762306a36Sopenharmony_ci
329862306a36Sopenharmony_ci	if (!addr)
329962306a36Sopenharmony_ci		return -ENOMEM;
330062306a36Sopenharmony_ci	port_str = strrchr(addr, ':');
330162306a36Sopenharmony_ci	if (port_str && strchr(port_str, ']'))
330262306a36Sopenharmony_ci		port_str = NULL;
330362306a36Sopenharmony_ci	if (port_str)
330462306a36Sopenharmony_ci		*port_str++ = '\0';
330562306a36Sopenharmony_ci	if (has_port)
330662306a36Sopenharmony_ci		*has_port = port_str != NULL;
330762306a36Sopenharmony_ci	ret = inet_pton_with_scope(net, AF_INET, addr, port_str, sa);
330862306a36Sopenharmony_ci	if (ret && addr[0]) {
330962306a36Sopenharmony_ci		addr_end = addr + strlen(addr) - 1;
331062306a36Sopenharmony_ci		if (addr[0] == '[' && *addr_end == ']') {
331162306a36Sopenharmony_ci			*addr_end = '\0';
331262306a36Sopenharmony_ci			ret = inet_pton_with_scope(net, AF_INET6, addr + 1,
331362306a36Sopenharmony_ci						   port_str, sa);
331462306a36Sopenharmony_ci		}
331562306a36Sopenharmony_ci	}
331662306a36Sopenharmony_ci	kfree(addr);
331762306a36Sopenharmony_ci	pr_debug("%s -> %pISpfsc\n", addr_port_str, sa);
331862306a36Sopenharmony_ci	return ret;
331962306a36Sopenharmony_ci}
332062306a36Sopenharmony_ci
332162306a36Sopenharmony_cistatic int srp_parse_options(struct net *net, const char *buf,
332262306a36Sopenharmony_ci			     struct srp_target_port *target)
332362306a36Sopenharmony_ci{
332462306a36Sopenharmony_ci	char *options, *sep_opt;
332562306a36Sopenharmony_ci	char *p;
332662306a36Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
332762306a36Sopenharmony_ci	unsigned long long ull;
332862306a36Sopenharmony_ci	bool has_port;
332962306a36Sopenharmony_ci	int opt_mask = 0;
333062306a36Sopenharmony_ci	int token;
333162306a36Sopenharmony_ci	int ret = -EINVAL;
333262306a36Sopenharmony_ci	int i;
333362306a36Sopenharmony_ci
333462306a36Sopenharmony_ci	options = kstrdup(buf, GFP_KERNEL);
333562306a36Sopenharmony_ci	if (!options)
333662306a36Sopenharmony_ci		return -ENOMEM;
333762306a36Sopenharmony_ci
333862306a36Sopenharmony_ci	sep_opt = options;
333962306a36Sopenharmony_ci	while ((p = strsep(&sep_opt, ",\n")) != NULL) {
334062306a36Sopenharmony_ci		if (!*p)
334162306a36Sopenharmony_ci			continue;
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci		token = match_token(p, srp_opt_tokens, args);
334462306a36Sopenharmony_ci		opt_mask |= token;
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_ci		switch (token) {
334762306a36Sopenharmony_ci		case SRP_OPT_ID_EXT:
334862306a36Sopenharmony_ci			p = match_strdup(args);
334962306a36Sopenharmony_ci			if (!p) {
335062306a36Sopenharmony_ci				ret = -ENOMEM;
335162306a36Sopenharmony_ci				goto out;
335262306a36Sopenharmony_ci			}
335362306a36Sopenharmony_ci			ret = kstrtoull(p, 16, &ull);
335462306a36Sopenharmony_ci			if (ret) {
335562306a36Sopenharmony_ci				pr_warn("invalid id_ext parameter '%s'\n", p);
335662306a36Sopenharmony_ci				kfree(p);
335762306a36Sopenharmony_ci				goto out;
335862306a36Sopenharmony_ci			}
335962306a36Sopenharmony_ci			target->id_ext = cpu_to_be64(ull);
336062306a36Sopenharmony_ci			kfree(p);
336162306a36Sopenharmony_ci			break;
336262306a36Sopenharmony_ci
336362306a36Sopenharmony_ci		case SRP_OPT_IOC_GUID:
336462306a36Sopenharmony_ci			p = match_strdup(args);
336562306a36Sopenharmony_ci			if (!p) {
336662306a36Sopenharmony_ci				ret = -ENOMEM;
336762306a36Sopenharmony_ci				goto out;
336862306a36Sopenharmony_ci			}
336962306a36Sopenharmony_ci			ret = kstrtoull(p, 16, &ull);
337062306a36Sopenharmony_ci			if (ret) {
337162306a36Sopenharmony_ci				pr_warn("invalid ioc_guid parameter '%s'\n", p);
337262306a36Sopenharmony_ci				kfree(p);
337362306a36Sopenharmony_ci				goto out;
337462306a36Sopenharmony_ci			}
337562306a36Sopenharmony_ci			target->ioc_guid = cpu_to_be64(ull);
337662306a36Sopenharmony_ci			kfree(p);
337762306a36Sopenharmony_ci			break;
337862306a36Sopenharmony_ci
337962306a36Sopenharmony_ci		case SRP_OPT_DGID:
338062306a36Sopenharmony_ci			p = match_strdup(args);
338162306a36Sopenharmony_ci			if (!p) {
338262306a36Sopenharmony_ci				ret = -ENOMEM;
338362306a36Sopenharmony_ci				goto out;
338462306a36Sopenharmony_ci			}
338562306a36Sopenharmony_ci			if (strlen(p) != 32) {
338662306a36Sopenharmony_ci				pr_warn("bad dest GID parameter '%s'\n", p);
338762306a36Sopenharmony_ci				kfree(p);
338862306a36Sopenharmony_ci				goto out;
338962306a36Sopenharmony_ci			}
339062306a36Sopenharmony_ci
339162306a36Sopenharmony_ci			ret = hex2bin(target->ib_cm.orig_dgid.raw, p, 16);
339262306a36Sopenharmony_ci			kfree(p);
339362306a36Sopenharmony_ci			if (ret < 0)
339462306a36Sopenharmony_ci				goto out;
339562306a36Sopenharmony_ci			break;
339662306a36Sopenharmony_ci
339762306a36Sopenharmony_ci		case SRP_OPT_PKEY:
339862306a36Sopenharmony_ci			ret = match_hex(args, &token);
339962306a36Sopenharmony_ci			if (ret) {
340062306a36Sopenharmony_ci				pr_warn("bad P_Key parameter '%s'\n", p);
340162306a36Sopenharmony_ci				goto out;
340262306a36Sopenharmony_ci			}
340362306a36Sopenharmony_ci			target->ib_cm.pkey = cpu_to_be16(token);
340462306a36Sopenharmony_ci			break;
340562306a36Sopenharmony_ci
340662306a36Sopenharmony_ci		case SRP_OPT_SERVICE_ID:
340762306a36Sopenharmony_ci			p = match_strdup(args);
340862306a36Sopenharmony_ci			if (!p) {
340962306a36Sopenharmony_ci				ret = -ENOMEM;
341062306a36Sopenharmony_ci				goto out;
341162306a36Sopenharmony_ci			}
341262306a36Sopenharmony_ci			ret = kstrtoull(p, 16, &ull);
341362306a36Sopenharmony_ci			if (ret) {
341462306a36Sopenharmony_ci				pr_warn("bad service_id parameter '%s'\n", p);
341562306a36Sopenharmony_ci				kfree(p);
341662306a36Sopenharmony_ci				goto out;
341762306a36Sopenharmony_ci			}
341862306a36Sopenharmony_ci			target->ib_cm.service_id = cpu_to_be64(ull);
341962306a36Sopenharmony_ci			kfree(p);
342062306a36Sopenharmony_ci			break;
342162306a36Sopenharmony_ci
342262306a36Sopenharmony_ci		case SRP_OPT_IP_SRC:
342362306a36Sopenharmony_ci			p = match_strdup(args);
342462306a36Sopenharmony_ci			if (!p) {
342562306a36Sopenharmony_ci				ret = -ENOMEM;
342662306a36Sopenharmony_ci				goto out;
342762306a36Sopenharmony_ci			}
342862306a36Sopenharmony_ci			ret = srp_parse_in(net, &target->rdma_cm.src.ss, p,
342962306a36Sopenharmony_ci					   NULL);
343062306a36Sopenharmony_ci			if (ret < 0) {
343162306a36Sopenharmony_ci				pr_warn("bad source parameter '%s'\n", p);
343262306a36Sopenharmony_ci				kfree(p);
343362306a36Sopenharmony_ci				goto out;
343462306a36Sopenharmony_ci			}
343562306a36Sopenharmony_ci			target->rdma_cm.src_specified = true;
343662306a36Sopenharmony_ci			kfree(p);
343762306a36Sopenharmony_ci			break;
343862306a36Sopenharmony_ci
343962306a36Sopenharmony_ci		case SRP_OPT_IP_DEST:
344062306a36Sopenharmony_ci			p = match_strdup(args);
344162306a36Sopenharmony_ci			if (!p) {
344262306a36Sopenharmony_ci				ret = -ENOMEM;
344362306a36Sopenharmony_ci				goto out;
344462306a36Sopenharmony_ci			}
344562306a36Sopenharmony_ci			ret = srp_parse_in(net, &target->rdma_cm.dst.ss, p,
344662306a36Sopenharmony_ci					   &has_port);
344762306a36Sopenharmony_ci			if (!has_port)
344862306a36Sopenharmony_ci				ret = -EINVAL;
344962306a36Sopenharmony_ci			if (ret < 0) {
345062306a36Sopenharmony_ci				pr_warn("bad dest parameter '%s'\n", p);
345162306a36Sopenharmony_ci				kfree(p);
345262306a36Sopenharmony_ci				goto out;
345362306a36Sopenharmony_ci			}
345462306a36Sopenharmony_ci			target->using_rdma_cm = true;
345562306a36Sopenharmony_ci			kfree(p);
345662306a36Sopenharmony_ci			break;
345762306a36Sopenharmony_ci
345862306a36Sopenharmony_ci		case SRP_OPT_MAX_SECT:
345962306a36Sopenharmony_ci			ret = match_int(args, &token);
346062306a36Sopenharmony_ci			if (ret) {
346162306a36Sopenharmony_ci				pr_warn("bad max sect parameter '%s'\n", p);
346262306a36Sopenharmony_ci				goto out;
346362306a36Sopenharmony_ci			}
346462306a36Sopenharmony_ci			target->scsi_host->max_sectors = token;
346562306a36Sopenharmony_ci			break;
346662306a36Sopenharmony_ci
346762306a36Sopenharmony_ci		case SRP_OPT_QUEUE_SIZE:
346862306a36Sopenharmony_ci			ret = match_int(args, &token);
346962306a36Sopenharmony_ci			if (ret) {
347062306a36Sopenharmony_ci				pr_warn("match_int() failed for queue_size parameter '%s', Error %d\n",
347162306a36Sopenharmony_ci					p, ret);
347262306a36Sopenharmony_ci				goto out;
347362306a36Sopenharmony_ci			}
347462306a36Sopenharmony_ci			if (token < 1) {
347562306a36Sopenharmony_ci				pr_warn("bad queue_size parameter '%s'\n", p);
347662306a36Sopenharmony_ci				ret = -EINVAL;
347762306a36Sopenharmony_ci				goto out;
347862306a36Sopenharmony_ci			}
347962306a36Sopenharmony_ci			target->scsi_host->can_queue = token;
348062306a36Sopenharmony_ci			target->queue_size = token + SRP_RSP_SQ_SIZE +
348162306a36Sopenharmony_ci					     SRP_TSK_MGMT_SQ_SIZE;
348262306a36Sopenharmony_ci			if (!(opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
348362306a36Sopenharmony_ci				target->scsi_host->cmd_per_lun = token;
348462306a36Sopenharmony_ci			break;
348562306a36Sopenharmony_ci
348662306a36Sopenharmony_ci		case SRP_OPT_MAX_CMD_PER_LUN:
348762306a36Sopenharmony_ci			ret = match_int(args, &token);
348862306a36Sopenharmony_ci			if (ret) {
348962306a36Sopenharmony_ci				pr_warn("match_int() failed for max cmd_per_lun parameter '%s', Error %d\n",
349062306a36Sopenharmony_ci					p, ret);
349162306a36Sopenharmony_ci				goto out;
349262306a36Sopenharmony_ci			}
349362306a36Sopenharmony_ci			if (token < 1) {
349462306a36Sopenharmony_ci				pr_warn("bad max cmd_per_lun parameter '%s'\n",
349562306a36Sopenharmony_ci					p);
349662306a36Sopenharmony_ci				ret = -EINVAL;
349762306a36Sopenharmony_ci				goto out;
349862306a36Sopenharmony_ci			}
349962306a36Sopenharmony_ci			target->scsi_host->cmd_per_lun = token;
350062306a36Sopenharmony_ci			break;
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_ci		case SRP_OPT_TARGET_CAN_QUEUE:
350362306a36Sopenharmony_ci			ret = match_int(args, &token);
350462306a36Sopenharmony_ci			if (ret) {
350562306a36Sopenharmony_ci				pr_warn("match_int() failed for max target_can_queue parameter '%s', Error %d\n",
350662306a36Sopenharmony_ci					p, ret);
350762306a36Sopenharmony_ci				goto out;
350862306a36Sopenharmony_ci			}
350962306a36Sopenharmony_ci			if (token < 1) {
351062306a36Sopenharmony_ci				pr_warn("bad max target_can_queue parameter '%s'\n",
351162306a36Sopenharmony_ci					p);
351262306a36Sopenharmony_ci				ret = -EINVAL;
351362306a36Sopenharmony_ci				goto out;
351462306a36Sopenharmony_ci			}
351562306a36Sopenharmony_ci			target->target_can_queue = token;
351662306a36Sopenharmony_ci			break;
351762306a36Sopenharmony_ci
351862306a36Sopenharmony_ci		case SRP_OPT_IO_CLASS:
351962306a36Sopenharmony_ci			ret = match_hex(args, &token);
352062306a36Sopenharmony_ci			if (ret) {
352162306a36Sopenharmony_ci				pr_warn("bad IO class parameter '%s'\n", p);
352262306a36Sopenharmony_ci				goto out;
352362306a36Sopenharmony_ci			}
352462306a36Sopenharmony_ci			if (token != SRP_REV10_IB_IO_CLASS &&
352562306a36Sopenharmony_ci			    token != SRP_REV16A_IB_IO_CLASS) {
352662306a36Sopenharmony_ci				pr_warn("unknown IO class parameter value %x specified (use %x or %x).\n",
352762306a36Sopenharmony_ci					token, SRP_REV10_IB_IO_CLASS,
352862306a36Sopenharmony_ci					SRP_REV16A_IB_IO_CLASS);
352962306a36Sopenharmony_ci				ret = -EINVAL;
353062306a36Sopenharmony_ci				goto out;
353162306a36Sopenharmony_ci			}
353262306a36Sopenharmony_ci			target->io_class = token;
353362306a36Sopenharmony_ci			break;
353462306a36Sopenharmony_ci
353562306a36Sopenharmony_ci		case SRP_OPT_INITIATOR_EXT:
353662306a36Sopenharmony_ci			p = match_strdup(args);
353762306a36Sopenharmony_ci			if (!p) {
353862306a36Sopenharmony_ci				ret = -ENOMEM;
353962306a36Sopenharmony_ci				goto out;
354062306a36Sopenharmony_ci			}
354162306a36Sopenharmony_ci			ret = kstrtoull(p, 16, &ull);
354262306a36Sopenharmony_ci			if (ret) {
354362306a36Sopenharmony_ci				pr_warn("bad initiator_ext value '%s'\n", p);
354462306a36Sopenharmony_ci				kfree(p);
354562306a36Sopenharmony_ci				goto out;
354662306a36Sopenharmony_ci			}
354762306a36Sopenharmony_ci			target->initiator_ext = cpu_to_be64(ull);
354862306a36Sopenharmony_ci			kfree(p);
354962306a36Sopenharmony_ci			break;
355062306a36Sopenharmony_ci
355162306a36Sopenharmony_ci		case SRP_OPT_CMD_SG_ENTRIES:
355262306a36Sopenharmony_ci			ret = match_int(args, &token);
355362306a36Sopenharmony_ci			if (ret) {
355462306a36Sopenharmony_ci				pr_warn("match_int() failed for max cmd_sg_entries parameter '%s', Error %d\n",
355562306a36Sopenharmony_ci					p, ret);
355662306a36Sopenharmony_ci				goto out;
355762306a36Sopenharmony_ci			}
355862306a36Sopenharmony_ci			if (token < 1 || token > 255) {
355962306a36Sopenharmony_ci				pr_warn("bad max cmd_sg_entries parameter '%s'\n",
356062306a36Sopenharmony_ci					p);
356162306a36Sopenharmony_ci				ret = -EINVAL;
356262306a36Sopenharmony_ci				goto out;
356362306a36Sopenharmony_ci			}
356462306a36Sopenharmony_ci			target->cmd_sg_cnt = token;
356562306a36Sopenharmony_ci			break;
356662306a36Sopenharmony_ci
356762306a36Sopenharmony_ci		case SRP_OPT_ALLOW_EXT_SG:
356862306a36Sopenharmony_ci			ret = match_int(args, &token);
356962306a36Sopenharmony_ci			if (ret) {
357062306a36Sopenharmony_ci				pr_warn("bad allow_ext_sg parameter '%s'\n", p);
357162306a36Sopenharmony_ci				goto out;
357262306a36Sopenharmony_ci			}
357362306a36Sopenharmony_ci			target->allow_ext_sg = !!token;
357462306a36Sopenharmony_ci			break;
357562306a36Sopenharmony_ci
357662306a36Sopenharmony_ci		case SRP_OPT_SG_TABLESIZE:
357762306a36Sopenharmony_ci			ret = match_int(args, &token);
357862306a36Sopenharmony_ci			if (ret) {
357962306a36Sopenharmony_ci				pr_warn("match_int() failed for max sg_tablesize parameter '%s', Error %d\n",
358062306a36Sopenharmony_ci					p, ret);
358162306a36Sopenharmony_ci				goto out;
358262306a36Sopenharmony_ci			}
358362306a36Sopenharmony_ci			if (token < 1 || token > SG_MAX_SEGMENTS) {
358462306a36Sopenharmony_ci				pr_warn("bad max sg_tablesize parameter '%s'\n",
358562306a36Sopenharmony_ci					p);
358662306a36Sopenharmony_ci				ret = -EINVAL;
358762306a36Sopenharmony_ci				goto out;
358862306a36Sopenharmony_ci			}
358962306a36Sopenharmony_ci			target->sg_tablesize = token;
359062306a36Sopenharmony_ci			break;
359162306a36Sopenharmony_ci
359262306a36Sopenharmony_ci		case SRP_OPT_COMP_VECTOR:
359362306a36Sopenharmony_ci			ret = match_int(args, &token);
359462306a36Sopenharmony_ci			if (ret) {
359562306a36Sopenharmony_ci				pr_warn("match_int() failed for comp_vector parameter '%s', Error %d\n",
359662306a36Sopenharmony_ci					p, ret);
359762306a36Sopenharmony_ci				goto out;
359862306a36Sopenharmony_ci			}
359962306a36Sopenharmony_ci			if (token < 0) {
360062306a36Sopenharmony_ci				pr_warn("bad comp_vector parameter '%s'\n", p);
360162306a36Sopenharmony_ci				ret = -EINVAL;
360262306a36Sopenharmony_ci				goto out;
360362306a36Sopenharmony_ci			}
360462306a36Sopenharmony_ci			target->comp_vector = token;
360562306a36Sopenharmony_ci			break;
360662306a36Sopenharmony_ci
360762306a36Sopenharmony_ci		case SRP_OPT_TL_RETRY_COUNT:
360862306a36Sopenharmony_ci			ret = match_int(args, &token);
360962306a36Sopenharmony_ci			if (ret) {
361062306a36Sopenharmony_ci				pr_warn("match_int() failed for tl_retry_count parameter '%s', Error %d\n",
361162306a36Sopenharmony_ci					p, ret);
361262306a36Sopenharmony_ci				goto out;
361362306a36Sopenharmony_ci			}
361462306a36Sopenharmony_ci			if (token < 2 || token > 7) {
361562306a36Sopenharmony_ci				pr_warn("bad tl_retry_count parameter '%s' (must be a number between 2 and 7)\n",
361662306a36Sopenharmony_ci					p);
361762306a36Sopenharmony_ci				ret = -EINVAL;
361862306a36Sopenharmony_ci				goto out;
361962306a36Sopenharmony_ci			}
362062306a36Sopenharmony_ci			target->tl_retry_count = token;
362162306a36Sopenharmony_ci			break;
362262306a36Sopenharmony_ci
362362306a36Sopenharmony_ci		case SRP_OPT_MAX_IT_IU_SIZE:
362462306a36Sopenharmony_ci			ret = match_int(args, &token);
362562306a36Sopenharmony_ci			if (ret) {
362662306a36Sopenharmony_ci				pr_warn("match_int() failed for max it_iu_size parameter '%s', Error %d\n",
362762306a36Sopenharmony_ci					p, ret);
362862306a36Sopenharmony_ci				goto out;
362962306a36Sopenharmony_ci			}
363062306a36Sopenharmony_ci			if (token < 0) {
363162306a36Sopenharmony_ci				pr_warn("bad maximum initiator to target IU size '%s'\n", p);
363262306a36Sopenharmony_ci				ret = -EINVAL;
363362306a36Sopenharmony_ci				goto out;
363462306a36Sopenharmony_ci			}
363562306a36Sopenharmony_ci			target->max_it_iu_size = token;
363662306a36Sopenharmony_ci			break;
363762306a36Sopenharmony_ci
363862306a36Sopenharmony_ci		case SRP_OPT_CH_COUNT:
363962306a36Sopenharmony_ci			ret = match_int(args, &token);
364062306a36Sopenharmony_ci			if (ret) {
364162306a36Sopenharmony_ci				pr_warn("match_int() failed for channel count parameter '%s', Error %d\n",
364262306a36Sopenharmony_ci					p, ret);
364362306a36Sopenharmony_ci				goto out;
364462306a36Sopenharmony_ci			}
364562306a36Sopenharmony_ci			if (token < 1) {
364662306a36Sopenharmony_ci				pr_warn("bad channel count %s\n", p);
364762306a36Sopenharmony_ci				ret = -EINVAL;
364862306a36Sopenharmony_ci				goto out;
364962306a36Sopenharmony_ci			}
365062306a36Sopenharmony_ci			target->ch_count = token;
365162306a36Sopenharmony_ci			break;
365262306a36Sopenharmony_ci
365362306a36Sopenharmony_ci		default:
365462306a36Sopenharmony_ci			pr_warn("unknown parameter or missing value '%s' in target creation request\n",
365562306a36Sopenharmony_ci				p);
365662306a36Sopenharmony_ci			ret = -EINVAL;
365762306a36Sopenharmony_ci			goto out;
365862306a36Sopenharmony_ci		}
365962306a36Sopenharmony_ci	}
366062306a36Sopenharmony_ci
366162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(srp_opt_mandatory); i++) {
366262306a36Sopenharmony_ci		if ((opt_mask & srp_opt_mandatory[i]) == srp_opt_mandatory[i]) {
366362306a36Sopenharmony_ci			ret = 0;
366462306a36Sopenharmony_ci			break;
366562306a36Sopenharmony_ci		}
366662306a36Sopenharmony_ci	}
366762306a36Sopenharmony_ci	if (ret)
366862306a36Sopenharmony_ci		pr_warn("target creation request is missing one or more parameters\n");
366962306a36Sopenharmony_ci
367062306a36Sopenharmony_ci	if (target->scsi_host->cmd_per_lun > target->scsi_host->can_queue
367162306a36Sopenharmony_ci	    && (opt_mask & SRP_OPT_MAX_CMD_PER_LUN))
367262306a36Sopenharmony_ci		pr_warn("cmd_per_lun = %d > queue_size = %d\n",
367362306a36Sopenharmony_ci			target->scsi_host->cmd_per_lun,
367462306a36Sopenharmony_ci			target->scsi_host->can_queue);
367562306a36Sopenharmony_ci
367662306a36Sopenharmony_ciout:
367762306a36Sopenharmony_ci	kfree(options);
367862306a36Sopenharmony_ci	return ret;
367962306a36Sopenharmony_ci}
368062306a36Sopenharmony_ci
368162306a36Sopenharmony_cistatic ssize_t add_target_store(struct device *dev,
368262306a36Sopenharmony_ci				struct device_attribute *attr, const char *buf,
368362306a36Sopenharmony_ci				size_t count)
368462306a36Sopenharmony_ci{
368562306a36Sopenharmony_ci	struct srp_host *host =
368662306a36Sopenharmony_ci		container_of(dev, struct srp_host, dev);
368762306a36Sopenharmony_ci	struct Scsi_Host *target_host;
368862306a36Sopenharmony_ci	struct srp_target_port *target;
368962306a36Sopenharmony_ci	struct srp_rdma_ch *ch;
369062306a36Sopenharmony_ci	struct srp_device *srp_dev = host->srp_dev;
369162306a36Sopenharmony_ci	struct ib_device *ibdev = srp_dev->dev;
369262306a36Sopenharmony_ci	int ret, i, ch_idx;
369362306a36Sopenharmony_ci	unsigned int max_sectors_per_mr, mr_per_cmd = 0;
369462306a36Sopenharmony_ci	bool multich = false;
369562306a36Sopenharmony_ci	uint32_t max_iu_len;
369662306a36Sopenharmony_ci
369762306a36Sopenharmony_ci	target_host = scsi_host_alloc(&srp_template,
369862306a36Sopenharmony_ci				      sizeof (struct srp_target_port));
369962306a36Sopenharmony_ci	if (!target_host)
370062306a36Sopenharmony_ci		return -ENOMEM;
370162306a36Sopenharmony_ci
370262306a36Sopenharmony_ci	target_host->transportt  = ib_srp_transport_template;
370362306a36Sopenharmony_ci	target_host->max_channel = 0;
370462306a36Sopenharmony_ci	target_host->max_id      = 1;
370562306a36Sopenharmony_ci	target_host->max_lun     = -1LL;
370662306a36Sopenharmony_ci	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
370762306a36Sopenharmony_ci	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
370862306a36Sopenharmony_ci
370962306a36Sopenharmony_ci	if (!(ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG))
371062306a36Sopenharmony_ci		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
371162306a36Sopenharmony_ci
371262306a36Sopenharmony_ci	target = host_to_target(target_host);
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ci	target->net		= kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
371562306a36Sopenharmony_ci	target->io_class	= SRP_REV16A_IB_IO_CLASS;
371662306a36Sopenharmony_ci	target->scsi_host	= target_host;
371762306a36Sopenharmony_ci	target->srp_host	= host;
371862306a36Sopenharmony_ci	target->lkey		= host->srp_dev->pd->local_dma_lkey;
371962306a36Sopenharmony_ci	target->global_rkey	= host->srp_dev->global_rkey;
372062306a36Sopenharmony_ci	target->cmd_sg_cnt	= cmd_sg_entries;
372162306a36Sopenharmony_ci	target->sg_tablesize	= indirect_sg_entries ? : cmd_sg_entries;
372262306a36Sopenharmony_ci	target->allow_ext_sg	= allow_ext_sg;
372362306a36Sopenharmony_ci	target->tl_retry_count	= 7;
372462306a36Sopenharmony_ci	target->queue_size	= SRP_DEFAULT_QUEUE_SIZE;
372562306a36Sopenharmony_ci
372662306a36Sopenharmony_ci	/*
372762306a36Sopenharmony_ci	 * Avoid that the SCSI host can be removed by srp_remove_target()
372862306a36Sopenharmony_ci	 * before this function returns.
372962306a36Sopenharmony_ci	 */
373062306a36Sopenharmony_ci	scsi_host_get(target->scsi_host);
373162306a36Sopenharmony_ci
373262306a36Sopenharmony_ci	ret = mutex_lock_interruptible(&host->add_target_mutex);
373362306a36Sopenharmony_ci	if (ret < 0)
373462306a36Sopenharmony_ci		goto put;
373562306a36Sopenharmony_ci
373662306a36Sopenharmony_ci	ret = srp_parse_options(target->net, buf, target);
373762306a36Sopenharmony_ci	if (ret)
373862306a36Sopenharmony_ci		goto out;
373962306a36Sopenharmony_ci
374062306a36Sopenharmony_ci	if (!srp_conn_unique(target->srp_host, target)) {
374162306a36Sopenharmony_ci		if (target->using_rdma_cm) {
374262306a36Sopenharmony_ci			shost_printk(KERN_INFO, target->scsi_host,
374362306a36Sopenharmony_ci				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;dest=%pIS\n",
374462306a36Sopenharmony_ci				     be64_to_cpu(target->id_ext),
374562306a36Sopenharmony_ci				     be64_to_cpu(target->ioc_guid),
374662306a36Sopenharmony_ci				     &target->rdma_cm.dst);
374762306a36Sopenharmony_ci		} else {
374862306a36Sopenharmony_ci			shost_printk(KERN_INFO, target->scsi_host,
374962306a36Sopenharmony_ci				     PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n",
375062306a36Sopenharmony_ci				     be64_to_cpu(target->id_ext),
375162306a36Sopenharmony_ci				     be64_to_cpu(target->ioc_guid),
375262306a36Sopenharmony_ci				     be64_to_cpu(target->initiator_ext));
375362306a36Sopenharmony_ci		}
375462306a36Sopenharmony_ci		ret = -EEXIST;
375562306a36Sopenharmony_ci		goto out;
375662306a36Sopenharmony_ci	}
375762306a36Sopenharmony_ci
375862306a36Sopenharmony_ci	if (!srp_dev->has_fr && !target->allow_ext_sg &&
375962306a36Sopenharmony_ci	    target->cmd_sg_cnt < target->sg_tablesize) {
376062306a36Sopenharmony_ci		pr_warn("No MR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
376162306a36Sopenharmony_ci		target->sg_tablesize = target->cmd_sg_cnt;
376262306a36Sopenharmony_ci	}
376362306a36Sopenharmony_ci
376462306a36Sopenharmony_ci	if (srp_dev->use_fast_reg) {
376562306a36Sopenharmony_ci		bool gaps_reg = ibdev->attrs.kernel_cap_flags &
376662306a36Sopenharmony_ci				 IBK_SG_GAPS_REG;
376762306a36Sopenharmony_ci
376862306a36Sopenharmony_ci		max_sectors_per_mr = srp_dev->max_pages_per_mr <<
376962306a36Sopenharmony_ci				  (ilog2(srp_dev->mr_page_size) - 9);
377062306a36Sopenharmony_ci		if (!gaps_reg) {
377162306a36Sopenharmony_ci			/*
377262306a36Sopenharmony_ci			 * FR can only map one HCA page per entry. If the start
377362306a36Sopenharmony_ci			 * address is not aligned on a HCA page boundary two
377462306a36Sopenharmony_ci			 * entries will be used for the head and the tail
377562306a36Sopenharmony_ci			 * although these two entries combined contain at most
377662306a36Sopenharmony_ci			 * one HCA page of data. Hence the "+ 1" in the
377762306a36Sopenharmony_ci			 * calculation below.
377862306a36Sopenharmony_ci			 *
377962306a36Sopenharmony_ci			 * The indirect data buffer descriptor is contiguous
378062306a36Sopenharmony_ci			 * so the memory for that buffer will only be
378162306a36Sopenharmony_ci			 * registered if register_always is true. Hence add
378262306a36Sopenharmony_ci			 * one to mr_per_cmd if register_always has been set.
378362306a36Sopenharmony_ci			 */
378462306a36Sopenharmony_ci			mr_per_cmd = register_always +
378562306a36Sopenharmony_ci				(target->scsi_host->max_sectors + 1 +
378662306a36Sopenharmony_ci				 max_sectors_per_mr - 1) / max_sectors_per_mr;
378762306a36Sopenharmony_ci		} else {
378862306a36Sopenharmony_ci			mr_per_cmd = register_always +
378962306a36Sopenharmony_ci				(target->sg_tablesize +
379062306a36Sopenharmony_ci				 srp_dev->max_pages_per_mr - 1) /
379162306a36Sopenharmony_ci				srp_dev->max_pages_per_mr;
379262306a36Sopenharmony_ci		}
379362306a36Sopenharmony_ci		pr_debug("max_sectors = %u; max_pages_per_mr = %u; mr_page_size = %u; max_sectors_per_mr = %u; mr_per_cmd = %u\n",
379462306a36Sopenharmony_ci			 target->scsi_host->max_sectors, srp_dev->max_pages_per_mr, srp_dev->mr_page_size,
379562306a36Sopenharmony_ci			 max_sectors_per_mr, mr_per_cmd);
379662306a36Sopenharmony_ci	}
379762306a36Sopenharmony_ci
379862306a36Sopenharmony_ci	target_host->sg_tablesize = target->sg_tablesize;
379962306a36Sopenharmony_ci	target->mr_pool_size = target->scsi_host->can_queue * mr_per_cmd;
380062306a36Sopenharmony_ci	target->mr_per_cmd = mr_per_cmd;
380162306a36Sopenharmony_ci	target->indirect_size = target->sg_tablesize *
380262306a36Sopenharmony_ci				sizeof (struct srp_direct_buf);
380362306a36Sopenharmony_ci	max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
380462306a36Sopenharmony_ci				       srp_use_imm_data,
380562306a36Sopenharmony_ci				       target->max_it_iu_size);
380662306a36Sopenharmony_ci
380762306a36Sopenharmony_ci	INIT_WORK(&target->tl_err_work, srp_tl_err_work);
380862306a36Sopenharmony_ci	INIT_WORK(&target->remove_work, srp_remove_work);
380962306a36Sopenharmony_ci	spin_lock_init(&target->lock);
381062306a36Sopenharmony_ci	ret = rdma_query_gid(ibdev, host->port, 0, &target->sgid);
381162306a36Sopenharmony_ci	if (ret)
381262306a36Sopenharmony_ci		goto out;
381362306a36Sopenharmony_ci
381462306a36Sopenharmony_ci	ret = -ENOMEM;
381562306a36Sopenharmony_ci	if (target->ch_count == 0) {
381662306a36Sopenharmony_ci		target->ch_count =
381762306a36Sopenharmony_ci			min(ch_count ?:
381862306a36Sopenharmony_ci				max(4 * num_online_nodes(),
381962306a36Sopenharmony_ci				    ibdev->num_comp_vectors),
382062306a36Sopenharmony_ci				num_online_cpus());
382162306a36Sopenharmony_ci	}
382262306a36Sopenharmony_ci
382362306a36Sopenharmony_ci	target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
382462306a36Sopenharmony_ci			     GFP_KERNEL);
382562306a36Sopenharmony_ci	if (!target->ch)
382662306a36Sopenharmony_ci		goto out;
382762306a36Sopenharmony_ci
382862306a36Sopenharmony_ci	for (ch_idx = 0; ch_idx < target->ch_count; ++ch_idx) {
382962306a36Sopenharmony_ci		ch = &target->ch[ch_idx];
383062306a36Sopenharmony_ci		ch->target = target;
383162306a36Sopenharmony_ci		ch->comp_vector = ch_idx % ibdev->num_comp_vectors;
383262306a36Sopenharmony_ci		spin_lock_init(&ch->lock);
383362306a36Sopenharmony_ci		INIT_LIST_HEAD(&ch->free_tx);
383462306a36Sopenharmony_ci		ret = srp_new_cm_id(ch);
383562306a36Sopenharmony_ci		if (ret)
383662306a36Sopenharmony_ci			goto err_disconnect;
383762306a36Sopenharmony_ci
383862306a36Sopenharmony_ci		ret = srp_create_ch_ib(ch);
383962306a36Sopenharmony_ci		if (ret)
384062306a36Sopenharmony_ci			goto err_disconnect;
384162306a36Sopenharmony_ci
384262306a36Sopenharmony_ci		ret = srp_connect_ch(ch, max_iu_len, multich);
384362306a36Sopenharmony_ci		if (ret) {
384462306a36Sopenharmony_ci			char dst[64];
384562306a36Sopenharmony_ci
384662306a36Sopenharmony_ci			if (target->using_rdma_cm)
384762306a36Sopenharmony_ci				snprintf(dst, sizeof(dst), "%pIS",
384862306a36Sopenharmony_ci					&target->rdma_cm.dst);
384962306a36Sopenharmony_ci			else
385062306a36Sopenharmony_ci				snprintf(dst, sizeof(dst), "%pI6",
385162306a36Sopenharmony_ci					target->ib_cm.orig_dgid.raw);
385262306a36Sopenharmony_ci			shost_printk(KERN_ERR, target->scsi_host,
385362306a36Sopenharmony_ci				PFX "Connection %d/%d to %s failed\n",
385462306a36Sopenharmony_ci				ch_idx,
385562306a36Sopenharmony_ci				target->ch_count, dst);
385662306a36Sopenharmony_ci			if (ch_idx == 0) {
385762306a36Sopenharmony_ci				goto free_ch;
385862306a36Sopenharmony_ci			} else {
385962306a36Sopenharmony_ci				srp_free_ch_ib(target, ch);
386062306a36Sopenharmony_ci				target->ch_count = ch - target->ch;
386162306a36Sopenharmony_ci				goto connected;
386262306a36Sopenharmony_ci			}
386362306a36Sopenharmony_ci		}
386462306a36Sopenharmony_ci		multich = true;
386562306a36Sopenharmony_ci	}
386662306a36Sopenharmony_ci
386762306a36Sopenharmony_ciconnected:
386862306a36Sopenharmony_ci	target->scsi_host->nr_hw_queues = target->ch_count;
386962306a36Sopenharmony_ci
387062306a36Sopenharmony_ci	ret = srp_add_target(host, target);
387162306a36Sopenharmony_ci	if (ret)
387262306a36Sopenharmony_ci		goto err_disconnect;
387362306a36Sopenharmony_ci
387462306a36Sopenharmony_ci	if (target->state != SRP_TARGET_REMOVED) {
387562306a36Sopenharmony_ci		if (target->using_rdma_cm) {
387662306a36Sopenharmony_ci			shost_printk(KERN_DEBUG, target->scsi_host, PFX
387762306a36Sopenharmony_ci				     "new target: id_ext %016llx ioc_guid %016llx sgid %pI6 dest %pIS\n",
387862306a36Sopenharmony_ci				     be64_to_cpu(target->id_ext),
387962306a36Sopenharmony_ci				     be64_to_cpu(target->ioc_guid),
388062306a36Sopenharmony_ci				     target->sgid.raw, &target->rdma_cm.dst);
388162306a36Sopenharmony_ci		} else {
388262306a36Sopenharmony_ci			shost_printk(KERN_DEBUG, target->scsi_host, PFX
388362306a36Sopenharmony_ci				     "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
388462306a36Sopenharmony_ci				     be64_to_cpu(target->id_ext),
388562306a36Sopenharmony_ci				     be64_to_cpu(target->ioc_guid),
388662306a36Sopenharmony_ci				     be16_to_cpu(target->ib_cm.pkey),
388762306a36Sopenharmony_ci				     be64_to_cpu(target->ib_cm.service_id),
388862306a36Sopenharmony_ci				     target->sgid.raw,
388962306a36Sopenharmony_ci				     target->ib_cm.orig_dgid.raw);
389062306a36Sopenharmony_ci		}
389162306a36Sopenharmony_ci	}
389262306a36Sopenharmony_ci
389362306a36Sopenharmony_ci	ret = count;
389462306a36Sopenharmony_ci
389562306a36Sopenharmony_ciout:
389662306a36Sopenharmony_ci	mutex_unlock(&host->add_target_mutex);
389762306a36Sopenharmony_ci
389862306a36Sopenharmony_ciput:
389962306a36Sopenharmony_ci	scsi_host_put(target->scsi_host);
390062306a36Sopenharmony_ci	if (ret < 0) {
390162306a36Sopenharmony_ci		/*
390262306a36Sopenharmony_ci		 * If a call to srp_remove_target() has not been scheduled,
390362306a36Sopenharmony_ci		 * drop the network namespace reference now that was obtained
390462306a36Sopenharmony_ci		 * earlier in this function.
390562306a36Sopenharmony_ci		 */
390662306a36Sopenharmony_ci		if (target->state != SRP_TARGET_REMOVED)
390762306a36Sopenharmony_ci			kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
390862306a36Sopenharmony_ci		scsi_host_put(target->scsi_host);
390962306a36Sopenharmony_ci	}
391062306a36Sopenharmony_ci
391162306a36Sopenharmony_ci	return ret;
391262306a36Sopenharmony_ci
391362306a36Sopenharmony_cierr_disconnect:
391462306a36Sopenharmony_ci	srp_disconnect_target(target);
391562306a36Sopenharmony_ci
391662306a36Sopenharmony_cifree_ch:
391762306a36Sopenharmony_ci	for (i = 0; i < target->ch_count; i++) {
391862306a36Sopenharmony_ci		ch = &target->ch[i];
391962306a36Sopenharmony_ci		srp_free_ch_ib(target, ch);
392062306a36Sopenharmony_ci	}
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci	kfree(target->ch);
392362306a36Sopenharmony_ci	goto out;
392462306a36Sopenharmony_ci}
392562306a36Sopenharmony_ci
392662306a36Sopenharmony_cistatic DEVICE_ATTR_WO(add_target);
392762306a36Sopenharmony_ci
392862306a36Sopenharmony_cistatic ssize_t ibdev_show(struct device *dev, struct device_attribute *attr,
392962306a36Sopenharmony_ci			  char *buf)
393062306a36Sopenharmony_ci{
393162306a36Sopenharmony_ci	struct srp_host *host = container_of(dev, struct srp_host, dev);
393262306a36Sopenharmony_ci
393362306a36Sopenharmony_ci	return sysfs_emit(buf, "%s\n", dev_name(&host->srp_dev->dev->dev));
393462306a36Sopenharmony_ci}
393562306a36Sopenharmony_ci
393662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(ibdev);
393762306a36Sopenharmony_ci
393862306a36Sopenharmony_cistatic ssize_t port_show(struct device *dev, struct device_attribute *attr,
393962306a36Sopenharmony_ci			 char *buf)
394062306a36Sopenharmony_ci{
394162306a36Sopenharmony_ci	struct srp_host *host = container_of(dev, struct srp_host, dev);
394262306a36Sopenharmony_ci
394362306a36Sopenharmony_ci	return sysfs_emit(buf, "%u\n", host->port);
394462306a36Sopenharmony_ci}
394562306a36Sopenharmony_ci
394662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(port);
394762306a36Sopenharmony_ci
394862306a36Sopenharmony_cistatic struct attribute *srp_class_attrs[] = {
394962306a36Sopenharmony_ci	&dev_attr_add_target.attr,
395062306a36Sopenharmony_ci	&dev_attr_ibdev.attr,
395162306a36Sopenharmony_ci	&dev_attr_port.attr,
395262306a36Sopenharmony_ci	NULL
395362306a36Sopenharmony_ci};
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_cistatic struct srp_host *srp_add_port(struct srp_device *device, u32 port)
395662306a36Sopenharmony_ci{
395762306a36Sopenharmony_ci	struct srp_host *host;
395862306a36Sopenharmony_ci
395962306a36Sopenharmony_ci	host = kzalloc(sizeof *host, GFP_KERNEL);
396062306a36Sopenharmony_ci	if (!host)
396162306a36Sopenharmony_ci		return NULL;
396262306a36Sopenharmony_ci
396362306a36Sopenharmony_ci	INIT_LIST_HEAD(&host->target_list);
396462306a36Sopenharmony_ci	spin_lock_init(&host->target_lock);
396562306a36Sopenharmony_ci	mutex_init(&host->add_target_mutex);
396662306a36Sopenharmony_ci	host->srp_dev = device;
396762306a36Sopenharmony_ci	host->port = port;
396862306a36Sopenharmony_ci
396962306a36Sopenharmony_ci	device_initialize(&host->dev);
397062306a36Sopenharmony_ci	host->dev.class = &srp_class;
397162306a36Sopenharmony_ci	host->dev.parent = device->dev->dev.parent;
397262306a36Sopenharmony_ci	if (dev_set_name(&host->dev, "srp-%s-%u", dev_name(&device->dev->dev),
397362306a36Sopenharmony_ci			 port))
397462306a36Sopenharmony_ci		goto put_host;
397562306a36Sopenharmony_ci	if (device_add(&host->dev))
397662306a36Sopenharmony_ci		goto put_host;
397762306a36Sopenharmony_ci
397862306a36Sopenharmony_ci	return host;
397962306a36Sopenharmony_ci
398062306a36Sopenharmony_ciput_host:
398162306a36Sopenharmony_ci	device_del(&host->dev);
398262306a36Sopenharmony_ci	put_device(&host->dev);
398362306a36Sopenharmony_ci	return NULL;
398462306a36Sopenharmony_ci}
398562306a36Sopenharmony_ci
398662306a36Sopenharmony_cistatic void srp_rename_dev(struct ib_device *device, void *client_data)
398762306a36Sopenharmony_ci{
398862306a36Sopenharmony_ci	struct srp_device *srp_dev = client_data;
398962306a36Sopenharmony_ci	struct srp_host *host, *tmp_host;
399062306a36Sopenharmony_ci
399162306a36Sopenharmony_ci	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
399262306a36Sopenharmony_ci		char name[IB_DEVICE_NAME_MAX + 8];
399362306a36Sopenharmony_ci
399462306a36Sopenharmony_ci		snprintf(name, sizeof(name), "srp-%s-%u",
399562306a36Sopenharmony_ci			 dev_name(&device->dev), host->port);
399662306a36Sopenharmony_ci		device_rename(&host->dev, name);
399762306a36Sopenharmony_ci	}
399862306a36Sopenharmony_ci}
399962306a36Sopenharmony_ci
400062306a36Sopenharmony_cistatic int srp_add_one(struct ib_device *device)
400162306a36Sopenharmony_ci{
400262306a36Sopenharmony_ci	struct srp_device *srp_dev;
400362306a36Sopenharmony_ci	struct ib_device_attr *attr = &device->attrs;
400462306a36Sopenharmony_ci	struct srp_host *host;
400562306a36Sopenharmony_ci	int mr_page_shift;
400662306a36Sopenharmony_ci	u32 p;
400762306a36Sopenharmony_ci	u64 max_pages_per_mr;
400862306a36Sopenharmony_ci	unsigned int flags = 0;
400962306a36Sopenharmony_ci
401062306a36Sopenharmony_ci	srp_dev = kzalloc(sizeof(*srp_dev), GFP_KERNEL);
401162306a36Sopenharmony_ci	if (!srp_dev)
401262306a36Sopenharmony_ci		return -ENOMEM;
401362306a36Sopenharmony_ci
401462306a36Sopenharmony_ci	/*
401562306a36Sopenharmony_ci	 * Use the smallest page size supported by the HCA, down to a
401662306a36Sopenharmony_ci	 * minimum of 4096 bytes. We're unlikely to build large sglists
401762306a36Sopenharmony_ci	 * out of smaller entries.
401862306a36Sopenharmony_ci	 */
401962306a36Sopenharmony_ci	mr_page_shift		= max(12, ffs(attr->page_size_cap) - 1);
402062306a36Sopenharmony_ci	srp_dev->mr_page_size	= 1 << mr_page_shift;
402162306a36Sopenharmony_ci	srp_dev->mr_page_mask	= ~((u64) srp_dev->mr_page_size - 1);
402262306a36Sopenharmony_ci	max_pages_per_mr	= attr->max_mr_size;
402362306a36Sopenharmony_ci	do_div(max_pages_per_mr, srp_dev->mr_page_size);
402462306a36Sopenharmony_ci	pr_debug("%s: %llu / %u = %llu <> %u\n", __func__,
402562306a36Sopenharmony_ci		 attr->max_mr_size, srp_dev->mr_page_size,
402662306a36Sopenharmony_ci		 max_pages_per_mr, SRP_MAX_PAGES_PER_MR);
402762306a36Sopenharmony_ci	srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR,
402862306a36Sopenharmony_ci					  max_pages_per_mr);
402962306a36Sopenharmony_ci
403062306a36Sopenharmony_ci	srp_dev->has_fr = (attr->device_cap_flags &
403162306a36Sopenharmony_ci			   IB_DEVICE_MEM_MGT_EXTENSIONS);
403262306a36Sopenharmony_ci	if (!never_register && !srp_dev->has_fr)
403362306a36Sopenharmony_ci		dev_warn(&device->dev, "FR is not supported\n");
403462306a36Sopenharmony_ci	else if (!never_register &&
403562306a36Sopenharmony_ci		 attr->max_mr_size >= 2 * srp_dev->mr_page_size)
403662306a36Sopenharmony_ci		srp_dev->use_fast_reg = srp_dev->has_fr;
403762306a36Sopenharmony_ci
403862306a36Sopenharmony_ci	if (never_register || !register_always || !srp_dev->has_fr)
403962306a36Sopenharmony_ci		flags |= IB_PD_UNSAFE_GLOBAL_RKEY;
404062306a36Sopenharmony_ci
404162306a36Sopenharmony_ci	if (srp_dev->use_fast_reg) {
404262306a36Sopenharmony_ci		srp_dev->max_pages_per_mr =
404362306a36Sopenharmony_ci			min_t(u32, srp_dev->max_pages_per_mr,
404462306a36Sopenharmony_ci			      attr->max_fast_reg_page_list_len);
404562306a36Sopenharmony_ci	}
404662306a36Sopenharmony_ci	srp_dev->mr_max_size	= srp_dev->mr_page_size *
404762306a36Sopenharmony_ci				   srp_dev->max_pages_per_mr;
404862306a36Sopenharmony_ci	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",
404962306a36Sopenharmony_ci		 dev_name(&device->dev), mr_page_shift, attr->max_mr_size,
405062306a36Sopenharmony_ci		 attr->max_fast_reg_page_list_len,
405162306a36Sopenharmony_ci		 srp_dev->max_pages_per_mr, srp_dev->mr_max_size);
405262306a36Sopenharmony_ci
405362306a36Sopenharmony_ci	INIT_LIST_HEAD(&srp_dev->dev_list);
405462306a36Sopenharmony_ci
405562306a36Sopenharmony_ci	srp_dev->dev = device;
405662306a36Sopenharmony_ci	srp_dev->pd  = ib_alloc_pd(device, flags);
405762306a36Sopenharmony_ci	if (IS_ERR(srp_dev->pd)) {
405862306a36Sopenharmony_ci		int ret = PTR_ERR(srp_dev->pd);
405962306a36Sopenharmony_ci
406062306a36Sopenharmony_ci		kfree(srp_dev);
406162306a36Sopenharmony_ci		return ret;
406262306a36Sopenharmony_ci	}
406362306a36Sopenharmony_ci
406462306a36Sopenharmony_ci	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
406562306a36Sopenharmony_ci		srp_dev->global_rkey = srp_dev->pd->unsafe_global_rkey;
406662306a36Sopenharmony_ci		WARN_ON_ONCE(srp_dev->global_rkey == 0);
406762306a36Sopenharmony_ci	}
406862306a36Sopenharmony_ci
406962306a36Sopenharmony_ci	rdma_for_each_port (device, p) {
407062306a36Sopenharmony_ci		host = srp_add_port(srp_dev, p);
407162306a36Sopenharmony_ci		if (host)
407262306a36Sopenharmony_ci			list_add_tail(&host->list, &srp_dev->dev_list);
407362306a36Sopenharmony_ci	}
407462306a36Sopenharmony_ci
407562306a36Sopenharmony_ci	ib_set_client_data(device, &srp_client, srp_dev);
407662306a36Sopenharmony_ci	return 0;
407762306a36Sopenharmony_ci}
407862306a36Sopenharmony_ci
407962306a36Sopenharmony_cistatic void srp_remove_one(struct ib_device *device, void *client_data)
408062306a36Sopenharmony_ci{
408162306a36Sopenharmony_ci	struct srp_device *srp_dev;
408262306a36Sopenharmony_ci	struct srp_host *host, *tmp_host;
408362306a36Sopenharmony_ci	struct srp_target_port *target;
408462306a36Sopenharmony_ci
408562306a36Sopenharmony_ci	srp_dev = client_data;
408662306a36Sopenharmony_ci
408762306a36Sopenharmony_ci	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
408862306a36Sopenharmony_ci		/*
408962306a36Sopenharmony_ci		 * Remove the add_target sysfs entry so that no new target ports
409062306a36Sopenharmony_ci		 * can be created.
409162306a36Sopenharmony_ci		 */
409262306a36Sopenharmony_ci		device_del(&host->dev);
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_ci		/*
409562306a36Sopenharmony_ci		 * Remove all target ports.
409662306a36Sopenharmony_ci		 */
409762306a36Sopenharmony_ci		spin_lock(&host->target_lock);
409862306a36Sopenharmony_ci		list_for_each_entry(target, &host->target_list, list)
409962306a36Sopenharmony_ci			srp_queue_remove_work(target);
410062306a36Sopenharmony_ci		spin_unlock(&host->target_lock);
410162306a36Sopenharmony_ci
410262306a36Sopenharmony_ci		/*
410362306a36Sopenharmony_ci		 * srp_queue_remove_work() queues a call to
410462306a36Sopenharmony_ci		 * srp_remove_target(). The latter function cancels
410562306a36Sopenharmony_ci		 * target->tl_err_work so waiting for the remove works to
410662306a36Sopenharmony_ci		 * finish is sufficient.
410762306a36Sopenharmony_ci		 */
410862306a36Sopenharmony_ci		flush_workqueue(srp_remove_wq);
410962306a36Sopenharmony_ci
411062306a36Sopenharmony_ci		put_device(&host->dev);
411162306a36Sopenharmony_ci	}
411262306a36Sopenharmony_ci
411362306a36Sopenharmony_ci	ib_dealloc_pd(srp_dev->pd);
411462306a36Sopenharmony_ci
411562306a36Sopenharmony_ci	kfree(srp_dev);
411662306a36Sopenharmony_ci}
411762306a36Sopenharmony_ci
411862306a36Sopenharmony_cistatic struct srp_function_template ib_srp_transport_functions = {
411962306a36Sopenharmony_ci	.has_rport_state	 = true,
412062306a36Sopenharmony_ci	.reset_timer_if_blocked	 = true,
412162306a36Sopenharmony_ci	.reconnect_delay	 = &srp_reconnect_delay,
412262306a36Sopenharmony_ci	.fast_io_fail_tmo	 = &srp_fast_io_fail_tmo,
412362306a36Sopenharmony_ci	.dev_loss_tmo		 = &srp_dev_loss_tmo,
412462306a36Sopenharmony_ci	.reconnect		 = srp_rport_reconnect,
412562306a36Sopenharmony_ci	.rport_delete		 = srp_rport_delete,
412662306a36Sopenharmony_ci	.terminate_rport_io	 = srp_terminate_io,
412762306a36Sopenharmony_ci};
412862306a36Sopenharmony_ci
412962306a36Sopenharmony_cistatic int __init srp_init_module(void)
413062306a36Sopenharmony_ci{
413162306a36Sopenharmony_ci	int ret;
413262306a36Sopenharmony_ci
413362306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct srp_aer_req) != 36);
413462306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct srp_cmd) != 48);
413562306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct srp_imm_buf) != 4);
413662306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct srp_indirect_buf) != 20);
413762306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct srp_login_req) != 64);
413862306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct srp_login_req_rdma) != 56);
413962306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct srp_rsp) != 36);
414062306a36Sopenharmony_ci
414162306a36Sopenharmony_ci	if (srp_sg_tablesize) {
414262306a36Sopenharmony_ci		pr_warn("srp_sg_tablesize is deprecated, please use cmd_sg_entries\n");
414362306a36Sopenharmony_ci		if (!cmd_sg_entries)
414462306a36Sopenharmony_ci			cmd_sg_entries = srp_sg_tablesize;
414562306a36Sopenharmony_ci	}
414662306a36Sopenharmony_ci
414762306a36Sopenharmony_ci	if (!cmd_sg_entries)
414862306a36Sopenharmony_ci		cmd_sg_entries = SRP_DEF_SG_TABLESIZE;
414962306a36Sopenharmony_ci
415062306a36Sopenharmony_ci	if (cmd_sg_entries > 255) {
415162306a36Sopenharmony_ci		pr_warn("Clamping cmd_sg_entries to 255\n");
415262306a36Sopenharmony_ci		cmd_sg_entries = 255;
415362306a36Sopenharmony_ci	}
415462306a36Sopenharmony_ci
415562306a36Sopenharmony_ci	if (!indirect_sg_entries)
415662306a36Sopenharmony_ci		indirect_sg_entries = cmd_sg_entries;
415762306a36Sopenharmony_ci	else if (indirect_sg_entries < cmd_sg_entries) {
415862306a36Sopenharmony_ci		pr_warn("Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n",
415962306a36Sopenharmony_ci			cmd_sg_entries);
416062306a36Sopenharmony_ci		indirect_sg_entries = cmd_sg_entries;
416162306a36Sopenharmony_ci	}
416262306a36Sopenharmony_ci
416362306a36Sopenharmony_ci	if (indirect_sg_entries > SG_MAX_SEGMENTS) {
416462306a36Sopenharmony_ci		pr_warn("Clamping indirect_sg_entries to %u\n",
416562306a36Sopenharmony_ci			SG_MAX_SEGMENTS);
416662306a36Sopenharmony_ci		indirect_sg_entries = SG_MAX_SEGMENTS;
416762306a36Sopenharmony_ci	}
416862306a36Sopenharmony_ci
416962306a36Sopenharmony_ci	srp_remove_wq = create_workqueue("srp_remove");
417062306a36Sopenharmony_ci	if (!srp_remove_wq) {
417162306a36Sopenharmony_ci		ret = -ENOMEM;
417262306a36Sopenharmony_ci		goto out;
417362306a36Sopenharmony_ci	}
417462306a36Sopenharmony_ci
417562306a36Sopenharmony_ci	ret = -ENOMEM;
417662306a36Sopenharmony_ci	ib_srp_transport_template =
417762306a36Sopenharmony_ci		srp_attach_transport(&ib_srp_transport_functions);
417862306a36Sopenharmony_ci	if (!ib_srp_transport_template)
417962306a36Sopenharmony_ci		goto destroy_wq;
418062306a36Sopenharmony_ci
418162306a36Sopenharmony_ci	ret = class_register(&srp_class);
418262306a36Sopenharmony_ci	if (ret) {
418362306a36Sopenharmony_ci		pr_err("couldn't register class infiniband_srp\n");
418462306a36Sopenharmony_ci		goto release_tr;
418562306a36Sopenharmony_ci	}
418662306a36Sopenharmony_ci
418762306a36Sopenharmony_ci	ib_sa_register_client(&srp_sa_client);
418862306a36Sopenharmony_ci
418962306a36Sopenharmony_ci	ret = ib_register_client(&srp_client);
419062306a36Sopenharmony_ci	if (ret) {
419162306a36Sopenharmony_ci		pr_err("couldn't register IB client\n");
419262306a36Sopenharmony_ci		goto unreg_sa;
419362306a36Sopenharmony_ci	}
419462306a36Sopenharmony_ci
419562306a36Sopenharmony_ciout:
419662306a36Sopenharmony_ci	return ret;
419762306a36Sopenharmony_ci
419862306a36Sopenharmony_ciunreg_sa:
419962306a36Sopenharmony_ci	ib_sa_unregister_client(&srp_sa_client);
420062306a36Sopenharmony_ci	class_unregister(&srp_class);
420162306a36Sopenharmony_ci
420262306a36Sopenharmony_cirelease_tr:
420362306a36Sopenharmony_ci	srp_release_transport(ib_srp_transport_template);
420462306a36Sopenharmony_ci
420562306a36Sopenharmony_cidestroy_wq:
420662306a36Sopenharmony_ci	destroy_workqueue(srp_remove_wq);
420762306a36Sopenharmony_ci	goto out;
420862306a36Sopenharmony_ci}
420962306a36Sopenharmony_ci
421062306a36Sopenharmony_cistatic void __exit srp_cleanup_module(void)
421162306a36Sopenharmony_ci{
421262306a36Sopenharmony_ci	ib_unregister_client(&srp_client);
421362306a36Sopenharmony_ci	ib_sa_unregister_client(&srp_sa_client);
421462306a36Sopenharmony_ci	class_unregister(&srp_class);
421562306a36Sopenharmony_ci	srp_release_transport(ib_srp_transport_template);
421662306a36Sopenharmony_ci	destroy_workqueue(srp_remove_wq);
421762306a36Sopenharmony_ci}
421862306a36Sopenharmony_ci
421962306a36Sopenharmony_cimodule_init(srp_init_module);
422062306a36Sopenharmony_cimodule_exit(srp_cleanup_module);
4221