firewire: fw-sbp2: use an own workqueue (fix system responsiveness)
[safe/jmp/linux-2.6] / drivers / base / attribute_container.c
index 6c0f493..7370d7c 100644 (file)
@@ -18,6 +18,9 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
+
+#include "base.h"
 
 /* This is a private structure used to tie the classdev and the
  * container .. it should never be visible outside this file */
@@ -27,6 +30,21 @@ struct internal_container {
        struct class_device classdev;
 };
 
+static void internal_container_klist_get(struct klist_node *n)
+{
+       struct internal_container *ic =
+               container_of(n, struct internal_container, node);
+       class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+       struct internal_container *ic =
+               container_of(n, struct internal_container, node);
+       class_device_put(&ic->classdev);
+}
+
+
 /**
  * attribute_container_classdev_to_container - given a classdev, return the container
  *
@@ -45,7 +63,7 @@ EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
 
 static struct list_head attribute_container_list;
 
-static DECLARE_MUTEX(attribute_container_mutex);
+static DEFINE_MUTEX(attribute_container_mutex);
 
 /**
  * attribute_container_register - register an attribute container
@@ -57,11 +75,12 @@ int
 attribute_container_register(struct attribute_container *cont)
 {
        INIT_LIST_HEAD(&cont->node);
-       klist_init(&cont->containers);
+       klist_init(&cont->containers,internal_container_klist_get,
+                  internal_container_klist_put);
                
-       down(&attribute_container_mutex);
+       mutex_lock(&attribute_container_mutex);
        list_add_tail(&cont->node, &attribute_container_list);
-       up(&attribute_container_mutex);
+       mutex_unlock(&attribute_container_mutex);
 
        return 0;
 }
@@ -76,7 +95,7 @@ int
 attribute_container_unregister(struct attribute_container *cont)
 {
        int retval = -EBUSY;
-       down(&attribute_container_mutex);
+       mutex_lock(&attribute_container_mutex);
        spin_lock(&cont->containers.k_lock);
        if (!list_empty(&cont->containers.k_list))
                goto out;
@@ -84,7 +103,7 @@ attribute_container_unregister(struct attribute_container *cont)
        list_del(&cont->node);
  out:
        spin_unlock(&cont->containers.k_lock);
-       up(&attribute_container_mutex);
+       mutex_unlock(&attribute_container_mutex);
        return retval;
                
 }
@@ -127,7 +146,7 @@ attribute_container_add_device(struct device *dev,
 {
        struct attribute_container *cont;
 
-       down(&attribute_container_mutex);
+       mutex_lock(&attribute_container_mutex);
        list_for_each_entry(cont, &attribute_container_list, node) {
                struct internal_container *ic;
 
@@ -136,12 +155,13 @@ attribute_container_add_device(struct device *dev,
 
                if (!cont->match(cont, dev))
                        continue;
-               ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL);
+
+               ic = kzalloc(sizeof(*ic), GFP_KERNEL);
                if (!ic) {
                        dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
                        continue;
                }
-               memset(ic, 0, sizeof(struct internal_container));
+
                ic->cont = cont;
                class_device_initialize(&ic->classdev);
                ic->classdev.dev = get_device(dev);
@@ -154,7 +174,7 @@ attribute_container_add_device(struct device *dev,
                        attribute_container_add_class_device(&ic->classdev);
                klist_add_tail(&ic->node, &cont->containers);
        }
-       up(&attribute_container_mutex);
+       mutex_unlock(&attribute_container_mutex);
 }
 
 /* FIXME: can't break out of this unless klist_iter_exit is also
@@ -163,8 +183,8 @@ attribute_container_add_device(struct device *dev,
 #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);\
+               n ? container_of(n, typeof(*pos), member) : \
+                       ({ klist_iter_exit(iter) ; NULL; }); \
        }) ) != NULL; )
                        
 
@@ -192,7 +212,7 @@ attribute_container_remove_device(struct device *dev,
 {
        struct attribute_container *cont;
 
-       down(&attribute_container_mutex);
+       mutex_lock(&attribute_container_mutex);
        list_for_each_entry(cont, &attribute_container_list, node) {
                struct internal_container *ic;
                struct klist_iter iter;
@@ -206,7 +226,7 @@ attribute_container_remove_device(struct device *dev,
                klist_for_each_entry(ic, &cont->containers, node, &iter) {
                        if (dev != ic->classdev.dev)
                                continue;
-                       klist_remove(&ic->node);
+                       klist_del(&ic->node);
                        if (fn)
                                fn(cont, dev, &ic->classdev);
                        else {
@@ -215,9 +235,8 @@ attribute_container_remove_device(struct device *dev,
                        }
                }
        }
-       up(&attribute_container_mutex);
+       mutex_unlock(&attribute_container_mutex);
 }
-EXPORT_SYMBOL_GPL(attribute_container_remove_device);
 
 /**
  * attribute_container_device_trigger - execute a trigger for each matching classdev
@@ -237,7 +256,7 @@ attribute_container_device_trigger(struct device *dev,
 {
        struct attribute_container *cont;
 
-       down(&attribute_container_mutex);
+       mutex_lock(&attribute_container_mutex);
        list_for_each_entry(cont, &attribute_container_list, node) {
                struct internal_container *ic;
                struct klist_iter iter;
@@ -255,9 +274,8 @@ attribute_container_device_trigger(struct device *dev,
                                fn(cont, dev, &ic->classdev);
                }
        }
-       up(&attribute_container_mutex);
+       mutex_unlock(&attribute_container_mutex);
 }
-EXPORT_SYMBOL_GPL(attribute_container_device_trigger);
 
 /**
  * attribute_container_trigger - trigger a function for each matching container
@@ -278,14 +296,13 @@ attribute_container_trigger(struct device *dev,
 {
        struct attribute_container *cont;
 
-       down(&attribute_container_mutex);
+       mutex_lock(&attribute_container_mutex);
        list_for_each_entry(cont, &attribute_container_list, node) {
                if (cont->match(cont, dev))
                        fn(cont, dev);
        }
-       up(&attribute_container_mutex);
+       mutex_unlock(&attribute_container_mutex);
 }
-EXPORT_SYMBOL_GPL(attribute_container_trigger);
 
 /**
  * attribute_container_add_attrs - add attributes
@@ -314,7 +331,6 @@ attribute_container_add_attrs(struct class_device *classdev)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(attribute_container_add_attrs);
 
 /**
  * attribute_container_add_class_device - same function as class_device_add
@@ -333,7 +349,6 @@ attribute_container_add_class_device(struct class_device *classdev)
                return error;
        return attribute_container_add_attrs(classdev);
 }
-EXPORT_SYMBOL_GPL(attribute_container_add_class_device);
 
 /**
  * attribute_container_add_class_device_adapter - simple adapter for triggers
@@ -348,7 +363,6 @@ attribute_container_add_class_device_adapter(struct attribute_container *cont,
 {
        return attribute_container_add_class_device(classdev);
 }
-EXPORT_SYMBOL_GPL(attribute_container_add_class_device_adapter);
 
 /**
  * attribute_container_remove_attrs - remove any attribute files
@@ -370,7 +384,6 @@ attribute_container_remove_attrs(struct class_device *classdev)
        for (i = 0; attrs[i]; i++)
                class_device_remove_file(classdev, attrs[i]);
 }
-EXPORT_SYMBOL_GPL(attribute_container_remove_attrs);
 
 /**
  * attribute_container_class_device_del - equivalent of class_device_del
@@ -386,7 +399,6 @@ attribute_container_class_device_del(struct class_device *classdev)
        attribute_container_remove_attrs(classdev);
        class_device_del(classdev);
 }
-EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
 
 /**
  * attribute_container_find_class_device - find the corresponding class_device