Commit d668723c authored by Patrick Mochel's avatar Patrick Mochel

Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5
parents bf72e973 aeb14ea3
#include <linux/init.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/cpu.h>
#include <linux/smp.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
......@@ -506,3 +507,37 @@ void __init cpu_init (void)
current->used_math = 0;
stts();
}
/*
* Bulk registration of the cpu devices with the system.
* Some of this stuff could possibly be moved into a shared
* location..
* Also, these devices should be integrated with other CPU data..
*/
static struct cpu cpu_devices[NR_CPUS];
static struct device_driver cpu_driver = {
.name = "cpu",
.bus = &system_bus_type,
.devclass = &cpu_devclass,
};
static int __init register_cpus(void)
{
int i;
driver_register(&cpu_driver);
for (i = 0; i < NR_CPUS; i++) {
struct sys_device * sysdev = &cpu_devices[i].sysdev;
sysdev->name = "cpu";
sysdev->id = i;
sysdev->dev.driver = &cpu_driver;
if (cpu_possible(i))
sys_device_register(sysdev);
}
return 0;
}
subsys_initcall(register_cpus);
......@@ -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)
{
......
# Makefile for the Linux device tree
obj-y := core.o sys.o interface.o power.o bus.o \
driver.o class.o intf.o platform.o
driver.o class.o intf.o platform.o \
cpu.o
obj-y += fs/
export-objs := core.o power.o sys.o bus.o driver.o \
class.o intf.o
class.o intf.o cpu.o
include $(TOPDIR)/Rules.make
......@@ -23,6 +23,19 @@ spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
#define to_dev(node) container_of(node,struct device,driver_list)
static int probe(struct device * dev, struct device_driver * drv)
{
dev->driver = drv;
return drv->probe ? drv->probe(dev) : 0;
}
static void attach(struct device * dev)
{
spin_lock(&device_lock);
list_add_tail(&dev->driver_list,&dev->driver->devices);
spin_unlock(&device_lock);
devclass_add_device(dev);
}
/**
* found_match - do actual binding of device to driver
......@@ -43,25 +56,14 @@ static int found_match(struct device * dev, struct device_driver * drv)
{
int error = 0;
dev->driver = get_driver(drv);
if (drv->probe)
if (drv->probe(dev))
goto ProbeFailed;
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id,drv->name);
spin_lock(&device_lock);
list_add_tail(&dev->driver_list,&drv->devices);
spin_unlock(&device_lock);
devclass_add_device(dev);
goto Done;
ProbeFailed:
put_driver(drv);
dev->driver = NULL;
Done:
if (!(error = probe(dev,get_driver(drv)))) {
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id,drv->name);
attach(dev);
} else {
put_driver(drv);
dev->driver = NULL;
}
return error;
}
......@@ -80,18 +82,19 @@ static int do_device_attach(struct device_driver * drv, void * data)
struct device * dev = (struct device *)data;
int error = 0;
if (!dev->driver) {
if (drv->bus->match && drv->bus->match(dev,drv))
error = found_match(dev,drv);
}
if (drv->bus->match && drv->bus->match(dev,drv))
error = found_match(dev,drv);
return error;
}
static int device_attach(struct device * dev)
{
int error = 0;
if (dev->bus)
error = bus_for_each_drv(dev->bus,dev,do_device_attach);
if (!dev->driver) {
if (dev->bus)
error = bus_for_each_drv(dev->bus,dev,do_device_attach);
} else
attach(dev);
return error;
}
......@@ -103,7 +106,6 @@ static void device_detach(struct device * dev)
devclass_remove_device(dev);
if (drv && drv->remove)
drv->remove(dev);
dev->driver = NULL;
}
}
......
/*
* cpu.c - basic cpu class support
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpu.h>
static int cpu_add_device(struct device * dev)
{
return 0;
}
struct device_class cpu_devclass = {
.name = "cpu",
.add_device = cpu_add_device,
};
static int __init cpu_devclass_init(void)
{
return devclass_register(&cpu_devclass);
}
postcore_initcall(cpu_devclass_init);
EXPORT_SYMBOL(cpu_devclass);
......@@ -6,44 +6,139 @@
*
* 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_register_root - add a subordinate system root
* @root: new root
*
* This is for NUMA-like systems so they can accurately
* represent the topology of the entire system.
* As boards are discovered, a new struct sys_root should
* be allocated and registered.
* The discovery mechanism should initialize the id field
* of the struture, as well as much of the embedded device
* structure as possible, inlcuding the name, the bus_id
* and parent fields.
*
* This simply calls device_register on the embedded device.
* On success, it will use the struct @root->sysdev
* device to create a pseudo-parent for system devices
* on that board.
*
* The platform code can then use @root to specifiy the
* controlling board when discovering and registering
* system devices.
*/
int sys_register_root(struct sys_root * root)
{
int error = -EINVAL;
if (dev) {
if (!dev->parent)
dev->parent = &system_bus;
error = device_register(dev);
}
return error;
int error = 0;
if (!root)
return -EINVAL;
pr_debug("Registering system board %d\n",root->id);
error = device_register(&root->dev);
if (!error) {
strncpy(root->sysdev.bus_id,"sys",BUS_ID_SIZE);
strncpy(root->sysdev.name,"System Bus",DEVICE_NAME_SIZE);
root->sysdev.parent = &root->dev;
error = device_register(&root->sysdev);
};
return error;
}
void unregister_sys_device(struct device * dev)
/**
* sys_unregister_root - remove subordinate root from tree
* @root: subordinate root in question.
*
* We only decrement the reference count on @root->sysdev
* and @root->dev.
* If both are 0, they will be cleaned up by the core.
*/
void sys_unegister_root(struct sys_root * root)
{
if (dev)
put_device(dev);
put_device(&root->sysdev);
put_device(&root->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)
{
if (!sysdev)
return -EINVAL;
if (!sysdev->dev.parent) {
if (sysdev->root)
sysdev->dev.parent = &sysdev->root->sysdev;
else
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 sys_device_unregister(struct sys_device * sysdev)
{
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);
......@@ -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);
......
......@@ -63,7 +63,8 @@ static void generic_release (struct device_driver * drv)
}
static struct device_driver usb_generic_driver = {
.name = "generic usb driver",
.name = "generic",
.bus = &usb_bus_type,
.probe = generic_probe,
.remove = generic_remove,
.release = generic_release,
......@@ -470,6 +471,10 @@ static int usb_device_match (struct device *dev, struct device_driver *drv)
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* check for generic driver, which we don't match any device with */
if (drv == &usb_generic_driver)
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
......@@ -1446,6 +1451,8 @@ static int __init usb_init(void)
usbfs_init();
usb_hub_init();
driver_register(&usb_generic_driver);
return 0;
}
......@@ -1454,6 +1461,7 @@ static int __init usb_init(void)
*/
static void __exit usb_exit(void)
{
remove_driver(&usb_generic_driver);
usb_major_cleanup();
usbfs_cleanup();
usb_hub_cleanup();
......
/*
* cpu.h - generic cpu defition
*
* This is mainly for topological representation. We define the
* basic 'struct cpu' here, which can be embedded in per-arch
* definitions of processors.
*
* Basic handling of the devices is done in drivers/base/cpu.c
* and system devices are handled in drivers/base/sys.c.
*
* CPUs are exported via driverfs in the class/cpu/devices/
* directory.
*
* Per-cpu interfaces can be implemented using a struct device_interface.
* See the following for how to do this:
* - drivers/base/intf.c
* - Documentation/driver-model/interface.txt
*
*/
#include <linux/device.h>
extern struct device_class cpu_devclass;
struct cpu {
struct sys_device sysdev;
};
......@@ -378,8 +378,28 @@ 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_root {
u32 id;
struct device dev;
struct device sysdev;
};
extern int sys_register_root(struct sys_root *);
extern void sys_unregister_root(struct sys_root *);
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