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