aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/attribute_container.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/attribute_container.c')
-rw-r--r--drivers/base/attribute_container.c67
1 files changed, 45 insertions, 22 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index ebcae5c34133..373e7b728fa7 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -22,11 +22,26 @@
22/* This is a private structure used to tie the classdev and the 22/* This is a private structure used to tie the classdev and the
23 * container .. it should never be visible outside this file */ 23 * container .. it should never be visible outside this file */
24struct internal_container { 24struct internal_container {
25 struct list_head node; 25 struct klist_node node;
26 struct attribute_container *cont; 26 struct attribute_container *cont;
27 struct class_device classdev; 27 struct class_device classdev;
28}; 28};
29 29
30static void internal_container_klist_get(struct klist_node *n)
31{
32 struct internal_container *ic =
33 container_of(n, struct internal_container, node);
34 class_device_get(&ic->classdev);
35}
36
37static void internal_container_klist_put(struct klist_node *n)
38{
39 struct internal_container *ic =
40 container_of(n, struct internal_container, node);
41 class_device_put(&ic->classdev);
42}
43
44
30/** 45/**
31 * attribute_container_classdev_to_container - given a classdev, return the container 46 * attribute_container_classdev_to_container - given a classdev, return the container
32 * 47 *
@@ -57,8 +72,8 @@ int
57attribute_container_register(struct attribute_container *cont) 72attribute_container_register(struct attribute_container *cont)
58{ 73{
59 INIT_LIST_HEAD(&cont->node); 74 INIT_LIST_HEAD(&cont->node);
60 INIT_LIST_HEAD(&cont->containers); 75 klist_init(&cont->containers,internal_container_klist_get,
61 spin_lock_init(&cont->containers_lock); 76 internal_container_klist_put);
62 77
63 down(&attribute_container_mutex); 78 down(&attribute_container_mutex);
64 list_add_tail(&cont->node, &attribute_container_list); 79 list_add_tail(&cont->node, &attribute_container_list);
@@ -78,13 +93,13 @@ attribute_container_unregister(struct attribute_container *cont)
78{ 93{
79 int retval = -EBUSY; 94 int retval = -EBUSY;
80 down(&attribute_container_mutex); 95 down(&attribute_container_mutex);
81 spin_lock(&cont->containers_lock); 96 spin_lock(&cont->containers.k_lock);
82 if (!list_empty(&cont->containers)) 97 if (!list_empty(&cont->containers.k_list))
83 goto out; 98 goto out;
84 retval = 0; 99 retval = 0;
85 list_del(&cont->node); 100 list_del(&cont->node);
86 out: 101 out:
87 spin_unlock(&cont->containers_lock); 102 spin_unlock(&cont->containers.k_lock);
88 up(&attribute_container_mutex); 103 up(&attribute_container_mutex);
89 return retval; 104 return retval;
90 105
@@ -143,7 +158,6 @@ attribute_container_add_device(struct device *dev,
143 continue; 158 continue;
144 } 159 }
145 memset(ic, 0, sizeof(struct internal_container)); 160 memset(ic, 0, sizeof(struct internal_container));
146 INIT_LIST_HEAD(&ic->node);
147 ic->cont = cont; 161 ic->cont = cont;
148 class_device_initialize(&ic->classdev); 162 class_device_initialize(&ic->classdev);
149 ic->classdev.dev = get_device(dev); 163 ic->classdev.dev = get_device(dev);
@@ -154,13 +168,22 @@ attribute_container_add_device(struct device *dev,
154 fn(cont, dev, &ic->classdev); 168 fn(cont, dev, &ic->classdev);
155 else 169 else
156 attribute_container_add_class_device(&ic->classdev); 170 attribute_container_add_class_device(&ic->classdev);
157 spin_lock(&cont->containers_lock); 171 klist_add_tail(&ic->node, &cont->containers);
158 list_add_tail(&ic->node, &cont->containers);
159 spin_unlock(&cont->containers_lock);
160 } 172 }
161 up(&attribute_container_mutex); 173 up(&attribute_container_mutex);
162} 174}
163 175
176/* FIXME: can't break out of this unless klist_iter_exit is also
177 * called before doing the break
178 */
179#define klist_for_each_entry(pos, head, member, iter) \
180 for (klist_iter_init(head, iter); (pos = ({ \
181 struct klist_node *n = klist_next(iter); \
182 n ? container_of(n, typeof(*pos), member) : \
183 ({ klist_iter_exit(iter) ; NULL; }); \
184 }) ) != NULL; )
185
186
164/** 187/**
165 * attribute_container_remove_device - make device eligible for removal. 188 * attribute_container_remove_device - make device eligible for removal.
166 * 189 *
@@ -187,18 +210,19 @@ attribute_container_remove_device(struct device *dev,
187 210
188 down(&attribute_container_mutex); 211 down(&attribute_container_mutex);
189 list_for_each_entry(cont, &attribute_container_list, node) { 212 list_for_each_entry(cont, &attribute_container_list, node) {
190 struct internal_container *ic, *tmp; 213 struct internal_container *ic;
214 struct klist_iter iter;
191 215
192 if (attribute_container_no_classdevs(cont)) 216 if (attribute_container_no_classdevs(cont))
193 continue; 217 continue;
194 218
195 if (!cont->match(cont, dev)) 219 if (!cont->match(cont, dev))
196 continue; 220 continue;
197 spin_lock(&cont->containers_lock); 221
198 list_for_each_entry_safe(ic, tmp, &cont->containers, node) { 222 klist_for_each_entry(ic, &cont->containers, node, &iter) {
199 if (dev != ic->classdev.dev) 223 if (dev != ic->classdev.dev)
200 continue; 224 continue;
201 list_del(&ic->node); 225 klist_del(&ic->node);
202 if (fn) 226 if (fn)
203 fn(cont, dev, &ic->classdev); 227 fn(cont, dev, &ic->classdev);
204 else { 228 else {
@@ -206,7 +230,6 @@ attribute_container_remove_device(struct device *dev,
206 class_device_unregister(&ic->classdev); 230 class_device_unregister(&ic->classdev);
207 } 231 }
208 } 232 }
209 spin_unlock(&cont->containers_lock);
210 } 233 }
211 up(&attribute_container_mutex); 234 up(&attribute_container_mutex);
212} 235}
@@ -232,7 +255,8 @@ attribute_container_device_trigger(struct device *dev,
232 255
233 down(&attribute_container_mutex); 256 down(&attribute_container_mutex);
234 list_for_each_entry(cont, &attribute_container_list, node) { 257 list_for_each_entry(cont, &attribute_container_list, node) {
235 struct internal_container *ic, *tmp; 258 struct internal_container *ic;
259 struct klist_iter iter;
236 260
237 if (!cont->match(cont, dev)) 261 if (!cont->match(cont, dev))
238 continue; 262 continue;
@@ -242,12 +266,10 @@ attribute_container_device_trigger(struct device *dev,
242 continue; 266 continue;
243 } 267 }
244 268
245 spin_lock(&cont->containers_lock); 269 klist_for_each_entry(ic, &cont->containers, node, &iter) {
246 list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
247 if (dev == ic->classdev.dev) 270 if (dev == ic->classdev.dev)
248 fn(cont, dev, &ic->classdev); 271 fn(cont, dev, &ic->classdev);
249 } 272 }
250 spin_unlock(&cont->containers_lock);
251 } 273 }
252 up(&attribute_container_mutex); 274 up(&attribute_container_mutex);
253} 275}
@@ -397,15 +419,16 @@ attribute_container_find_class_device(struct attribute_container *cont,
397{ 419{
398 struct class_device *cdev = NULL; 420 struct class_device *cdev = NULL;
399 struct internal_container *ic; 421 struct internal_container *ic;
422 struct klist_iter iter;
400 423
401 spin_lock(&cont->containers_lock); 424 klist_for_each_entry(ic, &cont->containers, node, &iter) {
402 list_for_each_entry(ic, &cont->containers, node) {
403 if (ic->classdev.dev == dev) { 425 if (ic->classdev.dev == dev) {
404 cdev = &ic->classdev; 426 cdev = &ic->classdev;
427 /* FIXME: must exit iterator then break */
428 klist_iter_exit(&iter);
405 break; 429 break;
406 } 430 }
407 } 431 }
408 spin_unlock(&cont->containers_lock);
409 432
410 return cdev; 433 return cdev;
411} 434}