| Linux kernel & device driver programming |
| [ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] |
1 /* 1 /*
2 * w1_family.c !! 2 * w1_family.c
3 * 3 *
4 * Copyright (c) 2004 Evgeniy Polyakov <johnpo 4 * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
5 * !! 5 *
6 * 6 *
7 * This program is free software; you can redi 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Publi 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either versio 9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope tha 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU 17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to t 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 33 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22 #include <linux/spinlock.h> 22 #include <linux/spinlock.h>
23 #include <linux/list.h> 23 #include <linux/list.h>
>> 24 #include <linux/sched.h> /* schedule_timeout() */
24 #include <linux/delay.h> 25 #include <linux/delay.h>
25 26
26 #include "w1_family.h" 27 #include "w1_family.h"
>> 28 #include "w1.h"
27 29
28 DEFINE_SPINLOCK(w1_flock); 30 DEFINE_SPINLOCK(w1_flock);
29 static LIST_HEAD(w1_families); 31 static LIST_HEAD(w1_families);
30 32
31 static int w1_check_family(struct w1_family *f <<
32 { <<
33 if (!f->fops->rname || !f->fops->rbin <<
34 return -EINVAL; <<
35 <<
36 return 0; <<
37 } <<
38 <<
39 int w1_register_family(struct w1_family *newf) 33 int w1_register_family(struct w1_family *newf)
40 { 34 {
41 struct list_head *ent, *n; 35 struct list_head *ent, *n;
42 struct w1_family *f; 36 struct w1_family *f;
43 int ret = 0; 37 int ret = 0;
44 38
45 if (w1_check_family(newf)) <<
46 return -EINVAL; <<
47 <<
48 spin_lock(&w1_flock); 39 spin_lock(&w1_flock);
49 list_for_each_safe(ent, n, &w1_familie 40 list_for_each_safe(ent, n, &w1_families) {
50 f = list_entry(ent, struct w1_ 41 f = list_entry(ent, struct w1_family, family_entry);
51 42
52 if (f->fid == newf->fid) { 43 if (f->fid == newf->fid) {
53 ret = -EEXIST; 44 ret = -EEXIST;
54 break; 45 break;
55 } 46 }
56 } 47 }
57 48
58 if (!ret) { 49 if (!ret) {
59 atomic_set(&newf->refcnt, 0); 50 atomic_set(&newf->refcnt, 0);
60 newf->need_exit = 0; <<
61 list_add_tail(&newf->family_en 51 list_add_tail(&newf->family_entry, &w1_families);
62 } 52 }
63 <<
64 spin_unlock(&w1_flock); 53 spin_unlock(&w1_flock);
65 54
>> 55 /* check default devices against the new set of drivers */
>> 56 w1_reconnect_slaves(newf, 1);
>> 57
66 return ret; 58 return ret;
67 } 59 }
68 60
69 void w1_unregister_family(struct w1_family *fe 61 void w1_unregister_family(struct w1_family *fent)
70 { 62 {
71 struct list_head *ent, *n; 63 struct list_head *ent, *n;
72 struct w1_family *f; 64 struct w1_family *f;
73 65
74 spin_lock(&w1_flock); 66 spin_lock(&w1_flock);
75 list_for_each_safe(ent, n, &w1_familie 67 list_for_each_safe(ent, n, &w1_families) {
76 f = list_entry(ent, struct w1_ 68 f = list_entry(ent, struct w1_family, family_entry);
77 69
78 if (f->fid == fent->fid) { 70 if (f->fid == fent->fid) {
79 list_del(&fent->family 71 list_del(&fent->family_entry);
80 break; 72 break;
81 } 73 }
82 } 74 }
83 <<
84 fent->need_exit = 1; <<
85 <<
86 spin_unlock(&w1_flock); 75 spin_unlock(&w1_flock);
87 76
>> 77 /* deatch devices using this family code */
>> 78 w1_reconnect_slaves(fent, 0);
>> 79
88 while (atomic_read(&fent->refcnt)) { 80 while (atomic_read(&fent->refcnt)) {
89 printk(KERN_INFO "Waiting for 81 printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n",
90 fent->fid, ato 82 fent->fid, atomic_read(&fent->refcnt));
91 83
92 if (msleep_interruptible(1000) 84 if (msleep_interruptible(1000))
93 flush_signals(current) 85 flush_signals(current);
94 } 86 }
95 } 87 }
96 88
97 /* 89 /*
98 * Should be called under w1_flock held. 90 * Should be called under w1_flock held.
99 */ 91 */
100 struct w1_family * w1_family_registered(u8 fid 92 struct w1_family * w1_family_registered(u8 fid)
101 { 93 {
102 struct list_head *ent, *n; 94 struct list_head *ent, *n;
103 struct w1_family *f = NULL; 95 struct w1_family *f = NULL;
104 int ret = 0; 96 int ret = 0;
105 97
106 list_for_each_safe(ent, n, &w1_familie 98 list_for_each_safe(ent, n, &w1_families) {
107 f = list_entry(ent, struct w1_ 99 f = list_entry(ent, struct w1_family, family_entry);
108 100
109 if (f->fid == fid) { 101 if (f->fid == fid) {
110 ret = 1; 102 ret = 1;
111 break; 103 break;
112 } 104 }
113 } 105 }
114 106
115 return (ret) ? f : NULL; 107 return (ret) ? f : NULL;
116 } 108 }
117 109
>> 110 static void __w1_family_put(struct w1_family *f)
>> 111 {
>> 112 atomic_dec(&f->refcnt);
>> 113 }
>> 114
118 void w1_family_put(struct w1_family *f) 115 void w1_family_put(struct w1_family *f)
119 { 116 {
120 spin_lock(&w1_flock); 117 spin_lock(&w1_flock);
121 __w1_family_put(f); 118 __w1_family_put(f);
122 spin_unlock(&w1_flock); 119 spin_unlock(&w1_flock);
123 } 120 }
124 121
125 void __w1_family_put(struct w1_family *f) !! 122 #if 0
126 { <<
127 if (atomic_dec_and_test(&f->refcnt)) <<
128 f->need_exit = 1; <<
129 } <<
130 <<
131 void w1_family_get(struct w1_family *f) 123 void w1_family_get(struct w1_family *f)
132 { 124 {
133 spin_lock(&w1_flock); 125 spin_lock(&w1_flock);
134 __w1_family_get(f); 126 __w1_family_get(f);
135 spin_unlock(&w1_flock); 127 spin_unlock(&w1_flock);
136 <<
137 } 128 }
>> 129 #endif /* 0 */
138 130
139 void __w1_family_get(struct w1_family *f) 131 void __w1_family_get(struct w1_family *f)
140 { 132 {
>> 133 smp_mb__before_atomic_inc();
141 atomic_inc(&f->refcnt); 134 atomic_inc(&f->refcnt);
>> 135 smp_mb__after_atomic_inc();
142 } 136 }
143 137
144 EXPORT_SYMBOL(w1_family_get); <<
145 EXPORT_SYMBOL(w1_family_put); <<
146 EXPORT_SYMBOL(__w1_family_get); <<
147 EXPORT_SYMBOL(__w1_family_put); <<
148 EXPORT_SYMBOL(w1_family_registered); <<
149 EXPORT_SYMBOL(w1_unregister_family); 138 EXPORT_SYMBOL(w1_unregister_family);
150 EXPORT_SYMBOL(w1_register_family); 139 EXPORT_SYMBOL(w1_register_family);
151 140
| This page was automatically generated by the LXR engine. |