Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc1bdbd9 authored by Bart Van Assche's avatar Bart Van Assche Committed by Roland Dreier
Browse files

IB/srp: Allow SRP disconnect through sysfs



Make it possible to disconnect the IB RC connection used by the SRP
protocol to communicate with a target.

Have the SRP transport layer create a sysfs "delete" attribute for
initiator drivers that support this functionality.

Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Acked-by: default avatarDavid Dillow <dillowda@ornl.gov>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 7e1265bf
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
What:		/sys/class/srp_remote_ports/port-<h>:<n>/delete
Date:		June 1, 2012
KernelVersion:	3.7
Contact:	linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
Description:	Instructs an SRP initiator to disconnect from a target and to
		remove all LUNs imported from that target.

What:		/sys/class/srp_remote_ports/port-<h>:<n>/port_id
Date:		June 27, 2007
KernelVersion:	2.6.24
+10 −0
Original line number Diff line number Diff line
@@ -549,6 +549,13 @@ static void srp_remove_work(struct work_struct *work)
	srp_remove_target(target);
}

static void srp_rport_delete(struct srp_rport *rport)
{
	struct srp_target_port *target = rport->lld_data;

	srp_queue_remove_work(target);
}

static int srp_connect_target(struct srp_target_port *target)
{
	int retries = 3;
@@ -1958,6 +1965,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
		return PTR_ERR(rport);
	}

	rport->lld_data = target;

	spin_lock(&host->target_lock);
	list_add_tail(&target->list, &host->target_list);
	spin_unlock(&host->target_lock);
@@ -2524,6 +2533,7 @@ static void srp_remove_one(struct ib_device *device)
}

static struct srp_function_template ib_srp_transport_functions = {
	.rport_delete		 = srp_rport_delete,
};

static int __init srp_init_module(void)
+21 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ struct srp_host_attrs {
#define to_srp_host_attrs(host)	((struct srp_host_attrs *)(host)->shost_data)

#define SRP_HOST_ATTRS 0
#define SRP_RPORT_ATTRS 2
#define SRP_RPORT_ATTRS 3

struct srp_internal {
	struct scsi_transport_template t;
@@ -116,6 +116,24 @@ show_srp_rport_roles(struct device *dev, struct device_attribute *attr,

static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);

static ssize_t store_srp_rport_delete(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t count)
{
	struct srp_rport *rport = transport_class_to_srp_rport(dev);
	struct Scsi_Host *shost = dev_to_shost(dev);
	struct srp_internal *i = to_srp_internal(shost->transportt);

	if (i->f->rport_delete) {
		i->f->rport_delete(rport);
		return count;
	} else {
		return -ENOSYS;
	}
}

static DEVICE_ATTR(delete, S_IWUSR, NULL, store_srp_rport_delete);

static void srp_rport_release(struct device *dev)
{
	struct srp_rport *rport = dev_to_rport(dev);
@@ -309,6 +327,8 @@ srp_attach_transport(struct srp_function_template *ft)
	count = 0;
	i->rport_attrs[count++] = &dev_attr_port_id;
	i->rport_attrs[count++] = &dev_attr_roles;
	if (ft->rport_delete)
		i->rport_attrs[count++] = &dev_attr_delete;
	i->rport_attrs[count++] = NULL;
	BUG_ON(count > ARRAY_SIZE(i->rport_attrs));

+8 −0
Original line number Diff line number Diff line
@@ -14,13 +14,21 @@ struct srp_rport_identifiers {
};

struct srp_rport {
	/* for initiator and target drivers */

	struct device dev;

	u8 port_id[16];
	u8 roles;

	/* for initiator drivers */

	void *lld_data;	/* LLD private data */
};

struct srp_function_template {
	/* for initiator drivers */
	void (*rport_delete)(struct srp_rport *rport);
	/* for target drivers */
	int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
	int (* it_nexus_response)(struct Scsi_Host *, u64, int);