include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / arch / powerpc / platforms / powermac / pfunc_core.c
index c32c623..cec6359 100644 (file)
@@ -5,14 +5,14 @@
  * FIXME: LOCKING !!!
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 
-#include <asm/semaphore.h>
 #include <asm/prom.h>
 #include <asm/pmac_pfunc.h>
 
 #define LOG_PARSE(fmt...)
 #define LOG_ERROR(fmt...)      printk(fmt)
 #define LOG_BLOB(t,b,c)
+
+#undef DEBUG
+#ifdef DEBUG
 #define DBG(fmt...)            printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
 /* Command numbers */
 #define PMF_CMD_LIST                   0
@@ -539,7 +545,8 @@ struct pmf_device {
 };
 
 static LIST_HEAD(pmf_devices);
-static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pmf_lock);
+static DEFINE_MUTEX(pmf_irq_mutex);
 
 static void pmf_release_device(struct kref *kref)
 {
@@ -685,8 +692,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata)
                name = pp->name + plen;
                if (strlen(name) && pp->length >= 12)
                        count += pmf_add_function_prop(dev, driverdata, name,
-                                                      (u32 *)pp->value,
-                                                      pp->length);
+                                                      pp->value, pp->length);
        }
        return count;
 }
@@ -806,14 +812,15 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
        struct pmf_device *dev;
        struct pmf_function *func, *result = NULL;
        char fname[64];
-       u32 *prop, ph;
+       const u32 *prop;
+       u32 ph;
 
        /*
         * Look for a "platform-*" function reference. If we can't find
         * one, then we fallback to a direct call attempt
         */
        snprintf(fname, 63, "platform-%s", name);
-       prop = (u32 *)get_property(target, fname, NULL);
+       prop = of_get_property(target, fname, NULL);
        if (prop == NULL)
                goto find_it;
        ph = *prop;
@@ -836,7 +843,7 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
        list_for_each_entry(func, &dev->functions, link) {
                if (name && strcmp(name, func->name))
                        continue;
-               if (func->phandle && target->node != func->phandle)
+               if (func->phandle && target->phandle != func->phandle)
                        continue;
                if ((func->flags & flags) == 0)
                        continue;
@@ -858,26 +865,49 @@ int pmf_register_irq_client(struct device_node *target,
 
        spin_lock_irqsave(&pmf_lock, flags);
        func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN);
-       if (func == NULL) {
-               spin_unlock_irqrestore(&pmf_lock, flags);
+       if (func)
+               func = pmf_get_function(func);
+       spin_unlock_irqrestore(&pmf_lock, flags);
+       if (func == NULL)
                return -ENODEV;
-       }
+
+       /* guard against manipulations of list */
+       mutex_lock(&pmf_irq_mutex);
+       if (list_empty(&func->irq_clients))
+               func->dev->handlers->irq_enable(func);
+
+       /* guard against pmf_do_irq while changing list */
+       spin_lock_irqsave(&pmf_lock, flags);
        list_add(&client->link, &func->irq_clients);
        spin_unlock_irqrestore(&pmf_lock, flags);
 
+       client->func = func;
+       mutex_unlock(&pmf_irq_mutex);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(pmf_register_irq_client);
 
-void pmf_unregister_irq_client(struct device_node *np,
-                             const char *name,
-                             struct pmf_irq_client *client)
+void pmf_unregister_irq_client(struct pmf_irq_client *client)
 {
+       struct pmf_function *func = client->func;
        unsigned long flags;
 
+       BUG_ON(func == NULL);
+
+       /* guard against manipulations of list */
+       mutex_lock(&pmf_irq_mutex);
+       client->func = NULL;
+
+       /* guard against pmf_do_irq while changing list */
        spin_lock_irqsave(&pmf_lock, flags);
        list_del(&client->link);
        spin_unlock_irqrestore(&pmf_lock, flags);
+
+       if (list_empty(&func->irq_clients))
+               func->dev->handlers->irq_disable(func);
+       mutex_unlock(&pmf_irq_mutex);
+       pmf_put_function(func);
 }
 EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);