xref: /linux/drivers/scsi/scsi_transport_srp.c (revision 62fe88261b9d865264d857777cf58a0335513151)
109345f65SFUJITA Tomonori /*
209345f65SFUJITA Tomonori  * SCSI RDMA (SRP) transport class
309345f65SFUJITA Tomonori  *
409345f65SFUJITA Tomonori  * Copyright (C) 2007 FUJITA Tomonori <tomof@acm.org>
509345f65SFUJITA Tomonori  *
609345f65SFUJITA Tomonori  * This program is free software; you can redistribute it and/or
709345f65SFUJITA Tomonori  * modify it under the terms of the GNU General Public License as
809345f65SFUJITA Tomonori  * published by the Free Software Foundation, version 2 of the
909345f65SFUJITA Tomonori  * License.
1009345f65SFUJITA Tomonori  *
1109345f65SFUJITA Tomonori  * This program is distributed in the hope that it will be useful, but
1209345f65SFUJITA Tomonori  * WITHOUT ANY WARRANTY; without even the implied warranty of
1309345f65SFUJITA Tomonori  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1409345f65SFUJITA Tomonori  * General Public License for more details.
1509345f65SFUJITA Tomonori  *
1609345f65SFUJITA Tomonori  * You should have received a copy of the GNU General Public License
1709345f65SFUJITA Tomonori  * along with this program; if not, write to the Free Software
1809345f65SFUJITA Tomonori  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1909345f65SFUJITA Tomonori  * 02110-1301 USA
2009345f65SFUJITA Tomonori  */
2109345f65SFUJITA Tomonori #include <linux/init.h>
2209345f65SFUJITA Tomonori #include <linux/module.h>
2309345f65SFUJITA Tomonori #include <linux/jiffies.h>
2409345f65SFUJITA Tomonori #include <linux/err.h>
2509345f65SFUJITA Tomonori #include <linux/slab.h>
2609345f65SFUJITA Tomonori #include <linux/string.h>
2709345f65SFUJITA Tomonori 
2809345f65SFUJITA Tomonori #include <scsi/scsi.h>
2909345f65SFUJITA Tomonori #include <scsi/scsi_device.h>
3009345f65SFUJITA Tomonori #include <scsi/scsi_host.h>
3109345f65SFUJITA Tomonori #include <scsi/scsi_transport.h>
3209345f65SFUJITA Tomonori #include <scsi/scsi_transport_srp.h>
33*62fe8826SFUJITA Tomonori #include <scsi/scsi_tgt.h>
3409345f65SFUJITA Tomonori 
3509345f65SFUJITA Tomonori struct srp_host_attrs {
3609345f65SFUJITA Tomonori 	atomic_t next_port_id;
3709345f65SFUJITA Tomonori };
3809345f65SFUJITA Tomonori #define to_srp_host_attrs(host)	((struct srp_host_attrs *)(host)->shost_data)
3909345f65SFUJITA Tomonori 
4009345f65SFUJITA Tomonori #define SRP_HOST_ATTRS 0
41aebd5e47SFUJITA Tomonori #define SRP_RPORT_ATTRS 2
4209345f65SFUJITA Tomonori 
4309345f65SFUJITA Tomonori struct srp_internal {
4409345f65SFUJITA Tomonori 	struct scsi_transport_template t;
4509345f65SFUJITA Tomonori 	struct srp_function_template *f;
4609345f65SFUJITA Tomonori 
4709345f65SFUJITA Tomonori 	struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
4809345f65SFUJITA Tomonori 
4909345f65SFUJITA Tomonori 	struct class_device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1];
5009345f65SFUJITA Tomonori 	struct class_device_attribute private_rport_attrs[SRP_RPORT_ATTRS];
5109345f65SFUJITA Tomonori 	struct transport_container rport_attr_cont;
5209345f65SFUJITA Tomonori };
5309345f65SFUJITA Tomonori 
5409345f65SFUJITA Tomonori #define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t)
5509345f65SFUJITA Tomonori 
5609345f65SFUJITA Tomonori #define	dev_to_rport(d)	container_of(d, struct srp_rport, dev)
5709345f65SFUJITA Tomonori #define transport_class_to_srp_rport(cdev) dev_to_rport((cdev)->dev)
5809345f65SFUJITA Tomonori 
5909345f65SFUJITA Tomonori static int srp_host_setup(struct transport_container *tc, struct device *dev,
6009345f65SFUJITA Tomonori 			  struct class_device *cdev)
6109345f65SFUJITA Tomonori {
6209345f65SFUJITA Tomonori 	struct Scsi_Host *shost = dev_to_shost(dev);
6309345f65SFUJITA Tomonori 	struct srp_host_attrs *srp_host = to_srp_host_attrs(shost);
6409345f65SFUJITA Tomonori 
6509345f65SFUJITA Tomonori 	atomic_set(&srp_host->next_port_id, 0);
6609345f65SFUJITA Tomonori 	return 0;
6709345f65SFUJITA Tomonori }
6809345f65SFUJITA Tomonori 
6909345f65SFUJITA Tomonori static DECLARE_TRANSPORT_CLASS(srp_host_class, "srp_host", srp_host_setup,
7009345f65SFUJITA Tomonori 			       NULL, NULL);
7109345f65SFUJITA Tomonori 
7209345f65SFUJITA Tomonori static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports",
7309345f65SFUJITA Tomonori 			       NULL, NULL, NULL);
7409345f65SFUJITA Tomonori 
7509345f65SFUJITA Tomonori #define SETUP_TEMPLATE(attrb, field, perm, test, ro_test, ro_perm)	\
7609345f65SFUJITA Tomonori 	i->private_##attrb[count] = class_device_attr_##field;		\
7709345f65SFUJITA Tomonori 	i->private_##attrb[count].attr.mode = perm;			\
7809345f65SFUJITA Tomonori 	if (ro_test) {							\
7909345f65SFUJITA Tomonori 		i->private_##attrb[count].attr.mode = ro_perm;		\
8009345f65SFUJITA Tomonori 		i->private_##attrb[count].store = NULL;			\
8109345f65SFUJITA Tomonori 	}								\
8209345f65SFUJITA Tomonori 	i->attrb[count] = &i->private_##attrb[count];			\
8309345f65SFUJITA Tomonori 	if (test)							\
8409345f65SFUJITA Tomonori 		count++
8509345f65SFUJITA Tomonori 
8609345f65SFUJITA Tomonori #define SETUP_RPORT_ATTRIBUTE_RD(field)					\
8709345f65SFUJITA Tomonori 	SETUP_TEMPLATE(rport_attrs, field, S_IRUGO, 1, 0, 0)
8809345f65SFUJITA Tomonori 
8909345f65SFUJITA Tomonori #define SETUP_RPORT_ATTRIBUTE_RW(field)					\
9009345f65SFUJITA Tomonori 	SETUP_TEMPLATE(rport_attrs, field, S_IRUGO | S_IWUSR,		\
9109345f65SFUJITA Tomonori 		       1, 1, S_IRUGO)
9209345f65SFUJITA Tomonori 
9309345f65SFUJITA Tomonori #define SRP_PID(p) \
9409345f65SFUJITA Tomonori 	(p)->port_id[0], (p)->port_id[1], (p)->port_id[2], (p)->port_id[3], \
9509345f65SFUJITA Tomonori 	(p)->port_id[4], (p)->port_id[5], (p)->port_id[6], (p)->port_id[7], \
9609345f65SFUJITA Tomonori 	(p)->port_id[8], (p)->port_id[9], (p)->port_id[10], (p)->port_id[11], \
9709345f65SFUJITA Tomonori 	(p)->port_id[12], (p)->port_id[13], (p)->port_id[14], (p)->port_id[15]
9809345f65SFUJITA Tomonori 
9909345f65SFUJITA Tomonori #define SRP_PID_FMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \
10009345f65SFUJITA Tomonori 	"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
10109345f65SFUJITA Tomonori 
10209345f65SFUJITA Tomonori static ssize_t
10309345f65SFUJITA Tomonori show_srp_rport_id(struct class_device *cdev, char *buf)
10409345f65SFUJITA Tomonori {
10509345f65SFUJITA Tomonori 	struct srp_rport *rport = transport_class_to_srp_rport(cdev);
10609345f65SFUJITA Tomonori 	return sprintf(buf, SRP_PID_FMT "\n", SRP_PID(rport));
10709345f65SFUJITA Tomonori }
10809345f65SFUJITA Tomonori 
10909345f65SFUJITA Tomonori static CLASS_DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL);
11009345f65SFUJITA Tomonori 
111aebd5e47SFUJITA Tomonori static const struct {
112aebd5e47SFUJITA Tomonori 	u32 value;
113aebd5e47SFUJITA Tomonori 	char *name;
114aebd5e47SFUJITA Tomonori } srp_rport_role_names[] = {
115aebd5e47SFUJITA Tomonori 	{SRP_RPORT_ROLE_INITIATOR, "SRP Initiator"},
116aebd5e47SFUJITA Tomonori 	{SRP_RPORT_ROLE_TARGET, "SRP Target"},
117aebd5e47SFUJITA Tomonori };
118aebd5e47SFUJITA Tomonori 
119aebd5e47SFUJITA Tomonori static ssize_t
120aebd5e47SFUJITA Tomonori show_srp_rport_roles(struct class_device *cdev, char *buf)
121aebd5e47SFUJITA Tomonori {
122aebd5e47SFUJITA Tomonori 	struct srp_rport *rport = transport_class_to_srp_rport(cdev);
123aebd5e47SFUJITA Tomonori 	int i;
124aebd5e47SFUJITA Tomonori 	char *name = NULL;
125aebd5e47SFUJITA Tomonori 
126aebd5e47SFUJITA Tomonori 	for (i = 0; i < ARRAY_SIZE(srp_rport_role_names); i++)
127aebd5e47SFUJITA Tomonori 		if (srp_rport_role_names[i].value == rport->roles) {
128aebd5e47SFUJITA Tomonori 			name = srp_rport_role_names[i].name;
129aebd5e47SFUJITA Tomonori 			break;
130aebd5e47SFUJITA Tomonori 		}
131aebd5e47SFUJITA Tomonori 	return sprintf(buf, "%s\n", name ? : "unknown");
132aebd5e47SFUJITA Tomonori }
133aebd5e47SFUJITA Tomonori 
134aebd5e47SFUJITA Tomonori static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
135aebd5e47SFUJITA Tomonori 
13609345f65SFUJITA Tomonori static void srp_rport_release(struct device *dev)
13709345f65SFUJITA Tomonori {
13809345f65SFUJITA Tomonori 	struct srp_rport *rport = dev_to_rport(dev);
13909345f65SFUJITA Tomonori 
14009345f65SFUJITA Tomonori 	put_device(dev->parent);
14109345f65SFUJITA Tomonori 	kfree(rport);
14209345f65SFUJITA Tomonori }
14309345f65SFUJITA Tomonori 
14409345f65SFUJITA Tomonori static int scsi_is_srp_rport(const struct device *dev)
14509345f65SFUJITA Tomonori {
14609345f65SFUJITA Tomonori 	return dev->release == srp_rport_release;
14709345f65SFUJITA Tomonori }
14809345f65SFUJITA Tomonori 
14909345f65SFUJITA Tomonori static int srp_rport_match(struct attribute_container *cont,
15009345f65SFUJITA Tomonori 			   struct device *dev)
15109345f65SFUJITA Tomonori {
15209345f65SFUJITA Tomonori 	struct Scsi_Host *shost;
15309345f65SFUJITA Tomonori 	struct srp_internal *i;
15409345f65SFUJITA Tomonori 
15509345f65SFUJITA Tomonori 	if (!scsi_is_srp_rport(dev))
15609345f65SFUJITA Tomonori 		return 0;
15709345f65SFUJITA Tomonori 
15809345f65SFUJITA Tomonori 	shost = dev_to_shost(dev->parent);
15909345f65SFUJITA Tomonori 	if (!shost->transportt)
16009345f65SFUJITA Tomonori 		return 0;
16109345f65SFUJITA Tomonori 	if (shost->transportt->host_attrs.ac.class != &srp_host_class.class)
16209345f65SFUJITA Tomonori 		return 0;
16309345f65SFUJITA Tomonori 
16409345f65SFUJITA Tomonori 	i = to_srp_internal(shost->transportt);
16509345f65SFUJITA Tomonori 	return &i->rport_attr_cont.ac == cont;
16609345f65SFUJITA Tomonori }
16709345f65SFUJITA Tomonori 
16809345f65SFUJITA Tomonori static int srp_host_match(struct attribute_container *cont, struct device *dev)
16909345f65SFUJITA Tomonori {
17009345f65SFUJITA Tomonori 	struct Scsi_Host *shost;
17109345f65SFUJITA Tomonori 	struct srp_internal *i;
17209345f65SFUJITA Tomonori 
17309345f65SFUJITA Tomonori 	if (!scsi_is_host_device(dev))
17409345f65SFUJITA Tomonori 		return 0;
17509345f65SFUJITA Tomonori 
17609345f65SFUJITA Tomonori 	shost = dev_to_shost(dev);
17709345f65SFUJITA Tomonori 	if (!shost->transportt)
17809345f65SFUJITA Tomonori 		return 0;
17909345f65SFUJITA Tomonori 	if (shost->transportt->host_attrs.ac.class != &srp_host_class.class)
18009345f65SFUJITA Tomonori 		return 0;
18109345f65SFUJITA Tomonori 
18209345f65SFUJITA Tomonori 	i = to_srp_internal(shost->transportt);
18309345f65SFUJITA Tomonori 	return &i->t.host_attrs.ac == cont;
18409345f65SFUJITA Tomonori }
18509345f65SFUJITA Tomonori 
18609345f65SFUJITA Tomonori /**
18709345f65SFUJITA Tomonori  * srp_rport_add - add a SRP remote port to the device hierarchy
18809345f65SFUJITA Tomonori  *
18909345f65SFUJITA Tomonori  * @shost:	scsi host the remote port is connected to.
19009345f65SFUJITA Tomonori  * @ids:	The port id for the remote port.
19109345f65SFUJITA Tomonori  *
19209345f65SFUJITA Tomonori  * publishes a port to the rest of the system
19309345f65SFUJITA Tomonori  */
19409345f65SFUJITA Tomonori struct srp_rport *srp_rport_add(struct Scsi_Host *shost,
19509345f65SFUJITA Tomonori 				struct srp_rport_identifiers *ids)
19609345f65SFUJITA Tomonori {
19709345f65SFUJITA Tomonori 	struct srp_rport *rport;
19809345f65SFUJITA Tomonori 	struct device *parent = &shost->shost_gendev;
19909345f65SFUJITA Tomonori 	int id, ret;
20009345f65SFUJITA Tomonori 
20109345f65SFUJITA Tomonori 	rport = kzalloc(sizeof(*rport), GFP_KERNEL);
20209345f65SFUJITA Tomonori 	if (!rport)
20309345f65SFUJITA Tomonori 		return ERR_PTR(-ENOMEM);
20409345f65SFUJITA Tomonori 
20509345f65SFUJITA Tomonori 	device_initialize(&rport->dev);
20609345f65SFUJITA Tomonori 
20709345f65SFUJITA Tomonori 	rport->dev.parent = get_device(parent);
20809345f65SFUJITA Tomonori 	rport->dev.release = srp_rport_release;
20909345f65SFUJITA Tomonori 
21009345f65SFUJITA Tomonori 	memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id));
211aebd5e47SFUJITA Tomonori 	rport->roles = ids->roles;
21209345f65SFUJITA Tomonori 
21309345f65SFUJITA Tomonori 	id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id);
21409345f65SFUJITA Tomonori 	sprintf(rport->dev.bus_id, "port-%d:%d", shost->host_no, id);
21509345f65SFUJITA Tomonori 
21609345f65SFUJITA Tomonori 	transport_setup_device(&rport->dev);
21709345f65SFUJITA Tomonori 
21809345f65SFUJITA Tomonori 	ret = device_add(&rport->dev);
21909345f65SFUJITA Tomonori 	if (ret) {
22009345f65SFUJITA Tomonori 		transport_destroy_device(&rport->dev);
22109345f65SFUJITA Tomonori 		put_device(&rport->dev);
22209345f65SFUJITA Tomonori 		return ERR_PTR(ret);
22309345f65SFUJITA Tomonori 	}
22409345f65SFUJITA Tomonori 
225*62fe8826SFUJITA Tomonori 	if (ids->roles == SRP_RPORT_ROLE_INITIATOR) {
226*62fe8826SFUJITA Tomonori 		ret = scsi_tgt_it_nexus_create(shost, (unsigned long)rport,
227*62fe8826SFUJITA Tomonori 					       rport->port_id);
228*62fe8826SFUJITA Tomonori 		if (ret) {
229*62fe8826SFUJITA Tomonori 			device_del(&rport->dev);
230*62fe8826SFUJITA Tomonori 			transport_destroy_device(&rport->dev);
231*62fe8826SFUJITA Tomonori 			put_device(&rport->dev);
232*62fe8826SFUJITA Tomonori 			return ERR_PTR(ret);
233*62fe8826SFUJITA Tomonori 		}
234*62fe8826SFUJITA Tomonori 	}
235*62fe8826SFUJITA Tomonori 
23609345f65SFUJITA Tomonori 	transport_add_device(&rport->dev);
23709345f65SFUJITA Tomonori 	transport_configure_device(&rport->dev);
23809345f65SFUJITA Tomonori 
23909345f65SFUJITA Tomonori 	return rport;
24009345f65SFUJITA Tomonori }
24109345f65SFUJITA Tomonori EXPORT_SYMBOL_GPL(srp_rport_add);
24209345f65SFUJITA Tomonori 
24309345f65SFUJITA Tomonori /**
24409345f65SFUJITA Tomonori  * srp_rport_del  --  remove a SRP remote port
24509345f65SFUJITA Tomonori  * @port:	SRP remote port to remove
24609345f65SFUJITA Tomonori  *
24709345f65SFUJITA Tomonori  * Removes the specified SRP remote port.
24809345f65SFUJITA Tomonori  */
24909345f65SFUJITA Tomonori void srp_rport_del(struct srp_rport *rport)
25009345f65SFUJITA Tomonori {
25109345f65SFUJITA Tomonori 	struct device *dev = &rport->dev;
25209345f65SFUJITA Tomonori 
253*62fe8826SFUJITA Tomonori 	if (rport->roles == SRP_RPORT_ROLE_INITIATOR)
254*62fe8826SFUJITA Tomonori 		scsi_tgt_it_nexus_destroy(dev_to_shost(dev->parent),
255*62fe8826SFUJITA Tomonori 					  (unsigned long)rport);
256*62fe8826SFUJITA Tomonori 
25709345f65SFUJITA Tomonori 	transport_remove_device(dev);
25809345f65SFUJITA Tomonori 	device_del(dev);
25909345f65SFUJITA Tomonori 	transport_destroy_device(dev);
26009345f65SFUJITA Tomonori 	put_device(dev);
26109345f65SFUJITA Tomonori }
26209345f65SFUJITA Tomonori EXPORT_SYMBOL_GPL(srp_rport_del);
26309345f65SFUJITA Tomonori 
26409345f65SFUJITA Tomonori static int do_srp_rport_del(struct device *dev, void *data)
26509345f65SFUJITA Tomonori {
26609345f65SFUJITA Tomonori 	srp_rport_del(dev_to_rport(dev));
26709345f65SFUJITA Tomonori 	return 0;
26809345f65SFUJITA Tomonori }
26909345f65SFUJITA Tomonori 
27009345f65SFUJITA Tomonori /**
27109345f65SFUJITA Tomonori  * srp_remove_host  --  tear down a Scsi_Host's SRP data structures
27209345f65SFUJITA Tomonori  * @shost:	Scsi Host that is torn down
27309345f65SFUJITA Tomonori  *
27409345f65SFUJITA Tomonori  * Removes all SRP remote ports for a given Scsi_Host.
27509345f65SFUJITA Tomonori  * Must be called just before scsi_remove_host for SRP HBAs.
27609345f65SFUJITA Tomonori  */
27709345f65SFUJITA Tomonori void srp_remove_host(struct Scsi_Host *shost)
27809345f65SFUJITA Tomonori {
27909345f65SFUJITA Tomonori 	device_for_each_child(&shost->shost_gendev, NULL, do_srp_rport_del);
28009345f65SFUJITA Tomonori }
28109345f65SFUJITA Tomonori EXPORT_SYMBOL_GPL(srp_remove_host);
28209345f65SFUJITA Tomonori 
283*62fe8826SFUJITA Tomonori static int srp_it_nexus_response(struct Scsi_Host *shost, u64 id, int result)
284*62fe8826SFUJITA Tomonori {
285*62fe8826SFUJITA Tomonori 	struct srp_internal *i = to_srp_internal(shost->transportt);
286*62fe8826SFUJITA Tomonori 	return i->f->it_nexus_response(shost, id, result);
287*62fe8826SFUJITA Tomonori }
288*62fe8826SFUJITA Tomonori 
28909345f65SFUJITA Tomonori /**
29009345f65SFUJITA Tomonori  * srp_attach_transport  --  instantiate SRP transport template
29109345f65SFUJITA Tomonori  * @ft:		SRP transport class function template
29209345f65SFUJITA Tomonori  */
29309345f65SFUJITA Tomonori struct scsi_transport_template *
29409345f65SFUJITA Tomonori srp_attach_transport(struct srp_function_template *ft)
29509345f65SFUJITA Tomonori {
29609345f65SFUJITA Tomonori 	int count;
29709345f65SFUJITA Tomonori 	struct srp_internal *i;
29809345f65SFUJITA Tomonori 
29909345f65SFUJITA Tomonori 	i = kzalloc(sizeof(*i), GFP_KERNEL);
30009345f65SFUJITA Tomonori 	if (!i)
30109345f65SFUJITA Tomonori 		return NULL;
30209345f65SFUJITA Tomonori 
303*62fe8826SFUJITA Tomonori 	i->t.it_nexus_response = srp_it_nexus_response;
304*62fe8826SFUJITA Tomonori 
30509345f65SFUJITA Tomonori 	i->t.host_size = sizeof(struct srp_host_attrs);
30609345f65SFUJITA Tomonori 	i->t.host_attrs.ac.attrs = &i->host_attrs[0];
30709345f65SFUJITA Tomonori 	i->t.host_attrs.ac.class = &srp_host_class.class;
30809345f65SFUJITA Tomonori 	i->t.host_attrs.ac.match = srp_host_match;
30909345f65SFUJITA Tomonori 	i->host_attrs[0] = NULL;
31009345f65SFUJITA Tomonori 	transport_container_register(&i->t.host_attrs);
31109345f65SFUJITA Tomonori 
31209345f65SFUJITA Tomonori 	i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
31309345f65SFUJITA Tomonori 	i->rport_attr_cont.ac.class = &srp_rport_class.class;
31409345f65SFUJITA Tomonori 	i->rport_attr_cont.ac.match = srp_rport_match;
31509345f65SFUJITA Tomonori 	transport_container_register(&i->rport_attr_cont);
31609345f65SFUJITA Tomonori 
31709345f65SFUJITA Tomonori 	count = 0;
31809345f65SFUJITA Tomonori 	SETUP_RPORT_ATTRIBUTE_RD(port_id);
319aebd5e47SFUJITA Tomonori 	SETUP_RPORT_ATTRIBUTE_RD(roles);
32009345f65SFUJITA Tomonori 	i->rport_attrs[count] = NULL;
32109345f65SFUJITA Tomonori 
32209345f65SFUJITA Tomonori 	i->f = ft;
32309345f65SFUJITA Tomonori 
32409345f65SFUJITA Tomonori 	return &i->t;
32509345f65SFUJITA Tomonori }
32609345f65SFUJITA Tomonori EXPORT_SYMBOL_GPL(srp_attach_transport);
32709345f65SFUJITA Tomonori 
32809345f65SFUJITA Tomonori /**
32909345f65SFUJITA Tomonori  * srp_release_transport  --  release SRP transport template instance
33009345f65SFUJITA Tomonori  * @t:		transport template instance
33109345f65SFUJITA Tomonori  */
33209345f65SFUJITA Tomonori void srp_release_transport(struct scsi_transport_template *t)
33309345f65SFUJITA Tomonori {
33409345f65SFUJITA Tomonori 	struct srp_internal *i = to_srp_internal(t);
33509345f65SFUJITA Tomonori 
33609345f65SFUJITA Tomonori 	transport_container_unregister(&i->t.host_attrs);
33709345f65SFUJITA Tomonori 	transport_container_unregister(&i->rport_attr_cont);
33809345f65SFUJITA Tomonori 
33909345f65SFUJITA Tomonori 	kfree(i);
34009345f65SFUJITA Tomonori }
34109345f65SFUJITA Tomonori EXPORT_SYMBOL_GPL(srp_release_transport);
34209345f65SFUJITA Tomonori 
34309345f65SFUJITA Tomonori static __init int srp_transport_init(void)
34409345f65SFUJITA Tomonori {
34509345f65SFUJITA Tomonori 	int ret;
34609345f65SFUJITA Tomonori 
34709345f65SFUJITA Tomonori 	ret = transport_class_register(&srp_host_class);
34809345f65SFUJITA Tomonori 	if (ret)
34909345f65SFUJITA Tomonori 		return ret;
35009345f65SFUJITA Tomonori 	ret = transport_class_register(&srp_rport_class);
35109345f65SFUJITA Tomonori 	if (ret)
35209345f65SFUJITA Tomonori 		goto unregister_host_class;
35309345f65SFUJITA Tomonori 
35409345f65SFUJITA Tomonori 	return 0;
35509345f65SFUJITA Tomonori unregister_host_class:
35609345f65SFUJITA Tomonori 	transport_class_unregister(&srp_host_class);
35709345f65SFUJITA Tomonori 	return ret;
35809345f65SFUJITA Tomonori }
35909345f65SFUJITA Tomonori 
36009345f65SFUJITA Tomonori static void __exit srp_transport_exit(void)
36109345f65SFUJITA Tomonori {
36209345f65SFUJITA Tomonori 	transport_class_unregister(&srp_host_class);
36309345f65SFUJITA Tomonori 	transport_class_unregister(&srp_rport_class);
36409345f65SFUJITA Tomonori }
36509345f65SFUJITA Tomonori 
36609345f65SFUJITA Tomonori MODULE_AUTHOR("FUJITA Tomonori");
36709345f65SFUJITA Tomonori MODULE_DESCRIPTION("SRP Transport Attributes");
36809345f65SFUJITA Tomonori MODULE_LICENSE("GPL");
36909345f65SFUJITA Tomonori 
37009345f65SFUJITA Tomonori module_init(srp_transport_init);
37109345f65SFUJITA Tomonori module_exit(srp_transport_exit);
372