linux设备驱动(2)device详解

Linux设备驱动的模型,是建立在sysfs设备文件系统和kobject上的,由总线(bus)、设备(device)、驱动(driver)和类(class)所组成的关系结构,在底层,Linux系统中的每个设备都有一个device结构体的实例。struct device已在上一博文中介绍,下面按顺序详细介绍device的主要API。

1.device_create

source位于:drivers\base\Core.c。向sysfs注册一个device,提供了强大的格式化注册接口。

 1 /**
 2  * device_create - creates a device and registers it with sysfs
 3  * @class: pointer to the struct class that this device should be registered to
 4  * @parent: pointer to the parent struct device of this new device, if any
 5  * @devt: the dev_t for the char device to be added
 6  * @drvdata: the data to be added to the device for callbacks
 7  * @fmt: string for the device's name
 8  *
 9  * This function can be used by char device classes.  A struct device
10  * will be created in sysfs, registered to the specified class.
11  *
12  * A "dev" file will be created, showing the dev_t for the device, if
13  * the dev_t is not 0,0.
14  * If a pointer to a parent struct device is passed in, the newly created
15  * struct device will be a child of that device in sysfs.
16  * The pointer to the struct device will be returned from the call.
17  * Any further sysfs files that might be required can be created using this
18  * pointer.
19  *
20  * Returns &struct device pointer on success, or ERR_PTR() on error.
21  *
22  * Note: the struct class passed to this function must have previously
23  * been created with a call to class_create().
24  */
25 struct device *device_create(struct class *class, struct device *parent,
26                  dev_t devt, void *drvdata, const char *fmt, ...)
27 {
28     va_list vargs;
29     struct device *dev;
30 
31     va_start(vargs, fmt);
32     dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
33     va_end(vargs);
34     return dev;
35 }

 1.1device_create_vargs 

上面API只是为了提供完善的接口,下面API这个才是真正工作的。所做的工作:

1)新建一个设备并kzalloc struct device,初步初始化部分结构体成员。

2)注册设备device

 1 /**
 2  * device_create_vargs - creates a device and registers it with sysfs
 3  * @class: pointer to the struct class that this device should be registered to
 4  * @parent: pointer to the parent struct device of this new device, if any
 5  * @devt: the dev_t for the char device to be added
 6  * @drvdata: the data to be added to the device for callbacks
 7  * @fmt: string for the device's name
 8  * @args: va_list for the device's name
 9  *
10  * This function can be used by char device classes.  A struct device
11  * will be created in sysfs, registered to the specified class.
12  *
13  * A "dev" file will be created, showing the dev_t for the device, if
14  * the dev_t is not 0,0.
15  * If a pointer to a parent struct device is passed in, the newly created
16  * struct device will be a child of that device in sysfs.
17  * The pointer to the struct device will be returned from the call.
18  * Any further sysfs files that might be required can be created using this
19  * pointer.
20  *
21  * Returns &struct device pointer on success, or ERR_PTR() on error.
22  *
23  * Note: the struct class passed to this function must have previously
24  * been created with a call to class_create().
25  */
26 struct device *device_create_vargs(struct class *class, struct device *parent,
27                    dev_t devt, void *drvdata, const char *fmt,
28                    va_list args)
29 {
30     struct device *dev = NULL;
31     int retval = -ENODEV;
32 
33     if (class == NULL || IS_ERR(class))
34         goto error;
35 
36     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
37     if (!dev) {
38         retval = -ENOMEM;
39         goto error;
40     }
41 
42     dev->devt = devt;
43     dev->class = class;
44     dev->parent = parent;
45     dev->release = device_create_release;
46     dev_set_drvdata(dev, drvdata);
47 
48     retval = kobject_set_name_vargs(&dev->kobj, fmt, args);//kobject相关知识,暂且跳过,后续介绍
49     if (retval)
50         goto error;
51 
52     retval = device_register(dev);
53     if (retval)
54         goto error;
55 
56     return dev;
57 
58 error:
59     put_device(dev);
60     return ERR_PTR(retval);
61 }

2 device_register

