*参照元 [#vb5dea8c] #backlinks *説明 [#c5a2de98] -パス: [[linux-2.6.33/drivers/base/core.c]] -FIXME: これは何? --説明 **引数 [#n102b8bd] -struct device *dev -- --[[linux-2.6.33/device]] **返り値 [#acebff9f] -int -- --0: 成功、0 以外: 失敗 --通例として失敗時はエラー番号を負の値で返す(-EINVAL など)ことが多い。 --[[linux-2.6.33/include/linux/errno.h]] **参考 [#h2017505] *実装 [#ibebcae1] /** * device_add - add device to device hierarchy. * @dev: device. * * This is part 2 of device_register(), though may be called * separately _iff_ device_initialize() has been called separately. * * This adds @dev to the kobject hierarchy via kobject_add(), adds it * to the global and sibling lists for the device, then * adds it to the other relevant subsystems of the driver model. * * NOTE: _Never_ directly free @dev after calling this function, even * if it returned an error! Always use put_device() to give up your * reference instead. */ int device_add(struct device *dev) { struct device *parent = NULL; struct class_interface *class_intf; - --[[linux-2.6.33/device]] - --[[linux-2.6.33/class_interface]] int error = -EINVAL; dev = get_device(dev); if (!dev) goto done; - --[[linux-2.6.33/get_device()]] if (!dev->p) { error = device_private_init(dev); if (error) goto done; } -dev->p は struct device_private 型 --[[linux-2.6.33/device_private]] - --[[linux-2.6.33/device_private_init()]] /* * for statically allocated devices, which should all be converted * some day, we need to initialize the name. We prevent reading back * the name, and force the use of dev_name() */ if (dev->init_name) { dev_set_name(dev, "%s", dev->init_name); dev->init_name = NULL; } - --[[linux-2.6.33/dev_set_name()]] if (!dev_name(dev)) { error = -EINVAL; goto name_error; } - --[[linux-2.6.33/dev_name()]] pr_debug("device: '%s': %s\n", dev_name(dev), __func__); - --[[linux-2.6.33/pr_debug()]] parent = get_device(dev->parent); setup_parent(dev, parent); - --[[linux-2.6.33/get_device()]] - --[[linux-2.6.33/setup_parent()]] /* use parent numa_node */ if (parent) set_dev_node(dev, dev_to_node(parent)); - --[[linux-2.6.33/set_dev_node()]] --[[linux-2.6.33/dev_to_node()]] /* first, register with generic layer. */ /* we require the name to be set before, and pass NULL */ error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); if (error) goto Error; -dev->kobj は kobject 型 --[[linux-2.6.33/kobject_add()]] --[[linux-2.6.33/kobject]] /* notify platform of device entry */ if (platform_notify) platform_notify(dev); - --[[linux-2.6.33/platform_notify()]] error = device_create_file(dev, &uevent_attr); if (error) goto attrError; - --[[linux-2.6.33/device_create_file()]] 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; -dev->devt は dev_t 型 --[[linux-2.6.33/dev_t]] - --[[linux-2.6.33/MAJOR()]] - --[[linux-2.6.33/device_create_sys_dev_entry()]] devtmpfs_create_node(dev); - --[[linux-2.6.33/devtmpfs_create_node()]] } error = device_add_class_symlinks(dev); if (error) goto SymlinkError; - --[[linux-2.6.33/device_add_class_symlinks()]] error = device_add_attrs(dev); if (error) goto AttrsError; - --[[linux-2.6.33/device_add_attrs()]] error = bus_add_device(dev); if (error) goto BusError; - --[[linux-2.6.33/bus_add_device()]] error = dpm_sysfs_add(dev); if (error) goto DPMError; - --[[linux-2.6.33/dpm_sysfs_add()]] device_pm_add(dev); - --[[linux-2.6.33/device_pm_add()]] /* Notify clients of device addition. This call must come * after dpm_sysf_add() and before kobject_uevent(). */ if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev); -dev->bus は struct bus_type 型 --[[linux-2.6.33/bus_type]] - --[[linux-2.6.33/blocking_notifier_call_chain()]] kobject_uevent(&dev->kobj, KOBJ_ADD); bus_probe_device(dev); if (parent) klist_add_tail(&dev->p->knode_parent, &parent->p->klist_children); - --[[linux-2.6.33/kobject_uevent()]] - --[[linux-2.6.33/bus_probe_device()]] - --[[linux-2.6.33/klist_add_tail()]] if (dev->class) { mutex_lock(&dev->class->p->class_mutex); /* tie the class to the device */ klist_add_tail(&dev->knode_class, &dev->class->p->class_devices); -dev->class は struct class 型 --[[linux-2.6.33/class]] - --[[linux-2.6.33/mutex_lock()]] - --[[linux-2.6.33/klist_add_tail()]] /* notify any interfaces that the device is here */ 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); - --[[linux-2.6.33/list_for_each_entry()]] -class_intf は struct class_interface * 型のローカル変数 --[[linux-2.6.33/class_interface]] - --[[linux-2.6.33/mutex_unlock()]] } done: put_device(dev); return error; - --[[linux-2.6.33/put_device()]] DPMError: bus_remove_device(dev); - --[[linux-2.6.33/bus_remove_device()]] BusError: device_remove_attrs(dev); - --[[linux-2.6.33/device_remove_attrs()]] AttrsError: device_remove_class_symlinks(dev); - --[[linux-2.6.33/device_remove_class_symlinks()]] SymlinkError: if (MAJOR(dev->devt)) devtmpfs_delete_node(dev); if (MAJOR(dev->devt)) device_remove_sys_dev_entry(dev); - --[[linux-2.6.33/devtmpfs_delete_node()]] - --[[linux-2.6.33/device_remove_sys_dev_entry()]] devtattrError: if (MAJOR(dev->devt)) device_remove_file(dev, &devt_attr); - --[[linux-2.6.33/device_remove_file()]] ueventattrError: device_remove_file(dev, &uevent_attr); - --[[linux-2.6.33/device_remove_file()]] attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); - --[[linux-2.6.33/kobject_uevent()]] - --[[linux-2.6.33/kobject_del()]] Error: cleanup_device_parent(dev); if (parent) put_device(parent); - --[[linux-2.6.33/cleanup_device_parent()]] - --[[linux-2.6.33/put_device()]] name_error: kfree(dev->p); dev->p = NULL; goto done; - --[[linux-2.6.33/kfree()]] } *コメント [#j25eb8c6]