[SCSI] correct attribute_container list usage
[linux-2.6.git] / drivers / base / attribute_container.c
index ec615d8..6c0f493 100644 (file)
@@ -22,7 +22,7 @@
 /* This is a private structure used to tie the classdev and the
  * container .. it should never be visible outside this file */
 struct internal_container {
-       struct list_head node;
+       struct klist_node node;
        struct attribute_container *cont;
        struct class_device classdev;
 };
@@ -57,7 +57,7 @@ int
 attribute_container_register(struct attribute_container *cont)
 {
        INIT_LIST_HEAD(&cont->node);
-       INIT_LIST_HEAD(&cont->containers);
+       klist_init(&cont->containers);
                
        down(&attribute_container_mutex);
        list_add_tail(&cont->node, &attribute_container_list);
@@ -77,11 +77,13 @@ attribute_container_unregister(struct attribute_container *cont)
 {
        int retval = -EBUSY;
        down(&attribute_container_mutex);
-       if (!list_empty(&cont->containers))
+       spin_lock(&cont->containers.k_lock);
+       if (!list_empty(&cont->containers.k_list))
                goto out;
        retval = 0;
        list_del(&cont->node);
  out:
+       spin_unlock(&cont->containers.k_lock);
        up(&attribute_container_mutex);
        return retval;
                
@@ -140,7 +142,6 @@ attribute_container_add_device(struct device *dev,
                        continue;
                }
                memset(ic, 0, sizeof(struct internal_container));
-               INIT_LIST_HEAD(&ic->node);
                ic->cont = cont;
                class_device_initialize(&ic->classdev);
                ic->classdev.dev = get_device(dev);
@@ -151,11 +152,22 @@ attribute_container_add_device(struct device *dev,
                        fn(cont, dev, &ic->classdev);
                else
                        attribute_container_add_class_device(&ic->classdev);
-               list_add_tail(&ic->node, &cont->containers);
+               klist_add_tail(&ic->node, &cont->containers);
        }
        up(&attribute_container_mutex);
 }
 
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+       for (klist_iter_init(head, iter); (pos = ({ \
+               struct klist_node *n = klist_next(iter); \
+               n ? ({ klist_iter_exit(iter) ; NULL; }) : \
+                       container_of(n, typeof(*pos), member);\
+       }) ) != NULL; )
+                       
+
 /**
  * attribute_container_remove_device - make device eligible for removal.
  *
@@ -182,17 +194,19 @@ attribute_container_remove_device(struct device *dev,
 
        down(&attribute_container_mutex);
        list_for_each_entry(cont, &attribute_container_list, node) {
-               struct internal_container *ic, *tmp;
+               struct internal_container *ic;
+               struct klist_iter iter;
 
                if (attribute_container_no_classdevs(cont))
                        continue;
 
                if (!cont->match(cont, dev))
                        continue;
-               list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+
+               klist_for_each_entry(ic, &cont->containers, node, &iter) {
                        if (dev != ic->classdev.dev)
                                continue;
-                       list_del(&ic->node);
+                       klist_remove(&ic->node);
                        if (fn)
                                fn(cont, dev, &ic->classdev);
                        else {
@@ -225,12 +239,18 @@ attribute_container_device_trigger(struct device *dev,
 
        down(&attribute_container_mutex);
        list_for_each_entry(cont, &attribute_container_list, node) {
-               struct internal_container *ic, *tmp;
+               struct internal_container *ic;
+               struct klist_iter iter;
 
                if (!cont->match(cont, dev))
                        continue;
 
-               list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+               if (attribute_container_no_classdevs(cont)) {
+                       fn(cont, dev, NULL);
+                       continue;
+               }
+
+               klist_for_each_entry(ic, &cont->containers, node, &iter) {
                        if (dev == ic->classdev.dev)
                                fn(cont, dev, &ic->classdev);
                }
@@ -368,6 +388,36 @@ attribute_container_class_device_del(struct class_device *classdev)
 }
 EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
 
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont:      the container
+ * @dev:       the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+                                     struct device *dev)
+{
+       struct class_device *cdev = NULL;
+       struct internal_container *ic;
+       struct klist_iter iter;
+
+       klist_for_each_entry(ic, &cont->containers, node, &iter) {
+               if (ic->classdev.dev == dev) {
+                       cdev = &ic->classdev;
+                       /* FIXME: must exit iterator then break */
+                       klist_iter_exit(&iter);
+                       break;
+               }
+       }
+
+       return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
 int __init
 attribute_container_init(void)
 {