*参照元 [#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]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS