4  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
 
   7  * This program is free software; you can redistribute it and/or modify
 
   8  * it under the terms of the GNU General Public License as published by
 
   9  * the Free Software Foundation; either version 2 of the License, or
 
  10  * (at your option) any later version.
 
  12  * This program is distributed in the hope that it will be useful,
 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  15  * GNU General Public License for more details.
 
  17  * You should have received a copy of the GNU General Public License
 
  18  * along with this program; if not, write to the Free Software
 
  19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
  22 #include <linux/spinlock.h>
 
  23 #include <linux/list.h>
 
  24 #include <linux/sched.h>        /* schedule_timeout() */
 
  25 #include <linux/delay.h>
 
  27 #include "w1_family.h"
 
  30 DEFINE_SPINLOCK(w1_flock);
 
  31 static LIST_HEAD(w1_families);
 
  33 int w1_register_family(struct w1_family *newf)
 
  35         struct list_head *ent, *n;
 
  40         list_for_each_safe(ent, n, &w1_families) {
 
  41                 f = list_entry(ent, struct w1_family, family_entry);
 
  43                 if (f->fid == newf->fid) {
 
  50                 atomic_set(&newf->refcnt, 0);
 
  52                 list_add_tail(&newf->family_entry, &w1_families);
 
  54         spin_unlock(&w1_flock);
 
  56         w1_reconnect_slaves(newf);
 
  61 void w1_unregister_family(struct w1_family *fent)
 
  63         struct list_head *ent, *n;
 
  67         list_for_each_safe(ent, n, &w1_families) {
 
  68                 f = list_entry(ent, struct w1_family, family_entry);
 
  70                 if (f->fid == fent->fid) {
 
  71                         list_del(&fent->family_entry);
 
  78         spin_unlock(&w1_flock);
 
  80         while (atomic_read(&fent->refcnt)) {
 
  81                 printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n",
 
  82                                 fent->fid, atomic_read(&fent->refcnt));
 
  84                 if (msleep_interruptible(1000))
 
  85                         flush_signals(current);
 
  90  * Should be called under w1_flock held.
 
  92 struct w1_family * w1_family_registered(u8 fid)
 
  94         struct list_head *ent, *n;
 
  95         struct w1_family *f = NULL;
 
  98         list_for_each_safe(ent, n, &w1_families) {
 
  99                 f = list_entry(ent, struct w1_family, family_entry);
 
 107         return (ret) ? f : NULL;
 
 110 static void __w1_family_put(struct w1_family *f)
 
 112         if (atomic_dec_and_test(&f->refcnt))
 
 116 void w1_family_put(struct w1_family *f)
 
 118         spin_lock(&w1_flock);
 
 120         spin_unlock(&w1_flock);
 
 124 void w1_family_get(struct w1_family *f)
 
 126         spin_lock(&w1_flock);
 
 128         spin_unlock(&w1_flock);
 
 132 void __w1_family_get(struct w1_family *f)
 
 134         smp_mb__before_atomic_inc();
 
 135         atomic_inc(&f->refcnt);
 
 136         smp_mb__after_atomic_inc();
 
 139 EXPORT_SYMBOL(w1_unregister_family);
 
 140 EXPORT_SYMBOL(w1_register_family);