diff options
Diffstat (limited to 'drivers')
92 files changed, 4671 insertions, 2356 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index f4487c38d9f..1b4cf984b08 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -743,7 +743,7 @@ static int __init acpi_bus_init(void) return -ENODEV; } -decl_subsys(acpi, NULL, NULL); +struct kobject *acpi_kobj; static int __init acpi_init(void) { @@ -755,10 +755,11 @@ static int __init acpi_init(void) return -ENODEV; } - result = firmware_register(&acpi_subsys); - if (result < 0) - printk(KERN_WARNING "%s: firmware_register error: %d\n", - __FUNCTION__, result); + acpi_kobj = kobject_create_and_add("acpi", firmware_kobj); + if (!acpi_kobj) { + printk(KERN_WARNING "%s: kset create error\n", __FUNCTION__); + acpi_kobj = NULL; + } result = acpi_bus_init(); diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index c9f526e5539..5400ea173f6 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -911,7 +911,7 @@ __setup("acpi_irq_balance", acpi_irq_balance_set); /* FIXME: we will remove this interface after all drivers call pci_disable_device */ static struct sysdev_class irqrouter_sysdev_class = { - set_kset_name("irqrouter"), + .name = "irqrouter", .resume = irqrouter_resume, }; diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index edee2806e37..5ffe0ea1896 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -58,7 +58,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); FS Interface (/sys) -------------------------------------------------------------------------- */ static LIST_HEAD(acpi_table_attr_list); -static struct kobject tables_kobj; +static struct kobject *tables_kobj; struct acpi_table_attr { struct bin_attribute attr; @@ -135,11 +135,9 @@ static int acpi_system_sysfs_init(void) int table_index = 0; int result; - tables_kobj.parent = &acpi_subsys.kobj; - kobject_set_name(&tables_kobj, "tables"); - result = kobject_register(&tables_kobj); - if (result) - return result; + tables_kobj = kobject_create_and_add("tables", acpi_kobj); + if (!tables_kobj) + return -ENOMEM; do { result = acpi_get_table_by_index(table_index, &table_header); @@ -153,7 +151,7 @@ static int acpi_system_sysfs_init(void) acpi_table_attr_init(table_attr, table_header); result = - sysfs_create_bin_file(&tables_kobj, + sysfs_create_bin_file(tables_kobj, &table_attr->attr); if (result) { kfree(table_attr); @@ -163,6 +161,7 @@ static int acpi_system_sysfs_init(void) &acpi_table_attr_list); } } while (!result); + kobject_uevent(tables_kobj, KOBJ_ADD); return 0; } diff --git a/drivers/base/Makefile b/drivers/base/Makefile index b39ea3f59c9..63e09c015ca 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -11,6 +11,9 @@ obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o obj-$(CONFIG_SMP) += topology.o +ifeq ($(CONFIG_SYSFS),y) +obj-$(CONFIG_MODULES) += module.o +endif obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o ifeq ($(CONFIG_DEBUG_DRIVER),y) diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 7370d7cf598..d4dfb97de3b 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -61,7 +61,7 @@ attribute_container_classdev_to_container(struct class_device *classdev) } EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container); -static struct list_head attribute_container_list; +static LIST_HEAD(attribute_container_list); static DEFINE_MUTEX(attribute_container_mutex); @@ -429,10 +429,3 @@ attribute_container_find_class_device(struct attribute_container *cont, return cdev; } EXPORT_SYMBOL_GPL(attribute_container_find_class_device); - -int __init -attribute_container_init(void) -{ - INIT_LIST_HEAD(&attribute_container_list); - return 0; -} diff --git a/drivers/base/base.h b/drivers/base/base.h index 10b2fb6c9ce..c0444146c09 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -1,6 +1,42 @@ -/* initialisation functions */ +/** + * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure. + * + * @subsys - the struct kset that defines this bus. This is the main kobject + * @drivers_kset - the list of drivers associated with this bus + * @devices_kset - the list of devices associated with this bus + * @klist_devices - the klist to iterate over the @devices_kset + * @klist_drivers - the klist to iterate over the @drivers_kset + * @bus_notifier - the bus notifier list for anything that cares about things + * on this bus. + * @bus - pointer back to the struct bus_type that this structure is associated + * with. + * + * This structure is the one that is the actual kobject allowing struct + * bus_type to be statically allocated safely. Nothing outside of the driver + * core should ever touch these fields. + */ +struct bus_type_private { + 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 driver_private { + struct kobject kobj; + struct klist klist_devices; + struct klist_node knode_bus; + struct module_kobject *mkobj; + struct device_driver *driver; +}; +#define to_driver(obj) container_of(obj, struct driver_private, kobj) +/* initialisation functions */ extern int devices_init(void); extern int buses_init(void); extern int classes_init(void); @@ -13,17 +49,16 @@ static inline int hypervisor_init(void) { return 0; } extern int platform_bus_init(void); extern int system_bus_init(void); extern int cpu_dev_init(void); -extern int attribute_container_init(void); -extern int bus_add_device(struct device * dev); -extern void bus_attach_device(struct device * dev); -extern void bus_remove_device(struct device * dev); +extern int bus_add_device(struct device *dev); +extern void bus_attach_device(struct device *dev); +extern void bus_remove_device(struct device *dev); -extern int bus_add_driver(struct device_driver *); -extern void bus_remove_driver(struct device_driver *); +extern int bus_add_driver(struct device_driver *drv); +extern void bus_remove_driver(struct device_driver *drv); -extern void driver_detach(struct device_driver * drv); -extern int driver_probe_device(struct device_driver *, struct device *); +extern void driver_detach(struct device_driver *drv); +extern int driver_probe_device(struct device_driver *drv, struct device *dev); extern void sysdev_shutdown(void); extern int sysdev_suspend(pm_message_t state); @@ -44,4 +79,13 @@ extern char *make_class_name(const char *name, struct kobject *kobj); extern int devres_release_all(struct device *dev); -extern struct kset devices_subsys; +extern struct kset *devices_kset; + +#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS) +extern void module_add_driver(struct module *mod, struct device_driver *drv); +extern void module_remove_driver(struct device_driver *drv); +#else +static inline void module_add_driver(struct module *mod, + struct device_driver *drv) { } +static inline void module_remove_driver(struct device_driver *drv) { } +#endif diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 9a19b071c57..f484495b2ad 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -3,6 +3,8 @@ * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs + * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> + * Copyright (c) 2007 Novell Inc. * * This file is released under the GPLv2 * @@ -17,14 +19,13 @@ #include "power/power.h" #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) -#define to_bus(obj) container_of(obj, struct bus_type, subsys.kobj) +#define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj) /* * sysfs bindings for drivers */ #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr) -#define to_driver(obj) container_of(obj, struct device_driver, kobj) static int __must_check bus_rescan_devices_helper(struct device *dev, @@ -32,37 +33,40 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, static struct bus_type *bus_get(struct bus_type *bus) { - return bus ? container_of(kset_get(&bus->subsys), - struct bus_type, subsys) : NULL; + if (bus) { + kset_get(&bus->p->subsys); + return bus; + } + return NULL; } static void bus_put(struct bus_type *bus) { - kset_put(&bus->subsys); + if (bus) + kset_put(&bus->p->subsys); } -static ssize_t -drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) +static ssize_t drv_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) { - struct driver_attribute * drv_attr = to_drv_attr(attr); - struct device_driver * drv = to_driver(kobj); + struct driver_attribute *drv_attr = to_drv_attr(attr); + struct driver_private *drv_priv = to_driver(kobj); ssize_t ret = -EIO; if (drv_attr->show) - ret = drv_attr->show(drv, buf); + ret = drv_attr->show(drv_priv->driver, buf); return ret; } -static ssize_t -drv_attr_store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count) +static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { - struct driver_attribute * drv_attr = to_drv_attr(attr); - struct device_driver * drv = to_driver(kobj); + struct driver_attribute *drv_attr = to_drv_attr(attr); + struct driver_private *drv_priv = to_driver(kobj); ssize_t ret = -EIO; if (drv_attr->store) - ret = drv_attr->store(drv, buf, count); + ret = drv_attr->store(drv_priv->driver, buf, count); return ret; } @@ -71,22 +75,12 @@ static struct sysfs_ops driver_sysfs_ops = { .store = drv_attr_store, }; - -static void driver_release(struct kobject * kobj) +static void driver_release(struct kobject *kobj) { - /* - * Yes this is an empty release function, it is this way because struct - * device is always a static object, not a dynamic one. Yes, this is - * not nice and bad, but remember, drivers are code, reference counted - * by the module count, not a device, which is really data. And yes, - * in the future I do want to have all drivers be created dynamically, - * and am working toward that goal, but it will take a bit longer... - * - * But do not let this example give _anyone_ the idea that they can - * create a release function without any code in it at all, to do that - * is almost always wrong. If you have any questions about this, - * please send an email to <greg@kroah.com> - */ + struct driver_private *drv_priv = to_driver(kobj); + + pr_debug("driver: '%s': %s\n", kobject_name(kobj), __FUNCTION__); + kfree(drv_priv); } static struct kobj_type driver_ktype = { @@ -94,34 +88,30 @@ static struct kobj_type driver_ktype = { .release = driver_release, }; - /* * sysfs bindings for buses */ - - -static ssize_t -bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) +static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) { - struct bus_attribute * bus_attr = to_bus_attr(attr); - struct bus_type * bus = to_bus(kobj); + struct bus_attribute *bus_attr = to_bus_attr(attr); + struct bus_type_private *bus_priv = to_bus(kobj); ssize_t ret = 0; if (bus_attr->show) - ret = bus_attr->show(bus, buf); + ret = bus_attr->show(bus_priv->bus, buf); return ret; } -static ssize_t -bus_attr_store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count) +static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { - struct bus_attribute * bus_attr = to_bus_attr(attr); - struct bus_type * bus = to_bus(kobj); + struct bus_attribute *bus_attr = to_bus_attr(attr); + struct bus_type_private *bus_priv = to_bus(kobj); ssize_t ret = 0; if (bus_attr->store) - ret = bus_attr->store(bus, buf, count); + ret = bus_attr->store(bus_priv->bus, buf, count); return ret; } @@ -130,24 +120,26 @@ static struct sysfs_ops bus_sysfs_ops = { .store = bus_attr_store, }; -int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) +int bus_create_file(struct bus_type *bus, struct bus_attribute *attr) { int error; if (bus_get(bus)) { - error = sysfs_create_file(&b |