Branch data Line data Source code
1 : : /*
2 : : * attribute_container.c - implementation of a simple container for classes
3 : : *
4 : : * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com>
5 : : *
6 : : * This file is licensed under GPLv2
7 : : *
8 : : * The basic idea here is to enable a device to be attached to an
9 : : * aritrary numer of classes without having to allocate storage for them.
10 : : * Instead, the contained classes select the devices they need to attach
11 : : * to via a matching function.
12 : : */
13 : :
14 : : #include <linux/attribute_container.h>
15 : : #include <linux/init.h>
16 : : #include <linux/device.h>
17 : : #include <linux/kernel.h>
18 : : #include <linux/slab.h>
19 : : #include <linux/list.h>
20 : : #include <linux/module.h>
21 : : #include <linux/mutex.h>
22 : :
23 : : #include "base.h"
24 : :
25 : : /* This is a private structure used to tie the classdev and the
26 : : * container .. it should never be visible outside this file */
27 : : struct internal_container {
28 : : struct klist_node node;
29 : : struct attribute_container *cont;
30 : : struct device classdev;
31 : : };
32 : :
33 : 0 : static void internal_container_klist_get(struct klist_node *n)
34 : : {
35 : : struct internal_container *ic =
36 : : container_of(n, struct internal_container, node);
37 : 0 : get_device(&ic->classdev);
38 : 0 : }
39 : :
40 : 0 : static void internal_container_klist_put(struct klist_node *n)
41 : : {
42 : : struct internal_container *ic =
43 : : container_of(n, struct internal_container, node);
44 : 0 : put_device(&ic->classdev);
45 : 0 : }
46 : :
47 : :
48 : : /**
49 : : * attribute_container_classdev_to_container - given a classdev, return the container
50 : : *
51 : : * @classdev: the class device created by attribute_container_add_device.
52 : : *
53 : : * Returns the container associated with this classdev.
54 : : */
55 : : struct attribute_container *
56 : 0 : attribute_container_classdev_to_container(struct device *classdev)
57 : : {
58 : : struct internal_container *ic =
59 : : container_of(classdev, struct internal_container, classdev);
60 : 0 : return ic->cont;
61 : : }
62 : : EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
63 : :
64 : : static LIST_HEAD(attribute_container_list);
65 : :
66 : : static DEFINE_MUTEX(attribute_container_mutex);
67 : :
68 : : /**
69 : : * attribute_container_register - register an attribute container
70 : : *
71 : : * @cont: The container to register. This must be allocated by the
72 : : * callee and should also be zeroed by it.
73 : : */
74 : : int
75 : 0 : attribute_container_register(struct attribute_container *cont)
76 : : {
77 : 0 : INIT_LIST_HEAD(&cont->node);
78 : 0 : klist_init(&cont->containers,internal_container_klist_get,
79 : : internal_container_klist_put);
80 : :
81 : 0 : mutex_lock(&attribute_container_mutex);
82 : : list_add_tail(&cont->node, &attribute_container_list);
83 : 0 : mutex_unlock(&attribute_container_mutex);
84 : :
85 : 0 : return 0;
86 : : }
87 : : EXPORT_SYMBOL_GPL(attribute_container_register);
88 : :
89 : : /**
90 : : * attribute_container_unregister - remove a container registration
91 : : *
92 : : * @cont: previously registered container to remove
93 : : */
94 : : int
95 : 0 : attribute_container_unregister(struct attribute_container *cont)
96 : : {
97 : : int retval = -EBUSY;
98 : 0 : mutex_lock(&attribute_container_mutex);
99 : : spin_lock(&cont->containers.k_lock);
100 [ # # ]: 0 : if (!list_empty(&cont->containers.k_list))
101 : : goto out;
102 : : retval = 0;
103 : : list_del(&cont->node);
104 : : out:
105 : : spin_unlock(&cont->containers.k_lock);
106 : 0 : mutex_unlock(&attribute_container_mutex);
107 : 0 : return retval;
108 : :
109 : : }
110 : : EXPORT_SYMBOL_GPL(attribute_container_unregister);
111 : :
112 : : /* private function used as class release */
113 : 0 : static void attribute_container_release(struct device *classdev)
114 : : {
115 : 0 : struct internal_container *ic
116 : : = container_of(classdev, struct internal_container, classdev);
117 : 0 : struct device *dev = classdev->parent;
118 : :
119 : 0 : kfree(ic);
120 : 0 : put_device(dev);
121 : 0 : }
122 : :
123 : : /**
124 : : * attribute_container_add_device - see if any container is interested in dev
125 : : *
126 : : * @dev: device to add attributes to
127 : : * @fn: function to trigger addition of class device.
128 : : *
129 : : * This function allocates storage for the class device(s) to be
130 : : * attached to dev (one for each matching attribute_container). If no
131 : : * fn is provided, the code will simply register the class device via
132 : : * device_add. If a function is provided, it is expected to add
133 : : * the class device at the appropriate time. One of the things that
134 : : * might be necessary is to allocate and initialise the classdev and
135 : : * then add it a later time. To do this, call this routine for
136 : : * allocation and initialisation and then use
137 : : * attribute_container_device_trigger() to call device_add() on
138 : : * it. Note: after this, the class device contains a reference to dev
139 : : * which is not relinquished until the release of the classdev.
140 : : */
141 : : void
142 : 0 : attribute_container_add_device(struct device *dev,
143 : : int (*fn)(struct attribute_container *,
144 : : struct device *,
145 : : struct device *))
146 : : {
147 : 0 : struct attribute_container *cont;
148 : :
149 : 0 : mutex_lock(&attribute_container_mutex);
150 [ # # ]: 0 : list_for_each_entry(cont, &attribute_container_list, node) {
151 : : struct internal_container *ic;
152 : :
153 [ # # ]: 0 : if (attribute_container_no_classdevs(cont))
154 : 0 : continue;
155 : :
156 [ # # ]: 0 : if (!cont->match(cont, dev))
157 : 0 : continue;
158 : :
159 : : ic = kzalloc(sizeof(*ic), GFP_KERNEL);
160 [ # # ]: 0 : if (!ic) {
161 : 0 : dev_err(dev, "failed to allocate class container\n");
162 : 0 : continue;
163 : : }
164 : :
165 : 0 : ic->cont = cont;
166 : 0 : device_initialize(&ic->classdev);
167 : 0 : ic->classdev.parent = get_device(dev);
168 : 0 : ic->classdev.class = cont->class;
169 : 0 : cont->class->dev_release = attribute_container_release;
170 : 0 : dev_set_name(&ic->classdev, "%s", dev_name(dev));
171 [ # # ]: 0 : if (fn)
172 : 0 : fn(cont, dev, &ic->classdev);
173 : : else
174 : 0 : attribute_container_add_class_device(&ic->classdev);
175 : 0 : klist_add_tail(&ic->node, &cont->containers);
176 : : }
177 : 0 : mutex_unlock(&attribute_container_mutex);
178 : 0 : }
179 : :
180 : : /* FIXME: can't break out of this unless klist_iter_exit is also
181 : : * called before doing the break
182 : : */
183 : : #define klist_for_each_entry(pos, head, member, iter) \
184 : : for (klist_iter_init(head, iter); (pos = ({ \
185 : : struct klist_node *n = klist_next(iter); \
186 : : n ? container_of(n, typeof(*pos), member) : \
187 : : ({ klist_iter_exit(iter) ; NULL; }); \
188 : : }) ) != NULL; )
189 : :
190 : :
191 : : /**
192 : : * attribute_container_remove_device - make device eligible for removal.
193 : : *
194 : : * @dev: The generic device
195 : : * @fn: A function to call to remove the device
196 : : *
197 : : * This routine triggers device removal. If fn is NULL, then it is
198 : : * simply done via device_unregister (note that if something
199 : : * still has a reference to the classdev, then the memory occupied
200 : : * will not be freed until the classdev is released). If you want a
201 : : * two phase release: remove from visibility and then delete the
202 : : * device, then you should use this routine with a fn that calls
203 : : * device_del() and then use attribute_container_device_trigger()
204 : : * to do the final put on the classdev.
205 : : */
206 : : void
207 : 0 : attribute_container_remove_device(struct device *dev,
208 : : void (*fn)(struct attribute_container *,
209 : : struct device *,
210 : : struct device *))
211 : : {
212 : 0 : struct attribute_container *cont;
213 : :
214 : 0 : mutex_lock(&attribute_container_mutex);
215 [ # # ]: 0 : list_for_each_entry(cont, &attribute_container_list, node) {
216 : : struct internal_container *ic;
217 : : struct klist_iter iter;
218 : :
219 [ # # ]: 0 : if (attribute_container_no_classdevs(cont))
220 : 0 : continue;
221 : :
222 [ # # ]: 0 : if (!cont->match(cont, dev))
223 : 0 : continue;
224 : :
225 [ # # ][ # # ]: 0 : klist_for_each_entry(ic, &cont->containers, node, &iter) {
226 [ # # ]: 0 : if (dev != ic->classdev.parent)
227 : 0 : continue;
228 : 0 : klist_del(&ic->node);
229 [ # # ]: 0 : if (fn)
230 : 0 : fn(cont, dev, &ic->classdev);
231 : : else {
232 : 0 : attribute_container_remove_attrs(&ic->classdev);
233 : 0 : device_unregister(&ic->classdev);
234 : : }
235 : : }
236 : : }
237 : 0 : mutex_unlock(&attribute_container_mutex);
238 : 0 : }
239 : :
240 : : /**
241 : : * attribute_container_device_trigger - execute a trigger for each matching classdev
242 : : *
243 : : * @dev: The generic device to run the trigger for
244 : : * @fn the function to execute for each classdev.
245 : : *
246 : : * This funcion is for executing a trigger when you need to know both
247 : : * the container and the classdev. If you only care about the
248 : : * container, then use attribute_container_trigger() instead.
249 : : */
250 : : void
251 : 0 : attribute_container_device_trigger(struct device *dev,
252 : : int (*fn)(struct attribute_container *,
253 : : struct device *,
254 : : struct device *))
255 : : {
256 : 0 : struct attribute_container *cont;
257 : :
258 : 0 : mutex_lock(&attribute_container_mutex);
259 [ # # ]: 0 : list_for_each_entry(cont, &attribute_container_list, node) {
260 : : struct internal_container *ic;
261 : : struct klist_iter iter;
262 : :
263 [ # # ]: 0 : if (!cont->match(cont, dev))
264 : 0 : continue;
265 : :
266 [ # # ]: 0 : if (attribute_container_no_classdevs(cont)) {
267 : 0 : fn(cont, dev, NULL);
268 : 0 : continue;
269 : : }
270 : :
271 [ # # ][ # # ]: 0 : klist_for_each_entry(ic, &cont->containers, node, &iter) {
272 [ # # ]: 0 : if (dev == ic->classdev.parent)
273 : 0 : fn(cont, dev, &ic->classdev);
274 : : }
275 : : }
276 : 0 : mutex_unlock(&attribute_container_mutex);
277 : 0 : }
278 : :
279 : : /**
280 : : * attribute_container_trigger - trigger a function for each matching container
281 : : *
282 : : * @dev: The generic device to activate the trigger for
283 : : * @fn: the function to trigger
284 : : *
285 : : * This routine triggers a function that only needs to know the
286 : : * matching containers (not the classdev) associated with a device.
287 : : * It is more lightweight than attribute_container_device_trigger, so
288 : : * should be used in preference unless the triggering function
289 : : * actually needs to know the classdev.
290 : : */
291 : : void
292 : 0 : attribute_container_trigger(struct device *dev,
293 : : int (*fn)(struct attribute_container *,
294 : : struct device *))
295 : : {
296 : : struct attribute_container *cont;
297 : :
298 : 0 : mutex_lock(&attribute_container_mutex);
299 [ # # ]: 0 : list_for_each_entry(cont, &attribute_container_list, node) {
300 [ # # ]: 0 : if (cont->match(cont, dev))
301 : 0 : fn(cont, dev);
302 : : }
303 : 0 : mutex_unlock(&attribute_container_mutex);
304 : 0 : }
305 : :
306 : : /**
307 : : * attribute_container_add_attrs - add attributes
308 : : *
309 : : * @classdev: The class device
310 : : *
311 : : * This simply creates all the class device sysfs files from the
312 : : * attributes listed in the container
313 : : */
314 : : int
315 : 0 : attribute_container_add_attrs(struct device *classdev)
316 : : {
317 : : struct attribute_container *cont =
318 : : attribute_container_classdev_to_container(classdev);
319 : 0 : struct device_attribute **attrs = cont->attrs;
320 : : int i, error;
321 : :
322 [ # # ][ # # ]: 0 : BUG_ON(attrs && cont->grp);
323 : :
324 [ # # ][ # # ]: 0 : if (!attrs && !cont->grp)
325 : : return 0;
326 : :
327 [ # # ]: 0 : if (cont->grp)
328 : 0 : return sysfs_create_group(&classdev->kobj, cont->grp);
329 : :
330 [ # # ]: 0 : for (i = 0; attrs[i]; i++) {
331 : : sysfs_attr_init(&attrs[i]->attr);
332 : 0 : error = device_create_file(classdev, attrs[i]);
333 [ # # ]: 0 : if (error)
334 : : return error;
335 : : }
336 : :
337 : : return 0;
338 : : }
339 : :
340 : : /**
341 : : * attribute_container_add_class_device - same function as device_add
342 : : *
343 : : * @classdev: the class device to add
344 : : *
345 : : * This performs essentially the same function as device_add except for
346 : : * attribute containers, namely add the classdev to the system and then
347 : : * create the attribute files
348 : : */
349 : : int
350 : 0 : attribute_container_add_class_device(struct device *classdev)
351 : : {
352 : 0 : int error = device_add(classdev);
353 [ # # ]: 0 : if (error)
354 : : return error;
355 : 0 : return attribute_container_add_attrs(classdev);
356 : : }
357 : :
358 : : /**
359 : : * attribute_container_add_class_device_adapter - simple adapter for triggers
360 : : *
361 : : * This function is identical to attribute_container_add_class_device except
362 : : * that it is designed to be called from the triggers
363 : : */
364 : : int
365 : 0 : attribute_container_add_class_device_adapter(struct attribute_container *cont,
366 : : struct device *dev,
367 : : struct device *classdev)
368 : : {
369 : 0 : return attribute_container_add_class_device(classdev);
370 : : }
371 : :
372 : : /**
373 : : * attribute_container_remove_attrs - remove any attribute files
374 : : *
375 : : * @classdev: The class device to remove the files from
376 : : *
377 : : */
378 : : void
379 : 0 : attribute_container_remove_attrs(struct device *classdev)
380 : : {
381 : : struct attribute_container *cont =
382 : : attribute_container_classdev_to_container(classdev);
383 : 0 : struct device_attribute **attrs = cont->attrs;
384 : : int i;
385 : :
386 [ # # ][ # # ]: 0 : if (!attrs && !cont->grp)
387 : : return;
388 : :
389 [ # # ]: 0 : if (cont->grp) {
390 : 0 : sysfs_remove_group(&classdev->kobj, cont->grp);
391 : 0 : return ;
392 : : }
393 : :
394 [ # # ]: 0 : for (i = 0; attrs[i]; i++)
395 : 0 : device_remove_file(classdev, attrs[i]);
396 : : }
397 : :
398 : : /**
399 : : * attribute_container_class_device_del - equivalent of class_device_del
400 : : *
401 : : * @classdev: the class device
402 : : *
403 : : * This function simply removes all the attribute files and then calls
404 : : * device_del.
405 : : */
406 : : void
407 : 0 : attribute_container_class_device_del(struct device *classdev)
408 : : {
409 : 0 : attribute_container_remove_attrs(classdev);
410 : 0 : device_del(classdev);
411 : 0 : }
412 : :
413 : : /**
414 : : * attribute_container_find_class_device - find the corresponding class_device
415 : : *
416 : : * @cont: the container
417 : : * @dev: the generic device
418 : : *
419 : : * Looks up the device in the container's list of class devices and returns
420 : : * the corresponding class_device.
421 : : */
422 : : struct device *
423 : 0 : attribute_container_find_class_device(struct attribute_container *cont,
424 : : struct device *dev)
425 : : {
426 : : struct device *cdev = NULL;
427 : : struct internal_container *ic;
428 : : struct klist_iter iter;
429 : :
430 [ # # ][ # # ]: 0 : klist_for_each_entry(ic, &cont->containers, node, &iter) {
431 [ # # ]: 0 : if (ic->classdev.parent == dev) {
432 : 0 : cdev = &ic->classdev;
433 : : /* FIXME: must exit iterator then break */
434 : 0 : klist_iter_exit(&iter);
435 : 0 : break;
436 : : }
437 : : }
438 : :
439 : 0 : return cdev;
440 : : }
441 : : EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
|