[转] linux设备模型之bus,device,driver分析

[本文转自:http://blog.csdn.net/gdt_a20]

内核的开发者将总线,设备,驱动这三者用软件思想抽象了出来,巧妙的建立了其间的关系,使之更形象化。结合前面所学的知识,总的来说其三者间的关系为bus有两条链表,分别用于挂接设备和驱动,指定了其自身bus的device或者driver最后都会分别连接到对应bus的这两条链表上,而总线又有其始端,为bus_kset,一个driver可以对应于几个设备,因此driver同样有其设备链表,用于挂接可以操作的设备,其自身也有bus挂接点,用于将自身挂接到对应bus(每个driver只属于一条总线),而对于device,一个设备只属于一条总线,只能有一个driver与其对应,因此对于device,都是单一的,一个driver挂接点,一个bus挂接点,device与bus相同的是都有始端,device为devices_kset,因此device的注册同时会出现在对应的bus目录和device总目录下。好了,下面就以源码为例分别分析一下bus,device,driver的注册过程。

 

一、bus的注册

      bus的注册比较简单,首先来看一下bus的结构:

struct bus_type {
    const char        *name;                //名字
    struct bus_attribute    *bus_attrs;           //bus属性集
    struct device_attribute    *dev_attrs;           //device属性集
    struct driver_attribute    *drv_attrs;           //driver属性集
    int (*match)(struct device *dev, struct device_driver *drv);
    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
    int (*probe)(struct device *dev);
    int (*remove)(struct device *dev);
    void (*shutdown)(struct device *dev);
    int (*suspend)(struct device *dev, pm_message_t state);
    int (*resume)(struct device *dev);
    const struct dev_pm_ops *pm;
    struct bus_type_private *p;                   //bus的私有成员
};
//其中重点看一下私有成员结构体:
struct bus_type_private {
    struct kset subsys;                           //bus内嵌的kset,代表其自身
    struct kset *drivers_kset;                    
    struct kset *devices_kset;
    struct klist klist_devices;                   //包含devices链表及其操作函数
    struct klist klist_drivers;                   //driver链表及其操作函数
    struct blocking_notifier_head bus_notifier;
    unsigned int drivers_autoprobe:1;              //匹配成功自动初始化标志
    struct bus_type *bus;                          
};

无论是bus,driver,还是device其本身特征都放在私有成员里,其注册时,都会申请并填充这个结构体,下面具体分析一下bus的注册流程,从bus_register开始:

int bus_register(struct bus_type *bus)
{
    int retval;
    struct bus_type_private *priv;
    priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);    //进入时bus_type->bus_type_private为NULL
    if (!priv)                                                      //该函数主要是对其的设置
        return -ENOMEM;
    priv->bus = bus;                                                //私有成员的bus回指该bus
    bus->p = priv;                                                  //初始化bus->p,即其私有属性
    BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
    retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);  //设置该bus的名字,bus是kset的封装
    if (retval)
        goto out;
                                                      //bus_kset即为所有bus的总起始端点
                                                      //围绕bus内嵌的kset初始化,和kset的初始化时围绕
    priv->subsys.kobj.kset = bus_kset;                //kobj相似,没有parent时,就会用kset的kobj,此处即是
    priv->subsys.kobj.ktype = &bus_ktype;                    //属性操作级别统一为bus_ktype
    priv->drivers_autoprobe = 1;                                    //设置该标志,当有driver注册时,会自动匹配devices
                                                                    //上的设备并用probe初始化,
                                                                    //当有device注册时也同样找到  driver并会初始化
    retval = kset_register(&priv->subsys);                          //注册kset,创建目录结构,以及层次关系
    if (retval)
        goto out;
    retval = bus_create_file(bus, &bus_attr_uevent);                //当前bus目录下生成bus_attr_uevent属性文件
    if (retval)
        goto bus_uevent_fail;
    priv->devices_kset = kset_create_and_add("devices", NULL,       //初始化bus目录下的devices目录,里面级联了该bus下设备,
                         &priv->subsys.kobj);                    //仍然以kset为原型
    if (!priv->devices_kset) {
        retval = -ENOMEM;
        goto bus_devices_fail;
    }
    priv->drivers_kset = kset_create_and_add("drivers", NULL,       //初始化bus目录下的drivers目录,里面级联了该bus下设备的driver
                         &priv->subsys.kobj);
    if (!priv->drivers_kset) {
        retval = -ENOMEM;
        goto bus_drivers_fail;
    }
    klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);  //初始化klist_devices里的操作函数成员
    klist_init(&priv->klist_drivers, NULL, NULL);                            //klist_drivers里的操作函数置空
    retval = add_probe_files(bus);                                           //增加bus_attr_drivers_probe和bus_attr_drivers_autoprobe
    if (retval)                                                              //属性文件
        goto bus_probe_files_fail;
    retval = bus_add_attrs(bus);                                             //增加默认的属性文件
    if (retval)
        goto bus_attrs_fail;
    pr_debug("bus: '%s': registered/n", bus->name);
    return 0;
bus_attrs_fail:                                                               //以下为错误处理
    remove_probe_files(bus);
bus_probe_files_fail:
    kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
    kset_unregister(bus->p->devices_kset);
bus_devices_fail:
    bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
    kset_unregister(&bus->p->subsys);
out:
    kfree(bus->p);
    bus->p = NULL;
    return retval;
}

由此可见,bus又是kset的封装,bus_register主要完成了其私有成员bus_type_private的初始化,并初始化了其下的两个目录devices和drivers,及其属性文件,bus有个自己的根目录也就是bus有个起始端点,是bus_kset,经过此番的注册,bus目录下将会出现我们注册的bus,并且其下会有device和driver两个子目录,代表它下面的driver和device链表。

二、driver的注册

  下面看一下driver是怎么和bus关联起来的,首先看下driver的结构:

struct device_driver {
    const char        *name;            //名字
    struct bus_type        *bus;        //其所在的bus
    struct module        *owner;
    const char        *mod_name;    /* used for built-in modules */
    bool suppress_bind_attrs;    /* disables bind/unbind via sysfs */
#if defined(CONFIG_OF)
    const struct of_device_id    *of_match_table;
#endif
    int (*probe) (struct device *dev);        //匹配成功时可能会调用到的函数
    int (*remove) (struct device *dev);
    void (*shutdown) (struct device *dev);
    int (*suspend) (struct device *dev, pm_message_t state);
    int (*resume) (struct device *dev);
    const struct attribute_group **groups;
    const struct dev_pm_ops *pm;
    struct driver_private *p;                 //私有成员,表示driver
};
//重点看下driver的私有成员
struct driver_private {
    struct kobject kobj;                      //代表driver自身
    struct klist klist_devices;               //可以操控的设备链表
    struct klist_node knode_bus;              //挂接到bus的节点
    struct module_kobject *mkobj;             //模块相关
    struct device_driver *driver;             //回指该driver
};

 如同bus一样,重点的仍是可以代表其自身的私有属性,下面具体看一下driver的注册过程,从driver_register开始:

int driver_register(struct device_driver *drv)
{
    int ret;
    struct device_driver *other;
    BUG_ON(!drv->bus->p);
    if ((drv->bus->probe && drv->probe) ||           //driver和bus的同名操作函数如果同时存在,会出现警告
        (drv->bus->remove && drv->remove) ||         //并且会优先选用bus的
        (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);        //进入bus的driver链表,确认该driver是否已经注册
    if (other) {
        put_driver(other);                            //找到了再减少引用计数,并且报错退出
        printk(KERN_ERR "Error: Driver '%s' is already registered, "
            "aborting.../n", drv->name);
        return -EBUSY;
    }
    ret = bus_add_driver(drv);                       //如果没有注册,那么把该driver加入所在bus
    if (ret)
        return ret;
    ret = driver_add_groups(drv, drv->groups);
    if (ret)
        bus_remove_driver(drv);
    return ret;
}
/****************************************************
× 跟踪一下driver_find(drv->name, drv->bus)
****************************************************/
struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
    struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);  //bus->p->drivers_kset代表bus下
    struct driver_private *priv;                                    //的driver目录,此处会遍历bus的    
                                                                    //driver链表,通过driver内嵌的
    if (k) {                                                        //kobj名字比较
        priv = to_driver(k);
        return priv->driver;                                 //如果找到同名的kobj那么返回该driver
    }
    return NULL;
}
//看一下kset_find_obj吧:
struct kobject *kset_find_obj(struct kset *kset, const char *name)
{
    struct kobject *k;
    struct kobject *ret = NULL;
    spin_lock(&kset->list_lock);
    list_for_each_entry(k, &kset->list, entry) {                   //遍历bus下的driver链表,如果
        if (kobject_name(k) && !strcmp(kobject_name(k), name)) {   //找到那么返回找到的kobj,并且把
            ret = kobject_get(k);                                  //该driver的kobj引用计数+1
            break;
        }
    }
    spin_unlock(&kset->list_lock);
    return ret;
}
/************************************************
× 再来跟踪一下driver_register里面的另外一个函数
× bus_add_driver(drv)
************************************************/
int bus_add_driver(struct device_driver *drv) 
{
    struct bus_type *bus;
    struct driver_private *priv;
    int error = 0;
    bus = bus_get(drv->bus);                                        //取得其所在bus的指针
    if (!bus)
        return -EINVAL;
    pr_debug("bus: '%s': add driver %s/n", bus->name, drv->name);   //开始初始化这个driver的私有成员,
                                                                    //和bus类似
    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;                          //kset指定到bus下面
    error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,   //建立层次结构和属性文件
                     "%s", drv->name);
    if (error)
        goto out_unregister;
    if (drv->bus->p->drivers_autoprobe) {                            //bus的自动匹配如果设置为真,
        error = driver_attach(drv);                                  //那么到bus的devices上去匹配设备
        if (error)
            goto out_unregister;
    }
    klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);        //把driver挂接到bus的driver链表
    module_add_driver(drv->owner, drv);
    error = driver_create_file(drv, &driver_attr_uevent);            //以下添加该driver相关属性文件
    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(drv)了,我们来看一下:
****************************************************************/
int driver_attach(struct device_driver *drv)                            //遍历bus的设备链表找到
{                                                                       //合适的设备就调用__driver_attach,
    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);      //NULL表示从头开始遍历
}  
//============
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,              //进入bus的devices链表
                 (start ? &start->p->knode_bus : NULL));
    while ((dev = next_device(&i)) && !error)                     //设备存在则调用fn即__driver_attach
        error = fn(dev, data);                                    //进行匹配
    klist_iter_exit(&i);
    return error;
} 
/*********************************************
× 接着看一下__driver_attach这个函数
*********************************************/
static int __driver_attach(struct device *dev, void *data)
{
    struct device_driver *drv = data;
    if (!driver_match_device(drv, dev))                //进行匹配
        return 0;
    if (dev->parent)    /* Needed for USB */
        device_lock(dev->parent);
    device_lock(dev);
    if (!dev->driver)                               //如果设备没有指定driver
        driver_probe_device(drv, dev);              //那么需要初始化匹配到的这个设备
    device_unlock(dev);
    if (dev->parent)
        device_unlock(dev->parent);
    return 0;
}
/*********************************************
× 又遇到两个分支,囧,先看一下driver_match_device 
*********************************************/ 
static inline int driver_match_device(struct device_driver *drv,      //bus的match存在就用bus的
                                      struct device *dev)             //,否则就直接匹配成功...
{                                                                     //match通常实现为首先扫描
    return drv->bus->match ? drv->bus->match(dev, drv) : 1;           //driver支持的id设备表,如果
}                                                                     //为NULL就用名字进行匹配
/************************************
× 再来看一下driver_probe_device这个函数 
************************************/ 
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_runtime_barrier(dev);
    ret = really_probe(dev, drv);                               //调用really_probe
    pm_runtime_put_sync(dev);
    return ret;
}
/************************************
× 看一下device_is_registered
************************************/
static inline int device_is_registered(struct device *dev)
{
    return dev->kobj.state_in_sysfs;                           //在sysfs中表示已经注册
}
/************************************
× 再看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;                                     //device的driver初始化成该driver
    if (driver_sysfs_add(dev)) {                      
                 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed/n",
            __func__, dev_name(dev));
        goto probe_failed;
    }
                                                         //利用probe初始化设备
    if (dev->bus->probe) {                               //如果bus的probe存在就用bus的,
        ret = dev->bus->probe(dev);                      //如果bus的不存在driver的存在
        if (ret)                                         //再用driver的
            goto probe_failed;
    } else if (drv->probe) {
        ret = drv->probe(dev);
        if (ret)
            goto probe_failed;
    }
    driver_bound(dev);                              //调用driver_bound进行绑定
    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;
}
/**********************************
* 最后跟一下driver_bound(dev)这个函数
**********************************/
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);  //将设备添加
                                                                            //到driver的链表
    if (dev->bus)
        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,      //通知链
                         BUS_NOTIFY_BOUND_DRIVER, dev);
}
//all end

总结一下,driver的注册,主要涉及将自身挂接到bus的driver链表,并将匹配到的设备加入自己的device链表,并且将匹配到的device的driver成员初始化为该driver,私有属性的driver节点也挂到driver的设备链表下,其中匹配函数是利用利用bus的match函数,该函数通常判断如果driver有id表,就查表匹配,如果没有就用driver和device名字匹配。当匹配成功后如果自动初始化标志允许则调用初始化函数probe,bus的probe优先级始终高于driver的。另外注意一点driver是没有总的起始端点的,driver不是可具体描述的事物。

三、device的注册

   还是照例先看一下device的结构:

struct device {
    struct device        *parent;
    struct device_private    *p;                                              //私有属性结构,重点
    struct kobject kobj;
    const char        *init_name; /* initial name of the device */
    struct device_type    *type;
    struct mutex        mutex;    /* mutex to synchronize calls to
                     * its driver.
                     */
    struct bus_type    *bus;        /* type of bus device is on */            //所在bus
    struct device_driver *driver;    /* which driver has allocated this    //匹配的driver
                       device */
    void        *platform_data;    /* Platform specific data, device
                       core doesn't touch it */
    struct dev_pm_info    power;
#ifdef CONFIG_NUMA
    int        numa_node;    /* NUMA node this device is close to */
#endif
    u64        *dma_mask;    /* dma mask (if dma'able device) */
    u64        coherent_dma_mask;/* Like dma_mask, but for
                         alloc_coherent mappings as
                         not all hardware supports
                         64 bit addresses for consistent
                         allocations such descriptors. */
    struct device_dma_parameters *dma_parms;
    struct list_head    dma_pools;    /* dma pools (if dma'ble) */
    struct dma_coherent_mem    *dma_mem; /* internal for coherent mem
                         override */
    /* arch specific additions */
    struct dev_archdata    archdata;
#ifdef CONFIG_OF
    struct device_node    *of_node;
#endif
    dev_t            devt;    /* dev_t, creates the sysfs "dev" */
    spinlock_t        devres_lock;
    struct list_head    devres_head;
    struct klist_node    knode_class;
    struct class        *class;
    const struct attribute_group **groups;    /* optional groups */
    void    (*release)(struct device *dev);
};
//重点看一下私有属性结构
struct device_private {
    struct klist klist_children;             //子集结构
    struct klist_node knode_parent;          //父级挂接点
    struct klist_node knode_driver;          //driver挂接点
    struct klist_node knode_bus;             //bus挂接点
    void *driver_data;
    struct device *device;                   //回指
};

接下来详细看一下device的注册device_register:

int device_register(struct device *dev)
{
    device_initialize(dev);                //初始化dev
    return device_add(dev);                //添加dev
}
/******************************
* 先看一下device_initialize(dev)
******************************/
void device_initialize(struct device *dev)
{
    dev->kobj.kset = devices_kset;                  //可见device和bus都有其起始的kset,而driver没有
    kobject_init(&dev->kobj, &device_ktype);        //初始化这个kobj并建立层次关系以及属性文件,此时
    INIT_LIST_HEAD(&dev->dma_pools);                //是放到了总的device文件目录下面
    mutex_init(&dev->mutex);
    lockdep_set_novalidate_class(&dev->mutex);
    spin_lock_init(&dev->devres_lock);
    INIT_LIST_HEAD(&dev->devres_head);
    device_pm_init(dev);
    set_dev_node(dev, -1);
}
/******************************
* 再来看一下device_add(dev)
******************************/
int device_add(struct device *dev)
{
    struct device *parent = NULL;
    struct class_interface *class_intf;
    int error = -EINVAL;
    dev = get_device(dev);
    if (!dev)
        goto done;
    if (!dev->p) {
        error = device_private_init(dev);                        //初始化dev的私有成员,及其链表操作函数
        if (error)
            goto done;
    }
    /*
     * for statically allocated devices, which should all be converted
     * some day, we need to initialize the name. We prevent reading back
     * the name, and force the use of dev_name()
     */
    if (dev->init_name) {
        dev_set_name(dev, "%s", dev->init_name);                 //设置名字,给kobj
        dev->init_name = NULL;
    }
    if (!dev_name(dev)) {                                         //名字为空出错退出
        error = -EINVAL;
        goto name_error;
    }
    pr_debug("device: '%s': %s/n", dev_name(dev), __func__);
    parent = get_device(dev->parent);                          //返回父节点,如果有返回,没有返回NULL
    setup_parent(dev, parent);                   
    /* use parent numa_node */
    if (parent)
        set_dev_node(dev, dev_to_node(parent));
    /* first, register with generic layer. */
    /* we require the name to be set before, and pass NULL */
    error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);   //初始化kobj与其父节点的连接
    if (error)
        goto Error;
    /* notify platform of device entry */
    if (platform_notify)
        platform_notify(dev);
    error = device_create_file(dev, &uevent_attr);             //产生属性文件
    if (error)
        goto attrError;
    if (MAJOR(dev->devt)) {
        error = device_create_file(dev, &devt_attr);             //在sys下产生dev属性文件
        if (error)
            goto ueventattrError;
        error = device_create_sys_dev_entry(dev);
        if (error)
            goto devtattrError;
        devtmpfs_create_node(dev);                               
    }
    error = device_add_class_symlinks(dev);                    
    if (error)
        goto SymlinkError;
    error = device_add_attrs(dev);                             //增加属性文件
    if (error)
        goto AttrsError;
    error = bus_add_device(dev);                               //把device的bus节点挂到bus的设备节点上
    if (error)
        goto BusError;
    error = dpm_sysfs_add(dev);
    if (error)
        goto DPMError;
    device_pm_add(dev);
    /* Notify clients of device addition.  This call must come
     * after dpm_sysf_add() and before kobject_uevent().
     */
    if (dev->bus)
        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                         BUS_NOTIFY_ADD_DEVICE, dev);
    kobject_uevent(&dev->kobj, KOBJ_ADD);
    bus_probe_device(dev);                                    //匹配driver
    if (parent)
        klist_add_tail(&dev->p->knode_parent,                 //把该设备的节点挂到其父节点的链表
                   &parent->p->klist_children);
    if (dev->class) {
        mutex_lock(&dev->class->p->class_mutex);
        /* tie the class to the device */
        klist_add_tail(&dev->knode_class,
                   &dev->class->p->class_devices);
        /* notify any interfaces that the device is here */
        list_for_each_entry(class_intf,
                    &dev->class->p->class_interfaces, node)
            if (class_intf->add_dev)
                class_intf->add_dev(dev, class_intf);
        mutex_unlock(&dev->class->p->class_mutex);
    }
done:
    put_device(dev);
    return error;
 DPMError:
    bus_remove_device(dev);
 BusError:
    device_remove_attrs(dev);
 AttrsError:
    device_remove_class_symlinks(dev);
 SymlinkError:
    if (MAJOR(dev->devt))
        devtmpfs_delete_node(dev);
    if (MAJOR(dev->devt))
        device_remove_sys_dev_entry(dev);
 devtattrError:
    if (MAJOR(dev->devt))
        device_remove_file(dev, &devt_attr);
 ueventattrError:
    device_remove_file(dev, &uevent_attr);
 attrError:
    kobject_uevent(&dev->kobj, KOBJ_REMOVE);
    kobject_del(&dev->kobj);
 Error:
    cleanup_device_parent(dev);
    if (parent)
        put_device(parent);
name_error:
    kfree(dev->p);
    dev->p = NULL;
    goto done;
}
/***********************************************
* 重点看一下bus_probe_device匹配driver以及初始化过程
***********************************************/
void bus_probe_device(struct device *dev)
{
    struct bus_type *bus = dev->bus;
    int ret;
    if (bus && bus->p->drivers_autoprobe) {         //设置了自动匹配初始化那么就开始匹配
        ret = device_attach(dev);
        WARN_ON(ret < 0);
    }
}
/******************
* 继续device_attach
******************/
int device_attach(struct device *dev)
{
    int ret = 0;
    device_lock(dev);
    if (dev->driver) {                            //默认指定了driver就直接绑定
        ret = device_bind_driver(dev);
        if (ret == 0)
            ret = 1;
        else {
            dev->driver = NULL;
            ret = 0;
        }
    } else {                                      //没有指定就进行遍历匹配
        pm_runtime_get_noresume(dev);
        ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
        pm_runtime_put_sync(dev);
    }
    device_unlock(dev);
    return ret;
}
/**************************
* 再来看device_bind_driver分支
**************************/
int device_bind_driver(struct device *dev)
{
    int ret;
    ret = driver_sysfs_add(dev);
    if (!ret)
        driver_bound(dev);              //主要是完成了将私有成员的driver节点挂到
    return ret;                         //了driver的设备链表
}
/**************************
* 先看bus_for_each_drv分支
**************************/
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
             void *data, int (*fn)(struct device_driver *, void *))
{
    struct klist_iter i;
    struct device_driver *drv;
    int error = 0;
    if (!bus)
        return -EINVAL;
    klist_iter_init_node(&bus->p->klist_drivers, &i,           //和driver遍历device类似,从头开始遍历bus的driver链表
                 start ? &start->p->knode_bus : NULL);         //发现一个driver就调用fn即__device_attach进行匹配
    while ((drv = next_driver(&i)) && !error)
        error = fn(drv, data);
    klist_iter_exit(&i);
    return error;
}
/*********************************
* 最后来看一下__device_attach这个函数
*********************************/
static int __device_attach(struct device_driver *drv, void *data)
{
    struct device *dev = data;
    if (!driver_match_device(drv, dev))    
        return 0;
    return driver_probe_device(drv, dev);
}
/*
  对比driver的注册最后调用的__driver_attach可以发现其实质是一样的,都最后归宿到了
  这driver_match_device,driver_probe_device两个函数,本质参数的和谐做到了通用
  性在这里就不继续分析了,不是很清楚的可以看前一篇文章driver最后一部分的分析  ^_^
*/  

以上便是device的注册,可以发现device和driver围绕着bus最后有种殊途同归的感觉,下面结合driver的流程给出一个框图

以便更明确其间的流程:

 

 

 

 

posted @ 2012-11-12 16:58  zhgt  阅读(597)  评论(0编辑  收藏  举报