您的位置:首页 > 理论基础 > 数据结构算法

linux中platform_bus_type注册使用到的数据结构和函数

2014-09-10 19:05 274 查看
该篇文章解决了我在看arm嵌入式平台如何在/sys/platform/目录下生成相关的驱动代码中关于platfrom_bus_type的priv成员赋值的问题,波浪线下添加,困惑的处由浅紫色部分表示出了,有收获所以转载。

转自http://blog.chinaunix.net/uid-20620288-id-3134258.html,

struct bus_type { // include/linux/device.h

const char *name;

struct bus_attribute *bus_attrs;

struct device_attribute *dev_attrs;

struct driver_attribute *drv_attrs;

int (*match)(struct device *dev, struct device_driver *drv);

int (*uevent)(struct device *dev, struct kobj_uevent_env *env);

int (*probe)(struct device *dev);

int (*remove)(struct device *dev);

void (*shutdown)(struct device *dev);

int (*suspend)(struct device *dev, pm_message_t state);

int (*resume)(struct device *dev);

const struct dev_pm_ops *pm;

struct bus_type_private *p;

};

struct bus_type_private { // include/linux/device.h

struct kset subsys;

struct kset *drivers_kset;

struct kset *devices_kset;

struct klist klist_devices;

struct klist klist_drivers;

struct blocking_notifier_head bus_notifier;

unsigned int drivers_autoprobe:1;

struct bus_type *bus;

};

struct bus_type platform_bus_type = { // driver/base/platform.c

.name = "platform",

.dev_attrs = platform_dev_attrs,

.match = platform_match,

.uevent = platform_uevent,

.pm = &platform_dev_pm_ops,

};

EXPORT_SYMBOL_GPL(platform_bus_type);

int __init platform_bus_init(void) // driver/base/platform.c

{

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;

}

struct device platform_bus = {

.init_name = "platform",

};

EXPORT_SYMBOL_GPL(platform_bus);

void __init driver_init(void) // driver/base/init.c

{

/* These are the core pieces */

devtmpfs_init();

devices_init();

buses_init(); // sys/bus的注册(其实就是一个kset的注册)

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();

}

static void __init do_basic_setup(void) // init/main.c

{

init_workqueues();

cpuset_init_smp();

usermodehelper_init();

init_tmpfs();

driver_init();

init_irq_proc();

do_ctors();

do_initcalls();

}

static int __init kernel_init(void * unused)// init/main.c

{

********************

do_basic_setup();

********************

}

static noinline void __init_refok rest_init(void)

__releases(kernel_lock)

{

**********************

kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

**********************

}

int bus_register(struct bus_type *bus)

{

int retval;

struct bus_type_private *priv;

priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);

if (!priv)

return -ENOMEM;

priv->bus = bus;

bus->p = priv;

BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);

retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);

if (retval)

goto out;

priv->subsys.kobj.kset = bus_kset;// 指向bus目录

priv->subsys.kobj.ktype = &bus_ktype;

priv->drivers_autoprobe = 1;

retval = kset_register(&priv->subsys); // 生成platform目录

if (retval)

goto out;

retval = bus_create_file(bus, &bus_attr_uevent);

if (retval)

goto bus_uevent_fail;

priv->devices_kset = kset_create_and_add("devices", NULL,

&priv->subsys.kobj);// 在platform下生成devices目录

if (!priv->devices_kset) {

retval = -ENOMEM;

goto bus_devices_fail;

}

priv->drivers_kset = kset_create_and_add("drivers", NULL,

&priv->subsys.kobj);// 在platform下生成drivers目录

if (!priv->drivers_kset) {

retval = -ENOMEM;

goto bus_drivers_fail;

}

klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);

klist_init(&priv->klist_drivers, NULL, NULL);

retval = add_probe_files(bus);

if (retval)

goto bus_probe_files_fail;

retval = bus_add_attrs(bus);

if (retval)

goto bus_attrs_fail;

pr_debug("bus: '%s': registered\n", bus->name);

return 0;

bus_attrs_fail:

remove_probe_files(bus);

bus_probe_files_fail:

kset_unregister(bus->p->drivers_kset);

bus_drivers_fail:

kset_unregister(bus->p->devices_kset);

bus_devices_fail:

bus_remove_file(bus, &bus_attr_uevent);

bus_uevent_fail:

kset_unregister(&bus->p->subsys);

kfree(bus->p);

out:

bus->p = NULL;

return retval;

}

EXPORT_SYMBOL_GPL(bus_register);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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\n", drv->name);

other = driver_find(drv->name, drv->bus);

if (other) {

printk(KERN_ERR "Error: Driver '%s' is already registered, "

"aborting...\n", drv->name);

return -EBUSY;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: