diff options
| author | Bart Van Assche <bvanassche@acm.org> | 2011-09-16 14:41:13 -0400 |
|---|---|---|
| committer | Roland Dreier <roland@purestorage.com> | 2012-11-30 20:40:33 -0500 |
| commit | dc1bdbd9b8a077018d82230bc378f1bcfd8adba8 (patch) | |
| tree | e6484d9d378a0bad8a4f7057ae29d4164b33278e | |
| parent | 7e1265bfe75f0ef1a9f5cfde202df68b7e35a53f (diff) | |
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: Bart Van Assche <bvanassche@acm.org>
Acked-by: David Dillow <dillowda@ornl.gov>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
| -rw-r--r-- | Documentation/ABI/stable/sysfs-transport-srp | 7 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 10 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_srp.c | 22 | ||||
| -rw-r--r-- | include/scsi/scsi_transport_srp.h | 8 |
4 files changed, 46 insertions, 1 deletions
diff --git a/Documentation/ABI/stable/sysfs-transport-srp b/Documentation/ABI/stable/sysfs-transport-srp index 7b0d4a5350f1..b36fb0dc13c8 100644 --- a/Documentation/ABI/stable/sysfs-transport-srp +++ b/Documentation/ABI/stable/sysfs-transport-srp | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | What: /sys/class/srp_remote_ports/port-<h>:<n>/delete | ||
| 2 | Date: June 1, 2012 | ||
| 3 | KernelVersion: 3.7 | ||
| 4 | Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org | ||
| 5 | Description: Instructs an SRP initiator to disconnect from a target and to | ||
| 6 | remove all LUNs imported from that target. | ||
| 7 | |||
| 1 | What: /sys/class/srp_remote_ports/port-<h>:<n>/port_id | 8 | What: /sys/class/srp_remote_ports/port-<h>:<n>/port_id |
| 2 | Date: June 27, 2007 | 9 | Date: June 27, 2007 |
| 3 | KernelVersion: 2.6.24 | 10 | KernelVersion: 2.6.24 |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 84d9298ed989..d5088ce78290 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
| @@ -549,6 +549,13 @@ static void srp_remove_work(struct work_struct *work) | |||
| 549 | srp_remove_target(target); | 549 | srp_remove_target(target); |
| 550 | } | 550 | } |
| 551 | 551 | ||
| 552 | static void srp_rport_delete(struct srp_rport *rport) | ||
| 553 | { | ||
| 554 | struct srp_target_port *target = rport->lld_data; | ||
| 555 | |||
| 556 | srp_queue_remove_work(target); | ||
| 557 | } | ||
| 558 | |||
| 552 | static int srp_connect_target(struct srp_target_port *target) | 559 | static int srp_connect_target(struct srp_target_port *target) |
| 553 | { | 560 | { |
| 554 | int retries = 3; | 561 | int retries = 3; |
| @@ -1958,6 +1965,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) | |||
| 1958 | return PTR_ERR(rport); | 1965 | return PTR_ERR(rport); |
| 1959 | } | 1966 | } |
| 1960 | 1967 | ||
| 1968 | rport->lld_data = target; | ||
| 1969 | |||
| 1961 | spin_lock(&host->target_lock); | 1970 | spin_lock(&host->target_lock); |
| 1962 | list_add_tail(&target->list, &host->target_list); | 1971 | list_add_tail(&target->list, &host->target_list); |
| 1963 | spin_unlock(&host->target_lock); | 1972 | spin_unlock(&host->target_lock); |
| @@ -2524,6 +2533,7 @@ static void srp_remove_one(struct ib_device *device) | |||
| 2524 | } | 2533 | } |
| 2525 | 2534 | ||
| 2526 | static struct srp_function_template ib_srp_transport_functions = { | 2535 | static struct srp_function_template ib_srp_transport_functions = { |
| 2536 | .rport_delete = srp_rport_delete, | ||
| 2527 | }; | 2537 | }; |
| 2528 | 2538 | ||
| 2529 | static int __init srp_init_module(void) | 2539 | static int __init srp_init_module(void) |
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 0d85f797141f..f379c7f3034c 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c | |||
| @@ -38,7 +38,7 @@ struct srp_host_attrs { | |||
| 38 | #define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) | 38 | #define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) |
| 39 | 39 | ||
| 40 | #define SRP_HOST_ATTRS 0 | 40 | #define SRP_HOST_ATTRS 0 |
| 41 | #define SRP_RPORT_ATTRS 2 | 41 | #define SRP_RPORT_ATTRS 3 |
| 42 | 42 | ||
| 43 | struct srp_internal { | 43 | struct srp_internal { |
| 44 | struct scsi_transport_template t; | 44 | struct scsi_transport_template t; |
| @@ -116,6 +116,24 @@ show_srp_rport_roles(struct device *dev, struct device_attribute *attr, | |||
| 116 | 116 | ||
| 117 | static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL); | 117 | static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL); |
| 118 | 118 | ||
| 119 | static ssize_t store_srp_rport_delete(struct device *dev, | ||
| 120 | struct device_attribute *attr, | ||
| 121 | const char *buf, size_t count) | ||
| 122 | { | ||
| 123 | struct srp_rport *rport = transport_class_to_srp_rport(dev); | ||
| 124 | struct Scsi_Host *shost = dev_to_shost(dev); | ||
| 125 | struct srp_internal *i = to_srp_internal(shost->transportt); | ||
| 126 | |||
| 127 | if (i->f->rport_delete) { | ||
| 128 | i->f->rport_delete(rport); | ||
| 129 | return count; | ||
| 130 | } else { | ||
| 131 | return -ENOSYS; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | static DEVICE_ATTR(delete, S_IWUSR, NULL, store_srp_rport_delete); | ||
| 136 | |||
| 119 | static void srp_rport_release(struct device *dev) | 137 | static void srp_rport_release(struct device *dev) |
| 120 | { | 138 | { |
| 121 | struct srp_rport *rport = dev_to_rport(dev); | 139 | struct srp_rport *rport = dev_to_rport(dev); |
| @@ -309,6 +327,8 @@ srp_attach_transport(struct srp_function_template *ft) | |||
| 309 | count = 0; | 327 | count = 0; |
| 310 | i->rport_attrs[count++] = &dev_attr_port_id; | 328 | i->rport_attrs[count++] = &dev_attr_port_id; |
| 311 | i->rport_attrs[count++] = &dev_attr_roles; | 329 | i->rport_attrs[count++] = &dev_attr_roles; |
| 330 | if (ft->rport_delete) | ||
| 331 | i->rport_attrs[count++] = &dev_attr_delete; | ||
| 312 | i->rport_attrs[count++] = NULL; | 332 | i->rport_attrs[count++] = NULL; |
| 313 | BUG_ON(count > ARRAY_SIZE(i->rport_attrs)); | 333 | BUG_ON(count > ARRAY_SIZE(i->rport_attrs)); |
| 314 | 334 | ||
diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h index 9c60ca1c08c5..ff0f04ac91aa 100644 --- a/include/scsi/scsi_transport_srp.h +++ b/include/scsi/scsi_transport_srp.h | |||
| @@ -14,13 +14,21 @@ struct srp_rport_identifiers { | |||
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | struct srp_rport { | 16 | struct srp_rport { |
| 17 | /* for initiator and target drivers */ | ||
| 18 | |||
| 17 | struct device dev; | 19 | struct device dev; |
| 18 | 20 | ||
| 19 | u8 port_id[16]; | 21 | u8 port_id[16]; |
| 20 | u8 roles; | 22 | u8 roles; |
| 23 | |||
| 24 | /* for initiator drivers */ | ||
| 25 | |||
| 26 | void *lld_data; /* LLD private data */ | ||
| 21 | }; | 27 | }; |
| 22 | 28 | ||
| 23 | struct srp_function_template { | 29 | struct srp_function_template { |
| 30 | /* for initiator drivers */ | ||
| 31 | void (*rport_delete)(struct srp_rport *rport); | ||
| 24 | /* for target drivers */ | 32 | /* for target drivers */ |
| 25 | int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); | 33 | int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); |
| 26 | int (* it_nexus_response)(struct Scsi_Host *, u64, int); | 34 | int (* it_nexus_response)(struct Scsi_Host *, u64, int); |