真正注册设备device。

 1 /**
 2  * device_register - register a device with the system.
 3  * @dev: pointer to the device structure
 4  *
 5  * This happens in two clean steps - initialize the device
 6  * and add it to the system. The two steps can be called
 7  * separately, but this is the easiest and most common.
 8  * I.e. you should only call the two helpers separately if
 9  * have a clearly defined need to use and refcount the device
10  * before it is added to the hierarchy.
11  *
12  * For more information, see the kerneldoc for device_initialize()
13  * and device_add().
14  *
15  * NOTE: _Never_ directly free @dev after calling this function, even
16  * if it returned an error! Always use put_device() to give up the
17  * reference initialized in this function instead.
18  */
19 int device_register(struct device *dev)
20 {
21     device_initialize(dev);
22     return device_add(dev);
23 }

3 device_initialize

 1 /**
 2  * device_initialize - init device structure.
 3  * @dev: device.
 4  *
 5  * This prepares the device for use by other layers by initializing
 6  * its fields.
 7  * It is the first half of device_register(), if called by
 8  * that function, though it can also be called separately, so one
 9  * may use @dev's fields. In particular, get_device()/put_device()
10  * may be used for reference counting of @dev after calling this
11  * function.
12  *
13  * All fields in @dev must be initialized by the caller to 0, except
14  * for those explicitly set to some other value.  The simplest
15  * approach is to use kzalloc() to allocate the structure containing
16  * @dev.
17  *
18  * NOTE: Use put_device() to give up your reference instead of freeing
19  * @dev directly once you have called this function.
20  */
21 void device_initialize(struct device *dev)
22 {
23     dev->kobj.kset = devices_kset;//所有的dev都有公共的device_set,在系统初始化的时候动态申请的,具体的回掉函数show,store,release还是要由dev里的release或dev_type里的release或从属的class里的dev_release来清除
24     kobject_init(&dev->kobj, &device_ktype);//初始化kobject
25     INIT_LIST_HEAD(&dev->dma_pools);//初始化链表
26     mutex_init(&dev->mutex);//避免被打扰,加锁
27     lockdep_set_novalidate_class(&dev->mutex);
28     spin_lock_init(&dev->devres_lock);
29     INIT_LIST_HEAD(&dev->devres_head);//将此device加入链表中
30     device_pm_init(dev);//电源管理的初始化
31     set_dev_node(dev, -1);
32 }

