学习《Linux设备模型浅析之设备篇》笔记(二)

文件/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;

}


该源码在《linux设备:初始化》中已经粘贴过,是和devices_init()一起被driver_init(void)调用的,只不过当时没有深挖


文件/drivers/base/core.c

/**
 * device_add - 添加device到设备层
 * @dev: device.
 *
 * 这是device_register()的第二层, 不过如果device_initialize()已经被
 * 调用过的话,它也可以被单独调用。
 *
 * 这里通过kobject_add()添加@dev到 kobject 层, 添加它到全局和设备的
 * sibling(兄弟) lists,然后把它添加到驱动module的其他相关子系统。
 *
 * 不要为任何device结构调用该方法或device_register()超过一次。该
 * 模型核心不是为那些可以注销掉之后再返回继续使用的设备设计的。
 * (在其他部分,很难保证@dev的所有索引都已经释放了) 应该要分配并
 * 注册一个新的device结构。
 *
 * NOTE: 在调用该方法之后绝对不要直接释放 @dev,即使它返回一个
 * error! 应该使用put_device()来释放其索引。
 */
int device_add(struct device *dev)
{
        struct device *parent = NULL;
        struct kobject *kobj;
        struct class_interface *class_intf;
        int error = -EINVAL;

        dev = get_device(dev);
        if (!dev)
                goto done;

        if (!dev->p) {
                error = device_private_init(dev);
                if (error)
                        goto done;
        }

        /*
        * for statically allocated devices, which should all be converted
        * some day, we need to initialize the name. We prevent reading back
        * the name, and force the use of dev_name()
        */
        if (dev->init_name) {
                dev_set_name(dev, "%s", dev->init_name);
                dev->init_name = NULL;
        }

        /* subsystems can specify simple device enumeration */
        if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
                dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);

        if (!dev_name(dev)) {
                error = -EINVAL;
                goto name_error;
        }

        pr_debug("device: '%s': %s\n", dev_name(dev), __func__);

        parent = get_device(dev->parent);
        kobj = get_device_parent(dev, parent);
        if (kobj)
                dev->kobj.parent = kobj;

        /* use parent numa_node */
        if (parent)
                set_dev_node(dev, dev_to_node(parent));

        /* first, register with generic layer. */
        /* we require the name to be set before, and pass NULL */
        error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
        if (error)
                goto Error;

        /* notify platform of device entry */
        if (platform_notify)
                platform_notify(dev);

        error = device_create_file(dev, &dev_attr_uevent);
        if (error)
                goto attrError;

        if (MAJOR(dev->devt)) {
                error = device_create_file(dev, &dev_attr_dev);
                if (error)
                        goto ueventattrError;

                error = device_create_sys_dev_entry(dev);
                if (error)
                        goto devtattrError;

                devtmpfs_create_node(dev);
        }

        error = device_add_class_symlinks(dev);
        if (error)
                goto SymlinkError;
        error = device_add_attrs(dev);
        if (error)
                goto AttrsError;
        error = bus_add_device(dev);
        if (error)
                goto BusError;
        error = dpm_sysfs_add(dev);
        if (error)
                goto DPMError;
        device_pm_add(dev);

        /* Notify clients of device addition.  该调用必须在dpm_sysfs_add()
        * 之后而在kobject_uevent()之前.
        */
        if (dev->bus)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev);

        kobject_uevent(&dev->kobj, KOBJ_ADD);
        bus_probe_device(dev);
        if (parent)
                klist_add_tail(&dev->p->knode_parent, &parent->p->klist_children);

        if (dev->class) {
                mutex_lock(&dev->class->p->mutex);
                /* tie the class to the device */
                klist_add_tail(&dev->knode_class, &dev->class->p->klist_devices);

                /* notify any interfaces that the device is here */
                list_for_each_entry(class_intf, &dev->class->p->interfaces, node)
                if (class_intf->add_dev)
                        class_intf->add_dev(dev, class_intf);
                mutex_unlock(&dev->class->p->mutex);
        }
        done:
        put_device(dev);
        return error;
DPMError:
        bus_remove_device(dev);
 BusError:
        device_remove_attrs(dev);
 AttrsError:
        device_remove_class_symlinks(dev);
 SymlinkError:
        if (MAJOR(dev->devt))
                devtmpfs_delete_node(dev);
        if (MAJOR(dev->devt))
                device_remove_sys_dev_entry(dev);
devtattrError:
        if (MAJOR(dev->devt))
                device_remove_file(dev, &dev_attr_dev);
ueventattrError:
        device_remove_file(dev, &dev_attr_uevent);
 attrError:
        kobject_uevent(&dev->kobj, KOBJ_REMOVE);
        kobject_del(&dev->kobj);
 Error:
        cleanup_device_parent(dev);
        if (parent)
                put_device(parent);
name_error:
        kfree(dev->p);
        dev->p = NULL;
        goto done;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值