免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2232 | 回复: 3
打印 上一主题 下一主题

[硬件及驱动] 设备模型中bus的probe和driver的probe函数有什么区别? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-07 22:41 |只看该作者 |倒序浏览
如题,两者的工作有什么不同?

论坛徽章:
0
2 [报告]
发表于 2012-09-09 15:55 |只看该作者
本帖最后由 hk2305621 于 2012-09-09 15:56 编辑

在 Linux 设备模型中,  bus 和 driver 的关系是, driver 都是服务于某一种 bus 上的某一类型 device的. 我这里看的代码是 Linux 2.6.38 的. 好像从2.6.32都差不多这样.
如果 bus 有定义 prober 函数, 那就直接执行 bus 的probe 函数, 会忽略掉 driver 的probe 函数. 但是, bus 一般不会声明 probe 函数.

当你注册一个 driver 的时候, 会调用
  1. int driver_register(struct device_driver *drv)  // define in <drivers/base/driver.c>
复制代码
driver_register 函数会调用
  1. int bus_add_driver(struct device_driver *drv)  //define in <driver/base/bus.c>
复制代码
bus_add_driver 函数中有如下一段代码

  1. if (drv->bus->p->drivers_autoprobe) {
  2.     error = driver_attach(drv);
  3.     if (error)
  4.         goto out_unregister;
  5. }
复制代码
就是用来调用 probe 函数.

driver_attach(drv) 函数如下:
  1. int driver_attach(struct device_driver *drv)
  2. {
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
  4. }
复制代码
其中 __driver_attach 是一个函数. 如下. 这个函数会调用 driver_probe_device 去调用 bus 或者 driver 的 probe 函数.
  1. static int __driver_attach(struct device *dev, void *data)
  2. {
  3.         struct device_driver *drv = data;

  4.         /*
  5.          * Lock device and try to bind to it. We drop the error
  6.          * here and always return 0, because we need to keep trying
  7.          * to bind to devices and some drivers will return an error
  8.          * simply if it didn't support the device.
  9.          *
  10.          * driver_probe_device() will spit a warning if there
  11.          * is an error.
  12.          */

  13.         if (!driver_match_device(drv, dev))
  14.                 return 0;

  15.         if (dev->parent)        /* Needed for USB */
  16.                 device_lock(dev->parent);
  17.         device_lock(dev);
  18.         if (!dev->driver)
  19.                 driver_probe_device(drv, dev);
  20.         device_unlock(dev);
  21.         if (dev->parent)
  22.                 device_unlock(dev->parent);

  23.         return 0;
  24. }
复制代码
driver_probe_device 函数定义如下: 它会调用函数 really_probe 函数.
  1. int driver_probe_device(struct device_driver *drv, struct device *dev)
  2. {
  3.         int ret = 0;

  4.         if (!device_is_registered(dev))
  5.                 return -ENODEV;

  6.         pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
  7.                  drv->bus->name, __func__, dev_name(dev), drv->name);

  8.         pm_runtime_get_noresume(dev);
  9.         pm_runtime_barrier(dev);
  10.         ret = really_probe(dev, drv);
  11.         pm_runtime_put_sync(dev);

  12.         return ret;
  13. }
复制代码
really_probe 函数如下:
  1. static int really_probe(struct device *dev, struct device_driver *drv)
  2. {
  3.         int ret = 0;

  4.         atomic_inc(&probe_count);
  5.         pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
  6.                  drv->bus->name, __func__, drv->name, dev_name(dev));
  7.         WARN_ON(!list_empty(&dev->devres_head));

  8.         dev->driver = drv;
  9.         if (driver_sysfs_add(dev)) {
  10.                 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
  11.                         __func__, dev_name(dev));
  12.                 goto probe_failed;
  13.         }

  14.         if (dev->bus->probe) {
  15.                 ret = dev->bus->probe(dev);
  16.                 if (ret)
  17.                         goto probe_failed;
  18.         } else if (drv->probe) {
  19.                 ret = drv->probe(dev);
  20.                 if (ret)
  21.                         goto probe_failed;
  22.         }

  23.         driver_bound(dev);
  24.         ret = 1;
  25.         pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
  26.                  drv->bus->name, __func__, dev_name(dev), drv->name);
  27.         goto done;

  28. probe_failed:
  29.         devres_release_all(dev);
  30.         driver_sysfs_remove(dev);
  31.         dev->driver = NULL;

  32.         if (ret != -ENODEV && ret != -ENXIO) {
  33.                 /* driver matched but the probe failed */
  34.                 printk(KERN_WARNING
  35.                        "%s: probe of %s failed with error %d\n",
  36.                        drv->name, dev_name(dev), ret);
  37.         }
  38.         /*
  39.          * Ignore errors returned by ->probe so that the next driver can try
  40.          * its luck.
  41.          */
  42.         ret = 0;
  43. done:
  44.         atomic_dec(&probe_count);
  45.         wake_up(&probe_waitqueue);
  46.         return ret;
  47. }
复制代码
really_probe 函数有一段代码:如下, 就是,
1. 判断 bus 有没有声明 probe 函数, 如果有, 就调用 bus 的 probe 函数.
2. 如果 bus 没有定义 probe 函数, 就检查 driver 有没有定义 probe 函数, 如果有, 就调用 driver 的 probe 函数.
3. 如果 bus 和 driver 都没有定义 probe 函数, 就不执行. 继续往下.
  1.         if (dev->bus->probe) {
  2.                 ret = dev->bus->probe(dev);
  3.                 if (ret)
  4.                         goto probe_failed;
  5.         } else if (drv->probe) {
  6.                 ret = drv->probe(dev);
  7.                 if (ret)
  8.                         goto probe_failed;
  9.         }
复制代码

论坛徽章:
0
3 [报告]
发表于 2012-10-13 20:49 |只看该作者
回复 2# hk2305621

明白了,非常感谢!
   
        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;
        }

论坛徽章:
0
4 [报告]
发表于 2012-10-13 22:35 |只看该作者
回复 3# 厚发至仁


    有空可以看看内核代码.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP