[PATCH 31/47] Class: add support for class interfaces for devices

Greg KH
2006-09-26T05:46:51Z

From: Greg Kroah-Hartman <gregkh@suse.de>

When moving class_device usage over to device, we need to handle
class_interfaces properly with devices. This patch adds that support.

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/base/class.c | 10 ++++++++++
drivers/base/core.c | 14 +++++++++++++-
include/linux/device.h | 2 ++
3 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/drivers/base/class.c b/drivers/base/class.c
index cbdf47c..b06b0e2 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -842,6 +842,7 @@ int class_interface_register(struct clas
{
struct class *parent;
struct class_device *class_dev;
+ struct device *dev;

if (!class_intf || !class_intf->class)
return -ENODEV;
@@ -856,6 +857,10 @@ int class_interface_register(struct clas
list_for_each_entry(class_dev, &parent->children, node)
class_intf->add(class_dev, class_intf);
}
+ if (class_intf->add_dev) {
+ list_for_each_entry(dev, &parent->devices, node)
+ class_intf->add_dev(dev, class_intf);
+ }
up(&parent->sem);

return 0;
@@ -865,6 +870,7 @@ void class_interface_unregister(struct c
{
struct class * parent = class_intf->class;
struct class_device *class_dev;
+ struct device *dev;

if (!parent)
return;
@@ -875,6 +881,10 @@ void class_interface_unregister(struct c
list_for_each_entry(class_dev, &parent->children, node)
class_intf->remove(class_dev, class_intf);
}
+ if (class_intf->remove_dev) {
+ list_for_each_entry(dev, &parent->devices, node)
+ class_intf->remove_dev(dev, class_intf);
+ }
up(&parent->sem);

class_put(parent);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index e21a65f..1d3d358 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -372,6 +372,7 @@ int device_add(struct device *dev)
{
struct device *parent = NULL;
char *class_name = NULL;
+ struct class_interface *class_intf;
int error = -EINVAL;

dev = get_device(dev);
@@ -451,9 +452,14 @@ int device_add(struct device *dev)
klist_add_tail(&dev->knode_parent, &parent->klist_children);

if (dev->class) {
- /* tie the class to the device */
down(&dev->class->sem);
+ /* tie the class to the device */
list_add_tail(&dev->node, &dev->class->devices);
+
+ /* notify any interfaces that the device is here */
+ list_for_each_entry(class_intf, &dev->class->interfaces, node)
+ if (class_intf->add_dev)
+ class_intf->add_dev(dev, class_intf);
up(&dev->class->sem);
}

@@ -548,6 +554,7 @@ void device_del(struct device * dev)
{
struct device * parent = dev->parent;
char *class_name = NULL;
+ struct class_interface *class_intf;

if (parent)
klist_del(&dev->knode_parent);
@@ -563,6 +570,11 @@ void device_del(struct device * dev)
}
kfree(class_name);
down(&dev->class->sem);
+ /* notify any interfaces that the device is now gone */
+ list_for_each_entry(class_intf, &dev->class->interfaces, node)
+ if (class_intf->remove_dev)
+ class_intf->remove_dev(dev, class_intf);
+ /* remove the device from the class list */
list_del_init(&dev->node);
up(&dev->class->sem);
}
diff --git a/include/linux/device.h b/include/linux/device.h
index bbb0d6b..e0fae0e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -278,6 +278,8 @@ struct class_interface {

int (*add) (struct class_device *, struct class_interface *);
void (*remove) (struct class_device *, struct class_interface *);
+ int (*add_dev) (struct device *, struct class_interface *);
+ void (*remove_dev) (struct device *, struct class_interface *);
};

extern int class_interface_register(struct class_interface *);
--
1.4.2.1