Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *      w1_family.c
  3  *
  4  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
  5  *
  6  *
  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.
 11  *
 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.
 16  *
 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
 20  */
 21 
 22 #include <linux/spinlock.h>
 23 #include <linux/list.h>
 24 #include <linux/sched.h>        /* schedule_timeout() */
 25 #include <linux/delay.h>
 26 
 27 #include "w1_family.h"
 28 #include "w1.h"
 29 
 30 DEFINE_SPINLOCK(w1_flock);
 31 static LIST_HEAD(w1_families);
 32 
 33 int w1_register_family(struct w1_family *newf)
 34 {
 35         struct list_head *ent, *n;
 36         struct w1_family *f;
 37         int ret = 0;
 38 
 39         spin_lock(&w1_flock);
 40         list_for_each_safe(ent, n, &w1_families) {
 41                 f = list_entry(ent, struct w1_family, family_entry);
 42 
 43                 if (f->fid == newf->fid) {
 44                         ret = -EEXIST;
 45                         break;
 46                 }
 47         }
 48 
 49         if (!ret) {
 50                 atomic_set(&newf->refcnt, 0);
 51                 newf->need_exit = 0;
 52                 list_add_tail(&newf->family_entry, &w1_families);
 53         }
 54         spin_unlock(&w1_flock);
 55 
 56         w1_reconnect_slaves(newf);
 57 
 58         return ret;
 59 }
 60 
 61 void w1_unregister_family(struct w1_family *fent)
 62 {
 63         struct list_head *ent, *n;
 64         struct w1_family *f;
 65 
 66         spin_lock(&w1_flock);
 67         list_for_each_safe(ent, n, &w1_families) {
 68                 f = list_entry(ent, struct w1_family, family_entry);
 69 
 70                 if (f->fid == fent->fid) {
 71                         list_del(&fent->family_entry);
 72                         break;
 73                 }
 74         }
 75 
 76         fent->need_exit = 1;
 77 
 78         spin_unlock(&w1_flock);
 79 
 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));
 83 
 84                 if (msleep_interruptible(1000))
 85                         flush_signals(current);
 86         }
 87 }
 88 
 89 /*
 90  * Should be called under w1_flock held.
 91  */
 92 struct w1_family * w1_family_registered(u8 fid)
 93 {
 94         struct list_head *ent, *n;
 95         struct w1_family *f = NULL;
 96         int ret = 0;
 97 
 98         list_for_each_safe(ent, n, &w1_families) {
 99                 f = list_entry(ent, struct w1_family, family_entry);
100 
101                 if (f->fid == fid) {
102                         ret = 1;
103                         break;
104                 }
105         }
106 
107         return (ret) ? f : NULL;
108 }
109 
110 static void __w1_family_put(struct w1_family *f)
111 {
112         if (atomic_dec_and_test(&f->refcnt))
113                 f->need_exit = 1;
114 }
115 
116 void w1_family_put(struct w1_family *f)
117 {
118         spin_lock(&w1_flock);
119         __w1_family_put(f);
120         spin_unlock(&w1_flock);
121 }
122 
123 #if 0
124 void w1_family_get(struct w1_family *f)
125 {
126         spin_lock(&w1_flock);
127         __w1_family_get(f);
128         spin_unlock(&w1_flock);
129 }
130 #endif  /*  0  */
131 
132 void __w1_family_get(struct w1_family *f)
133 {
134         smp_mb__before_atomic_inc();
135         atomic_inc(&f->refcnt);
136         smp_mb__after_atomic_inc();
137 }
138 
139 EXPORT_SYMBOL(w1_unregister_family);
140 EXPORT_SYMBOL(w1_register_family);
141 
  This page was automatically generated by the LXR engine.