linux 驱动加载过程

比较 compatibal 字符串的地方在这里, 通常我们增加一个自己的驱动,只要 dts 中的 compatible 字符串和 驱动中的 compatible 字符串相等,就会调用 驱动的 probe 函数。

一直想找到在哪里比较的,通过 dump_stack() , 可以跟踪到代码实现在这里

dts 中:

misc_cm {
        compatible = "misc-functions";
        status = "okay";

};

驱动代码中:

static const struct of_device_id cm_functions_match[] = {
        { .compatible = "misc-functions" },
        { /* Sentinel */ }
};

 

最终在这个函数真正比较这两个 字符串

static int __of_device_is_compatible(const struct device_node *device,  const char *compat, const char *type, const char *name);

const struct of_device_id *of_match_device(const struct of_device_id *matches,  const struct device *dev)
{
        if ((!matches) || (!dev->of_node))
    return NULL;
  return of_match_node(matches, dev->of_node);
}

static inline int of_driver_match_device(struct device *dev, const struct device_driver *drv)
{
  return of_match_device(drv->of_match_table, dev) != NULL;
}

static int platform_match(struct device *dev, struct device_driver *drv)
{
  struct platform_device *pdev = to_platform_device(dev);
  struct platform_driver *pdrv = to_platform_driver(drv);

  /* When driver_override is set, only bind to the matching driver */
  if (pdev->driver_override)
    return !strcmp(pdev->driver_override, drv->name);

  /* Attempt an OF style match first */

    // 如果定义了 CONFIG_OF 宏

   if (of_driver_match_device(dev, drv)) {

          return 1;
     }

/* Then try ACPI style match */
if (acpi_driver_match_device(dev, drv))
return 1;

/* Then try to match against the id table */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;

/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);
}

struct bus_type platform_bus_type = {
.name = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};

static inline int driver_match_device(struct device_driver *drv,  struct device *dev)
{
        return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}

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

// 检查 compatible 字符串
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_probe_device(drv, dev);  // 会调用 驱动的 probe 函数
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);

return 0;
}

 

[ 1.373872] Call trace:
[ 1.373893] [<ffffff8008089c10>] dump_backtrace+0x0/0x1f4
[ 1.373905] [<ffffff8008089e18>] show_stack+0x14/0x1c
[ 1.373918] [<ffffff80083add98>] dump_stack+0x94/0xbc
[ 1.373929] [<ffffff800853b878>] cm_functions_probe+0x88/0x244
[ 1.373941] [<ffffff80085127e4>] platform_drv_probe+0x54/0xa8
[ 1.373950] [<ffffff8008510ac4>] driver_probe_device+0x188/0x26c
[ 1.373959] [<ffffff8008510c6c>] __driver_attach+0xc4/0xe0
[ 1.373970] [<ffffff800850ef30>] bus_for_each_dev+0x9c/0xbc
[ 1.373990] [<ffffff8008510594>] driver_attach+0x20/0x28
[ 1.373999] [<ffffff80085101b4>] bus_add_driver+0x198/0x1dc
[ 1.374008] [<ffffff80085117e0>] driver_register+0x98/0xd0
[ 1.374017] [<ffffff800851273c>] __platform_driver_register+0x48/0x50
[ 1.374028] [<ffffff800912e6f4>] cm_functions_driver_init+0x18/0x20
[ 1.374038] [<ffffff8008083468>] do_one_initcall+0x84/0x1a4
[ 1.374049] [<ffffff8009100e94>] kernel_init_freeable+0x220/0x224
[ 1.374061] [<ffffff8008b784d4>] kernel_init+0x10/0xf8
[ 1.374070] [<ffffff80080832a0>] ret_from_fork+0x10/0x30

posted @ 2020-05-09 18:52  mojl  阅读(1070)  评论(0编辑  收藏  举报