zoukankan      html  css  js  c++  java
  • platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备【转】

    kernel_init中do_basic_setup()->driver_init()->platform_bus_init()->...初始化platform bus(虚拟总线)
    设备向内核注册的时候platform_device_register()->platform_device_add()->...内核把设备挂在虚拟的platform bus下
    驱动注册的时候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev()
    对每个挂在虚拟的platform bus的设备作__driver_attach()->driver_probe_device()->drv->bus->match()==platform_match()->比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),
    如果相符就调用platform_drv_probe()->driver->probe(),如果probe成功则绑定该设备到该驱动.
    kernel/init/main.c 
     
    static int __init kernel_init(void * unused)
    {
    /*
     * Wait until kthreadd is all set-up.
     */
    wait_for_completion(&kthreadd_done);
    /*
     * init can allocate pages on any node
     */
    set_mems_allowed(node_states[N_HIGH_MEMORY]);
    /*
     * init can run on any cpu.
     */
    set_cpus_allowed_ptr(current, cpu_all_mask);
     
    cad_pid = task_pid(current);
     
    smp_prepare_cpus(setup_max_cpus);
     
    do_pre_smp_initcalls();
    lockup_detector_init();
     
    smp_init();
    sched_init_smp();
     
    do_basic_setup();
     
    /* Open the /dev/console on the rootfs, this should never fail */
    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
    printk(KERN_WARNING "Warning: unable to open an initial console. ");
     
    (void) sys_dup(0);
    (void) sys_dup(0);
    /*
     * check if there is an early userspace init.  If yes, let it do all
     * the work
     */
     
    if (!ramdisk_execute_command)
    ramdisk_execute_command = "/init";
     
    if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
    ramdisk_execute_command = NULL;
    prepare_namespace();
    }
     
    /*
     * Ok, we have completed the initial bootup, and
     * we're essentially up and running. Get rid of the
     * initmem segments and start the user-mode stuff..
     */
     
    init_post();
    return 0;
    }
     
     
    static void __init do_basic_setup(void)
    {
    cpuset_init_smp();
    usermodehelper_init();
    init_tmpfs();
    driver_init();
    init_irq_proc();
    do_ctors();
    do_initcalls();
    }
     
    kernel/drivers/base/init.c
     
    void __init driver_init(void)
    {
    /* These are the core pieces */
    devtmpfs_init();
    devices_init();
    buses_init();
    classes_init();
    firmware_init();
    hypervisor_init();
     
    /* These are also core pieces, but must come after the
     * core core pieces.
     */
    platform_bus_init();
    system_bus_init();
    cpu_dev_init();
    memory_dev_init();
    }
     
    kernel/drivers/base/platform.c
    注册虚拟总线
    int __init platform_bus_init(void)
    {
    int error;
     
    early_platform_cleanup();
     
    error = device_register(&platform_bus);
    if (error)
    return error;
    error =  bus_register(&platform_bus_type);
    if (error)
    device_unregister(&platform_bus);
    return error;
    }
     
     
    kernel/drivers/base/platform.c
     
    int platform_device_register(struct platform_device *pdev)
    {
    device_initialize(&pdev->dev);
    return platform_device_add(pdev);
    }
     
     
    kernel/drivers/base/platform.c
     
    int platform_driver_register(struct platform_driver *drv)
    {
    drv->driver.bus = &platform_bus_type;
    if (drv->probe)
    drv->driver.probe = platform_drv_probe;
    if (drv->remove)
    drv->driver.remove = platform_drv_remove;
    if (drv->shutdown)
    drv->driver.shutdown = platform_drv_shutdown;
     
    return driver_register(&drv->driver);
    }
     
    kernel/drivers/base/driver.c
     
    int driver_register(struct device_driver *drv)
    {
    int ret;
    struct device_driver *other;
     
    BUG_ON(!drv->bus->p);
     
    if ((drv->bus->probe && drv->probe) ||
        (drv->bus->remove && drv->remove) ||
        (drv->bus->shutdown && drv->shutdown))
    printk(KERN_WARNING "Driver '%s' needs updating - please use "
    "bus_type methods ", drv->name);
     
    other = driver_find(drv->name, drv->bus);
    if (other) {
    put_driver(other);
    printk(KERN_ERR "Error: Driver '%s' is already registered, "
    "aborting... ", drv->name);
    return -EBUSY;
    }
     
    ret = bus_add_driver(drv);
    if (ret)
    return ret;
    ret = driver_add_groups(drv, drv->groups);
    if (ret)
    bus_remove_driver(drv);
    return ret;
    }
     
    kernel/drivers/base/bus.c
     
    int bus_add_driver(struct device_driver *drv)
    {
    struct bus_type *bus;
    struct driver_private *priv;
    int error = 0;
     
    bus = bus_get(drv->bus);
    if (!bus)
    return -EINVAL;
     
    pr_debug("bus: '%s': add driver %s ", bus->name, drv->name);
     
    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;
    error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
         "%s", drv->name);
    if (error)
    goto out_unregister;
     
    if (drv->bus->p->drivers_autoprobe) {
    error = driver_attach(drv);
    if (error)
    goto out_unregister;
    }
    klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
    module_add_driver(drv->owner, drv);
     
    error = driver_create_file(drv, &driver_attr_uevent);
    if (error) {
    printk(KERN_ERR "%s: uevent attr (%s) failed ",
    __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 ",
    __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 ",
    __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;
    }
     
    kernel/drivers/base/Dd.c
     
    int driver_attach(struct device_driver *drv)
    {
    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
    }
    EXPORT_SYMBOL_GPL(driver_attach);
     
    kernel/drivers/base/bus.c
     
    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,
         (start ? &start->p->knode_bus : NULL));
    while ((dev = next_device(&i)) && !error)
    error = fn(dev, data);
    klist_iter_exit(&i);
    return error;
    }
    EXPORT_SYMBOL_GPL(bus_for_each_dev);
  • 相关阅读:
    iOS,Layer
    iOS 手势冲突
    ECharts
    手动安装Package Control
    webstorm配置svn详解
    js 对象 类型转换
    google 跨域解决办法
    关于内层DIV设置margin-top不起作用的解决方案
    图片与文字在div里实现垂直水平都居中
    css3之3D翻牌效果
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/5526309.html
Copyright © 2011-2022 走看看