mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
[SCSI] 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 Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
10c1b88987
commit
d0a7e57400
6 changed files with 72 additions and 20 deletions
|
@ -58,6 +58,7 @@ attribute_container_register(struct attribute_container *cont)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&cont->node);
|
INIT_LIST_HEAD(&cont->node);
|
||||||
INIT_LIST_HEAD(&cont->containers);
|
INIT_LIST_HEAD(&cont->containers);
|
||||||
|
spin_lock_init(&cont->containers_lock);
|
||||||
|
|
||||||
down(&attribute_container_mutex);
|
down(&attribute_container_mutex);
|
||||||
list_add_tail(&cont->node, &attribute_container_list);
|
list_add_tail(&cont->node, &attribute_container_list);
|
||||||
|
@ -77,11 +78,13 @@ attribute_container_unregister(struct attribute_container *cont)
|
||||||
{
|
{
|
||||||
int retval = -EBUSY;
|
int retval = -EBUSY;
|
||||||
down(&attribute_container_mutex);
|
down(&attribute_container_mutex);
|
||||||
|
spin_lock(&cont->containers_lock);
|
||||||
if (!list_empty(&cont->containers))
|
if (!list_empty(&cont->containers))
|
||||||
goto out;
|
goto out;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
list_del(&cont->node);
|
list_del(&cont->node);
|
||||||
out:
|
out:
|
||||||
|
spin_unlock(&cont->containers_lock);
|
||||||
up(&attribute_container_mutex);
|
up(&attribute_container_mutex);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
@ -151,7 +154,9 @@ attribute_container_add_device(struct device *dev,
|
||||||
fn(cont, dev, &ic->classdev);
|
fn(cont, dev, &ic->classdev);
|
||||||
else
|
else
|
||||||
attribute_container_add_class_device(&ic->classdev);
|
attribute_container_add_class_device(&ic->classdev);
|
||||||
|
spin_lock(&cont->containers_lock);
|
||||||
list_add_tail(&ic->node, &cont->containers);
|
list_add_tail(&ic->node, &cont->containers);
|
||||||
|
spin_unlock(&cont->containers_lock);
|
||||||
}
|
}
|
||||||
up(&attribute_container_mutex);
|
up(&attribute_container_mutex);
|
||||||
}
|
}
|
||||||
|
@ -189,6 +194,7 @@ attribute_container_remove_device(struct device *dev,
|
||||||
|
|
||||||
if (!cont->match(cont, dev))
|
if (!cont->match(cont, dev))
|
||||||
continue;
|
continue;
|
||||||
|
spin_lock(&cont->containers_lock);
|
||||||
list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
|
list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
|
||||||
if (dev != ic->classdev.dev)
|
if (dev != ic->classdev.dev)
|
||||||
continue;
|
continue;
|
||||||
|
@ -200,6 +206,7 @@ attribute_container_remove_device(struct device *dev,
|
||||||
class_device_unregister(&ic->classdev);
|
class_device_unregister(&ic->classdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spin_unlock(&cont->containers_lock);
|
||||||
}
|
}
|
||||||
up(&attribute_container_mutex);
|
up(&attribute_container_mutex);
|
||||||
}
|
}
|
||||||
|
@ -230,10 +237,12 @@ attribute_container_device_trigger(struct device *dev,
|
||||||
if (!cont->match(cont, dev))
|
if (!cont->match(cont, dev))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
spin_lock(&cont->containers_lock);
|
||||||
list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
|
list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
|
||||||
if (dev == ic->classdev.dev)
|
if (dev == ic->classdev.dev)
|
||||||
fn(cont, dev, &ic->classdev);
|
fn(cont, dev, &ic->classdev);
|
||||||
}
|
}
|
||||||
|
spin_unlock(&cont->containers_lock);
|
||||||
}
|
}
|
||||||
up(&attribute_container_mutex);
|
up(&attribute_container_mutex);
|
||||||
}
|
}
|
||||||
|
@ -368,6 +377,35 @@ attribute_container_class_device_del(struct class_device *classdev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
|
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
|
int __init
|
||||||
attribute_container_init(void)
|
attribute_container_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,7 +64,9 @@ void transport_class_unregister(struct transport_class *tclass)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(transport_class_unregister);
|
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 */
|
/* do nothing */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -115,9 +117,10 @@ static int transport_setup_classdev(struct attribute_container *cont,
|
||||||
struct class_device *classdev)
|
struct class_device *classdev)
|
||||||
{
|
{
|
||||||
struct transport_class *tclass = class_to_transport_class(cont->class);
|
struct transport_class *tclass = class_to_transport_class(cont->class);
|
||||||
|
struct transport_container *tcont = attribute_container_to_transport_container(cont);
|
||||||
|
|
||||||
if (tclass->setup)
|
if (tclass->setup)
|
||||||
tclass->setup(dev);
|
tclass->setup(tcont, dev, classdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -178,12 +181,14 @@ void transport_add_device(struct device *dev)
|
||||||
EXPORT_SYMBOL_GPL(transport_add_device);
|
EXPORT_SYMBOL_GPL(transport_add_device);
|
||||||
|
|
||||||
static int transport_configure(struct attribute_container *cont,
|
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_class *tclass = class_to_transport_class(cont->class);
|
||||||
|
struct transport_container *tcont = attribute_container_to_transport_container(cont);
|
||||||
|
|
||||||
if (tclass->configure)
|
if (tclass->configure)
|
||||||
tclass->configure(dev);
|
tclass->configure(tcont, dev, cdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +207,7 @@ static int transport_configure(struct attribute_container *cont,
|
||||||
*/
|
*/
|
||||||
void transport_configure_device(struct device *dev)
|
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);
|
EXPORT_SYMBOL_GPL(transport_configure_device);
|
||||||
|
|
||||||
|
@ -215,7 +220,7 @@ static int transport_remove_classdev(struct attribute_container *cont,
|
||||||
struct transport_class *tclass = class_to_transport_class(cont->class);
|
struct transport_class *tclass = class_to_transport_class(cont->class);
|
||||||
|
|
||||||
if (tclass->remove)
|
if (tclass->remove)
|
||||||
tclass->remove(dev);
|
tclass->remove(tcont, dev, classdev);
|
||||||
|
|
||||||
if (tclass->remove != anon_transport_dummy_function) {
|
if (tclass->remove != anon_transport_dummy_function) {
|
||||||
if (tcont->statistics)
|
if (tcont->statistics)
|
||||||
|
|
|
@ -252,7 +252,8 @@ struct fc_internal {
|
||||||
|
|
||||||
#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
|
#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 scsi_target *starget = to_scsi_target(dev);
|
||||||
struct fc_rport *rport = starget_to_rport(starget);
|
struct fc_rport *rport = starget_to_rport(starget);
|
||||||
|
@ -281,7 +282,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
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);
|
struct Scsi_Host *shost = dev_to_shost(dev);
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
|
||||||
return SPI_SIGNAL_UNKNOWN;
|
return 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);
|
struct Scsi_Host *shost = dev_to_shost(dev);
|
||||||
|
|
||||||
|
@ -196,7 +197,9 @@ static int spi_host_match(struct attribute_container *cont,
|
||||||
return &i->t.host_attrs.ac == cont;
|
return &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_device *sdev = to_scsi_device(dev);
|
||||||
struct scsi_target *starget = sdev->sdev_target;
|
struct scsi_target *starget = sdev->sdev_target;
|
||||||
|
@ -214,7 +217,9 @@ static int spi_device_configure(struct device *dev)
|
||||||
return 0;
|
return 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);
|
struct scsi_target *starget = to_scsi_target(dev);
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
struct attribute_container {
|
struct attribute_container {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
struct list_head containers;
|
struct list_head containers;
|
||||||
|
spinlock_t containers_lock;
|
||||||
struct class *class;
|
struct class *class;
|
||||||
struct class_device_attribute **attrs;
|
struct class_device_attribute **attrs;
|
||||||
int (*match)(struct attribute_container *, struct device *);
|
int (*match)(struct attribute_container *, struct device *);
|
||||||
|
@ -62,12 +64,7 @@ int attribute_container_add_class_device_adapter(struct attribute_container *con
|
||||||
struct class_device *classdev);
|
struct class_device *classdev);
|
||||||
void attribute_container_remove_attrs(struct class_device *classdev);
|
void attribute_container_remove_attrs(struct class_device *classdev);
|
||||||
void attribute_container_class_device_del(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);
|
struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,11 +12,16 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/attribute_container.h>
|
#include <linux/attribute_container.h>
|
||||||
|
|
||||||
|
struct transport_container;
|
||||||
|
|
||||||
struct transport_class {
|
struct transport_class {
|
||||||
struct class class;
|
struct class class;
|
||||||
int (*setup)(struct device *);
|
int (*setup)(struct transport_container *, struct device *,
|
||||||
int (*configure)(struct device *);
|
struct class_device *);
|
||||||
int (*remove)(struct 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) \
|
#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue