driver_register分析

在上一篇文章中分析了,i2c设备和i2c驱动的向总线注册过程。在总线-设备-驱动这种模型中,无论是先进行driver_register还是后进行device_register,总线驱动都会对进行匹配,只有匹配工程后,才会执行驱动的probe函数;
首先分析driver_register函数,先看此函数源码(driver/base/driver.c):

int driver_register(struct device_driver *drv)
{
    int ret;
    struct device_driver *other;

    BUG_ON(!drv->bus->p);
/*检查总线上注册的函数和driver注册的函数是否一样*/
    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);
/*查找总线上是否注册了这个设备驱动,此函数见分析1*/
    other = driver_find(drv->name, drv->bus);
    if (other) {
        printk(KERN_ERR "Error: Driver '%s' is already registered, "
            "aborting...\n", drv->name);
        return -EBUSY;
    }
    ret = bus_add_driver(drv);//向bus中添加此设备驱动程序,下面详细分析此函数,见2
    if (ret)
        return ret;
    ret = driver_add_groups(drv, drv->groups);
    if (ret)
        bus_remove_driver(drv);
    return ret;
}

**1.**driver_find源码如下:

struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
    /*这里涉及到kobj和kset的概念,将bus的kset传入函数kset_find_obj,kset是一个结构体,结构体里有链表这一成员,链表里面记录着这类kobjet,通过比较object的成员变量name和传进来的name是否相等,来判断是否注册过此类设备。kset_find_obj函数就不向下跟了,有兴趣可参考https://blog.csdn.net/tmkeepgood/article/details/8767408*/
    struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
    struct driver_private *priv;

    if (k) {
        /* Drop reference added by kset_find_obj() */
        kobject_put(k);
        priv = to_driver(k);
        return priv->driver;
    }
    return NULL;
}

**2.**bus_add_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;
    error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
                     "%s", drv->name);
    /*初始化并添加kobject,就是在sys/bus/i2c/driver目录下新建此驱动对应的目录*/
    if (error)
        goto out_unregister;

    if (drv->bus->p->drivers_autoprobe) {
        error = driver_attach(drv);//匹配函数,下面重点分析。
        if (error)
            goto out_unregister;
    }
/*一旦匹配成功,下面的函数就是为上面kobject_init_and_add函数建立的驱动文件添加相应的属性*/
    klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
    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_attrs(bus, drv);
    if (error) {
        /* How the hell do we get out of this pickle? Give up */
        printk(KERN_ERR "%s: driver_add_attrs(%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);
        }
    }

    kobject_uevent(&priv->kobj, KOBJ_ADD);
    return 0;

out_unregister:
    kobject_put(&priv->kobj);
    kfree(drv->p);
    drv->p = NULL;
out_put_bus:
    bus_put(bus);
    return error;
}

下面主要看driver_attach函数,此函数是driver主动去匹配device,源码如下(driver/base/dd.c):

int driver_attach(struct device_driver *drv)
{
    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);//调用此函数,这里的__driver_attach是一个函数指针,传递给bus_for_each_dev函数
}

函数bus_for_each_dev源码如下(driver/base/bus.c):

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)
/*这里调用next_device,类似于之前分析的next_driver,
拿出设备链表中的每一个设备,
将dirver和device传递给fn,即__driver_attach*/
        error = fn(dev, data);
    klist_iter_exit(&i);
    return error;
}

下面看__driver_attach源码,看其是怎么样匹配设备和驱动的(driver/base/dd.c):

static int __driver_attach(struct device *dev, void *data)
{
    struct device_driver *drv = data;

    /*
     * 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.
     */

    if (!driver_match_device(drv, dev))//匹配设备和驱动,详见2.1
        return 0;

    if (dev->parent)    /* Needed for USB */
        device_lock(dev->parent);
    device_lock(dev);
    if (!dev->driver)
        driver_probe_device(drv, dev);//匹配成功以后调用此函数,详见2.2
    device_unlock(dev);
    if (dev->parent)
        device_unlock(dev->parent);

    return 0;
}

