*参照元 [#c7e8bd92] #backlinks *説明 [#cc3bb7b6] -パス: [[linux-4.4.1/drivers/base/core.c]] -FIXME: これは何? --説明 **引数 [#v998f4a0] -struct device *dev -- --[[linux-4.4.1/device]] **返り値 [#p5c3cea0] -int -- **参考 [#u64911db] *実装 [#vde1ce94] /** * 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. * * Do not call this routine or device_register() more than once for * any device structure. The driver model core is not designed to work * with devices that get unregistered and then spring back to life. * (Among other things, it's very hard to guarantee that all references * to the previous incarnation of @dev have been dropped.) Allocate * and register a fresh new struct device instead. * * 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 kobject *kobj; struct class_interface *class_intf; int error = -EINVAL; - --[[linux-4.4.1/kobject]] --[[linux-4.4.1/class_interface]] dev = get_device(dev); if (!dev) goto done; - --[[linux-4.4.1/get_device()]] if (!dev->p) { error = device_private_init(dev); if (error) goto done; } - --[[linux-4.4.1/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-4.4.1/dev_set_name()]] /* subsystems can specify simple device enumeration */ if (!dev_name(dev) && dev->bus && dev->bus->dev_name) dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); - --dev->bus は struct bus_type * 型 --[[linux-4.4.1/bus_type]] --[[linux-4.4.1/dev_name()]] if (!dev_name(dev)) { error = -EINVAL; goto name_error; } pr_debug("device: '%s': %s\n", dev_name(dev), __func__); - --[[linux-4.4.1/pr_debug()]] parent = get_device(dev->parent); kobj = get_device_parent(dev, parent); if (kobj) dev->kobj.parent = kobj; - --[[linux-4.4.1/get_device_parent()]] /* use parent numa_node */ if (parent && (dev_to_node(dev) == NUMA_NO_NODE)) set_dev_node(dev, dev_to_node(parent)); - --[[linux-4.4.1/dev_to_node()]] --[[linux-4.4.1/set_dev_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; - --[[linux-4.4.1/kobject_add()]] /* notify platform of device entry */ if (platform_notify) platform_notify(dev); - --[[linux-4.4.1/platform_notify(global)]] error = device_create_file(dev, &dev_attr_uevent); if (error) goto attrError; - --[[linux-4.4.1/device_create_file()]] --[[linux-4.4.1/dev_attr_uevent(global)]] 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); - --[[linux-4.4.1/device_add_class_symlinks()]] --[[linux-4.4.1/device_add_attrs()]] --[[linux-4.4.1/bus_add_device()]] --[[linux-4.4.1/dpm_sysfs_add()]] --[[linux-4.4.1/device_pm_add()]] if (MAJOR(dev->devt)) { error = device_create_file(dev, &dev_attr_dev); if (error) goto DevAttrError; error = device_create_sys_dev_entry(dev); if (error) goto SysEntryError; devtmpfs_create_node(dev); } - --[[linux-4.4.1/MAJOR()]] --[[linux-4.4.1/device_create_file()]] --[[linux-4.4.1/dev_attr_dev(global)]] --[[linux-4.4.1/device_create_sys_dev_entry()]] --[[linux-4.4.1/devtmpfs_craete_node()]] /* Notify clients of device addition. This call must come * after dpm_sysfs_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 * 型 --dev->bus->p は struct subsys_private * 型 --[[linux-4.4.1/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-4.4.1/kobject_uevent()]] --[[linux-4.4.1/bus_probe_device()]] --[[linux-4.4.1/klist_add_tail()]] if (dev->class) { mutex_lock(&dev->class->p->mutex); /* tie the class to the device */ klist_add_tail(&dev->knode_class, &dev->class->p->klist_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, &dev->class->p->interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); mutex_unlock(&dev->class->p->mutex); } - --[[linux-4.4.1/mutex_lock()]] --[[linux-4.4.1/klist_add_tail()]] --[[linux-4.4.1/list_for_each_entry()]] --[[linux-4.4.1/mutex_unlock()]] done: put_device(dev); return error; - --[[linux-4.4.1/put_device()]] SysEntryError: if (MAJOR(dev->devt)) device_remove_file(dev, &dev_attr_dev); - --[[linux-4.4.1/device_remove_file()]] --[[linux-4.4.1/dev_attr_dev(global)]] DevAttrError: device_pm_remove(dev); dpm_sysfs_remove(dev); - --[[linux-4.4.1/device_pm_remove()]] --[[linux-4.4.1/dpm_sysfs_remove()]] DPMError: bus_remove_device(dev); - --[[linux-4.4.1/bus_remove_device()]] BusError: device_remove_attrs(dev); - --[[linux-4.4.1/device_remove_attrs()]] AttrsError: device_remove_class_symlinks(dev); - --[[linux-4.4.1/device_remove_class_symlinks()]] SymlinkError: device_remove_file(dev, &dev_attr_uevent); - --[[linux-4.4.1/device_remove_file()]] attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); - --[[linux-4.4.1/kobject_uevent()]] --[[linux-4.4.1/kobject_del()]] Error: cleanup_device_parent(dev); put_device(parent); - --[[linux-4.4.1/cleanup_device_parent()]] --[[linux-4.4.1/put_device()]] name_error: kfree(dev->p); dev->p = NULL; goto done; - --[[linux-4.4.1/kfree()]] } EXPORT_SYMBOL_GPL(device_add); - --[[linux-4.4.1/EXPORT_SYMBOL_GPL()]] *コメント [#e0fbac05]