Android device 注册、添加、管理(2)

/**   * 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;       int error = -EINVAL;          dev = get_device(dev);       if (!dev)           goto done;          if (!dev->p) {           error = device_private_init(dev);           if (error)               goto done;       }          /*       * 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;       }          if (!dev_name(dev))           goto name_error;          pr_debug("device: '%s': %s\n", dev_name(dev), __func__);          parent = get_device(dev->parent);       setup_parent(dev, parent);          /* use parent numa_node */       if (parent)           set_dev_node(dev, dev_to_node(parent));          /* 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;          /* notify platform of device entry */       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);          /* 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);          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);           /* tie the class to the device */           klist_add_tail(&dev->knode_class,                      &dev->class->p->class_devices);              /* 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);       }   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))           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;   }  

设备添加到电源管理链表中

代码目录:kernel/drivers/base/main.c

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzszy.html