linux/drivers/base/core.c
<<
>>
Prefs
   1/*
   2 * drivers/base/core.c - core driver model code (device registration, etc)
   3 *
   4 * Copyright (c) 2002-3 Patrick Mochel
   5 * Copyright (c) 2002-3 Open Source Development Labs
   6 *
   7 * This file is released under the GPLv2
   8 *
   9 */
  10
  11#include <linux/config.h>
  12#include <linux/device.h>
  13#include <linux/err.h>
  14#include <linux/init.h>
  15#include <linux/module.h>
  16#include <linux/slab.h>
  17#include <linux/string.h>
  18
  19#include <asm/semaphore.h>
  20
  21#include "base.h"
  22#include "power/power.h"
  23
  24int (*platform_notify)(struct device * dev) = NULL;
  25int (*platform_notify_remove)(struct device * dev) = NULL;
  26
  27/*
  28 * sysfs bindings for devices.
  29 */
  30
  31#define to_dev(obj) container_of(obj, struct device, kobj)
  32#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
  33
  34extern struct attribute * dev_default_attrs[];
  35
  36static ssize_t
  37dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
  38{
  39        struct device_attribute * dev_attr = to_dev_attr(attr);
  40        struct device * dev = to_dev(kobj);
  41        ssize_t ret = 0;
  42
  43        if (dev_attr->show)
  44                ret = dev_attr->show(dev, buf);
  45        return ret;
  46}
  47
  48static ssize_t
  49dev_attr_store(struct kobject * kobj, struct attribute * attr,
  50               const char * buf, size_t count)
  51{
  52        struct device_attribute * dev_attr = to_dev_attr(attr);
  53        struct device * dev = to_dev(kobj);
  54        ssize_t ret = 0;
  55
  56        if (dev_attr->store)
  57                ret = dev_attr->store(dev, buf, count);
  58        return ret;
  59}
  60
  61static struct sysfs_ops dev_sysfs_ops = {
  62        .show   = dev_attr_show,
  63        .store  = dev_attr_store,
  64};
  65
  66
  67/**
  68 *      device_release - free device structure.
  69 *      @kobj:  device's kobject.
  70 *
  71 *      This is called once the reference count for the object
  72 *      reaches 0. We forward the call to the device's release
  73 *      method, which should handle actually freeing the structure.
  74 */
  75static void device_release(struct kobject * kobj)
  76{
  77        struct device * dev = to_dev(kobj);
  78
  79        if (dev->release)
  80                dev->release(dev);
  81        else {
  82                printk(KERN_ERR "Device '%s' does not have a release() function, "
  83                        "it is broken and must be fixed.\n",
  84                        dev->bus_id);
  85                WARN_ON(1);
  86        }
  87}
  88
  89static struct kobj_type ktype_device = {
  90        .release        = device_release,
  91        .sysfs_ops      = &dev_sysfs_ops,
  92        .default_attrs  = dev_default_attrs,
  93};
  94
  95
  96static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
  97{
  98        struct kobj_type *ktype = get_ktype(kobj);
  99
 100        if (ktype == &ktype_device) {
 101                struct device *dev = to_dev(kobj);
 102                if (dev->bus)
 103                        return 1;
 104        }
 105        return 0;
 106}
 107
 108static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
 109{
 110        struct device *dev = to_dev(kobj);
 111
 112        return dev->bus->name;
 113}
 114
 115static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 116                        int num_envp, char *buffer, int buffer_size)
 117{
 118        struct device *dev = to_dev(kobj);
 119        int i = 0;
 120        int length = 0;
 121        int retval = 0;
 122
 123        /* add bus name of physical device */
 124        if (dev->bus)
 125                add_hotplug_env_var(envp, num_envp, &i,
 126                                    buffer, buffer_size, &length,
 127                                    "PHYSDEVBUS=%s", dev->bus->name);
 128
 129        /* add driver name of physical device */
 130        if (dev->driver)
 131                add_hotplug_env_var(envp, num_envp, &i,
 132                                    buffer, buffer_size, &length,
 133                                    "PHYSDEVDRIVER=%s", dev->driver->name);
 134
 135        /* terminate, set to next free slot, shrink available space */
 136        envp[i] = NULL;
 137        envp = &envp[i];
 138        num_envp -= i;
 139        buffer = &buffer[length];
 140        buffer_size -= length;
 141
 142        if (dev->bus->hotplug) {
 143                /* have the bus specific function add its stuff */
 144                retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
 145                        if (retval) {
 146                        pr_debug ("%s - hotplug() returned %d\n",
 147                                  __FUNCTION__, retval);
 148                }
 149        }
 150
 151        return retval;
 152}
 153
 154static struct kset_hotplug_ops device_hotplug_ops = {
 155        .filter =       dev_hotplug_filter,
 156        .name =         dev_hotplug_name,
 157        .hotplug =      dev_hotplug,
 158};
 159
 160/**
 161 *      device_subsys - structure to be registered with kobject core.
 162 */
 163
 164decl_subsys(devices, &ktype_device, &device_hotplug_ops);
 165
 166
 167/**
 168 *      device_create_file - create sysfs attribute file for device.
 169 *      @dev:   device.
 170 *      @attr:  device attribute descriptor.
 171 */
 172
 173int device_create_file(struct device * dev, struct device_attribute * attr)
 174{
 175        int error = 0;
 176        if (get_device(dev)) {
 177                error = sysfs_create_file(&dev->kobj, &attr->attr);
 178                put_device(dev);
 179        }
 180        return error;
 181}
 182
 183/**
 184 *      device_remove_file - remove sysfs attribute file.
 185 *      @dev:   device.
 186 *      @attr:  device attribute descriptor.
 187 */
 188
 189void device_remove_file(struct device * dev, struct device_attribute * attr)
 190{
 191        if (get_device(dev)) {
 192                sysfs_remove_file(&dev->kobj, &attr->attr);
 193                put_device(dev);
 194        }
 195}
 196
 197
 198/**
 199 *      device_initialize - init device structure.
 200 *      @dev:   device.
 201 *
 202 *      This prepares the device for use by other layers,
 203 *      including adding it to the device hierarchy.
 204 *      It is the first half of device_register(), if called by
 205 *      that, though it can also be called separately, so one
 206 *      may use @dev's fields (e.g. the refcount).
 207 */
 208
 209void device_initialize(struct device *dev)
 210{
 211        kobj_set_kset_s(dev, devices_subsys);
 212        kobject_init(&dev->kobj);
 213        INIT_LIST_HEAD(&dev->node);
 214        INIT_LIST_HEAD(&dev->children);
 215        INIT_LIST_HEAD(&dev->driver_list);
 216        INIT_LIST_HEAD(&dev->bus_list);
 217        INIT_LIST_HEAD(&dev->dma_pools);
 218}
 219
 220/**
 221 *      device_add - add device to device hierarchy.
 222 *      @dev:   device.
 223 *
 224 *      This is part 2 of device_register(), though may be called
 225 *      separately _iff_ device_initialize() has been called separately.
 226 *
 227 *      This adds it to the kobject hierarchy via kobject_add(), adds it
 228 *      to the global and sibling lists for the device, then
 229 *      adds it to the other relevant subsystems of the driver model.
 230 */
 231int device_add(struct device *dev)
 232{
 233        struct device *parent = NULL;
 234        int error = -EINVAL;
 235
 236        dev = get_device(dev);
 237        if (!dev || !strlen(dev->bus_id))
 238                goto Error;
 239
 240        parent = get_device(dev->parent);
 241
 242        pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
 243
 244        /* first, register with generic layer. */
 245        kobject_set_name(&dev->kobj, "%s", dev->bus_id);
 246        if (parent)
 247                dev->kobj.parent = &parent->kobj;
 248
 249        if ((error = kobject_add(&dev->kobj)))
 250                goto Error;
 251        if ((error = device_pm_add(dev)))
 252                goto PMError;
 253        if ((error = bus_add_device(dev)))
 254                goto BusError;
 255        down_write(&devices_subsys.rwsem);
 256        if (parent)
 257                list_add_tail(&dev->node, &parent->children);
 258        up_write(&devices_subsys.rwsem);
 259
 260        /* notify platform of device entry */
 261        if (platform_notify)
 262                platform_notify(dev);
 263 Done:
 264        put_device(dev);
 265        return error;
 266 BusError:
 267        device_pm_remove(dev);
 268 PMError:
 269        kobject_del(&dev->kobj);
 270 Error:
 271        if (parent)
 272                put_device(parent);
 273        goto Done;
 274}
 275
 276
 277/**
 278 *      device_register - register a device with the system.
 279 *      @dev:   pointer to the device structure
 280 *
 281 *      This happens in two clean steps - initialize the device
 282 *      and add it to the system. The two steps can be called
 283 *      separately, but this is the easiest and most common.
 284 *      I.e. you should only call the two helpers separately if
 285 *      have a clearly defined need to use and refcount the device
 286 *      before it is added to the hierarchy.
 287 */
 288
 289int device_register(struct device *dev)
 290{
 291        device_initialize(dev);
 292        return device_add(dev);
 293}
 294
 295
 296/**
 297 *      get_device - increment reference count for device.
 298 *      @dev:   device.
 299 *
 300 *      This simply forwards the call to kobject_get(), though
 301 *      we do take care to provide for the case that we get a NULL
 302 *      pointer passed in.
 303 */
 304
 305struct device * get_device(struct device * dev)
 306{
 307        return dev ? to_dev(kobject_get(&dev->kobj)) : NULL;
 308}
 309
 310
 311/**
 312 *      put_device - decrement reference count.
 313 *      @dev:   device in question.
 314 */
 315void put_device(struct device * dev)
 316{
 317        if (dev)
 318                kobject_put(&dev->kobj);
 319}
 320
 321
 322/**
 323 *      device_del - delete device from system.
 324 *      @dev:   device.
 325 *
 326 *      This is the first part of the device unregistration
 327 *      sequence. This removes the device from the lists we control
 328 *      from here, has it removed from the other driver model
 329 *      subsystems it was added to in device_add(), and removes it
 330 *      from the kobject hierarchy.
 331 *
 332 *      NOTE: this should be called manually _iff_ device_add() was
 333 *      also called manually.
 334 */
 335
 336void device_del(struct device * dev)
 337{
 338        struct device * parent = dev->parent;
 339
 340        down_write(&devices_subsys.rwsem);
 341        if (parent)
 342                list_del_init(&dev->node);
 343        up_write(&devices_subsys.rwsem);
 344
 345        /* Notify the platform of the removal, in case they
 346         * need to do anything...
 347         */
 348        if (platform_notify_remove)
 349                platform_notify_remove(dev);
 350        bus_remove_device(dev);
 351        device_pm_remove(dev);
 352        kobject_del(&dev->kobj);
 353        if (parent)
 354                put_device(parent);
 355}
 356
 357/**
 358 *      device_unregister - unregister device from system.
 359 *      @dev:   device going away.
 360 *
 361 *      We do this in two parts, like we do device_register(). First,
 362 *      we remove it from all the subsystems with device_del(), then
 363 *      we decrement the reference count via put_device(). If that
 364 *      is the final reference count, the device will be cleaned up
 365 *      via device_release() above. Otherwise, the structure will
 366 *      stick around until the final reference to the device is dropped.
 367 */
 368void device_unregister(struct device * dev)
 369{
 370        pr_debug("DEV: Unregistering device. ID = '%s'\n", dev->bus_id);
 371        device_del(dev);
 372        put_device(dev);
 373}
 374
 375
 376/**
 377 *      device_for_each_child - device child iterator.
 378 *      @dev:   parent struct device.
 379 *      @data:  data for the callback.
 380 *      @fn:    function to be called for each device.
 381 *
 382 *      Iterate over @dev's child devices, and call @fn for each,
 383 *      passing it @data.
 384 *
 385 *      We check the return of @fn each time. If it returns anything
 386 *      other than 0, we break out and return that value.
 387 */
 388int device_for_each_child(struct device * dev, void * data,
 389                     int (*fn)(struct device *, void *))
 390{
 391        struct device * child;
 392        int error = 0;
 393
 394        down_read(&devices_subsys.rwsem);
 395        list_for_each_entry(child, &dev->children, node) {
 396                if((error = fn(child, data)))
 397                        break;
 398        }
 399        up_read(&devices_subsys.rwsem);
 400        return error;
 401}
 402
 403/**
 404 *      device_find - locate device on a bus by name.
 405 *      @name:  name of the device.
 406 *      @bus:   bus to scan for the device.
 407 *
 408 *      Call kset_find_obj() to iterate over list of devices on
 409 *      a bus to find device by name. Return device if found.
 410 *
 411 *      Note that kset_find_obj increments device's reference count.
 412 */
 413struct device *device_find(const char *name, struct bus_type *bus)
 414{
 415        struct kobject *k = kset_find_obj(&bus->devices, name);
 416        if (k)
 417                return to_dev(k);
 418        return NULL;
 419}
 420
 421int __init devices_init(void)
 422{
 423        return subsystem_register(&devices_subsys);
 424}
 425
 426EXPORT_SYMBOL_GPL(device_for_each_child);
 427
 428EXPORT_SYMBOL_GPL(device_initialize);
 429EXPORT_SYMBOL_GPL(device_add);
 430EXPORT_SYMBOL_GPL(device_register);
 431
 432EXPORT_SYMBOL_GPL(device_del);
 433EXPORT_SYMBOL_GPL(device_unregister);
 434EXPORT_SYMBOL_GPL(get_device);
 435EXPORT_SYMBOL_GPL(put_device);
 436EXPORT_SYMBOL_GPL(device_find);
 437
 438EXPORT_SYMBOL_GPL(device_create_file);
 439EXPORT_SYMBOL_GPL(device_remove_file);
 440
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.