From 8b755139164c05fcff5e56617d2fa9886fea1825 Mon Sep 17 00:00:00 2001 From: Patrick Mochel <mochel@osdl.org> Date: Mon, 23 Sep 2002 01:19:20 -0700 Subject: [PATCH] Driver model: improve support for system devices. - Create struct sys_device to describe system-level devices (CPUs, PICs, etc.). This structure includes a 'name' and 'id' field for drivers to fill in with a simple canonical name (like 'pic' or 'floppy') and the id of the device relative to its discovery in the system (it's enumerated value). The core then constructs the bus_id for the device from these, giving them meaningful names when exporting them to userspace: # tree -d /sys/root/sys/ /sys/root/sys/ |-- pic0 `-- rtc0 - Replace int register_sys_device(struct device * dev); with int sys_device_register(struct sys_device * sysdev); - Fixup the users of the API. - Add a system_bus_type for devices to associate themselves with. This provides a bus/system/ directory in driverfs that looks like: # tree -d /sys/bus/system/ /sys/bus/system/ |-- devices | |-- pic0 -> ../../../root/sys/pic0 | `-- rtc0 -> ../../../root/sys/rtc0 `-- drivers `-- pic --- arch/i386/kernel/i8259.c | 20 +++++++----- arch/i386/kernel/time.c | 15 +++++---- drivers/base/sys.c | 68 ++++++++++++++++++++++++++++++---------- drivers/block/floppy.c | 13 +++++--- include/linux/device.h | 14 +++++++-- 5 files changed, 93 insertions(+), 37 deletions(-) diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index eb3fdd05b638..499b58a347c2 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -246,22 +246,28 @@ static int i8259A_resume(struct device *dev, u32 level) return 0; } -static struct device_driver driver_i8259A = { +static struct device_driver i8259A_driver = { + .name = "pic", + .bus = &system_bus_type, .resume = i8259A_resume, }; -static struct device device_i8259A = { - .name = "i8259A", - .bus_id = "0020", - .driver = &driver_i8259A, +static struct sys_device device_i8259A = { + .name = "pic", + .id = 0, + .dev = { + .name = "i8259A PIC", + .driver = &i8259A_driver, + }, }; static int __init init_8259A_devicefs(void) { - return register_sys_device(&device_i8259A); + driver_register(&i8259A_driver); + return sys_device_register(&device_i8259A); } -__initcall(init_8259A_devicefs); +device_initcall(init_8259A_devicefs); void init_8259A(int auto_eoi) { diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 9ad143fcd1c1..add66db72dcd 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -588,17 +588,20 @@ static unsigned long __init calibrate_tsc(void) } #endif /* CONFIG_X86_TSC */ -static struct device device_i8253 = { - .name = "i8253", - .bus_id = "0040", +static struct sys_device device_i8253 = { + .name = "rtc", + .id = 0, + .dev = { + .name = "i8253 Real Time Clock", + }, }; -static int time_init_driverfs(void) +static int time_init_device(void) { - return register_sys_device(&device_i8253); + return sys_device_register(&device_i8253); } -__initcall(time_init_driverfs); +device_initcall(time_init_device); void __init time_init(void) { diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 7120cce5cb39..8dfa5b7bfb2b 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -6,44 +6,78 @@ * * This exports a 'system' bus type. * By default, a 'sys' bus gets added to the root of the system. There will - * always be core system devices. Devices can use register_sys_device() to + * always be core system devices. Devices can use sys_device_register() to * add themselves as children of the system bus. */ #include <linux/device.h> #include <linux/module.h> +#include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> -#include <linux/errno.h> +#include <linux/err.h> +/* The default system device parent. */ static struct device system_bus = { .name = "System Bus", .bus_id = "sys", }; -int register_sys_device(struct device * dev) +/** + * sys_device_register - add a system device to the tree + * @sysdev: device in question + * + * The hardest part about this is getting the ancestry right. + * If the device has a parent - super! We do nothing. + * If the device doesn't, but @dev->root is set, then we're + * dealing with a NUMA like architecture where each root + * has a system pseudo-bus to foster the device. + * If not, then we fallback to system_bus (at the top of + * this file). + * + * One way or another, we call device_register() on it and + * are done. + * + * The caller is also responsible for initializing the bus_id + * and name fields of @sysdev->dev. + */ +int sys_device_register(struct sys_device * sysdev) { - int error = -EINVAL; - - if (dev) { - if (!dev->parent) - dev->parent = &system_bus; - error = device_register(dev); - } - return error; + if (!sysdev) + return -EINVAL; + + if (!sysdev->dev.parent) + sysdev->dev.parent = &system_bus; + + /* make sure bus type is set */ + if (!sysdev->dev.bus) + sysdev->dev.bus = &system_bus_type; + + /* construct bus_id */ + snprintf(sysdev->dev.bus_id,BUS_ID_SIZE,"%s%u",sysdev->name,sysdev->id); + + pr_debug("Registering system device %s\n", sysdev->dev.bus_id); + + return device_register(&sysdev->dev); } -void unregister_sys_device(struct device * dev) +void sys_device_unregister(struct sys_device * sysdev) { - if (dev) - put_device(dev); + if (sysdev) + put_device(&sysdev->dev); } +struct bus_type system_bus_type = { + .name = "system", +}; + static int sys_bus_init(void) { - return device_register(&system_bus); + bus_register(&system_bus_type); + return device_register(&system_bus); } postcore_initcall(sys_bus_init); -EXPORT_SYMBOL(register_sys_device); -EXPORT_SYMBOL(unregister_sys_device); +EXPORT_SYMBOL(system_bus_type); +EXPORT_SYMBOL(sys_device_register); +EXPORT_SYMBOL(sys_device_unregister); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 78989bde5cb5..b07e8efd12ea 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4220,9 +4220,12 @@ static int __init floppy_setup(char *str) static int have_no_fdc= -ENODEV; -static struct device device_floppy = { - name: "floppy", - bus_id: "03?0", +static struct sys_device floppy_device = { + .name = "floppy", + .id = 0, + .dev = { + .name = "Floppy Drive", + }, }; static struct gendisk *floppy_find(int minor) @@ -4376,7 +4379,7 @@ int __init floppy_init(void) add_disk(disks + drive); } - register_sys_device(&device_floppy); + sys_device_register(&floppy_device); return have_no_fdc; } @@ -4560,7 +4563,7 @@ void cleanup_module(void) { int drive; - unregister_sys_device(&device_floppy); + sys_device_unregister(&floppy_device); devfs_unregister (devfs_handle); unregister_blkdev(MAJOR_NR, "fd"); blk_set_probe(MAJOR_NR, NULL); diff --git a/include/linux/device.h b/include/linux/device.h index ea2a790723b3..7abeead7bfe1 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -378,8 +378,18 @@ extern struct device * get_device(struct device * dev); extern void put_device(struct device * dev); /* drivers/base/sys.c */ -extern int register_sys_device(struct device * dev); -extern void unregister_sys_device(struct device * dev); + +struct sys_device { + char * name; + u32 id; + struct sys_root * root; + struct device dev; +}; + +extern int sys_device_register(struct sys_device *); +extern void sys_device_unregister(struct sys_device *); + +extern struct bus_type system_bus_type; /* drivers/base/platform.c */ extern struct bus_type platform_bus; -- 2.30.9