}
EXPORT_SYMBOL_GPL(transport_setup_device);
+static int transport_add_class_device(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ int error = attribute_container_add_class_device(classdev);
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+
+ if (!error && tcont->statistics)
+ error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+ return error;
+}
+
/**
* transport_add_device - declare a new dev for transport class association
void transport_add_device(struct device *dev)
{
- attribute_container_device_trigger(dev,
- attribute_container_add_class_device_adapter);
+ attribute_container_device_trigger(dev, transport_add_class_device);
}
EXPORT_SYMBOL_GPL(transport_add_device);
struct device *dev,
struct class_device *classdev)
{
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
struct transport_class *tclass = class_to_transport_class(cont->class);
if (tclass->remove)
tclass->remove(dev);
- if (tclass->remove != anon_transport_dummy_function)
+ if (tclass->remove != anon_transport_dummy_function) {
+ if (tcont->statistics)
+ sysfs_remove_group(&classdev->kobj, tcont->statistics);
attribute_container_class_device_del(classdev);
+ }
return 0;
}
/* A blank transport template that is used in drivers that don't
* yet implement Transport Attributes */
-struct scsi_transport_template blank_transport_template = { NULL, };
+struct scsi_transport_template blank_transport_template = { { { {0, }, }, }, };
return 0;
shost = dev_to_shost(dev);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &fc_host_class.class)
return 0;
i = to_fc_internal(shost->transportt);
- return &i->t.host_attrs == cont;
+ return &i->t.host_attrs.ac == cont;
}
static int fc_target_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev->parent);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &fc_host_class.class)
return 0;
i = to_fc_internal(shost->transportt);
- return &i->t.target_attrs == cont;
+ return &i->t.target_attrs.ac == cont;
}
memset(i, 0, sizeof(struct fc_internal));
- i->t.target_attrs.attrs = &i->starget_attrs[0];
- i->t.target_attrs.class = &fc_transport_class.class;
- i->t.target_attrs.match = fc_target_match;
- attribute_container_register(&i->t.target_attrs);
+ i->t.target_attrs.ac.attrs = &i->starget_attrs[0];
+ i->t.target_attrs.ac.class = &fc_transport_class.class;
+ i->t.target_attrs.ac.match = fc_target_match;
+ transport_container_register(&i->t.target_attrs);
i->t.target_size = sizeof(struct fc_starget_attrs);
- i->t.host_attrs.attrs = &i->host_attrs[0];
- i->t.host_attrs.class = &fc_host_class.class;
- i->t.host_attrs.match = fc_host_match;
- attribute_container_register(&i->t.host_attrs);
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.class = &fc_host_class.class;
+ i->t.host_attrs.ac.match = fc_host_match;
i->t.host_size = sizeof(struct fc_host_attrs);
if (ft->get_fc_host_stats)
- i->t.host_statistics = &fc_statistics_group;
+ i->t.host_attrs.statistics = &fc_statistics_group;
+
+ transport_container_register(&i->t.host_attrs);
i->f = ft;
{
struct fc_internal *i = to_fc_internal(t);
+ transport_container_unregister(&i->t.target_attrs);
+ transport_container_unregister(&i->t.host_attrs);
+
kfree(i);
}
EXPORT_SYMBOL(fc_release_transport);
return 0;
shost = dev_to_shost(dev);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &iscsi_host_class.class)
return 0;
i = to_iscsi_internal(shost->transportt);
- return &i->t.host_attrs == cont;
+ return &i->t.host_attrs.ac == cont;
}
static int iscsi_target_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev->parent);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &iscsi_host_class.class)
return 0;
i = to_iscsi_internal(shost->transportt);
- return &i->t.target_attrs == cont;
+ return &i->t.target_attrs.ac == cont;
}
struct scsi_transport_template *
memset(i, 0, sizeof(struct iscsi_internal));
i->fnt = fnt;
- i->t.target_attrs.attrs = &i->session_attrs[0];
- i->t.target_attrs.class = &iscsi_transport_class.class;
- i->t.target_attrs.match = iscsi_target_match;
- attribute_container_register(&i->t.target_attrs);
+ i->t.target_attrs.ac.attrs = &i->session_attrs[0];
+ i->t.target_attrs.ac.class = &iscsi_transport_class.class;
+ i->t.target_attrs.ac.match = iscsi_target_match;
+ transport_container_register(&i->t.target_attrs);
i->t.target_size = sizeof(struct iscsi_class_session);
SETUP_SESSION_RD_ATTR(tsih);
BUG_ON(count > ISCSI_SESSION_ATTRS);
i->session_attrs[count] = NULL;
- i->t.host_attrs.attrs = &i->host_attrs[0];
- i->t.host_attrs.class = &iscsi_host_class.class;
- i->t.host_attrs.match = iscsi_host_match;
- attribute_container_register(&i->t.host_attrs);
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.class = &iscsi_host_class.class;
+ i->t.host_attrs.ac.match = iscsi_host_match;
+ transport_container_register(&i->t.host_attrs);
i->t.host_size = 0;
count = 0;
void iscsi_release_transport(struct scsi_transport_template *t)
{
struct iscsi_internal *i = to_iscsi_internal(t);
+
+ transport_container_unregister(&i->t.target_attrs);
+ transport_container_unregister(&i->t.host_attrs);
+
kfree(i);
}
return 0;
shost = dev_to_shost(dev);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &spi_host_class.class)
return 0;
i = to_spi_internal(shost->transportt);
- return &i->t.host_attrs == cont;
+ return &i->t.host_attrs.ac == cont;
}
static int spi_device_configure(struct device *dev)
sdev = to_scsi_device(dev);
shost = sdev->host;
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &spi_host_class.class)
return 0;
/* Note: this class has no device attributes, so it has
return 0;
shost = dev_to_shost(dev->parent);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &spi_host_class.class)
return 0;
i = to_spi_internal(shost->transportt);
- return &i->t.target_attrs == cont;
+ return &i->t.target_attrs.ac == cont;
}
static DECLARE_TRANSPORT_CLASS(spi_transport_class,
memset(i, 0, sizeof(struct spi_internal));
- i->t.target_attrs.class = &spi_transport_class.class;
- i->t.target_attrs.attrs = &i->attrs[0];
- i->t.target_attrs.match = spi_target_match;
- attribute_container_register(&i->t.target_attrs);
+ i->t.target_attrs.ac.class = &spi_transport_class.class;
+ i->t.target_attrs.ac.attrs = &i->attrs[0];
+ i->t.target_attrs.ac.match = spi_target_match;
+ transport_container_register(&i->t.target_attrs);
i->t.target_size = sizeof(struct spi_transport_attrs);
- i->t.host_attrs.class = &spi_host_class.class;
- i->t.host_attrs.attrs = &i->host_attrs[0];
- i->t.host_attrs.match = spi_host_match;
- attribute_container_register(&i->t.host_attrs);
+ i->t.host_attrs.ac.class = &spi_host_class.class;
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.match = spi_host_match;
+ transport_container_register(&i->t.host_attrs);
i->t.host_size = sizeof(struct spi_host_attrs);
i->f = ft;
{
struct spi_internal *i = to_spi_internal(t);
+ transport_container_unregister(&i->t.target_attrs);
+ transport_container_unregister(&i->t.host_attrs);
+
kfree(i);
}
EXPORT_SYMBOL(spi_release_transport);
#define class_to_transport_class(x) \
container_of(x, struct transport_class, class)
+struct transport_container {
+ struct attribute_container ac;
+ struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+ container_of(x, struct transport_container, ac)
+
void transport_remove_device(struct device *);
void transport_add_device(struct device *);
void transport_setup_device(struct device *);
transport_destroy_device(dev);
}
+static inline int transport_container_register(struct transport_container *tc)
+{
+ return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+ return attribute_container_unregister(&tc->ac);
+}
+
int transport_class_register(struct transport_class *);
int anon_transport_class_register(struct anon_transport_class *);
void transport_class_unregister(struct transport_class *);
#include <linux/transport_class.h>
struct scsi_transport_template {
- /* The statistics attached to the host class only */
- struct attribute_group *host_statistics;
-
/* the attribute containers */
- struct attribute_container host_attrs;
- struct attribute_container target_attrs;
- struct attribute_container device_attrs;
+ struct transport_container host_attrs;
+ struct transport_container target_attrs;
+ struct transport_container device_attrs;
/* The size of the specific transport attribute structure (a
* space of this size will be left at the end of the