Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3170393
  • 博文数量: 685
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5303
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-19 14:17
个人简介

文章分类

全部博文(685)

文章存档

2015年(116)

2014年(569)

分类: LINUX

2014-10-27 12:47:51

原文地址:http://blog.csdn.net/wang_zheng_kai/article/details/19037491

四、Register到MTD子系统

两种注册方式:(我们需要完成的)

1)直接注册整个flash设备(MTD Device)到MTD。

ret = add_mtd_device(mtd);

2)分partion添加到mtd_table,并将每个partion当成

  一个mtd设备注册到MTD。

ret = add_mtd_partitions(mtd, parts,num_part);

其中:

         add_mtd_partitions()->add_one_partition()

         slave->mtd.xxx= master->mtd.xxx;

         add_mtd_device(&slave->mtd);

         从master中获得type,read,write等参数。

         并将slave作为一个mtd设备添加到mtd_table。

         最后注册设备及创建dev下面的设备节点。

五、NAND FLASH驱动层

         Linux内核在MTD的下层实现了通用的NAND驱动( 主要通过drivers/mtd/nand/nand_base.c文件实现),因此芯片级的NAND 驱动不再需要实现mtd_info中的read()、write()、read_oob()、write_oob()等成员函数,而主体转移到了nand_chip数据结构。

         MTD使用nand_chip数据结构表示一个NANDFlash芯片,这个结构体中包含了关于NAND Flash的地址信息、读写方法、ECC模式、硬件控制等一些底层机制。

 

驱动实现层:jz4780_nand.c

1)通过platform注册。(加载驱动)

         platform_driver_register(&jz4780_nand_driver);

2)探测函数jz4780_nand_probe(重要,驱动实现的第一步)

         在probe函数中申请资源、硬件初始化、实现nand_chip结构体中的函数指针以及与NAND芯片进行交互,添加mtd设备到MTD。

3)实现一些nand_base.c没有实现的以及其他的一些操作一些操作如:read_buf()等。

4) remove函数

         当任意一方卸载时,会释放资源,当该驱动函数或者驱动函数正在操作的设备被移除时,内核会调用驱动函数中的remove函数调用,进行一些设备卸载相应的操作

5)注销jz4780_nand驱动(卸载驱动)

         platform_driver_unregister(&jz4780_nand_driver);

 驱动的加载程序流程如下图:

其驱动加载的代码分析如下图所示:


  1. NAND驱动的代码分析(一)  
  2. ----------驱动的加载  
  3. Joe  
  4.   
  5. device_driver和platform driver  
  6.  Platform device是一种device自己是不会做事情的,要有人为它做事情,那就是platform driver。platform driver遵循linux系统的driver model。对于device的discovery/enumerate都不是driver自己完成的而是由由系统的driver注册机制完成。 driver编写人员只要将注册必须的数据结构初始化并调用注册driver的kernel API就可以了。             
  7. 接下来来看platform_driver结构体的原型定义,代码如下:   
  8. struct platform_driver {      
  9.         int (*probe)(struct platform_device *);     
  10.         int (*remove)(struct platform_device *);      
  11.         void (*shutdown)(struct platform_device *);      
  12.         int (*suspend)(struct platform_device *, pm_message_t state);     
  13.         int (*suspend_late)(struct platform_device *, pm_message_t state);     
  14.         int (*resume_early)(struct platform_device *);     
  15.         int (*resume)(struct platform_device *);     
  16.         struct device_driver driver;     
  17. };              
  18. 可见,它包含了设备操作的几个功能函数,同时包含了一个device_driver结构,说明device_driver是 platform_driver的基类。驱动程序中需要初始化这个变量。下面看一下这个变量的定义  
  19. 121struct device_driver {     
  20. 122        const char              *name;    
  21. 123        struct bus_type         *bus;    
  22. 124     
  23. 125        struct module           *owner;     
  24. 126        const char              *mod_name;      /* used for built-in modules */    
  25. 127    
  26. 128        int (*probe) (struct device *dev);   
  27. 129        int (*remove) (struct device *dev);    
  28. 130        void (*shutdown) (struct device *dev);     
  29. 131        int (*suspend) (struct device *dev, pm_message_t state);    
  30. 132        int (*resume) (struct device *dev);    
  31. 133        struct attribute_group **groups;    
  32. 134     
  33. 135        struct driver_private *p;     
  34. 136};     
  35. device_driver提供了一些操作接口,但其并没有实现,相当于一些虚函数,由派生类platform_driver进行重载,无论何种类型的 driver都是基于device_driver派生而来的,具体的各种操作都是基于统一的基类接口的,这样就实现了面向对象的设计。    需要注意这两个变量:name和owner。其作用主要是为了和相关的platform_device关联起来,owner的作用是说明模块的所有者,驱动程序中一般初始化为THIS_MODULE。   device_driver结构中也有一个name变量。platform_driver从字面上来看就知道是设备驱动。设备驱动是为谁服务的呢?当然是设备了。内核正是通过这个一致性来为驱动程序找到资源,即 platform_device中的resource。  
  36.   
  37. 《一》 jz4780_nand_init  
  38. static int __init jz4780_nand_init(void)  
  39. {         
  40. //创建DebugFS,是一种用于内核调试的虚拟文件系统,内核开发者通过debugfs和用户空间交换数据。  
  41. #ifdef CONFIG_DEBUG_FS  
  42.         debugfs_root = debugfs_create_dir(DRVNAME, NULL);  
  43.         if (IS_ERR(debugfs_root))  
  44.                 return PTR_ERR(debugfs_root);  
  45. #endif            
  46.         return platform_driver_register(&jz4780_nand_driver);  
  47.   
  48. }  
  49.   
  50. 《二》platform_driver_registe  
  51. int platform_driver_register(struct platform_driver *drv)  
  52. {   
  53.  /*设置成platform_bus_type(当前驱动所在的总线,平台设备和平台驱动处在同一条总线上 )这个很重要,因为driver和device是通过bus联系在一起的,具体在本例中是通过platform_bus_type中注册的回调例程和属性来是实现的, driver与device的匹配就是通过 platform_bus_type注册的回调例程platform_match ()来完成的。*/  
  54. 表明该 dev 是 platform_bus_type 类型的,并且该 dev  
  55. 也会被添加到 platform_bus_type 的 devices_kset 容器中和 klist_devices 列表中。  
  56.   
  57.         drv->driver.bus = &platform_bus_type;   
  58.   
  59. //在really_probe函数中,回调了platform_drv_probe函数  
  60. 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。  
  61.         if (drv->probe)   
  62.                 drv->driver.probe = platform_drv_probe;  
  63.   
  64.         if (drv->remove)  
  65.                drv->driver.remove = platform_drv_remove;  
  66.   
  67.         if (drv->shutdown)  
  68.                drv->driver.shutdown = platform_drv_shutdown;  
  69.   
  70.   
  71. //把驱动注册到总线上  
  72.         return driver_register(&drv->driver);  
  73.   
  74. }   
  75. 代码中:  
  76. 1. 设置成 platform_bus_type 这个很重要,因为 driver 和 device 是通过 bus 联系在一起的,具体在本例中是通过 platform_bus_type 中注册的回调例程和属性来是实现的, driver 与 device 的匹配就是通过 platform_bus_type 注册的回到例程mach()来完成的。下面就分析 driver_register()。  
  77. 《三》 driver_register  
  78. 不要被上面的platform_drv_XXX吓倒了,它们其实很简单,就是将struct device转换为struct  platform_device和struct platform_driver,然后调用platform_driver中的相应接口函数。那为什么不直接调用platform_drv_XXX等接口呢?这就是Linux内核中面向对象的设计思想。device_driver提供了一些操作接口,但其并没有实现,相当于一些虚函数,由派生类platform_driver进行重载,无论何种类型的 driver都是基于device_driver派生而来的,device_driver中具体的各种操作都是基于统一的基类接口的,这样就实现了面向对象的设计。  
  79. 在此函数中,初始化结构体struct device_driver中的klist_device和unloaded字段,通过klist_device字段, 可以保存此驱动支持的设备链表,通过“完成”接口机制,完成线程间的同步。  
  80. int driver_register(struct device_driver *drv)  
  81. {  
  82.         int ret;  
  83.         struct device_driver *other;  
  84.   
  85.         BUG_ON(!drv->bus->p);  
  86.   
  87. // 如果总线的方法和设备自己的方法同时存在,将打印告警信息,对于platform bus,其没有probe等接口  
  88.         if ((drv->bus->probe && drv->probe) ||  
  89.             (drv->bus->remove && drv->remove) ||  
  90.             (drv->bus->shutdown && drv->shutdown))  
  91.   
  92.              printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  93.                       "bus_type methods\n", drv->name);  
  94. /*通过驱动的名字查找 driver,如果找到了,说明已经注册过,返回错误代码,后面会 
  95. 分析*/   
  96.         other = driver_find(drv->name, drv->bus);  
  97.         if (other) {  
  98.                 put_driver(other);  
  99.                 printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  100.                         "aborting...\n", drv->name);  
  101.                 return -EBUSY;  
  102.         }  
  103.   
  104.   /* 将 driver 加入到 bus 的 kset,并生成些文件夹和链接文件,将程序挂在到总线上,通过总线来驱动程序 
  105.  
  106.         ret = bus_add_driver(drv); //将本driver驱动注册登记到drv->bus所在的总线上。 
  107.         if (ret) 
  108.                 return ret; 
  109.  
  110. /* 添加 attribute_group,本例中没有设置 drv->groups */  
  111.   
  112.         ret = driver_add_groups(drv, drv->groups);  
  113.   
  114.         if (ret)  
  115.                 bus_remove_driver(drv);  
  116.         return ret;  
  117. }     
  118. 代码中,  
  119. 1.正如该例程的英文注释所言,大部分工作在 bus_add_driver()例程中完成。  
  120. 2. driver_find()例程通过驱动所属 bus 的 driver 容器 drivers_kset 来查找  
  121.   
  122. struct device_driver *driver_find(const charchar *name, struct bus_type *bus)  
  123. {  
  124.  // 在 drivers_kset 容器中查找  
  125.         struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);  
  126.         struct driver_private *priv;  
  127.   
  128.         if (k) {  
  129.                 priv = to_driver(k);  
  130.                 return priv->driver;  
  131. //返回找到的driver  
  132.         }  
  133.         return NULL;  
  134. }  
  135.   
  136. 代码中,  
  137. 通过 kset_find_obj(bus->p->drivers_kset, name)查找该 driver 的 kobj,其代码如下,  
  138.   
  139. struct kobject *kset_find_obj_hinted(struct kset *kset, const charchar *name,struct kobject *hint)  
  140. {  
  141.         struct kobject *k;  
  142.         struct kobject *ret = NULL;  
  143.   
  144.         
  145. //锁定自旋锁  
  146.         spin_lock(&kset->list_lock);  
  147.   
  148.         if (!hint)  
  149.                 goto slow_search;  
  150.   
  151.         /* end of list detection */  
  152.   
  153.         if (hint->entry.next == kset->list.next)  
  154.                 goto slow_search;  
  155.   
  156.         k = container_of(hint->entry.nextstruct kobject, entry);  
  157.   
  158.         if (!kobject_name(k) || strcmp(kobject_name(k), name))  
  159.                 goto slow_search;  
  160.   
  161.         ret = kobject_get(k);  
  162.   
  163.         goto unlock_exit;  
  164.   
  165. slow_search:  
  166.   
  167.         list_for_each_entry(k, &kset->list, entry) {// 遍历 kset->list 列表获取 kobj  
  168.                 if (kobject_name(k) && !strcmp(kobject_name(k), name)) { // 比较 name 字符  
  169.                         ret = kobject_get(k); // 如果找到就增加引用并返回  
  170.                         break;  
  171.                 }  
  172.         }  
  173.   
  174. //释放自旋锁  
  175. unlock_exit:  
  176.         spin_unlock(&kset->list_lock);  
  177.   
  178.         if (hint)     //这里hint为NULL  
  179.                 kobject_put(hint);  
  180.   
  181.         return ret;  
  182.   
  183. }  
  184. 《四》bus_add_driver(struct device_driver *drv)  
  185. 显然,所有同类型的 driver 都注册到了 一个 bus->p->drivers_kset->list 中,所以可通过其查找已经注册的 driver。下面分析 bus_add_driver()例程,该代码主要用来将驱动设备注册到bus总线中。  
  186.   
  187. int bus_add_driver(struct device_driver *drv) //将本driver驱动注册登记到drv->bus所在的总线上。   
  188. {         
  189.         struct bus_type *bus;  
  190.         struct driver_private *priv;  
  191.         int error = 0;        
  192.   
  193.         bus = bus_get(drv->bus);//获取总线内容,即前面定义的    
  194.   
  195.         if (!bus)  
  196.                 return -EINVAL;  
  197.   
  198.         pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);  
  199.   
  200.         priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  201. //为驱动私有成员申请内存且清0, 这个结构体中存放着 kobj 相关的数据,主要存放的是私有的数据。  
  202.   
  203.         if (!priv) {  
  204.                 error = -ENOMEM;  
  205.                 goto out_put_bus;  
  206.         }  
  207.   
  208.         klist_init(&priv->klist_devices, NULLNULL);//初始化驱动所支持的设备链表  
  209.   
  210.         priv->driver = drv;         // 将匹配的 driver 指针关联到 dev,以便后续使用  
  211.   
  212.         drv->p = priv;                // 将 priv 保存到 device_driver,  
  213. /* 指向 bus 的 drivers_kset 容器,该容器的作用与 device_kset 容器相同,前者是包含所有注册到该 bus 的 driver,后者是包含所有注册到该 bus 的 device。*/  
  214.   
  215.         priv->kobj.kset = bus->p->drivers_kset;  
  216.   
  217. /*初始化 priv->kobj,并将其添加到 bus->p->drivers_kset 中,在本例中生成/sys/bus/platform/drivers/jz4780_nand 目录,后面会分析 drivers_kset 的初始化及/sys/bus/platform/drivers/目录的生成 */  
  218.   
  219.         error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,"%s", drv->name);  
  220. //初始化并添加驱动kobject对象到总线驱动中  
  221.         if (error)  
  222.                 goto out_unregister;    
  223.   
  224.         if (drv->bus->p->drivers_autoprobe) {// 在 bus_register()例程中已经设置为 1 了  
  225.                 error = driver_attach(drv); // 所以会寻找匹配的 device,后面分析  
  226.   
  227.                 if (error)  
  228.                         goto out_unregister;  
  229.         }  
  230.   
  231. // 将 driver 链接到 klist_drivers,方便后续快速查找 driver//将驱动节点加入到总线链表中  
  232.         klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  233.   
  234. // 将 driver 添加到 module 模块,后面会分析  
  235.         module_add_driver(drv->owner, drv);  
  236.   
  237. /* 生成/sys//sys/bus/platform/drivers/属性文件,其作用与 device 中的 
  238. uevent 类似*/  
  239.         error = driver_create_file(drv, &driver_attr_uevent);  
  240.         if (error) {  
  241.                 printk(KERN_ERR "%s: uevent attr (%s) failed\n",__func__, drv->name);  
  242.         }  
  243.   
  244. /* 添加 bus 的公有属性文件到/sys//sys/bus/platform/drivers/目录,所有的 driver 
  245. 都添加 */  
  246.         error = driver_add_attrs(bus, drv);  
  247.         if (error) {  
  248.                 /* How the hell do we get out of this pickle? Give up */  
  249.                 printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",__func__, drv->name);  
  250.         }  
  251.     if (!drv->suppress_bind_attrs) {  
  252. /* 如果配置了”CONFIG_HOTPLUG",则生成“bind”和"unbind”属性文件,可用于手动匹 
  253. 配和移除 device 与 driver 之间的关联 */  
  254.                 error = add_bind_files(drv);  
  255.                 if (error) {  
  256.                         /* Ditto */  
  257.                         printk(KERN_ERR "%s: add_bind_files(%s) failed\n",__func__, drv->name);  
  258.                 }  
  259.         }  
  260.   
  261. // 通过 uevent 设置几个环境变量并通知用户空间,以便调用程序来完成相关设置  
  262.         kobject_uevent(&priv->kobj, KOBJ_ADD);  
  263.         return 0;  
  264.   
  265. out_unregister:  
  266.         kobject_put(&priv->kobj);  
  267.         kfree(drv->p);  
  268.         drv->p = NULL;  
  269. out_put_bus:  
  270.         bus_put(bus);  
  271.   
  272.         return error;  
  273. }  
  274. 代码中,  
  275. struct driver_private 来存放 kobj 相关的数据,将 struct driver_private 嵌入在 struct  
  276. device_driver 中。struct driver_private 定义如下:  
  277. struct driver_private {  
  278.         struct kobject kobj;  
  279. //代表该bus,里面的kobj是该bus的主kobj,也就是最顶层  
  280.         struct klist klist_devices;  
  281. //其作用与devices_kset->list作用相同  
  282.         struct klist_node knode_bus;  
  283.   
  284.         struct module_kobject *mkobj;  
  285.   
  286.         struct device_driver *driver;  
  287.   
  288. };  
  289. 《五》driver_attach(struct device_driver *drv)  
  290. //如果总线上的driver是自动probe的话,则将该总线上的driver和device绑定起来。  
  291. /** 
  292.  * driver_attach - try to bind driver to devices. 
  293.  * @drv: driver. 
  294.  * Walk the list of devices that the bus has on it and try to 
  295.  * match the driver with each one.  If driver_probe_device() 
  296.  * returns 0 and the @dev->driver is set, we've found a 
  297.  * compatible pair. 
  298.  */  
  299. int driver_attach(struct device_driver *drv)  
  300. {  
  301. /* 遍历 bus 的 klist_devices 列表,对每个 device 使用回调函数__driver_attach()来鉴别是否 
  302. 和 driver 匹配 */  
  303.         return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  304. }  
  305.   
  306. EXPORT_SYMBOL_GPL(driver_attach);  
  307.   
  308. int bus_for_each_dev(struct bus_type *bus, struct device *start,  
  309.   
  310.                      voidvoid *data, int (*fn)(struct device *, voidvoid *))  
  311.   
  312. {         
  313.   
  314.         struct klist_iter i;  
  315.   
  316.         struct device *dev;  
  317.   
  318.         int error = 0;  
  319.   
  320.   
  321.   
  322.         if (!bus)  
  323.   
  324.                 return -EINVAL;  
  325.   
  326.   
  327. //设置i  
  328.         klist_iter_init_node(&bus->p->klist_devices, &i,  
  329.   
  330.                              (start ? &start->p->knode_bus : NULL));  
  331.   
  332. //使用i进行遍历  
  333.         while ((dev = next_device(&i)) && !error)  
  334.   
  335.                 error = fn(dev, data);//   
  336. 使用回调例程,处理  
  337.         klist_iter_exit(&i);  
  338.   
  339.         return error;  
  340.   
  341. }         
  342. EXPORT_SYMBOL_GPL(bus_for_each_dev);  
  343. //扫描该总线上的每一个设备,将当前driver和总线上的设备进行match,如果匹配成功,则将设备和driver绑定起来。  
  344. 回调例程__driver_attach()  
  345. 函数__driver_attach()在调用driver_probe_device()函数前,需要进行线程间的互斥处理。《六》__driver_attach(struct device *dev, voidvoid *data)  
  346. static int __driver_attach(struct device *dev, voidvoid *data)  
  347. {  
  348.         struct device_driver *drv = data;  
  349.         /* 
  350.          * Lock device and try to bind to it. We drop the error 
  351.          * here and always return 0, because we need to keep trying 
  352.          * to bind to devices and some drivers will return an error 
  353.          * simply if it didn't support the device. 
  354.          * driver_probe_device() will spit a warning if there 
  355.          * is an error. 
  356.          */  
  357. /* 调用 bus 的 match (),在这里是 platform_bus_type 的 mach(),即 platform_match()例 
  358. 程 */  
  359.         if (!driver_match_device(drv, dev))  
  360.                return 0;  
  361.         if (dev->parent)        /* Needed for USB */  
  362.                 device_lock(dev->parent);  
  363.         device_lock(dev);  
  364.   
  365. //如果该设备尚没有匹配的driver,则尝试匹配。  
  366.         if (!dev->driver)  
  367.   
  368.                 driver_probe_device(drv, dev);  
  369. // 这里开始 probe  
  370.   
  371.         device_unlock(dev);  
  372.   
  373.         if (dev->parent)  
  374.   
  375.                 device_unlock(dev->parent);  
  376.   
  377.         return 0;  
  378.   
  379. }  
  380.   
  381. 《七》driver_probe_device(struct device_driver *drv, struct device *dev)  
  382. 在driver_probe_device()函数中,调用了match函数platform_match(),如果它返回0,    
  383. 表示驱动与设备不一致,函数返回;否则,调用really_probe()函数。    
  384. /** * driver_probe_device - attempt to bind device & driver together    
  385. * @drv: driver to bind a device to * @dev: device to try to bind to the driver * * First,  
  386. /** 
  387.  * driver_probe_device - attempt to bind device & driver together 
  388.  * @drv: driver to bind a device to 
  389.  * @dev: device to try to bind to the driver 
  390.  * This function returns -ENODEV if the device is not registered, 
  391.  * 1 if the device is bound successfully and 0 otherwise. 
  392.  * This function must be called with @dev lock held.  When called for a 
  393.  * USB interface, @dev->parent lock must be held as well. 
  394.  */  
  395. int driver_probe_device(struct device_driver *drv, struct device *dev)  
  396. {  
  397.         int ret = 0;  
  398.   
  399.         if (!device_is_registered(dev))  
  400.   //判断dev是否已经注册  
  401.                 return -ENODEV;  
  402.   
  403.         pr_debug("bus: '%s': %s: matched device %s with driver %s\n",  
  404.  drv->bus->name, __func__, dev_name(dev), drv->name);  
  405.   
  406.         pm_runtime_get_noresume(dev);  
  407.         pm_runtime_barrier(dev);  
  408.         ret = really_probe(dev, drv);  
  409.         pm_runtime_put_sync(dev);  
  410.   
  411.         return ret;  
  412.   
  413. }  
  414. 《八》really_probe(struct device *dev, struct device_driver *drv)  
  415. //在此函数中,回调了我们在jz4780.c文件中实现的探测函数jz4780_nand_probe(),至此,平台驱动的注册过程结束。    
  416. static int really_probe(struct device *dev, struct device_driver *drv)  
  417. {  
  418.         int ret = 0;  
  419.         atomic_inc(&probe_count);  
  420.  //原子锁上锁  
  421.       pr_debug("bus: '%s': %s: probing driver %s with device %s\n",  
  422. drv->bus->name, __func__, drv->name, dev_name(dev));  
  423.         WARN_ON(!list_empty(&dev->devres_head));  
  424.         dev->driver = drv;        
  425. // 将匹配的 driver 指针关联到 dev,以便后续使用  
  426.         if (driver_sysfs_add(dev)) {  
  427.                 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",  
  428.  __func__, dev_name(dev));  
  429.                 goto probe_failed;  
  430.         }  
  431.   
  432. // 如果设置了 dev->bus->probe,则调用,在 platform_bus_type 没有设置  
  433.   
  434.         if (dev->bus->probe) {  
  435.                 ret = dev->bus->probe(dev);  
  436.                 if (ret)  
  437.                         goto probe_failed;  
  438.   
  439.         } else if (drv->probe) {  
  440.                 ret = drv->probe(dev);  
  441.                 if (ret)  
  442.                         goto probe_failed;  
  443.         }  
  444. // 将 device 添加到 driver 列表中,并通知 bus 上的设备,表明 BOUND_DRIVER。  
  445. //设备与驱动绑定后,对系统中已注册的组件进行事件通知。  
  446.         driver_bound(dev);  
  447.   
  448.         ret = 1;  
  449.         pr_debug("bus: '%s': %s: bound device %s to driver %s\n",  
  450.                  drv->bus->name, __func__, dev_name(dev), drv->name);  
  451.         goto done;  
  452.   
  453. probe_failed:  
  454.         devres_release_all(dev);  
  455.         driver_sysfs_remove(dev);  
  456.         dev->driver = NULL;  
  457.   
  458.         if (ret != -ENODEV && ret != -ENXIO) {  
  459.   
  460.                 /* driver matched but the probe failed */  
  461.   
  462.                 printk(KERN_WARNING  
  463.                       "%s: probe of %s failed with error %d\n",  
  464.                        drv->name, dev_name(dev), ret);  
  465.         }  
  466.         /* 
  467.          * Ignore errors returned by ->probe so that the next driver can try 
  468.          * its luck. 
  469.          */  
  470.         ret = 0;  
  471. done:  
  472.         atomic_dec(&probe_count);  
  473.         wake_up(&probe_waitqueue);  
  474.         return ret;  
  475. }  


阅读(845) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~