Commit aa4e0186 authored by James Bottomley's avatar James Bottomley

Fix missed class_remove_file in attribute_container

This moves attribute addition (and removal) to where it
should have been in the first place, namely in the
attribute_container class.

Without this, the transport classes were leaving dangling
attributes when the devices were removed.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 3a35ed51
......@@ -150,7 +150,7 @@ attribute_container_add_device(struct device *dev,
if (fn)
fn(cont, dev, &ic->classdev);
else
class_device_add(&ic->classdev);
attribute_container_add_class_device(&ic->classdev);
list_add_tail(&ic->node, &cont->containers);
}
up(&attribute_container_mutex);
......@@ -195,8 +195,10 @@ attribute_container_remove_device(struct device *dev,
list_del(&ic->node);
if (fn)
fn(cont, dev, &ic->classdev);
else
else {
attribute_container_remove_attrs(&ic->classdev);
class_device_unregister(&ic->classdev);
}
}
}
up(&attribute_container_mutex);
......@@ -264,7 +266,107 @@ attribute_container_trigger(struct device *dev,
up(&attribute_container_mutex);
}
EXPORT_SYMBOL_GPL(attribute_container_trigger);
/**
* attribute_container_add_attrs - add attributes
*
* @classdev: The class device
*
* This simply creates all the class device sysfs files from the
* attributes listed in the container
*/
int
attribute_container_add_attrs(struct class_device *classdev)
{
struct attribute_container *cont =
attribute_container_classdev_to_container(classdev);
struct class_device_attribute **attrs = cont->attrs;
int i, error;
if (!attrs)
return 0;
for (i = 0; attrs[i]; i++) {
error = class_device_create_file(classdev, attrs[i]);
if (error)
return error;
}
return 0;
}
EXPORT_SYMBOL_GPL(attribute_container_add_attrs);
/**
* attribute_container_add_class_device - same function as class_device_add
*
* @classdev: the class device to add
*
* This performs essentially the same function as class_device_add except for
* attribute containers, namely add the classdev to the system and then
* create the attribute files
*/
int
attribute_container_add_class_device(struct class_device *classdev)
{
int error = class_device_add(classdev);
if (error)
return error;
return attribute_container_add_attrs(classdev);
}
EXPORT_SYMBOL_GPL(attribute_container_add_class_device);
/**
* attribute_container_add_class_device_adapter - simple adapter for triggers
*
* This function is identical to attribute_container_add_class_device except
* that it is designed to be called from the triggers
*/
int
attribute_container_add_class_device_adapter(struct attribute_container *cont,
struct device *dev,
struct class_device *classdev)
{
return attribute_container_add_class_device(classdev);
}
EXPORT_SYMBOL_GPL(attribute_container_add_class_device_adapter);
/**
* attribute_container_remove_attrs - remove any attribute files
*
* @classdev: The class device to remove the files from
*
*/
void
attribute_container_remove_attrs(struct class_device *classdev)
{
struct attribute_container *cont =
attribute_container_classdev_to_container(classdev);
struct class_device_attribute **attrs = cont->attrs;
int i;
if (!attrs)
return;
for (i = 0; attrs[i]; i++)
class_device_remove_file(classdev, attrs[i]);
}
EXPORT_SYMBOL_GPL(attribute_container_remove_attrs);
/**
* attribute_container_class_device_del - equivalent of class_device_del
*
* @classdev: the class device
*
* This function simply removes all the attribute files and then calls
* class_device_del.
*/
void
attribute_container_class_device_del(struct class_device *classdev)
{
attribute_container_remove_attrs(classdev);
class_device_del(classdev);
}
EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
int __init
attribute_container_init(void)
......
......@@ -146,25 +146,6 @@ void transport_setup_device(struct device *dev)
EXPORT_SYMBOL_GPL(transport_setup_device);
static int transport_add_classdev(struct attribute_container *cont,
struct device *dev,
struct class_device *classdev)
{
struct class_device_attribute **attrs = cont->attrs;
int i, error;
error = class_device_add(classdev);
if (error)
return error;
for (i = 0; attrs[i]; i++) {
error = class_device_create_file(classdev, attrs[i]);
if (error)
return error;
}
return 0;
}
/**
* transport_add_device - declare a new dev for transport class association
*
......@@ -178,7 +159,8 @@ static int transport_add_classdev(struct attribute_container *cont,
void transport_add_device(struct device *dev)
{
attribute_container_device_trigger(dev, transport_add_classdev);
attribute_container_device_trigger(dev,
attribute_container_add_class_device_adapter);
}
EXPORT_SYMBOL_GPL(transport_add_device);
......@@ -220,6 +202,9 @@ static int transport_remove_classdev(struct attribute_container *cont,
if (tclass->remove)
tclass->remove(dev);
if (tclass->remove != anon_transport_dummy_function)
attribute_container_class_device_del(classdev);
return 0;
}
......
......@@ -55,6 +55,18 @@ void attribute_container_device_trigger(struct device *dev,
void attribute_container_trigger(struct device *dev,
int (*fn)(struct attribute_container *,
struct device *));
int attribute_container_add_attrs(struct class_device *classdev);
int attribute_container_add_class_device(struct class_device *classdev);
int attribute_container_add_class_device_adapter(struct attribute_container *cont,
struct device *dev,
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 **attribute_container_classdev_to_attrs(const struct class_device *classdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment