您的位置:首页 > 运维架构 > Linux

linux内核学习设备模型之第二层driver_register

2012-04-18 22:40 357 查看
来自:drivers/base/driver.c:

int driver_register(struct device_driver *drv)

{

    int ret;

    struct device_driver *other;

    BUG_ON(!drv->bus->p);

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

    other = driver_find(drv->name, drv->bus);   

 //比较好理解的函数,也就是在总线中找到和该驱动同名的驱动

//说白了,就是看看这个驱动之前注册过没

    if (other) {

        put_driver(other);        //如果注册过,那么我们将不再注册,注意减少驱动引用,因为在driver_find中增加过

        printk(KERN_ERR "Error: Driver '%s' is already registered, "

            "aborting...\n", drv->name);

        return -EBUSY;

    }

    ret = bus_add_driver(drv);        //如果没有注册过,那么我们将该驱动加入总线中

    if (ret)

        return ret;

    ret = driver_add_groups(drv, drv->groups);

    if (ret)

        bus_remove_driver(drv);

    return ret;

}

struct device_driver *driver_find(const char *name, struct bus_type *bus)

{

    struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);  

 //这个函数顾名思义,就是在总线集合中找到名称为name的kobject对象,其实就是驱动名称了

    struct driver_private *priv;

    if (k) {   //如果找到了

        priv = to_driver(k);

        return priv->driver;     //返回驱动指针

    }

    return NULL;

}

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);   //为驱动私有成员申请内存且清0

    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所属集合,显然这里就是对于总线的驱动集合

    error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,

                     "%s", drv->name);         //初始化并添加驱动kobject对象到总线驱动中

    if (error)

        goto out_unregister;

    if (drv->bus->p->drivers_autoprobe) {       //还记得我说过这个变量,

        error = driver_attach(drv);       //如果需要自动的去匹配,那么调用驱动匹配函数

        if (error)

            goto out_unregister;

    }

    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;

}

来自base/dd.c:

int driver_attach(struct device_driver *drv)

{

    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

}

来自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)

        return -EINVAL;

    klist_iter_init_node(&bus->p->klist_devices, &i,

                 (start ? &start->p->knode_bus : NULL));     

//初始化i结构体,我们可以进去看看

    while ((dev = next_device(&i)) && !error)   //在总线的设备链表中遍历链表

        error = fn(dev, data);          //然后将设备和驱动进行匹配,这个fn=__driver_attch

    klist_iter_exit(&i);                 //清除i结构体

    return error;

}

struct klist_iter {

    struct klist        *i_klist;      //所属链表

    struct klist_node    *i_cur;  //链表中的节点

};

void klist_iter_init_node(struct klist *k, struct klist_iter *i,

              struct klist_node *n)

{

    i->i_klist = k;

    i->i_cur = n;  //这里的n为NULL

    if (n)

        kref_get(&n->n_ref);

}

static struct device *next_device(struct klist_iter *i)

{

    struct klist_node *n = klist_next(i);      //以i->i_cur节点为起点,得到链表i->i_klist的下一个节点

    struct device *dev = NULL;

    struct device_private *dev_prv;

    if (n) {       //如果有,返回该设备

        dev_prv = to_device_private_bus(n);

        dev = dev_prv->device;

    }

    return dev;

}

struct klist_node *klist_next(struct klist_iter *i)

{

    void (*put)(struct klist_node *) = i->i_klist->put;

    struct klist_node *last = i->i_cur;

    struct klist_node *next;

    spin_lock(&i->i_klist->k_lock);

    if (last) {      //这里的last为空

        next = to_klist_node(last->n_node.next);

        if (!klist_dec_and_del(last))

            put = NULL;

    } else

        next = to_klist_node(i->i_klist->k_list.next);  //得到链表的第一个节点

    i->i_cur = NULL;

    while (next != to_klist_node(&i->i_klist->k_list)) {  //遍历链表,如果没有到头

        if (likely(!knode_dead(next))) {  //如果发现节点next为有效节点

            kref_get(&next->n_ref);      //增加节点引用

            i->i_cur = next;                   //将i结构的起始节点设为next

            break;

        }

        next = to_klist_node(next->n_node.next);   //继续遍历链表中下一个节点

    }

    spin_unlock(&i->i_klist->k_lock);

    if (put && last)

        put(last);

    return i->i_cur;

}

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))   //将驱动和设备匹配,如果成功返回0

        return 0;

//总线去匹配没有成功不要紧,因为,它只是一个很低级的匹配函数,我们还有更高级的

    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;

}

static inline int driver_match_device(struct device_driver *drv,

                      struct device *dev)

{

    return drv->bus->match ? drv->bus->match(dev, drv) : 1;   

//这里就要用到总线的match函数了,所有的匹配都是通过它来的

}

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

    pm_runtime_get_noresume(dev);  //pm_xxx电源管理类

    pm_runtime_barrier(dev);

    ret = really_probe(dev, drv);    //真正执行的寒酸

    pm_runtime_put_sync(dev);

    return ret;

}

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;

    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) {       //总线不存在,则看驱动的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 != -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);

    }

    /*

     * 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;

}

static void driver_bound(struct device *dev)

{

    if (klist_node_attached(&dev->p->knode_driver)) {   //如果设备已经绑定到了一个驱动,则返回

        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_name(dev),

         __func__, dev->driver->name);

    klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);  //将设备节点加入到该设备对应的驱动链表中

    if (dev->bus)

        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

                         BUS_NOTIFY_BOUND_DRIVER, dev);

}

总体来说,驱动的注册比较复杂,但是我们可以简单概况一下。

1、在总线上找找该驱动有没有被注册过

2、若没有注册过,则将驱动加入到总线驱动集合中

3、在总线上找能匹配驱动的设备

     1、将总线上每个设备进行匹配

     2、首先用总线的match 函数进行低级匹配

     3、然后在用总线的probe函数进行高级匹配,若失败,则用驱动上的probe寒酸进行高级匹配

     4、如果匹配成功,则将设备绑定到驱动链表中

4、如果匹配成功,则将驱动加入到总线的驱动链表中

92d9
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息