Class: add support for class interfaces for devices
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 13 Sep 2006 13:34:05 +0000 (15:34 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 26 Sep 2006 04:08:38 +0000 (21:08 -0700)
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
drivers/base/core.c
include/linux/device.h

index cbdf47c0c60dcdcf9f7348ff9bf559827e164a71..b06b0e2b9c62b536a321d12295988af5801012b3 100644 (file)
@@ -842,6 +842,7 @@ int class_interface_register(struct class_interface *class_intf)
 {
        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 class_interface *class_intf)
                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 class_interface *class_intf)
 {
        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 class_interface *class_intf)
                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);
index e21a65fc043e9d20cb899a0f231db59cc0c761fe..1d3d3582fcca2764204ba40813e44ff541dfdfcb 100644 (file)
@@ -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);
        }
index bbb0d6b5d23275ac097d055282c82c230c05ee5d..e0fae0e76fa99ac53325bdac014152862cb347f5 100644 (file)
@@ -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 *);