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)
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)
{
......
......@@ -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)
{
......
......@@ -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)
{
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);
......@@ -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);
......
......@@ -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;
......
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