Linux Kernel设备驱动模型之 设备添加

对于设备模型来说,设备添加是向设备模型层添加一个设备。

/**  * 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;  struct kobject *glue_dir = NULL;

 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;  }

 /* 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);

 if (!dev_name(dev)) {   error = -EINVAL;   goto name_error;  }

 pr_debug("device: '%s': %s\n", dev_name(dev), __func__);

 parent = get_device(dev->parent);  kobj = get_device_parent(dev, parent);  if (kobj)   dev->kobj.parent = kobj;

 /* use parent numa_node */  if (parent && (dev_to_node(dev) == NUMA_NO_NODE))   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) {   glue_dir = get_glue_dir(dev);   goto Error;  }

 /* notify platform of device entry */  if (platform_notify)   platform_notify(dev);

 error = device_create_file(dev, &dev_attr_uevent);  if (error)   goto attrError;

 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 (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);  }

 /* 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);

 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->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);  } done:  put_device(dev);  return error;  SysEntryError:  if (MAJOR(dev->devt))   device_remove_file(dev, &dev_attr_dev);  DevAttrError:  device_pm_remove(dev);  dpm_sysfs_remove(dev);  DPMError:  bus_remove_device(dev);  BusError:  device_remove_attrs(dev);  AttrsError:  device_remove_class_symlinks(dev);  SymlinkError:  device_remove_file(dev, &dev_attr_uevent);  attrError:  kobject_uevent(&dev->kobj, KOBJ_REMOVE);  glue_dir = get_glue_dir(dev);  kobject_del(&dev->kobj);  Error:  cleanup_glue_dir(dev, glue_dir);  put_device(parent); name_error:  kfree(dev->p);  dev->p = NULL;  goto done; }

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值