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*0012fdf9SFUJITA Tomonori #include "scsi_transport_srp_internal.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 22562fe8826SFUJITA Tomonori if (ids->roles == SRP_RPORT_ROLE_INITIATOR) { 226*0012fdf9SFUJITA Tomonori ret = srp_tgt_it_nexus_create(shost, (unsigned long)rport, 22762fe8826SFUJITA Tomonori rport->port_id); 22862fe8826SFUJITA Tomonori if (ret) { 22962fe8826SFUJITA Tomonori device_del(&rport->dev); 23062fe8826SFUJITA Tomonori transport_destroy_device(&rport->dev); 23162fe8826SFUJITA Tomonori put_device(&rport->dev); 23262fe8826SFUJITA Tomonori return ERR_PTR(ret); 23362fe8826SFUJITA Tomonori } 23462fe8826SFUJITA Tomonori } 23562fe8826SFUJITA 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 25362fe8826SFUJITA Tomonori if (rport->roles == SRP_RPORT_ROLE_INITIATOR) 254*0012fdf9SFUJITA Tomonori srp_tgt_it_nexus_destroy(dev_to_shost(dev->parent), 25562fe8826SFUJITA Tomonori (unsigned long)rport); 25662fe8826SFUJITA 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 283bfb74374SFUJITA Tomonori static int srp_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, 284bfb74374SFUJITA Tomonori int result) 28562fe8826SFUJITA Tomonori { 28662fe8826SFUJITA Tomonori struct srp_internal *i = to_srp_internal(shost->transportt); 287bfb74374SFUJITA Tomonori return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); 288bfb74374SFUJITA Tomonori } 289bfb74374SFUJITA Tomonori 290bfb74374SFUJITA Tomonori static int srp_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) 291bfb74374SFUJITA Tomonori { 292bfb74374SFUJITA Tomonori struct srp_internal *i = to_srp_internal(shost->transportt); 293bfb74374SFUJITA Tomonori return i->f->it_nexus_response(shost, nexus, result); 29462fe8826SFUJITA Tomonori } 29562fe8826SFUJITA Tomonori 29609345f65SFUJITA Tomonori /** 29709345f65SFUJITA Tomonori * srp_attach_transport -- instantiate SRP transport template 29809345f65SFUJITA Tomonori * @ft: SRP transport class function template 29909345f65SFUJITA Tomonori */ 30009345f65SFUJITA Tomonori struct scsi_transport_template * 30109345f65SFUJITA Tomonori srp_attach_transport(struct srp_function_template *ft) 30209345f65SFUJITA Tomonori { 30309345f65SFUJITA Tomonori int count; 30409345f65SFUJITA Tomonori struct srp_internal *i; 30509345f65SFUJITA Tomonori 30609345f65SFUJITA Tomonori i = kzalloc(sizeof(*i), GFP_KERNEL); 30709345f65SFUJITA Tomonori if (!i) 30809345f65SFUJITA Tomonori return NULL; 30909345f65SFUJITA Tomonori 310bfb74374SFUJITA Tomonori i->t.tsk_mgmt_response = srp_tsk_mgmt_response; 31162fe8826SFUJITA Tomonori i->t.it_nexus_response = srp_it_nexus_response; 31262fe8826SFUJITA Tomonori 31309345f65SFUJITA Tomonori i->t.host_size = sizeof(struct srp_host_attrs); 31409345f65SFUJITA Tomonori i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 31509345f65SFUJITA Tomonori i->t.host_attrs.ac.class = &srp_host_class.class; 31609345f65SFUJITA Tomonori i->t.host_attrs.ac.match = srp_host_match; 31709345f65SFUJITA Tomonori i->host_attrs[0] = NULL; 31809345f65SFUJITA Tomonori transport_container_register(&i->t.host_attrs); 31909345f65SFUJITA Tomonori 32009345f65SFUJITA Tomonori i->rport_attr_cont.ac.attrs = &i->rport_attrs[0]; 32109345f65SFUJITA Tomonori i->rport_attr_cont.ac.class = &srp_rport_class.class; 32209345f65SFUJITA Tomonori i->rport_attr_cont.ac.match = srp_rport_match; 32309345f65SFUJITA Tomonori transport_container_register(&i->rport_attr_cont); 32409345f65SFUJITA Tomonori 32509345f65SFUJITA Tomonori count = 0; 32609345f65SFUJITA Tomonori SETUP_RPORT_ATTRIBUTE_RD(port_id); 327aebd5e47SFUJITA Tomonori SETUP_RPORT_ATTRIBUTE_RD(roles); 32809345f65SFUJITA Tomonori i->rport_attrs[count] = NULL; 32909345f65SFUJITA Tomonori 33009345f65SFUJITA Tomonori i->f = ft; 33109345f65SFUJITA Tomonori 33209345f65SFUJITA Tomonori return &i->t; 33309345f65SFUJITA Tomonori } 33409345f65SFUJITA Tomonori EXPORT_SYMBOL_GPL(srp_attach_transport); 33509345f65SFUJITA Tomonori 33609345f65SFUJITA Tomonori /** 33709345f65SFUJITA Tomonori * srp_release_transport -- release SRP transport template instance 33809345f65SFUJITA Tomonori * @t: transport template instance 33909345f65SFUJITA Tomonori */ 34009345f65SFUJITA Tomonori void srp_release_transport(struct scsi_transport_template *t) 34109345f65SFUJITA Tomonori { 34209345f65SFUJITA Tomonori struct srp_internal *i = to_srp_internal(t); 34309345f65SFUJITA Tomonori 34409345f65SFUJITA Tomonori transport_container_unregister(&i->t.host_attrs); 34509345f65SFUJITA Tomonori transport_container_unregister(&i->rport_attr_cont); 34609345f65SFUJITA Tomonori 34709345f65SFUJITA Tomonori kfree(i); 34809345f65SFUJITA Tomonori } 34909345f65SFUJITA Tomonori EXPORT_SYMBOL_GPL(srp_release_transport); 35009345f65SFUJITA Tomonori 35109345f65SFUJITA Tomonori static __init int srp_transport_init(void) 35209345f65SFUJITA Tomonori { 35309345f65SFUJITA Tomonori int ret; 35409345f65SFUJITA Tomonori 35509345f65SFUJITA Tomonori ret = transport_class_register(&srp_host_class); 35609345f65SFUJITA Tomonori if (ret) 35709345f65SFUJITA Tomonori return ret; 35809345f65SFUJITA Tomonori ret = transport_class_register(&srp_rport_class); 35909345f65SFUJITA Tomonori if (ret) 36009345f65SFUJITA Tomonori goto unregister_host_class; 36109345f65SFUJITA Tomonori 36209345f65SFUJITA Tomonori return 0; 36309345f65SFUJITA Tomonori unregister_host_class: 36409345f65SFUJITA Tomonori transport_class_unregister(&srp_host_class); 36509345f65SFUJITA Tomonori return ret; 36609345f65SFUJITA Tomonori } 36709345f65SFUJITA Tomonori 36809345f65SFUJITA Tomonori static void __exit srp_transport_exit(void) 36909345f65SFUJITA Tomonori { 37009345f65SFUJITA Tomonori transport_class_unregister(&srp_host_class); 37109345f65SFUJITA Tomonori transport_class_unregister(&srp_rport_class); 37209345f65SFUJITA Tomonori } 37309345f65SFUJITA Tomonori 37409345f65SFUJITA Tomonori MODULE_AUTHOR("FUJITA Tomonori"); 37509345f65SFUJITA Tomonori MODULE_DESCRIPTION("SRP Transport Attributes"); 37609345f65SFUJITA Tomonori MODULE_LICENSE("GPL"); 37709345f65SFUJITA Tomonori 37809345f65SFUJITA Tomonori module_init(srp_transport_init); 37909345f65SFUJITA Tomonori module_exit(srp_transport_exit); 380