correct transport class abstraction to work outside SCSI
Subsystems (2)
PATCH 1/1 correct transport class abstraction to work outside SCSI
I recently tried to construct a totally generic transport class and found there were certain features missing from the current abstract transport class. Most notable is that you have to hang the data on the class_device but most of the API is framed in terms of the generic device, not the class_device.
These changes are two fold
- Provide the class_device to all of the setup and configure APIs
- Provide and extra API to take the device and the attribute class and return the corresponding class_device
James
drivers/base/attribute_container.c +38 -0
@@ -58,6 +58,7 @@ attribute_container_register(struct attr {INIT_LIST_HEAD (&cont->node);INIT_LIST_HEAD (&cont->containers); +spin_lock_init (&cont->containers_lock);down (&attribute_container_mutex);list_add_tail (&cont->node, &attribute_container_list);
@@ -77,11 +78,13 @@ attribute_container_unregister(struct at {int retval = -EBUSY ;down (&attribute_container_mutex); +spin_lock (&cont->containers_lock);if (!list_empty (&cont->containers)) goto out; retval =0 ;list_del (&cont->node); out: +spin_unlock (&cont->containers_lock);up (&attribute_container_mutex);return retval;
@@ -151,7 +154,9 @@ attribute_container_add_device(struct defn (cont, dev, &ic->classdev); else attribute_container_add_class_device(&ic->classdev); +spin_lock (&cont->containers_lock);list_add_tail (&ic->node, &cont->containers); +spin_unlock (&cont->containers_lock); }up (&attribute_container_mutex); }
@@ -189,6 +194,7 @@ attribute_container_remove_device(structif (!cont->match (cont, dev))continue ; +spin_lock (&cont->containers_lock);list_for_each_entry_safe (ic, tmp, &cont->containers, node) {if (dev != ic->classdev.dev)continue ;
@@ -200,6 +206,7 @@ attribute_container_remove_device(structclass_device_unregister (&ic->classdev); } } +spin_unlock (&cont->containers_lock); }up (&attribute_container_mutex); }
@@ -230,10 +237,12 @@ attribute_container_device_trigger(strucif (!cont->match (cont, dev))continue ; +spin_lock (&cont->containers_lock);list_for_each_entry_safe (ic, tmp, &cont->containers, node) {if (dev == ic->classdev.dev)fn (cont, dev, &ic->classdev); } +spin_unlock (&cont->containers_lock); }up (&attribute_container_mutex); }
@@ -368,6 +377,35 @@ attribute_container_class_device_del(str }EXPORT_SYMBOL_GPL (attribute_container_class_device_del); +/** +* attribute_container_find_class_device - find the corresponding class_device +* +* @cont: the container +* @dev: the generic device +* +* Looks up the device in the container's list of class devices and returns +* the corresponding class_device. +*/ +struct class_device * +attribute_container_find_class_device (struct attribute_container *cont, +struct device *dev) +{ +struct class_device *cdev =NULL ; +struct internal_container *ic; + +spin_lock (&cont->containers_lock); +list_for_each_entry (ic, &cont->containers, node) { +if (ic->classdev.dev == dev) { + cdev = &ic->classdev; +break ; + } + } +spin_unlock (&cont->containers_lock); + +return cdev; +} +EXPORT_SYMBOL_GPL (attribute_container_find_class_device); +int __init attribute_container_init (void ) {
drivers/base/transport_class.c +11 -6
@@ -64,7 +64,9 @@ void transport_class_unregister(struct t }EXPORT_SYMBOL_GPL (transport_class_unregister); -static int anon_transport_dummy_function (struct device *dev) +static int anon_transport_dummy_function (struct transport_container *tc, +struct device *dev, +struct class_device *cdev) {/* do nothing */ return 0 ;
@@ -115,9 +117,10 @@ static int transport_setup_classdev(stru struct class_device *classdev) {struct transport_class *tclass =class_to_transport_class (cont->class); +struct transport_container *tcont =attribute_container_to_transport_container (cont);if (tclass->setup) - tclass->setup (dev); + tclass->setup (tcont, dev, classdev);return 0 ; }
@@ -178,12 +181,14 @@ void transport_add_device(struct deviceEXPORT_SYMBOL_GPL (transport_add_device);static int transport_configure (struct attribute_container *cont, -struct device *dev) +struct device *dev, +struct class_device *cdev) {struct transport_class *tclass =class_to_transport_class (cont->class); +struct transport_container *tcont =attribute_container_to_transport_container (cont);if (tclass->configure) - tclass->configure (dev); + tclass->configure (tcont, dev, cdev);return 0 ; }
@@ -202,7 +207,7 @@ static int transport_configure(struct at*/ void transport_configure_device (struct device *dev) { -attribute_container_trigger (dev, transport_configure); +attribute_container_device_trigger (dev, transport_configure); }EXPORT_SYMBOL_GPL (transport_configure_device);
@@ -215,7 +220,7 @@ static int transport_remove_classdev(strstruct transport_class *tclass =class_to_transport_class (cont->class);if (tclass->remove) - tclass->remove (dev); + tclass->remove (tcont, dev, classdev);if (tclass->remove != anon_transport_dummy_function) {if (tcont->statistics)
drivers/scsi/scsi_transport_fc.c +4 -2
@@ -252,7 +252,8 @@ struct fc_internal {#define to_fc_internal (tmpl) container_of(tmpl, struct fc_internal, t) -static int fc_target_setup (struct device *dev) +static int fc_target_setup (struct transport_container *tc,struct device *dev, +struct class_device *cdev) {struct scsi_target *starget =to_scsi_target (dev);struct fc_rport *rport =starget_to_rport (starget);
@@ -281,7 +282,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transpNULL , NULL); -static int fc_host_setup (struct device *dev) +static int fc_host_setup (struct transport_container *tc,struct device *dev, +struct class_device *cdev) {struct Scsi_Host *shost =dev_to_shost (dev);
drivers/scsi/scsi_transport_spi.c +8 -3
@@ -166,7 +166,8 @@ static inline enum spi_signal_type spi_sreturn SPI_SIGNAL_UNKNOWN ; } -static int spi_host_setup (struct device *dev) +static int spi_host_setup (struct transport_container *tc,struct device *dev, +struct class_device *cdev) {struct Scsi_Host *shost =dev_to_shost (dev);
@@ -200,7 +201,9 @@ static int spi_host_match(struct attribureturn &i->t.host_attrs.ac == cont; } -static int spi_device_configure (struct device *dev) +static int spi_device_configure (struct transport_container *tc, +struct device *dev, +struct class_device *cdev) {struct scsi_device *sdev =to_scsi_device (dev);struct scsi_target *starget = sdev->sdev_target;
@@ -218,7 +221,9 @@ static int spi_device_configure(struct dreturn 0 ; } -static int spi_setup_transport_attrs (struct device *dev) +static int spi_setup_transport_attrs (struct transport_container *tc, +struct device *dev, +struct class_device *cdev) {struct scsi_target *starget =to_scsi_target (dev);
include/linux/attribute_container.h +3 -6
@@ -11,10 +11,12 @@#include <linux/device.h> #include <linux/list.h> +#include <linux/spinlock.h> struct attribute_container {struct list_head node;struct list_head containers; +spinlock_t containers_lock;struct class *class;struct class_device_attribute **attrs;int (*match)(struct attribute_container *,struct device *);
@@ -62,12 +64,7 @@ int attribute_container_add_class_device struct class_device *classdev);void attribute_container_remove_attrs (struct class_device *classdev);void attribute_container_class_device_del (struct class_device *classdev); - - - - - - +struct class_device *attribute_container_find_class_device (struct attribute_container *,struct device *);struct class_device_attribute **attribute_container_classdev_to_attrs (const struct class_device *classdev);#endif
include/linux/transport_class.h +8 -3
@@ -12,11 +12,16 @@#include <linux/device.h> #include <linux/attribute_container.h> +struct transport_container ; +struct transport_class {struct class class; -int (*setup)(struct device *); -int (*configure)(struct device *); -int (*remove)(struct device *); +int (*setup)(struct transport_container *,struct device *, +struct class_device *); +int (*configure)(struct transport_container *,struct device *, +struct class_device *); +int (*remove)(struct transport_container *,struct device *, +struct class_device *); };#define DECLARE_TRANSPORT_CLASS (cls, nm, su, rm, cfg) \