fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / w1 / w1_family.c
index 6a62d2a..a3c95bd 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_family.c
+ *     w1_family.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/sched.h>       /* schedule_timeout() */
+#include <linux/delay.h>
 
 #include "w1_family.h"
+#include "w1.h"
 
-spinlock_t w1_flock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(w1_flock);
 static LIST_HEAD(w1_families);
 
-static int w1_check_family(struct w1_family *f)
-{
-       if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
-               return -EINVAL;
-
-       return 0;
-}
-
 int w1_register_family(struct w1_family *newf)
 {
        struct list_head *ent, *n;
        struct w1_family *f;
        int ret = 0;
 
-       if (w1_check_family(newf))
-               return -EINVAL;
-
        spin_lock(&w1_flock);
        list_for_each_safe(ent, n, &w1_families) {
                f = list_entry(ent, struct w1_family, family_entry);
@@ -59,9 +51,10 @@ int w1_register_family(struct w1_family *newf)
                newf->need_exit = 0;
                list_add_tail(&newf->family_entry, &w1_families);
        }
-
        spin_unlock(&w1_flock);
 
+       w1_reconnect_slaves(newf);
+
        return ret;
 }
 
@@ -84,8 +77,13 @@ void w1_unregister_family(struct w1_family *fent)
 
        spin_unlock(&w1_flock);
 
-       while (atomic_read(&fent->refcnt))
-               schedule_timeout(10);
+       while (atomic_read(&fent->refcnt)) {
+               printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n",
+                               fent->fid, atomic_read(&fent->refcnt));
+
+               if (msleep_interruptible(1000))
+                       flush_signals(current);
+       }
 }
 
 /*
@@ -109,6 +107,12 @@ struct w1_family * w1_family_registered(u8 fid)
        return (ret) ? f : NULL;
 }
 
+static void __w1_family_put(struct w1_family *f)
+{
+       if (atomic_dec_and_test(&f->refcnt))
+               f->need_exit = 1;
+}
+
 void w1_family_put(struct w1_family *f)
 {
        spin_lock(&w1_flock);
@@ -116,29 +120,21 @@ void w1_family_put(struct w1_family *f)
        spin_unlock(&w1_flock);
 }
 
-void __w1_family_put(struct w1_family *f)
-{
-       if (atomic_dec_and_test(&f->refcnt))
-               f->need_exit = 1;
-}
-
+#if 0
 void w1_family_get(struct w1_family *f)
 {
        spin_lock(&w1_flock);
        __w1_family_get(f);
        spin_unlock(&w1_flock);
-
 }
+#endif  /*  0  */
 
 void __w1_family_get(struct w1_family *f)
 {
+       smp_mb__before_atomic_inc();
        atomic_inc(&f->refcnt);
+       smp_mb__after_atomic_inc();
 }
 
-EXPORT_SYMBOL(w1_family_get);
-EXPORT_SYMBOL(w1_family_put);
-EXPORT_SYMBOL(__w1_family_get);
-EXPORT_SYMBOL(__w1_family_put);
-EXPORT_SYMBOL(w1_family_registered);
 EXPORT_SYMBOL(w1_unregister_family);
 EXPORT_SYMBOL(w1_register_family);