4 device_add

  1 /**
  2  * device_add - add device to device hierarchy.
  3  * @dev: device.
  4  *
  5  * This is part 2 of device_register(), though may be called
  6  * separately _iff_ device_initialize() has been called separately.
  7  *
  8  * This adds @dev to the kobject hierarchy via kobject_add(), adds it
  9  * to the global and sibling lists for the device, then
 10  * adds it to the other relevant subsystems of the driver model.
 11  *
 12  * Do not call this routine or device_register() more than once for
 13  * any device structure.  The driver model core is not designed to work
 14  * with devices that get unregistered and then spring back to life.
 15  * (Among other things, it's very hard to guarantee that all references
 16  * to the previous incarnation of @dev have been dropped.)  Allocate
 17  * and register a fresh new struct device instead.
 18  *
 19  * NOTE: _Never_ directly free @dev after calling this function, even
 20  * if it returned an error! Always use put_device() to give up your
 21  * reference instead.
 22  */
 23 int device_add(struct device *dev)
 24 {
 25     struct device *parent = NULL;
 26     struct kobject *kobj;
 27     struct class_interface *class_intf;
 28     int error = -EINVAL;
 29 
 30     dev = get_device(dev);//增加设备的引用计数 dev->kobj->kref
 31     if (!dev)
 32         goto done;
 33 
 34     if (!dev->p) {
 35         error = device_private_init(dev);//私有数据没有的话申请并初始化,这个数据很重要,它是连接所属bus,parent,对应驱动等的重要连接点.
 36         if (error)
 37             goto done;
 38     }
 39 
 40     /*
 41      * for statically allocated devices, which should all be converted
 42      * some day, we need to initialize the name. We prevent reading back
 43      * the name, and force the use of dev_name()
 44      */
 45     if (dev->init_name) {
 46         dev_set_name(dev, "%s", dev->init_name);//用dev的init_name初始化dev-kobject->name,实际就是目录名。
 47         dev->init_name = NULL;
 48     }
 49 
 50     /* subsystems can specify simple device enumeration */
 51     if (!dev_name(dev) && dev->bus && dev->bus->dev_name)//dev的init_name不存在且dev-kobject->name也不存在,则使用bus的dev_name和dev_id来设置目录名
 52         dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
 53 
 54     if (!dev_name(dev)) //如果上面几个步骤都还没找到可设的目录名,则失败返回,设备必须要放在某个目录下。
 55         error = -EINVAL;
 56         goto name_error;
 57     }
 58 
 59     pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
 60 
 61     parent = get_device(dev->parent);//父节点引用计数加1
 62     kobj = get_device_parent(dev, parent);//拿到父节点
 63     if (kobj)
 64         dev->kobj.parent = kobj;//拿到的父节点赋值给本dev->kobj.parent,确定设备父子关系,也确定了sysfs中的目录关系
 65 
 66     /* use parent numa_node */
 67     if (parent)
 68         set_dev_node(dev, dev_to_node(parent));//设置该设备节点为-1,一般未注册前在device_initialize已经初始化为-1
 69 
 70     /* first, register with generic layer. */
 71     /* we require the name to be set before, and pass NULL */
 72     error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);//把内嵌的kobject注册到设备模型中将设备加入到kobject模型中,创建sys相关目录,目录名字为kobj->name
 73     if (error)
 74         goto Error;
 75 
 76     /* notify platform of device entry */
 77     if (platform_notify)
 78         platform_notify(dev);
 79     /*创建sys目录下设备的uevent属性文件,通过它可以查看设备的uevent事件,主要是在/sys/devices/.../中添加dev的uevent属性文件*/
 80     error = device_create_file(dev, &uevent_attr);
 81     if (error)
 82         goto attrError;
 83     /* 主设备号存在,则产生dev属性,并在/dev目录下产生设备节点文件 */
 84     if (MAJOR(dev->devt)) {
/*创建sys目录下设备的设备号属性,即major和minor /主要是在sys/devices/...中添加dev属性文件*/
85 error = device_create_file(dev, &devt_attr); 86 if (error) 87 goto ueventattrError; 88 /*在/sys/dev/char/或者/sys/dev/block/创建devt的属性的连接文件,形如10:45,由主设备号和次设备号构成,指向/sys/devices/.../的具体设备目录*/ 89 error = device_create_sys_dev_entry(dev);//该链接文件只具备读属性,显示主设备号:次设备号,如10:45,用户空间udev响应uevent事件时,将根据设备号在/dev下创建节点文件 90 if (error) 91 goto devtattrError; 92 93 devtmpfs_create_node(dev); 94 } 95 /*实际创建的kobject都是在device下面,其他class,bus之类的里面的具体设备都是device目录下设备的符号链接,这里是在class下创建符号链接 */ 96 error = device_add_class_symlinks(dev); 97 if (error) 98 goto SymlinkError; 99 error = device_add_attrs(dev);//创建sys目录下设备其他属性文件(添加设备属性文件) 100 if (error) 101 goto AttrsError; 102 error = bus_add_device(dev);//添加设备的总线属性,将设备加入到管理它的bus总线的设备连表上,创建subsystem链接文件,链接class下的具体的子系统文件夹 将设备添加到其总线的设备列表中。 103 if (error) 104 goto BusError; 105 error = dpm_sysfs_add(dev);//把设备增加到sysfs电源管理power目录(组)下,如果该设备设置电源管理相关的内容 106 if (error) 107 goto DPMError; 108 device_pm_add(dev);//设备添加到电源管理相关的设备列表中 109 110 /* Notify clients of device addition. This call must come 111 * after dpm_sysfs_add() and before kobject_uevent(). 112 */ 113 if (dev->bus)//通知客户端,有新设备加入 114 blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 115 BUS_NOTIFY_ADD_DEVICE, dev); 116 /*产生一个内核uevent事件(这里是有设备加入),可以是helper,也可是通过netlink机制和用户空间通信该事件可以被内核以及应用层捕获,属于linux设备模型中热插拔机制*/ 117 kobject_uevent(&dev->kobj, KOBJ_ADD); 118 bus_probe_device(dev);//给设备探测寻找相对应的驱动,在bus上找dev对应的drv,主要执行__device_attach,主要进行match,sys_add,执行probe函数和绑定等操作 119 if (parent) 120 klist_add_tail(&dev->p->knode_parent,//添加新设备到父设备的子列表中 121 &parent->p->klist_children); 122 123 if (dev->class) {//如果改dev有所属类,则将dev的添加到类的设备列表里面 124 mutex_lock(&dev->class->p->mutex);//要使用class的互斥锁 125 /* tie the class to the device */ 126 klist_add_tail(&dev->knode_class,//dev添加到class的klist_device链表(对driver也有klist_driver链表) 127 &dev->class->p->klist_devices); 128 /*通知有新设备加入,执行该dev的class_intf->add_dev(),好处是只有设备匹配注册成功了,才进行其它的注册工作(如字符设备的注册,生成/dev/***节点文件)以及部分初始化工作。*/ 129 /* notify any interfaces that the device is here */ 130 list_for_each_entry(class_intf, 131 &dev->class->p->interfaces, node) 132 if (class_intf->add_dev) 133 class_intf->add_dev(dev, class_intf); 134 mutex_unlock(&dev->class->p->mutex); 135 } 136 done: 137 put_device(dev); 138 return error; 139 DPMError: 140 bus_remove_device(dev); 141 BusError: 142 device_remove_attrs(dev); 143 AttrsError: 144 device_remove_class_symlinks(dev); 145 SymlinkError: 146 if (MAJOR(dev->devt)) 147 devtmpfs_delete_node(dev); 148 if (MAJOR(dev->devt)) 149 device_remove_sys_dev_entry(dev); 150 devtattrError: 151 if (MAJOR(dev->devt)) 152 device_remove_file(dev, &devt_attr); 153 ueventattrError: 154 device_remove_file(dev, &uevent_attr); 155 attrError: 156 kobject_uevent(&dev->kobj, KOBJ_REMOVE); 157 kobject_del(&dev->kobj); 158 Error: 159 cleanup_device_parent(dev); 160 if (parent) 161 put_device(parent); 162 name_error: 163 kfree(dev->p); 164 dev->p = NULL; 165 goto done; 166 }

5 device_private_init

初始化私有数据,很重要的一个数据,它是连接所属bus、parent和对应驱动等的重要连接桥梁。
 1 int device_private_init(struct device *dev)
 2 {
 3     dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
 4     if (!dev->p)
 5         return -ENOMEM;
 6     dev->p->device = dev;//暂时只明确它是那个设备,先把自己绑定进去,后面再加如bus,driver之类
 7     klist_init(&dev->p->klist_children, klist_children_get,
 8            klist_children_put);
 9     INIT_LIST_HEAD(&dev->p->deferred_probe);
10     return 0;
11 }

6 bus_add_device

将新建设备添加到对应的bus上。

 1 /**
 2  * bus_add_device - add device to bus
 3  * @dev: device being added
 4  *
 5  * - Add device's bus attributes.
 6  * - Create links to device's bus.
 7  * - Add the device to its bus's list of devices.
 8  */
 9 int bus_add_device(struct device *dev)
10 {
11     struct bus_type *bus = bus_get(dev->bus);//拿到device对应的总线,且把总线引用计数加1
12     int error = 0;
13 
14     if (bus) {
15         pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
16         error = device_add_attrs(bus, dev);//创建添加相应属性
17         if (error)
18             goto out_put;
19         error = sysfs_create_link(&bus->p->devices_kset->kobj,
20                         &dev->kobj, dev_name(dev));//在sys/bus/总线类型/devices/目录下,创建名字为dev_name的符号链接,指向sys/devices/相同设备名字(前面创建了class目录下的,这创建bus目录下的符号链接)
21         if (error)
22             goto out_id;
23         error = sysfs_create_link(&dev->kobj,//在sys/devices/分类/设备名字/目录下创建目录名字为subsystem的符号链接,并且指向在sys/bus/总线类型
24                 &dev->bus->p->subsys.kobj, "subsystem");
25         if (error)
26             goto out_subsys;
27         klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);//设备加到总线链表中
28     }
29     return 0;
30 
31 out_subsys:
32     sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
33 out_id:
34     device_remove_attrs(bus, dev);
35 out_put:
36     bus_put(dev->bus);
37     return error;
38 }

 7 bus_probe_device

 1 /**
 2  * bus_probe_device - probe drivers for a new device
 3  * @dev: device to probe
 4  *
 5  * - Automatically probe for a driver if the bus allows it.
 6  */
 7 void bus_probe_device(struct device *dev)
 8 {
 9     struct bus_type *bus = dev->bus;
10     struct subsys_interface *sif;
11     int ret;
12 
13     if (!bus)
14         return;//确定总线存在,否则出错返回
15     /*drivers_autoprobe是一个bit变量,为l则允许本条总线上的device注册时自动匹配driver,drivers_autoprobe默认总是为1,除非用户空间修改*/
16     if (bus->p->drivers_autoprobe) {
17         ret = device_attach(dev);//匹配设备和驱动
18         WARN_ON(ret < 0);
19     }
20 
21     mutex_lock(&bus->p->mutex);
22     list_for_each_entry(sif, &bus->p->interfaces, node)
23         if (sif->add_dev)
24             sif->add_dev(dev, sif);
25     mutex_unlock(&bus->p->mutex);
26 }

8 device_attach

两种情况:

1)默认注册的device自带有驱动,只需要调用device_bind_driver绑定,不需要匹配。

2)如果没有带有驱动,则需要后面遍历总线,调用匹配函数__device_attach分析匹配对应的驱动

 1 /**
 2  * device_attach - try to attach device to a driver.
 3  * @dev: device.
 4  *
 5  * Walk the list of drivers that the bus has and call
 6  * driver_probe_device() for each pair. If a compatible
 7  * pair is found, break out and return.
 8  *
 9  * Returns 1 if the device was bound to a driver;
10  * 0 if no matching driver was found;
11  * -ENODEV if the device is not registered.
12  *
13  * When called for a USB interface, @dev->parent lock must be held.
14  */
15 int device_attach(struct device *dev)
16 {
17     int ret = 0;
18 
19     device_lock(dev);
20     if (dev->driver) {//driver已经放在device了(初始化device,时,手动添加的driver)
21         if (klist_node_attached(&dev->p->knode_driver)) {
22             ret = 1;
23             goto out_unlock;
24         }
25         ret = device_bind_driver(dev);//driver放在device里了,但还没真正的绑定 ,则执行这个函数绑定
26         if (ret == 0)
27             ret = 1;
28         else {
29             dev->driver = NULL;
30             ret = 0;
31         }
32     } else {//刚注册的device,没有添加对应的driver,需要查找匹配对应的驱动
33         ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);//遍历总线上的driver链表,一个一个进行匹配
34         pm_request_idle(dev);
35     }
36 out_unlock:
37     device_unlock(dev);
38     return ret;
39 }

8.1 device_bind_driver

device上有driver,只需绑定即可。

 1 /**
 2  * device_bind_driver - bind a driver to one device.
 3  * @dev: device.
 4  *
 5  * Allow manual attachment of a driver to a device.
 6  * Caller must have already set @dev->driver.
 7  *
 8  * Note that this does not modify the bus reference count
 9  * nor take the bus's rwsem. Please verify those are accounted
10  * for before calling this. (It is ok to call with no other effort
11  * from a driver's probe() method.)
12  *
13  * This function must be called with the device lock held.
14  */
15 int device_bind_driver(struct device *dev)
16 {
17     int ret;
18 
19     ret = driver_sysfs_add(dev);//把dev和driver链接起来
20     if (!ret)
21         driver_bound(dev);//device里面私有的driver节点挂接到driver的设备链表(一个driver可能对应多个device)
22     return ret;
23 }
24 
25 static int driver_sysfs_add(struct device *dev)
26 {
27     int ret;
28 
29     if (dev->bus)
30         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,//通知其它总线将要绑定driver 到device
31                          BUS_NOTIFY_BIND_DRIVER, dev);
32 
33     ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
34               kobject_name(&dev->kobj));//在driver目录下创建device目录的符号链接,名字为设备的名字
35     if (ret == 0) {
36         ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
37                     "driver");//在device目录下创建driver的目录,名字为driver
38         if (ret)
39             sysfs_remove_link(&dev->driver->p->kobj,
40                     kobject_name(&dev->kobj));
41     }
42     return ret;
43 }
44 
45 static void driver_bound(struct device *dev)
46 {
47     if (klist_node_attached(&dev->p->knode_driver)) {//再次检查,确定没绑定
48         printk(KERN_WARNING "%s: device %s already bound\n",
49             __func__, kobject_name(&dev->kobj));
50         return;
51     }
52 
53     pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
54          __func__, dev->driver->name);
55     /* 绑定!!!!!! 把device私有的p里的knode_driver,绑定到driver里面的klist_device链表上 */
56     klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
57 
58     /*
59      * Make sure the device is no longer in one of the deferred lists and
60      * kick off retrying all pending devices
61      */
62     driver_deferred_probe_del(dev);
63     driver_deferred_probe_trigger();
64 
65     if (dev->bus)//通知其它子模块以及绑定成功
66         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
67                          BUS_NOTIFY_BOUND_DRIVER, dev);
68 }

8.2 bus_for_each_drv(dev->bus, NULL, dev, __device_attach)

如果设备没有对应的驱动,则需要遍历总线上的driver链表,一个一个进行匹配。

 1 /**
 2  * bus_for_each_drv - driver iterator
 3  * @bus: bus we're dealing with.
 4  * @start: driver to start iterating on.
 5  * @data: data to pass to the callback.
 6  * @fn: function to call for each driver.
 7  *
 8  * This is nearly identical to the device iterator above.
 9  * We iterate over each driver that belongs to @bus, and call
10  * @fn for each. If @fn returns anything but 0, we break out
11  * and return it. If @start is not NULL, we use it as the head
12  * of the list.
13  *
14  * NOTE: we don't return the driver that returns a non-zero
15  * value, nor do we leave the reference count incremented for that
16  * driver. If the caller needs to know that info, it must set it
17  * in the callback. It must also be sure to increment the refcount
18  * so it doesn't disappear before returning to the caller.
19  */
20 int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
21              void *data, int (*fn)(struct device_driver *, void *))
22 {
23     struct klist_iter i;
24     struct device_driver *drv;
25     int error = 0;
26 
27     if (!bus)
28         return -EINVAL;
29 
30     klist_iter_init_node(&bus->p->klist_drivers, &i,
31                  start ? &start->p->knode_bus : NULL);
32     while ((drv = next_driver(&i)) && !error)
33         error = fn(drv, data);
34     klist_iter_exit(&i);
35     return error;
36 }
37 
38 static int __device_attach(struct device_driver *drv, void *data)
39 {
40     struct device *dev = data;
41 
42     if (!driver_match_device(drv, dev))
43         return 0;
44 
45     return driver_probe_device(drv, dev);
46 }

8.3 __device_attach

 1 static int __device_attach(struct device_driver *drv, void *data)
 2 {
 3     struct device *dev = data;
 4 
 5     if (!driver_match_device(drv, dev))//确认匹配成功
 6         return 0;
 7 
 8     return driver_probe_device(drv, dev);//调用probe函数
 9 }
10 
11 static inline int driver_match_device(struct device_driver *drv,
12                       struct device *dev)
13 {
14     return drv->bus->match ? drv->bus->match(dev, drv) : 1;
15 }
16 
17 /**
18  * driver_probe_device - attempt to bind device & driver together
19  * @drv: driver to bind a device to
20  * @dev: device to try to bind to the driver
21  *
22  * This function returns -ENODEV if the device is not registered,
23  * 1 if the device is bound successfully and 0 otherwise.
24  *
25  * This function must be called with @dev lock held.  When called for a
26  * USB interface, @dev->parent lock must be held as well.
27  */
28 int driver_probe_device(struct device_driver *drv, struct device *dev)
29 {
30     int ret = 0;
31 
32     if (!device_is_registered(dev))//通过查看在sysfs中的状态判断是都已经注册
33         return -ENODEV;
34 
35     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
36          drv->bus->name, __func__, dev_name(dev), drv->name);
37 
38     pm_runtime_barrier(dev);
39     ret = really_probe(dev, drv);//真正的probe函数
40     pm_request_idle(dev);
41 
42     return ret;
43 }

8.4 really_probe

source code位于:drivers\base\dd.c

 1 static int really_probe(struct device *dev, struct device_driver *drv)
 2 {
 3     int ret = 0;
 4     int local_trigger_count = atomic_read(&deferred_trigger_count);
 5 
 6     atomic_inc(&probe_count);
 7     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
 8          drv->bus->name, __func__, drv->name, dev_name(dev));
 9     WARN_ON(!list_empty(&dev->devres_head));
10 
11     dev->driver = drv;//匹配好后的驱动信息记录到设备内部
12 
13     /* If using pinctrl, bind pins now before probing */
14     ret = pinctrl_bind_pins(dev);
15     if (ret)
16         goto probe_failed;
17 
18     if (driver_sysfs_add(dev)) {//driver加入sysfs(其实就是创建各种符号链接,前面device默认绑定有driver那里已经分析过了)
19         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
20             __func__, dev_name(dev));
21         goto probe_failed;
22     }
23 
24     if (dev->bus->probe) {//如果总线上定义probe函数则调用
25         ret = dev->bus->probe(dev);
26         if (ret)
27             goto probe_failed;
28     } else if (drv->probe) {//否则调用驱动上的probe函数
29         ret = drv->probe(dev);
30         if (ret)
31             goto probe_failed;
32     }
33 
34     driver_bound(dev);//将设备加入到驱动支持的设备链表中,一个设备需要一个驱动,一个驱动支持多个设备,前面device默认绑定driver那里已经分析过了
35     ret = 1;
36     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
37          drv->bus->name, __func__, dev_name(dev), drv->name);
38     goto done;
39 
40 probe_failed:
41     devres_release_all(dev);
42     driver_sysfs_remove(dev);
43     dev->driver = NULL;
44     dev_set_drvdata(dev, NULL);
45 
46     if (ret == -EPROBE_DEFER) {
47         /* Driver requested deferred probing */
48         dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
49         driver_deferred_probe_add(dev);
50         /* Did a trigger occur while probing? Need to re-trigger if yes */
51         if (local_trigger_count != atomic_read(&deferred_trigger_count))
52             driver_deferred_probe_trigger();
53     } else if (ret != -ENODEV && ret != -ENXIO) {
54         /* driver matched but the probe failed */
55         printk(KERN_WARNING
56                "%s: probe of %s failed with error %d\n",
57                drv->name, dev_name(dev), ret);
58     } else {
59         pr_debug("%s: probe of %s rejects match %d\n",
60                drv->name, dev_name(dev), ret);
61     }
62     /*
63      * Ignore errors returned by ->probe so that the next driver can try
64      * its luck.
65      */
66     ret = 0;
67 done:
68     atomic_dec(&probe_count);
69     wake_up(&probe_waitqueue);
70     return ret;
71 }

2总结

上面API的一层层的嵌套,看完之后有点蒙,最后整体总结下,整体的调用过程如下:

device_create()

    device_create_vargs();//新建结构体dev

        kobject_set_name_vargs();

        device_register();

            device_initialize();

            device_add();

 

device_register(struct device *dev)

    device_initialize();        /* 初始化通用数据结构 */

    device_add();        /* 加入到该dev所属bus上 */

 

device_initialize(struct device *dev)

    kobject_init();

    INIT_LIST_HEAD(&dev->dma_pools);

    INIT_LIST_HEAD(&dev->devres_head);

    device_pm_init();

    set_dev_node(); 

 

device_add()//把设备加到对应的bus上

    get_device();

   device_private_init();

   dev_set_name();//用dev的init_name初始化dev-kobject->name即目录名

   !dev_name(dev) && dev->bus && dev->bus->dev_name;

   get_device(dev->parent);//父节点的引用计数加1

   get_device_parent();//找到其父类

   kobject_add();//把内嵌的kobject注册到设备模型中,在sys下建目录kobj->name

   platform_notify();//如果platform_notify定义的话,通知平台设备,一般不用

   device_create_file();//创建sys目录下设备的uevent属性文件

   device_create_file();//创建sys目录下设备的设备号属性,即major和minor /主要是在sys/devices/...中添加dev属性文件.

   device_create_sys_dev_entry();//在/sys/dev/char/或者/sys/dev/block/创建devt的属性的连接文件,形如10:45,由主设备号和次设备号构成,指向/sys/devices/.../的具体设备目录,该链接文件只具备读属性,显示主设备号:次设备号,如10:45,用户空间udev响应uevent事件时,将根据设备号在/dev下创建节点文件

   device_add_class_symlinks();//实际创建的kobject都是在device下面,其他class,bus之类的里面的具体设备都是device目录下设备的符号链接,这里是在class下创建符号链接.

   device_add_attrs();//创建sys目录下设备其他属性文件(添加设备属性文件)

   bus_add_device();//添加设备的总线属性 将设备加入到管理它的bus总线的设备连表上  创建subsystem链接文件,链接class下的具体的子系统文件夹  将设备添加到其总线的设备列表中。

   dpm_sysfs_add();//把设备增加到sysfs电源管理power目录(组)下,如果该设备设置电源管理相关的内容.

   device_pm_add();//设备添加到电源管理相关的设备列表中

   blocking_notifier_call_chain();//通知客户端,有新设备加入

   kobject_uevent();//产生一个内核uevent事件(这里是有设备加入),可以是helper,也可是通过netlink机制和用户空间通信该事件可以被内核以及应用层捕获,属于linux设备模型中热插拔机制.

   bus_probe_device();在bus上匹配dev对应的drv。

   klist_add_tail();//将设备添加到其父设备的子列表中

   klist_add_tail()//将dev添加到class的klist_device链表(对driver有klist_driver链表)

   list_for_each_entry();

   add_dev(dev, class_intf);//通知有新设备加入,执行该dev的class_intf->add_dev(),只有设备匹配注册成功了,才进行其它的注册工作(如字符设备的注册,生成/dev/***节点文件)以及部分初始化工作.

 

device_private_init(struct device *dev)

    kzalloc(dev->p);

    klist_init();

    INIT_LIST_HEAD();

 

bus_add_device(struct device *dev)

    bus_get();//对总线的引用计数加1

    device_add_attrs(); //创建相应的属性文件

    device_add_groups();//增加到组中,就是再加一层目录封装

    sysfs_create_link();//在sys/bus/总线类型/devices/目录下,创建名字为devname(d)指向sys/devices/相同设备名字的符号链接(前面创建了class目录下的,这创建bus目录下的符号链接)

    sysfs_create_link();//在sys/devices/分类/设备名字/目录下创建目录名字为 subsystem 并且指向在sys/bus/总线类型 的符号链接

    klist_add_tail();//把设备加入到总线的设备链中

 

bus_probe_device(struct device *dev)

    device_attach();//if (bus->p->drivers_autoprobe),drivers_autoprobe是一个bit变量,为l则允许本条总线上的device注册时自动匹配driver。drivers_autoprobe默认总是为1,除非用户空间修改 */

   list_for_each_entry();

   add_dev();

 

device_attach(struct device *dev)

    klist_node_attached();

    device_bind_driver();

        driver_sysfs_add(dev);//把dev和driver链接起来

            blocking_notifier_call_chain();//通知其它总线将要绑定driver 到device

            sysfs_create_link(&dev->driver->p->kobj,&dev->kobj,kobject_name(&dev->kobj);在driver目录下创建device目录的符号链接,名字为设备的名字

            sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,"driver");//在device目录下创建driver的目录,名字为driver

       driver_bound(dev);//device里面私有的driver节点挂接到driver的设备链表,一个driver可能对应多个device

            klist_add_tail();//把device私有的p里的knode_driver,绑定到driver里面的klist_device链表上

            blocking_notifier_call_chain();//通知其它子模块以及绑定成功

    bus_for_each_drv();

       __device_attach();

          driver_match_device();//drv和dev匹配成功的话,才会往下执行的probe函数

              drv->bus->match(dev, drv) ;//drv对应的bus存在的话,call此bus的match函数

          driver_probe_device();

          device_is_registered();//确定设备已注册

          pm_runtime_barrier();//电源管理

          really_probe();//调用驱动的probe函数

              dev->driver = drv;//匹配好后的驱动信息记录到设备内部

              driver_sysfs_add(); //driver加入sysfs,就是创建各种符号链接

              dev->bus->probe(); //若bus的probe函数存在,则执行bus的probe     drv->probe();// 否则,指向device的probe函数

              driver_bound();//将设备加入到驱动支持的设备链表中,一个设备需要一个驱动,一个驱动支持多个设备,前面device默认绑定driver那里已经分析过了 */

          pm_request_idle();

    pm_request_idle(dev);

 

参考博文:https://blog.csdn.net/qq_16777851/java/article/details/81437352

posted @ 2020-05-16 13:15  Action_er  阅读(4873)  评论(0编辑  收藏  举报