linux/drivers/base/attribute_container.c
<<
>>
Prefs
   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 */
  27struct internal_container {
  28        struct klist_node node;
  29        struct attribute_container *cont;
  30        struct device classdev;
  31};
  32
  33static void internal_container_klist_get(struct klist_node *n)
  34{
  35        struct internal_container *ic =
  36                container_of(n, struct internal_container, node);
  37        get_device(&ic->classdev);
  38}
  39
  40static void internal_container_klist_put(struct klist_node *n)
  41{
  42        struct internal_container *ic =
  43                container_of(n, struct internal_container, node);
  44        put_device(&ic->classdev);
  45}
  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 */
  55struct attribute_container *
  56attribute_container_classdev_to_container(struct device *classdev)
  57{
  58        struct internal_container *ic =
  59                container_of(classdev, struct internal_container, classdev);
  60        return ic->cont;
  61}
  62EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
  63
  64static LIST_HEAD(attribute_container_list);
  65
  66static 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 */
  74int
  75attribute_container_register(struct attribute_container *cont)
  76{
  77        INIT_LIST_HEAD(&cont->node);
  78        klist_init(&cont->containers,internal_container_klist_get,
  79                   internal_container_klist_put);
  80                
  81        mutex_lock(&attribute_container_mutex);
  82        list_add_tail(&cont->node, &attribute_container_list);
  83        mutex_unlock(&attribute_container_mutex);
  84
  85        return 0;
  86}
  87EXPORT_SYMBOL_GPL(attribute_container_register);
  88
  89/**
  90 * attribute_container_unregister - remove a container registration
  91 *
  92 * @cont: previously registered container to remove
  93 */
  94int
  95attribute_container_unregister(struct attribute_container *cont)
  96{
  97        int retval = -EBUSY;
  98        mutex_lock(&attribute_container_mutex);
  99        spin_lock(&cont->containers.k_lock);
 100        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        mutex_unlock(&attribute_container_mutex);
 107        return retval;
 108                
 109}
 110EXPORT_SYMBOL_GPL(attribute_container_unregister);
 111
 112/* private function used as class release */
 113static void attribute_container_release(struct device *classdev)
 114{
 115        struct internal_container *ic 
 116                = container_of(classdev, struct internal_container, classdev);
 117        struct device *dev = classdev->parent;
 118
 119        kfree(ic);
 120        put_device(dev);
 121}
 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 */
 141void
 142attribute_container_add_device(struct device *dev,
 143                               int (*fn)(struct attribute_container *,
 144                                         struct device *,
 145                                         struct device *))
 146{
 147        struct attribute_container *cont;
 148
 149        mutex_lock(&attribute_container_mutex);
 150        list_for_each_entry(cont, &attribute_container_list, node) {
 151                struct internal_container *ic;
 152
 153                if (attribute_container_no_classdevs(cont))
 154                        continue;
 155
 156                if (!cont->match(cont, dev))
 157                        continue;
 158
 159                ic = kzalloc(sizeof(*ic), GFP_KERNEL);
 160                if (!ic) {
 161                        dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
 162                        continue;
 163                }
 164
 165                ic->cont = cont;
 166                device_initialize(&ic->classdev);
 167                ic->classdev.parent = get_device(dev);
 168                ic->classdev.class = cont->class;
 169                cont->class->dev_release = attribute_container_release;
 170                dev_set_name(&ic->classdev, dev_name(dev));
 171                if (fn)
 172                        fn(cont, dev, &ic->classdev);
 173                else
 174                        attribute_container_add_class_device(&ic->classdev);
 175                klist_add_tail(&ic->node, &cont->containers);
 176        }
 177        mutex_unlock(&attribute_container_mutex);
 178}
 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 */
 206void
 207attribute_container_remove_device(struct device *dev,
 208                                  void (*fn)(struct attribute_container *,
 209                                             struct device *,
 210                                             struct device *))
 211{
 212        struct attribute_container *cont;
 213
 214        mutex_lock(&attribute_container_mutex);
 215        list_for_each_entry(cont, &attribute_container_list, node) {
 216                struct internal_container *ic;
 217                struct klist_iter iter;
 218
 219                if (attribute_container_no_classdevs(cont))
 220                        continue;
 221
 222                if (!cont->match(cont, dev))
 223                        continue;
 224
 225                klist_for_each_entry(ic, &cont->containers, node, &iter) {
 226                        if (dev != ic->classdev.parent)
 227                                continue;
 228                        klist_del(&ic->node);
 229                        if (fn)
 230                                fn(cont, dev, &ic->classdev);
 231                        else {
 232                                attribute_container_remove_attrs(&ic->classdev);
 233                                device_unregister(&ic->classdev);
 234                        }
 235                }
 236        }
 237        mutex_unlock(&attribute_container_mutex);
 238}
 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 */
 250void
 251attribute_container_device_trigger(struct device *dev, 
 252                                   int (*fn)(struct attribute_container *,
 253                                             struct device *,
 254                                             struct device *))
 255{
 256        struct attribute_container *cont;
 257
 258        mutex_lock(&attribute_container_mutex);
 259        list_for_each_entry(cont, &attribute_container_list, node) {
 260                struct internal_container *ic;
 261                struct klist_iter iter;
 262
 263                if (!cont->match(cont, dev))
 264                        continue;
 265
 266                if (attribute_container_no_classdevs(cont)) {
 267                        fn(cont, dev, NULL);
 268                        continue;
 269                }
 270
 271                klist_for_each_entry(ic, &cont->containers, node, &iter) {
 272                        if (dev == ic->classdev.parent)
 273                                fn(cont, dev, &ic->classdev);
 274                }
 275        }
 276        mutex_unlock(&attribute_container_mutex);
 277}
 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 */
 291void
 292attribute_container_trigger(struct device *dev,
 293                            int (*fn)(struct attribute_container *,
 294                                      struct device *))
 295{
 296        struct attribute_container *cont;
 297
 298        mutex_lock(&attribute_container_mutex);
 299        list_for_each_entry(cont, &attribute_container_list, node) {
 300                if (cont->match(cont, dev))
 301                        fn(cont, dev);
 302        }
 303        mutex_unlock(&attribute_container_mutex);
 304}
 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 */
 314int
 315attribute_container_add_attrs(struct device *classdev)
 316{
 317        struct attribute_container *cont =
 318                attribute_container_classdev_to_container(classdev);
 319        struct device_attribute **attrs = cont->attrs;
 320        int i, error;
 321
 322        BUG_ON(attrs && cont->grp);
 323
 324        if (!attrs && !cont->grp)
 325                return 0;
 326
 327        if (cont->grp)
 328                return sysfs_create_group(&classdev->kobj, cont->grp);
 329
 330        for (i = 0; attrs[i]; i++) {
 331                sysfs_attr_init(&attrs[i]->attr);
 332                error = device_create_file(classdev, attrs[i]);
 333                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 */
 349int
 350attribute_container_add_class_device(struct device *classdev)
 351{
 352        int error = device_add(classdev);
 353        if (error)
 354                return error;
 355        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 */
 364int
 365attribute_container_add_class_device_adapter(struct attribute_container *cont,
 366                                             struct device *dev,
 367                                             struct device *classdev)
 368{
 369        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 */
 378void
 379attribute_container_remove_attrs(struct device *classdev)
 380{
 381        struct attribute_container *cont =
 382                attribute_container_classdev_to_container(classdev);
 383        struct device_attribute **attrs = cont->attrs;
 384        int i;
 385
 386        if (!attrs && !cont->grp)
 387                return;
 388
 389        if (cont->grp) {
 390                sysfs_remove_group(&classdev->kobj, cont->grp);
 391                return ;
 392        }
 393
 394        for (i = 0; attrs[i]; i++)
 395                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 */
 406void
 407attribute_container_class_device_del(struct device *classdev)
 408{
 409        attribute_container_remove_attrs(classdev);
 410        device_del(classdev);
 411}
 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 */
 422struct device *
 423attribute_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        klist_for_each_entry(ic, &cont->containers, node, &iter) {
 431                if (ic->classdev.parent == dev) {
 432                        cdev = &ic->classdev;
 433                        /* FIXME: must exit iterator then break */
 434                        klist_iter_exit(&iter);
 435                        break;
 436                }
 437        }
 438
 439        return cdev;
 440}
 441EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
 442