platform device probe 顺序

遇到一个跟init顺序相关的问题,code结构大概如下,目的是用initcall的顺序来控制flag_a的相关的flow

  test_a_init
  {
  if(flag_a)
......
paltform_driver_register(&a_driver);
}
arch_initcall(test_a_init);b_probe{set_flag_a=1;}
b_driver={
.probe = b_probe;
.driver = {
    .of_match_table = b_match;
    .name = "b_driver";
}
};

test_b_init
{
 paltform_driver_register(&b_driver);
}
core_initcall(test_b_init);
1、initcall的顺序的定义在init.h中,init/main.c 中会根据level一级一级的调用init函数
所以init函数的顺序  A < B
static void __init do_initcalls(void)
{int level;for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)do_initcall_level(level);}

#define pure_initcall(fn)		__define_initcall(fn, 0)
#define core_initcall(fn)		__define_initcall(fn, 1)
#define core_initcall_sync(fn)		__define_initcall(fn, 1s)
#define postcore_initcall(fn)		__define_initcall(fn, 2)
#define postcore_initcall_sync(fn)	__define_initcall(fn, 2s)
#define arch_initcall(fn)		__define_initcall(fn, 3)
#define arch_initcall_sync(fn)		__define_initcall(fn, 3s)
#define subsys_initcall(fn)		__define_initcall(fn, 4)
#define subsys_initcall_sync(fn)	__define_initcall(fn, 4s)
#define fs_initcall(fn)			__define_initcall(fn, 5)
#define fs_initcall_sync(fn)		__define_initcall(fn, 5s)
#define rootfs_initcall(fn)		__define_initcall(fn, rootfs)
#define device_initcall(fn)		__define_initcall(fn, 6)
#define device_initcall_sync(fn)	__define_initcall(fn, 6s)
#define late_initcall(fn)		__define_initcall(fn, 7)
#define late_initcall_sync(fn)		__define_initcall(fn, 7s)

2、在调用的B的init函数的时候platform_driver_register函数的call tree如下

paltform_driver_register(drv)
->__platform_driver_register(drv, THIS_MODULE)
-->drv->driver.bus = &platform_bus_type;
drv->driver.probe = platform_drv_probe;
driver_register(&drv->driver);
  --->bus_add_driver(drv->driver); ---->driver_attach(drv->driver); ----->int driver_attach(struct device_driver *drv) bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);       //找不到device会直接return,到底platform的device在这时候有没有添加到platform bus呢? ------>__driver_attach(dev,drv) driver_match_device(drv, dev);         if (!dev->driver)         driver_probe_device(drv, dev); -------> really_probe(dev, drv);
         if (dev->bus->probe) //会优先调用platform的probe          dev->bus->probe(dev);
else if (drv->probe)
drv->probe(dev);          
         driver_bound(dev);
3、platform 的populate的过程会把platform bus的所有设备添加到platform device list里
精简代码如下
->arch_initcall_sync(of_platform_default_populate_init);

-->node = of_find_node_by_path("/reserved-memory");
   if (node) node = of_find_compatible_node(node, NULL, "ramoops");
   /* Populate everything else. */
   of_platform_default_populate(NULL, NULL, NULL);

--->of_platform_populate(NULL, of_default_bus_match_table, NULL,NULL);

---->for_each_child_of_node(root, child)
     of_platform_bus_create(child, NULL, NULL, NULL, true);

----->of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
      for_each_child_of_node(bus, child)
      of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
      //递归的创建platform bus下的所有device
      //可见platform  device的probe 的顺序与dts中中节点的顺序是对应的

------>of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
       of_device_alloc(np, bus_id, parent);
       dev->dev.bus = &platform_bus_type;
       dev->dev.platform_data = platform_data;
       of_dma_configure(&dev->dev, dev->dev.of_node);
       of_device_add(dev);

------->device_add(&ofdev->dev);

-------->bus_add_device(dev);
 /* - Add device's bus attributes.
 * - Create links to device's bus.
 * - Add the device to its bus's list of devices*/
总结:platform device的init的时候并不一定就会调用probe函数
     arch_inicall_sync < arch_initcall < core_initcall 

猜你喜欢

转载自blog.csdn.net/shenhuxi_yu/article/details/80850238