Commit c47ed219 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Class: add support for class interfaces for devices

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: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c205ef48
...@@ -842,6 +842,7 @@ int class_interface_register(struct class_interface *class_intf) ...@@ -842,6 +842,7 @@ int class_interface_register(struct class_interface *class_intf)
{ {
struct class *parent; struct class *parent;
struct class_device *class_dev; struct class_device *class_dev;
struct device *dev;
if (!class_intf || !class_intf->class) if (!class_intf || !class_intf->class)
return -ENODEV; return -ENODEV;
...@@ -856,6 +857,10 @@ int class_interface_register(struct class_interface *class_intf) ...@@ -856,6 +857,10 @@ int class_interface_register(struct class_interface *class_intf)
list_for_each_entry(class_dev, &parent->children, node) list_for_each_entry(class_dev, &parent->children, node)
class_intf->add(class_dev, class_intf); 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); up(&parent->sem);
return 0; return 0;
...@@ -865,6 +870,7 @@ void class_interface_unregister(struct class_interface *class_intf) ...@@ -865,6 +870,7 @@ void class_interface_unregister(struct class_interface *class_intf)
{ {
struct class * parent = class_intf->class; struct class * parent = class_intf->class;
struct class_device *class_dev; struct class_device *class_dev;
struct device *dev;
if (!parent) if (!parent)
return; return;
...@@ -875,6 +881,10 @@ void class_interface_unregister(struct class_interface *class_intf) ...@@ -875,6 +881,10 @@ void class_interface_unregister(struct class_interface *class_intf)
list_for_each_entry(class_dev, &parent->children, node) list_for_each_entry(class_dev, &parent->children, node)
class_intf->remove(class_dev, class_intf); 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); up(&parent->sem);
class_put(parent); class_put(parent);
......
...@@ -372,6 +372,7 @@ int device_add(struct device *dev) ...@@ -372,6 +372,7 @@ int device_add(struct device *dev)
{ {
struct device *parent = NULL; struct device *parent = NULL;
char *class_name = NULL; char *class_name = NULL;
struct class_interface *class_intf;
int error = -EINVAL; int error = -EINVAL;
dev = get_device(dev); dev = get_device(dev);
...@@ -451,9 +452,14 @@ int device_add(struct device *dev) ...@@ -451,9 +452,14 @@ int device_add(struct device *dev)
klist_add_tail(&dev->knode_parent, &parent->klist_children); klist_add_tail(&dev->knode_parent, &parent->klist_children);
if (dev->class) { if (dev->class) {
/* tie the class to the device */
down(&dev->class->sem); down(&dev->class->sem);
/* tie the class to the device */
list_add_tail(&dev->node, &dev->class->devices); 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); up(&dev->class->sem);
} }
...@@ -548,6 +554,7 @@ void device_del(struct device * dev) ...@@ -548,6 +554,7 @@ void device_del(struct device * dev)
{ {
struct device * parent = dev->parent; struct device * parent = dev->parent;
char *class_name = NULL; char *class_name = NULL;
struct class_interface *class_intf;
if (parent) if (parent)
klist_del(&dev->knode_parent); klist_del(&dev->knode_parent);
...@@ -563,6 +570,11 @@ void device_del(struct device * dev) ...@@ -563,6 +570,11 @@ void device_del(struct device * dev)
} }
kfree(class_name); kfree(class_name);
down(&dev->class->sem); 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); list_del_init(&dev->node);
up(&dev->class->sem); up(&dev->class->sem);
} }
......
...@@ -278,6 +278,8 @@ struct class_interface { ...@@ -278,6 +278,8 @@ struct class_interface {
int (*add) (struct class_device *, struct class_interface *); int (*add) (struct class_device *, struct class_interface *);
void (*remove) (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 *); extern int class_interface_register(struct class_interface *);
......
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