2.1下面看driver_match_device源码(driver/base/base.h):

static inline int driver_match_device(struct device_driver *drv,
                      struct device *dev)
{
    return drv->bus->match ? drv->bus->match(dev, drv) : 1;
    /*如果注册了bus的match函数,就调用bus的match函数,没有则返回1
    这个bus的match在哪里注册的呢?是在i2c_register_driver函数中注册的
    i2c_register_driver函数中这条程序driver->driver.bus = &i2c_bus_type;
    对bus进行了注册,i2c_bus_type源码如下:
    struct bus_type i2c_bus_type = {
    .name       = "i2c",
    .match      = i2c_device_match,//这些函数在i2c_register_driver都有定义
    .probe      = i2c_device_probe,
    .remove     = i2c_device_remove,
    .shutdown   = i2c_device_shutdown,
    .pm     = &i2c_device_pm_ops,
};
    */
}//这是一个内联函数,只能定义在头文件中

下面看i2c_device_match的源码(driver/i2c/i2c-core.c):

static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
    struct i2c_client   *client = i2c_verify_client(dev);
    struct i2c_driver   *driver;

    if (!client)
        return 0;

    /* Attempt an OF style match */
    /*这个函数是也是进行dev和drv的匹配,当平台使用设备树来记录硬件信息时,
    会调用此函数进行匹配,使用设备树时drv和dev匹配的依据是.compatible这一属性*/
    if (of_driver_match_device(dev, drv))
        return 1;

    driver = to_i2c_driver(drv);
    /* match on an id table if there is one */
    if (driver->id_table)
        return i2c_match_id(driver->id_table, client) != NULL;
    /*当平台使用i2c_board_info结构体来记录板级信息时,使用此函数进行drv和dev的匹配,两种匹配的依据是dev的name和drv的id_table,下面继续分析这种方法的匹配*/
    return 0;
}

下面看i2c_match_id函数的源码:

static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
                        const struct i2c_client *client)
{
    while (id->name[0]) {
        if (strcmp(client->name, id->name) == 0)//比较client和drv中id_table是否相同
            return id;
        id++;
    }
    return NULL;
}

2.2无论是使用of_driver_match_device(设备树)函数进行匹配还是使用i2c_match_id(结构体记录板级信息)函数进行匹配,匹配成功时都会调用driver_probe_device函数。下面看这个函数源码,看其实怎么调用设备驱动中的probe函数的(driver/base/dd.c):

nt 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);

    pm_runtime_get_noresume(dev);
    pm_runtime_barrier(dev);
    ret = really_probe(dev, drv);//在调用此函数
    pm_runtime_put_sync(dev);

    return ret;
}

看really_probe函数源码:

static int really_probe(struct device *dev, struct device_driver *drv)
{
    int ret = 0;

    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;
    /*driver_sysfs_add函数就是建立sys/bus/i2c/driver下的驱动
    与sys/bus/i2c/devicec下设备的链接*/
    if (driver_sysfs_add(dev)) {
        printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
            __func__, dev_name(dev));
        goto probe_failed;
    }

    if (dev->bus->probe) {//先调用驱动总线的probe函数
        ret = dev->bus->probe(dev);
        if (ret)
            goto probe_failed;
    } else if (drv->probe) {
    //再调用自己driver的probe函数。执行到这就是已经调用驱动程序中的probe函数了
        ret = drv->probe(dev);
        if (ret)
            goto probe_failed;
    }

    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:
    devres_release_all(dev);
    driver_sysfs_remove(dev);
    dev->driver = NULL;

    if (ret == -EPROBE_DEFER) {
        /* Driver requested deferred probing */
        dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
        driver_deferred_probe_add(dev);
    } else if (ret != -ENODEV && ret != -ENXIO) {
        /* driver matched but the probe failed */
        printk(KERN_WARNING
               "%s: probe of %s failed with error %d\n",
               drv->name, dev_name(dev), ret);
    } else {
        pr_debug("%s: probe of %s rejects match %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;
}

猜你喜欢

转载自blog.csdn.net/chihunqi5879/article/details/79993537