设备驱动中的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_unbinddriver_attr_bind创建属性文件。

回到driver_register函数:
driver_register调用driver_add_groups,创建属性组。

driver_register,调用kobject_uevent(&drv->p->kobj, KOBJ_ADD),发送uenvnt事件通知用户空间。
至此,我们就清楚device_driver是怎样注册的了。

1 0