aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/class.c10
-rw-r--r--drivers/base/core.c14
-rw-r--r--include/linux/device.h2
3 files changed, 25 insertions, 1 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c
index cbdf47c0c60d..b06b0e2b9c62 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -842,6 +842,7 @@ int class_interface_register(struct class_interface *class_intf)
842{ 842{
843 struct class *parent; 843 struct class *parent;
844 struct class_device *class_dev; 844 struct class_device *class_dev;
845 struct device *dev;
845 846
846 if (!class_intf || !class_intf->class) 847 if (!class_intf || !class_intf->class)
847 return -ENODEV; 848 return -ENODEV;
@@ -856,6 +857,10 @@ int class_interface_register(struct class_interface *class_intf)
856 list_for_each_entry(class_dev, &parent->children, node) 857 list_for_each_entry(class_dev, &parent->children, node)
857 class_intf->add(class_dev, class_intf); 858 class_intf->add(class_dev, class_intf);
858 } 859 }
860 if (class_intf->add_dev) {
861 list_for_each_entry(dev, &parent->devices, node)
862 class_intf->add_dev(dev, class_intf);
863 }
859 up(&parent->sem); 864 up(&parent->sem);
860 865
861 return 0; 866 return 0;
@@ -865,6 +870,7 @@ void class_interface_unregister(struct class_interface *class_intf)
865{ 870{
866 struct class * parent = class_intf->class; 871 struct class * parent = class_intf->class;
867 struct class_device *class_dev; 872 struct class_device *class_dev;
873 struct device *dev;
868 874
869 if (!parent) 875 if (!parent)
870 return; 876 return;
@@ -875,6 +881,10 @@ void class_interface_unregister(struct class_interface *class_intf)
875 list_for_each_entry(class_dev, &parent->children, node) 881 list_for_each_entry(class_dev, &parent->children, node)
876 class_intf->remove(class_dev, class_intf); 882 class_intf->remove(class_dev, class_intf);
877 } 883 }
884 if (class_intf->remove_dev) {
885 list_for_each_entry(dev, &parent->devices, node)
886 class_intf->remove_dev(dev, class_intf);
887 }
878 up(&parent->sem); 888 up(&parent->sem);
879 889
880 class_put(parent); 890 class_put(parent);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index e21a65fc043e..1d3d3582fcca 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -372,6 +372,7 @@ int device_add(struct device *dev)
372{ 372{
373 struct device *parent = NULL; 373 struct device *parent = NULL;
374 char *class_name = NULL; 374 char *class_name = NULL;
375 struct class_interface *class_intf;
375 int error = -EINVAL; 376 int error = -EINVAL;
376 377
377 dev = get_device(dev); 378 dev = get_device(dev);
@@ -451,9 +452,14 @@ int device_add(struct device *dev)
451 klist_add_tail(&dev->knode_parent, &parent->klist_children); 452 klist_add_tail(&dev->knode_parent, &parent->klist_children);
452 453
453 if (dev->class) { 454 if (dev->class) {
454 /* tie the class to the device */
455 down(&dev->class->sem); 455 down(&dev->class->sem);
456 /* tie the class to the device */
456 list_add_tail(&dev->node, &dev->class->devices); 457 list_add_tail(&dev->node, &dev->class->devices);
458
459 /* notify any interfaces that the device is here */
460 list_for_each_entry(class_intf, &dev->class->interfaces, node)
461 if (class_intf->add_dev)
462 class_intf->add_dev(dev, class_intf);
457 up(&dev->class->sem); 463 up(&dev->class->sem);
458 } 464 }
459 465
@@ -548,6 +554,7 @@ void device_del(struct device * dev)
548{ 554{
549 struct device * parent = dev->parent; 555 struct device * parent = dev->parent;
550 char *class_name = NULL; 556 char *class_name = NULL;
557 struct class_interface *class_intf;
551 558
552 if (parent) 559 if (parent)
553 klist_del(&dev->knode_parent); 560 klist_del(&dev->knode_parent);
@@ -563,6 +570,11 @@ void device_del(struct device * dev)
563 } 570 }
564 kfree(class_name); 571 kfree(class_name);
565 down(&dev->class->sem); 572 down(&dev->class->sem);
573 /* notify any interfaces that the device is now gone */
574 list_for_each_entry(class_intf, &dev->class->interfaces, node)
575 if (class_intf->remove_dev)
576 class_intf->remove_dev(dev, class_intf);
577 /* remove the device from the class list */
566 list_del_init(&dev->node); 578 list_del_init(&dev->node);
567 up(&dev->class->sem); 579 up(&dev->class->sem);
568 } 580 }
diff --git a/include/linux/device.h b/include/linux/device.h
index bbb0d6b5d232..e0fae0e76fa9 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -278,6 +278,8 @@ struct class_interface {
278 278
279 int (*add) (struct class_device *, struct class_interface *); 279 int (*add) (struct class_device *, struct class_interface *);
280 void (*remove) (struct class_device *, struct class_interface *); 280 void (*remove) (struct class_device *, struct class_interface *);
281 int (*add_dev) (struct device *, struct class_interface *);
282 void (*remove_dev) (struct device *, struct class_interface *);
281}; 283};
282 284
283extern int class_interface_register(struct class_interface *); 285extern int class_interface_register(struct class_interface *);