设备驱动中的device_driver(kernel-4.7)
来源:互联网 发布:淘宝手机详情卖家推荐 编辑:程序博客网 时间:2024/05/24 01:45
device_driver结构体定义在driver/base/base.h中,如下:
/** * struct device_driver - The basic device driver structure * @name: Name of the device driver. * @bus: The bus which the device of this driver belongs to. * @owner: The module owner. * @mod_name: Used for built-in modules. * @suppress_bind_attrs: Disables bind/unbind via sysfs. * @probe_type: Type of the probe (synchronous or asynchronous) to use. * @of_match_table: The open firmware table. * @acpi_match_table: The ACPI match table. * @probe: Called to query the existence of a specific device, * whether this driver can work with it, and bind the driver * to a specific device. * @remove: Called when the device is removed from the system to * unbind a device from this driver. * @shutdown: Called at shut-down time to quiesce the device. * @suspend: Called to put the device to sleep mode. Usually to a * low power state. * @resume: Called to bring a device from sleep mode. * @groups: Default attributes that get created by the driver core * automatically. * @pm: Power management operations of the device which matched * this driver. * @p: Driver core's private data, no one other than the driver * core can touch this. * * The device driver-model tracks all of the drivers known to the system. * The main reason for this tracking is to enable the driver core to match * up drivers with new devices. Once drivers are known objects within the * system, however, a number of other things become possible. Device drivers * can export information and configuration variables that are independent * of any specific device. */struct device_driver { const char *name; /*设备驱动程序的名称*/ struct bus_type *bus; //device_driver支持的device所依附的bus struct module *owner; //所属的设备驱动程序的模块 const char *mod_name; /* used for built-in modules */ bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ enum probe_type probe_type; const struct of_device_id *of_match_table; const struct acpi_device_id *acpi_match_table; int (*probe) (struct device *dev); /*探测device_drvier是否支持参数指定的device*/ int (*remove) (struct device *dev);/*device被移除时调用该函数,解除该device与device_driver的绑定*/ void (*shutdown) (struct device *dev); /*当关机时调用该函数,以关闭参数指定的device*/ int (*suspend) (struct device *dev, pm_message_t state); //当device进入休眠状态时,调用该函数 int (*resume) (struct device *dev); //当device从休眠状态被唤醒时,调用该函数 const struct attribute_group **groups; const struct dev_pm_ops *pm; struct driver_private *p; //device_driver私有数据};
该结构体用于描述设备驱动程序模型中的驱动程序。
p是device_driver
私有数据,它是struct driver_private
类型,该类型定义在drivers/base/base.h文件中,其内容如下:
struct driver_private { struct kobject kobj; //是其所属的device_driver对应的kobject struct klist klist_devices; //其所属的device_driver支持的device链表 struct klist_node knode_bus; struct module_kobject *mkobj; struct device_driver *driver; //所属的device_driver};#define to_driver(obj) container_of(obj, struct driver_private, kobj)
device_driver
的注册是通过调用driver_register
函数完成的,该函数定义在drivers/base/driver.c文件中,其内容如下:
/** * driver_register - register driver with bus * @drv: driver to register * * We pass off most of the work to the bus_add_driver() call, * since most of the things we have to do deal with the bus * structures. */int driver_register(struct device_driver *drv){ int ret; struct device_driver *other; BUG_ON(!drv->bus->p);//如果bus和device_driver定义了相同的函数,会优先调用bus的相应函数,这里会发出警告信息 if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) printk(KERN_WARNING "Driver '%s' needs updating - please use " "bus_type methods\n", drv->name);//调用driver_find在bus的drivers_kset中查找是否已经有同名device_driver已经注册过,如果已经注册过,则退出。 other = driver_find(drv->name, drv->bus); if (other) { printk(KERN_ERR "Error: Driver '%s' is already registered, " "aborting...\n", drv->name); return -EBUSY; }//调用bus_add_driver函数完成注册 ret = bus_add_driver(drv); if (ret) return ret; ret = driver_add_groups(drv, drv->groups); if (ret) { bus_remove_driver(drv); return ret; } kobject_uevent(&drv->p->kobj, KOBJ_ADD); return ret;}
bus_add_driver
函数完成了注册,该函数定义在drivers/base/bus.c文件中,其内容如下:
/** * bus_add_driver - Add a driver to the bus. * @drv: driver. */int bus_add_driver(struct device_driver *drv){ struct bus_type *bus; struct driver_private *priv; int error = 0; bus = bus_get(drv->bus); if (!bus) return -EINVAL; pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { error = -ENOMEM; goto out_put_bus; } klist_init(&priv->klist_devices, NULL, NULL); priv->driver = drv; drv->p = priv; priv->kobj.kset = bus->p->drivers_kset; //调用kobject_init_and_add函数将device_driver添加到sysfs文件系统中 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name); if (error) goto out_unregister; //调用klist_add_tail将device_driver加入到bus->p->klist_drivers中 klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); if (drv->bus->p->drivers_autoprobe) { //如果drv->bus->p->drivers_autoprobe为1,则调用driver_attach(drv)函数将当前device_driver与相应device进行绑定 if (driver_allows_async_probing(drv)) { pr_debug("bus: '%s': probing driver %s asynchronously\n", drv->bus->name, drv->name); async_schedule(driver_attach_async, drv); } else { error = driver_attach(drv); if (error) goto out_unregister; } } module_add_driver(drv->owner, drv); error = driver_create_file(drv, &driver_attr_uevent); if (error) { printk(KERN_ERR "%s: uevent attr (%s) failed\n", __func__, drv->name); } error = driver_add_groups(drv, bus->drv_groups); if (error) { /* How the hell do we get out of this pickle? Give up */ printk(KERN_ERR "%s: driver_create_groups(%s) failed\n", __func__, drv->name); } if (!drv->suppress_bind_attrs) { error = add_bind_files(drv); if (error) { /* Ditto */ printk(KERN_ERR "%s: add_bind_files(%s) failed\n", __func__, drv->name); } } return 0;out_unregister: kobject_put(&priv->kobj); kfree(drv->p); drv->p = NULL;out_put_bus: bus_put(bus); return error;}
bus_add_driver
函数中调用的driver_attach
函数定义在drivers/base/dd.c文件中,其内容如下:
/** * driver_attach - try to bind driver to devices. * @drv: driver. * * Walk the list of devices that the bus has on it and try to * match the driver with each one. If driver_probe_device() * returns 0 and the @dev->driver is set, we've found a * compatible pair. */int driver_attach(struct device_driver *drv){ return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);}
其中bus_for_each_dev
函数定义在drivers/base/bus.c文件中,其内容如下:
/** * bus_for_each_dev - device iterator. * @bus: bus type. * @start: device to start iterating from. * @data: data for the callback. * @fn: function to be called for each device. * * Iterate over @bus's list of devices, and call @fn for each, * passing it @data. If @start is not NULL, we use that device to * begin iterating from. * * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * * NOTE: The device that returns a non-zero value is not retained * in any way, nor is its refcount incremented. If the caller needs * to retain this data, it should do so, and increment the reference * count in the supplied callback. */int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *)){ struct klist_iter i; struct device *dev; int error = 0; if (!bus || !bus->p) return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, (start ? &start->p->knode_bus : NULL)); while ((dev = next_device(&i)) && !error) error = fn(dev, data); klist_iter_exit(&i); return error;}
其中while循环遍历bus->p->klist_devices
链表,对注册在bus上的每个device调用fn函数,这里,fn函数是传递进来的__driver_attach
函数,该函数定义在drivers/base/dd.c文件中,其内容如下:
static int __driver_attach(struct device *dev, void *data){ struct device_driver *drv = data; int ret; /* * Lock device and try to bind to it. We drop the error * here and always return 0, because we need to keep trying * to bind to devices and some drivers will return an error * simply if it didn't support the device. * * driver_probe_device() will spit a warning if there * is an error. */ ret = driver_match_device(drv, dev); if (ret == 0) { /* no match */ return 0; } else if (ret == -EPROBE_DEFER) { dev_dbg(dev, "Device match requests probe deferral\n"); driver_deferred_probe_add(dev); } else if (ret < 0) { dev_dbg(dev, "Bus failed to match device: %d", ret); return ret; } /* ret > 0 means positive match */ if (dev->parent) /* Needed for USB */ device_lock(dev->parent); device_lock(dev); if (!dev->driver) driver_probe_device(drv, dev); device_unlock(dev); if (dev->parent) device_unlock(dev->parent); return 0;}
其中调用了driver_match_device
函数,该函数定义在drivers/base/base.h文件中,其内容如下:
static inline int driver_match_device(struct device_driver *drv, struct device *dev){ //如果定义了drv->bus->match函数,则调用之,否则直接返回1 return drv->bus->match ? drv->bus->match(dev, drv) : 1;}
__driver_attach
函数调用的driver_probe_device
函数,该函数定义在drivers/base/dd.c文件中,其内容如下:
/** * driver_probe_device - attempt to bind device & driver together * @drv: driver to bind a device to * @dev: device to try to bind to the driver * * This function returns -ENODEV if the device is not registered, * 1 if the device is bound successfully and 0 otherwise. * * This function must be called with @dev lock held. When called for a * USB interface, @dev->parent lock must be held as well. * * If the device has a parent, runtime-resume the parent before driver probing. */int driver_probe_device(struct device_driver *drv, struct device *dev){ int ret = 0; if (!device_is_registered(dev)) return -ENODEV; pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); if (dev->parent) pm_runtime_get_sync(dev->parent); pm_runtime_barrier(dev); ret = really_probe(dev, drv); pm_request_idle(dev); if (dev->parent) pm_runtime_put(dev->parent); return ret;}
其中调用device_is_registered
函数判断device是否已经在sysfs系统中注册过,如果还没有注册过,则返回ENODEV,退出。 该函数定义在include/linux/device.h文件中,其内容如下:
static inline int device_is_registered(struct device *dev){ return dev->kobj.state_in_sysfs;}
driver_probe_device
调用really_probe
函数,该函数定义在drivers/base/dd.c文件中,其内容如下:
static int really_probe(struct device *dev, struct device_driver *drv){ int ret = -EPROBE_DEFER; int local_trigger_count = atomic_read(&deferred_trigger_count); if (defer_all_probes) { /* * Value of defer_all_probes can be set only by * device_defer_all_probes_enable() which, in turn, will call * wait_for_device_probe() right after that to avoid any races. */ dev_dbg(dev, "Driver %s force probe deferral\n", drv->name); driver_deferred_probe_add(dev); return ret; } atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; /* If using pinctrl, bind pins now before probing */ ret = pinctrl_bind_pins(dev); if (ret) goto pinctrl_bind_failed; if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", __func__, dev_name(dev)); goto probe_failed; } if (dev->pm_domain && dev->pm_domain->activate) { ret = dev->pm_domain->activate(dev); if (ret) goto probe_failed; } /* * Ensure devices are listed in devices_kset in correct order * It's important to move Dev to the end of devices_kset before * calling .probe, because it could be recursive and parent Dev * should always go first */ devices_kset_move_last(dev); if (dev->bus->probe) { ret = dev->bus->probe(dev); if (ret) goto probe_failed; } else if (drv->probe) { ret = drv->probe(dev); if (ret) goto probe_failed; } pinctrl_init_done(dev); if (dev->pm_domain && dev->pm_domain->sync) dev->pm_domain->sync(dev); driver_bound(dev); ret = 1; pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); goto done;probe_failed: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DRIVER_NOT_BOUND, dev);pinctrl_bind_failed: devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; dev_set_drvdata(dev, NULL); if (dev->pm_domain && dev->pm_domain->dismiss) dev->pm_domain->dismiss(dev); pm_runtime_reinit(dev); switch (ret) { case -EPROBE_DEFER: /* Driver requested deferred probing */ dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name); driver_deferred_probe_add(dev); /* Did a trigger occur while probing? Need to re-trigger if yes */ if (local_trigger_count != atomic_read(&deferred_trigger_count)) driver_deferred_probe_trigger(); break; case -ENODEV: case -ENXIO: pr_debug("%s: probe of %s rejects match %d\n", drv->name, dev_name(dev), ret); break; default: /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev_name(dev), ret); } /* * Ignore errors returned by ->probe so that the next driver can try * its luck. */ ret = 0;done: atomic_dec(&probe_count); wake_up(&probe_waitqueue); return ret;}
其中,如果定义了dev->bus->probe
函数,则调用该函数;如果没有定义dev->bus->probe
函数,但是定义了drv->probe
函数,则调用drv->probe
函数。这里,我们一般写Linux驱动程序时都要实现的probe函数就会被调用了。 really_probe
中调用driver_bound(dev)
函数,该函数定义在drivers/base/dd.c文件中,其内容如下:
static void driver_bound(struct device *dev){ if (device_is_bound(dev)) { printk(KERN_WARNING "%s: device %s already bound\n", __func__, kobject_name(&dev->kobj)); return; } pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name, __func__, dev_name(dev)); //用klist_add_tail函数将device加入到device_driver的driver->p->klist_devices链表中 klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); device_pm_check_callbacks(dev); /* * Make sure the device is no longer in one of the deferred lists and * kick off retrying all pending devices */ driver_deferred_probe_del(dev); driver_deferred_probe_trigger(); if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BOUND_DRIVER, dev);}
至此,我们一步一步回退driver_bound
->really_probe
->driver_probe_device
->__driver_attach
->driver_attach
->bus_add_drive
回到到bus_add_driver
函数, 该函数中调用driver_create_file(drv, &driver_attr_uevent)
函数,创建属性文件,driver_attr_uevent
定义在drivers/base/bus.c文件中:
static DRIVER_ATTR_WO(uevent);
DRIVER_ATTR_WO
宏定义在include/linux/device.h文件中:
#define DRIVER_ATTR_WO(_name) \struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)
__ATTR_WO
宏定义在include/linux/sysfs.h文件中
#define __ATTR_WO(_name) { \ .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ .store = _name##_store, \}
回到bus_add_driver
函数: bus_add_driver
调用driver_add_groups
函数,将驱动加入bus->drv_groups
中。
bus_add_driver
调用add_bind_files
为`driver_attr_unbind
和driver_attr_bind
创建属性文件。
回到driver_register
函数: driver_register
调用driver_add_groups
,创建属性组。
driver_register
,调用kobject_uevent(&drv->p->kobj, KOBJ_ADD)
,发送uenvnt事件通知用户空间。
至此,我们就清楚device_driver
是怎样注册的了。
- 设备驱动中的device_driver(kernel-4.7)
- Linux Kernel设备驱动模型之 struct device_driver
- 设备驱动中的device(kernel-4.7)
- 设备驱动中的bus(kernel-4.7)
- 设备驱动中的kobject(kernel-4.7)
- 设备驱动中的kset(kernel-4.7)
- 设备驱动中的pinctrl(kernel-4.7)
- 设备驱动中的platform(kernel-4.7)
- 设备驱动中的class(kernel-4.7)
- 设备驱动中的i2c(kernel-4.7)
- 设备驱动中的tty(kernel-4.7)
- 设备驱动中的gadget(kernel-4.7)
- 设备驱动中的mutex(kernel-4.7)
- 设备驱动中的inode(kernel-4.7)
- 设备驱动中的spin_lock(kernel-4.7)
- 设备驱动中的misc(kernel-4.7)
- 设备驱动中的iomem(kernel-4.7)
- 设备驱动中的mmc(kernel-4.7)
- JQuery的文档处理
- byte[]和InputStream的相互转换
- 欧拉函数
- Unity Steam_VR开发工具插件---VRTK 自带案例分析
- Android最佳性能实践(二)分析内存的使用情况
- 设备驱动中的device_driver(kernel-4.7)
- windows:服务启动、暂停、停止按钮不能点击,是灰色如何解决
- 源码方式向openssl中添加新算法完整详细步骤(示例:摘要算法SM3)【非engine方式】
- GreenDao 3.2.0官网介绍的部分翻译(一)
- 腾讯云CentOS7.2 配置PHP7 MySQL 5.7.10
- 进程介绍及和线程的关系
- 数据结构之堆(Heap)及其用途
- 说说Xcode LLDB调试的那些事儿
- git常用指令