Commit 8b755139 authored by Patrick Mochel's avatar Patrick Mochel

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
parent 94eda096
...@@ -246,22 +246,28 @@ static int i8259A_resume(struct device *dev, u32 level) ...@@ -246,22 +246,28 @@ static int i8259A_resume(struct device *dev, u32 level)
return 0; return 0;
} }
static struct device_driver driver_i8259A = { static struct device_driver i8259A_driver = {
.name = "pic",
.bus = &system_bus_type,
.resume = i8259A_resume, .resume = i8259A_resume,
}; };
static struct device device_i8259A = { static struct sys_device device_i8259A = {
.name = "i8259A", .name = "pic",
.bus_id = "0020", .id = 0,
.driver = &driver_i8259A, .dev = {
.name = "i8259A PIC",
.driver = &i8259A_driver,
},
}; };
static int __init init_8259A_devicefs(void) 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) void init_8259A(int auto_eoi)
{ {
......
...@@ -588,17 +588,20 @@ static unsigned long __init calibrate_tsc(void) ...@@ -588,17 +588,20 @@ static unsigned long __init calibrate_tsc(void)
} }
#endif /* CONFIG_X86_TSC */ #endif /* CONFIG_X86_TSC */
static struct device device_i8253 = { static struct sys_device device_i8253 = {
.name = "i8253", .name = "rtc",
.bus_id = "0040", .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) void __init time_init(void)
{ {
......
...@@ -6,44 +6,78 @@ ...@@ -6,44 +6,78 @@
* *
* This exports a 'system' bus type. * This exports a 'system' bus type.
* By default, a 'sys' bus gets added to the root of the system. There will * 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. * add themselves as children of the system bus.
*/ */
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h> #include <linux/err.h>
/* The default system device parent. */
static struct device system_bus = { static struct device system_bus = {
.name = "System Bus", .name = "System Bus",
.bus_id = "sys", .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 (!sysdev)
return -EINVAL;
if (dev) {
if (!dev->parent) if (!sysdev->dev.parent)
dev->parent = &system_bus; sysdev->dev.parent = &system_bus;
error = device_register(dev);
} /* make sure bus type is set */
return error; 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) if (sysdev)
put_device(dev); put_device(&sysdev->dev);
} }
struct bus_type system_bus_type = {
.name = "system",
};
static int sys_bus_init(void) 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); postcore_initcall(sys_bus_init);
EXPORT_SYMBOL(register_sys_device); EXPORT_SYMBOL(system_bus_type);
EXPORT_SYMBOL(unregister_sys_device); EXPORT_SYMBOL(sys_device_register);
EXPORT_SYMBOL(sys_device_unregister);
...@@ -4220,9 +4220,12 @@ static int __init floppy_setup(char *str) ...@@ -4220,9 +4220,12 @@ static int __init floppy_setup(char *str)
static int have_no_fdc= -ENODEV; static int have_no_fdc= -ENODEV;
static struct device device_floppy = { static struct sys_device floppy_device = {
name: "floppy", .name = "floppy",
bus_id: "03?0", .id = 0,
.dev = {
.name = "Floppy Drive",
},
}; };
static struct gendisk *floppy_find(int minor) static struct gendisk *floppy_find(int minor)
...@@ -4376,7 +4379,7 @@ int __init floppy_init(void) ...@@ -4376,7 +4379,7 @@ int __init floppy_init(void)
add_disk(disks + drive); add_disk(disks + drive);
} }
register_sys_device(&device_floppy); sys_device_register(&floppy_device);
return have_no_fdc; return have_no_fdc;
} }
...@@ -4560,7 +4563,7 @@ void cleanup_module(void) ...@@ -4560,7 +4563,7 @@ void cleanup_module(void)
{ {
int drive; int drive;
unregister_sys_device(&device_floppy); sys_device_unregister(&floppy_device);
devfs_unregister (devfs_handle); devfs_unregister (devfs_handle);
unregister_blkdev(MAJOR_NR, "fd"); unregister_blkdev(MAJOR_NR, "fd");
blk_set_probe(MAJOR_NR, NULL); blk_set_probe(MAJOR_NR, NULL);
......
...@@ -378,8 +378,18 @@ extern struct device * get_device(struct device * dev); ...@@ -378,8 +378,18 @@ extern struct device * get_device(struct device * dev);
extern void put_device(struct device * dev); extern void put_device(struct device * dev);
/* drivers/base/sys.c */ /* 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 */ /* drivers/base/platform.c */
extern struct bus_type platform_bus; extern struct bus_type platform_bus;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment