===============================
本文系本站原创,欢迎转载!
转载请注明出处:http://blog.csdn.net/gdt_a20
===============================
上篇分析了bus,driver的注册过程,这篇主要分析device的注册,并总结给出个流程图。
三、device的注册
还是照例先看一下device的结构:
- struct device {
- struct device *parent;
- struct device_private *p;
- struct kobject kobj;
- const char *init_name;
- struct device_type *type;
- struct mutex mutex;
-
-
- struct bus_type *bus;
- struct device_driver *driver;
-
- void *platform_data;
-
- struct dev_pm_info power;
- #ifdef CONFIG_NUMA
- int numa_node;
- #endif
- u64 *dma_mask;
- u64 coherent_dma_mask;
-
-
-
-
- struct device_dma_parameters *dma_parms;
- struct list_head dma_pools;
- struct dma_coherent_mem *dma_mem;
-
-
- struct dev_archdata archdata;
- #ifdef CONFIG_OF
- struct device_node *of_node;
- #endif
- dev_t devt;
- spinlock_t devres_lock;
- struct list_head devres_head;
- struct klist_node knode_class;
- struct class *class;
- const struct attribute_group **groups;
- void (*release)(struct device *dev);
- };
-
- struct device_private {
- struct klist klist_children;
- struct klist_node knode_parent;
- struct klist_node knode_driver;
- struct klist_node knode_bus;
- void *driver_data;
- struct device *device;
- };
接下来详细看一下device的注册device_register:
- int device_register(struct device *dev)
- {
- device_initialize(dev);
- return device_add(dev);
- }
-
-
-
- void device_initialize(struct device *dev)
- {
- dev->kobj.kset = devices_kset;
- kobject_init(&dev->kobj, &device_ktype);
- INIT_LIST_HEAD(&dev->dma_pools);
- mutex_init(&dev->mutex);
- lockdep_set_novalidate_class(&dev->mutex);
- spin_lock_init(&dev->devres_lock);
- INIT_LIST_HEAD(&dev->devres_head);
- device_pm_init(dev);
- set_dev_node(dev, -1);
- }
-
-
-
- int device_add(struct device *dev)
- {
- struct device *parent = NULL;
- struct class_interface *class_intf;
- int error = -EINVAL;
- dev = get_device(dev);
- if (!dev)
- goto done;
- if (!dev->p) {
- error = device_private_init(dev);
- if (error)
- goto done;
- }
-
-
-
-
-
- if (dev->init_name) {
- dev_set_name(dev, "%s", dev->init_name);
- dev->init_name = NULL;
- }
- if (!dev_name(dev)) {
- error = -EINVAL;
- goto name_error;
- }
- pr_debug("device: '%s': %s/n", dev_name(dev), __func__);
- parent = get_device(dev->parent);
- setup_parent(dev, parent);
-
- if (parent)
- set_dev_node(dev, dev_to_node(parent));
-
-
- error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
- if (error)
- goto Error;
-
- if (platform_notify)
- platform_notify(dev);
- error = device_create_file(dev, &uevent_attr);
- if (error)
- goto attrError;
- if (MAJOR(dev->devt)) {
- error = device_create_file(dev, &devt_attr);
- if (error)
- goto ueventattrError;
- error = device_create_sys_dev_entry(dev);
- if (error)
- goto devtattrError;
- devtmpfs_create_node(dev);
- }
- error = device_add_class_symlinks(dev);
- if (error)
- goto SymlinkError;
- error = device_add_attrs(dev);
- if (error)
- goto AttrsError;
- error = bus_add_device(dev);
- if (error)
- goto BusError;
- error = dpm_sysfs_add(dev);
- if (error)
- goto DPMError;
- device_pm_add(dev);
-
-
-
- if (dev->bus)
- blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- BUS_NOTIFY_ADD_DEVICE, dev);
- kobject_uevent(&dev->kobj, KOBJ_ADD);
- bus_probe_device(dev);
- if (parent)
- klist_add_tail(&dev->p->knode_parent,
- &parent->p->klist_children);
- if (dev->class) {
- mutex_lock(&dev->class->p->class_mutex);
-
- klist_add_tail(&dev->knode_class,
- &dev->class->p->class_devices);
-
- list_for_each_entry(class_intf,
- &dev->class->p->class_interfaces, node)
- if (class_intf->add_dev)
- class_intf->add_dev(dev, class_intf);
- mutex_unlock(&dev->class->p->class_mutex);
- }
- done:
- put_device(dev);
- return error;
- DPMError:
- bus_remove_device(dev);
- BusError:
- device_remove_attrs(dev);
- AttrsError:
- device_remove_class_symlinks(dev);
- SymlinkError:
- if (MAJOR(dev->devt))
- devtmpfs_delete_node(dev);
- if (MAJOR(dev->devt))
- device_remove_sys_dev_entry(dev);
- devtattrError:
- if (MAJOR(dev->devt))
- device_remove_file(dev, &devt_attr);
- ueventattrError:
- device_remove_file(dev, &uevent_attr);
- attrError:
- kobject_uevent(&dev->kobj, KOBJ_REMOVE);
- kobject_del(&dev->kobj);
- Error:
- cleanup_device_parent(dev);
- if (parent)
- put_device(parent);
- name_error:
- kfree(dev->p);
- dev->p = NULL;
- goto done;
- }
-
-
-
- void bus_probe_device(struct device *dev)
- {
- struct bus_type *bus = dev->bus;
- int ret;
- if (bus && bus->p->drivers_autoprobe) {
- ret = device_attach(dev);
- WARN_ON(ret < 0);
- }
- }
-
-
-
- int device_attach(struct device *dev)
- {
- int ret = 0;
- device_lock(dev);
- if (dev->driver) {
- ret = device_bind_driver(dev);
- if (ret == 0)
- ret = 1;
- else {
- dev->driver = NULL;
- ret = 0;
- }
- } else {
- pm_runtime_get_noresume(dev);
- ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
- pm_runtime_put_sync(dev);
- }
- device_unlock(dev);
- return ret;
- }
-
-
-
- int device_bind_driver(struct device *dev)
- {
- int ret;
- ret = driver_sysfs_add(dev);
- if (!ret)
- driver_bound(dev);
- return ret;
- }
-
-
-
- int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
- void *data, int (*fn)(struct device_driver *, void *))
- {
- struct klist_iter i;
- struct device_driver *drv;
- int error = 0;
- if (!bus)
- return -EINVAL;
- klist_iter_init_node(&bus->p->klist_drivers, &i,
- start ? &start->p->knode_bus : NULL);
- while ((drv = next_driver(&i)) && !error)
- error = fn(drv, data);
- klist_iter_exit(&i);
- return error;
- }
-
-
-
- static int __device_attach(struct device_driver *drv, void *data)
- {
- struct device *dev = data;
- if (!driver_match_device(drv, dev))
- return 0;
- return driver_probe_device(drv, dev);
- }
-
-
-
-
-
以上便是device的注册,可以发现device和driver围绕着bus最后有种殊途同归的感觉,下面结合driver的流程给出一个框图
以便更明确其间的流程: