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