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);