Commit 0a983298 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/2.6.11/driver

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents aa61674d 0c156ba8
...@@ -15,3 +15,20 @@ Why: It has been unmaintained for a number of years, has unfixable ...@@ -15,3 +15,20 @@ Why: It has been unmaintained for a number of years, has unfixable
against the LSB, and can be replaced by using udev. against the LSB, and can be replaced by using udev.
Who: Greg Kroah-Hartman <greg@kroah.com> Who: Greg Kroah-Hartman <greg@kroah.com>
---------------------------
What: /proc/sys/cpu/*, sysctl and /proc/cpufreq interfaces to cpufreq (2.4.x interfaces)
When: January 2005
Files: drivers/cpufreq/: cpufreq_userspace.c, proc_intf.c
Why: /proc/sys/cpu/* has been deprecated since inclusion of cpufreq into
the main kernel tree. It bloats /proc/ unnecessarily and doesn't work
well with the "governor"-based design of cpufreq.
/proc/cpufreq/* has also been deprecated for a long time and was only
meant for usage during 2.5. until the new sysfs-based interface became
ready. It has an inconsistent interface which doesn't work well with
userspace setting the frequency. The output from /proc/cpufreq/* can
be emulated using "cpufreq-info --proc" (cpufrequtils).
Both interfaces are superseded by the cpufreq interface in
/sys/devices/system/cpu/cpu%n/cpufreq/.
Who: Dominik Brodowski <linux@brodo.de>
...@@ -65,7 +65,7 @@ static struct sysfs_ops driver_sysfs_ops = { ...@@ -65,7 +65,7 @@ static struct sysfs_ops driver_sysfs_ops = {
static void driver_release(struct kobject * kobj) static void driver_release(struct kobject * kobj)
{ {
struct device_driver * drv = to_driver(kobj); struct device_driver * drv = to_driver(kobj);
up(&drv->unload_sem); complete(&drv->unloaded);
} }
static struct kobj_type ktype_driver = { static struct kobj_type ktype_driver = {
...@@ -465,6 +465,7 @@ int bus_add_device(struct device * dev) ...@@ -465,6 +465,7 @@ int bus_add_device(struct device * dev)
up_write(&dev->bus->subsys.rwsem); up_write(&dev->bus->subsys.rwsem);
device_add_attrs(bus, dev); device_add_attrs(bus, dev);
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
} }
return error; return error;
} }
...@@ -481,6 +482,7 @@ int bus_add_device(struct device * dev) ...@@ -481,6 +482,7 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev) void bus_remove_device(struct device * dev)
{ {
if (dev->bus) { if (dev->bus) {
sysfs_remove_link(&dev->kobj, "bus");
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev); device_remove_attrs(dev->bus, dev);
down_write(&dev->bus->subsys.rwsem); down_write(&dev->bus->subsys.rwsem);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kdev_t.h>
#include "base.h" #include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
...@@ -139,6 +140,7 @@ int class_register(struct class * cls) ...@@ -139,6 +140,7 @@ int class_register(struct class * cls)
INIT_LIST_HEAD(&cls->children); INIT_LIST_HEAD(&cls->children);
INIT_LIST_HEAD(&cls->interfaces); INIT_LIST_HEAD(&cls->interfaces);
init_MUTEX(&cls->sem);
error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
if (error) if (error)
return error; return error;
...@@ -195,33 +197,6 @@ void class_device_remove_bin_file(struct class_device *class_dev, ...@@ -195,33 +197,6 @@ void class_device_remove_bin_file(struct class_device *class_dev,
sysfs_remove_bin_file(&class_dev->kobj, attr); sysfs_remove_bin_file(&class_dev->kobj, attr);
} }
static int class_device_dev_link(struct class_device * class_dev)
{
if (class_dev->dev)
return sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
return 0;
}
static void class_device_dev_unlink(struct class_device * class_dev)
{
sysfs_remove_link(&class_dev->kobj, "device");
}
static int class_device_driver_link(struct class_device * class_dev)
{
if ((class_dev->dev) && (class_dev->dev->driver))
return sysfs_create_link(&class_dev->kobj,
&class_dev->dev->driver->kobj, "driver");
return 0;
}
static void class_device_driver_unlink(struct class_device * class_dev)
{
sysfs_remove_link(&class_dev->kobj, "driver");
}
static ssize_t static ssize_t
class_device_attr_show(struct kobject * kobj, struct attribute * attr, class_device_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf) char * buf)
...@@ -298,9 +273,9 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp, ...@@ -298,9 +273,9 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size) int num_envp, char *buffer, int buffer_size)
{ {
struct class_device *class_dev = to_class_dev(kobj); struct class_device *class_dev = to_class_dev(kobj);
int retval = 0;
int i = 0; int i = 0;
int length = 0; int length = 0;
int retval = 0;
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
...@@ -313,26 +288,34 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp, ...@@ -313,26 +288,34 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
&length, "PHYSDEVPATH=%s", path); &length, "PHYSDEVPATH=%s", path);
kfree(path); kfree(path);
/* add bus name of physical device */
if (dev->bus) if (dev->bus)
add_hotplug_env_var(envp, num_envp, &i, add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length, buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name); "PHYSDEVBUS=%s", dev->bus->name);
/* add driver name of physical device */
if (dev->driver) if (dev->driver)
add_hotplug_env_var(envp, num_envp, &i, add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length, buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name); "PHYSDEVDRIVER=%s", dev->driver->name);
}
if (MAJOR(class_dev->devt)) {
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MAJOR=%u", MAJOR(class_dev->devt));
/* terminate, set to next free slot, shrink available space */ add_hotplug_env_var(envp, num_envp, &i,
envp[i] = NULL; buffer, buffer_size, &length,
envp = &envp[i]; "MINOR=%u", MINOR(class_dev->devt));
num_envp -= i;
buffer = &buffer[length];
buffer_size -= length;
} }
/* terminate, set to next free slot, shrink available space */
envp[i] = NULL;
envp = &envp[i];
num_envp -= i;
buffer = &buffer[length];
buffer_size -= length;
if (class_dev->class->hotplug) { if (class_dev->class->hotplug) {
/* have the bus specific function add its stuff */ /* have the bus specific function add its stuff */
retval = class_dev->class->hotplug (class_dev, envp, num_envp, retval = class_dev->class->hotplug (class_dev, envp, num_envp,
...@@ -388,6 +371,12 @@ static void class_device_remove_attrs(struct class_device * cd) ...@@ -388,6 +371,12 @@ static void class_device_remove_attrs(struct class_device * cd)
} }
} }
static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
return print_dev_t(buf, class_dev->devt);
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
void class_device_initialize(struct class_device *class_dev) void class_device_initialize(struct class_device *class_dev)
{ {
kobj_set_kset_s(class_dev, class_obj_subsys); kobj_set_kset_s(class_dev, class_obj_subsys);
...@@ -425,16 +414,21 @@ int class_device_add(struct class_device *class_dev) ...@@ -425,16 +414,21 @@ int class_device_add(struct class_device *class_dev)
/* now take care of our own registration */ /* now take care of our own registration */
if (parent) { if (parent) {
down_write(&parent->subsys.rwsem); down(&parent->sem);
list_add_tail(&class_dev->node, &parent->children); list_add_tail(&class_dev->node, &parent->children);
list_for_each_entry(class_intf, &parent->interfaces, node) list_for_each_entry(class_intf, &parent->interfaces, node)
if (class_intf->add) if (class_intf->add)
class_intf->add(class_dev); class_intf->add(class_dev);
up_write(&parent->subsys.rwsem); up(&parent->sem);
} }
if (MAJOR(class_dev->devt))
class_device_create_file(class_dev, &class_device_attr_dev);
class_device_add_attrs(class_dev); class_device_add_attrs(class_dev);
class_device_dev_link(class_dev); if (class_dev->dev)
class_device_driver_link(class_dev); sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
register_done: register_done:
if (error && parent) if (error && parent)
...@@ -455,16 +449,16 @@ void class_device_del(struct class_device *class_dev) ...@@ -455,16 +449,16 @@ void class_device_del(struct class_device *class_dev)
struct class_interface * class_intf; struct class_interface * class_intf;
if (parent) { if (parent) {
down_write(&parent->subsys.rwsem); down(&parent->sem);
list_del_init(&class_dev->node); list_del_init(&class_dev->node);
list_for_each_entry(class_intf, &parent->interfaces, node) list_for_each_entry(class_intf, &parent->interfaces, node)
if (class_intf->remove) if (class_intf->remove)
class_intf->remove(class_dev); class_intf->remove(class_dev);
up_write(&parent->subsys.rwsem); up(&parent->sem);
} }
class_device_dev_unlink(class_dev); if (class_dev->dev)
class_device_driver_unlink(class_dev); sysfs_remove_link(&class_dev->kobj, "device");
class_device_remove_attrs(class_dev); class_device_remove_attrs(class_dev);
kobject_del(&class_dev->kobj); kobject_del(&class_dev->kobj);
...@@ -516,8 +510,8 @@ void class_device_put(struct class_device *class_dev) ...@@ -516,8 +510,8 @@ void class_device_put(struct class_device *class_dev)
int class_interface_register(struct class_interface *class_intf) int class_interface_register(struct class_interface *class_intf)
{ {
struct class * parent; struct class *parent;
struct class_device * class_dev; struct class_device *class_dev;
if (!class_intf || !class_intf->class) if (!class_intf || !class_intf->class)
return -ENODEV; return -ENODEV;
...@@ -526,14 +520,13 @@ int class_interface_register(struct class_interface *class_intf) ...@@ -526,14 +520,13 @@ int class_interface_register(struct class_interface *class_intf)
if (!parent) if (!parent)
return -EINVAL; return -EINVAL;
down_write(&parent->subsys.rwsem); down(&parent->sem);
list_add_tail(&class_intf->node, &parent->interfaces); list_add_tail(&class_intf->node, &parent->interfaces);
if (class_intf->add) { if (class_intf->add) {
list_for_each_entry(class_dev, &parent->children, node) list_for_each_entry(class_dev, &parent->children, node)
class_intf->add(class_dev); class_intf->add(class_dev);
} }
up_write(&parent->subsys.rwsem); up(&parent->sem);
return 0; return 0;
} }
...@@ -546,14 +539,13 @@ void class_interface_unregister(struct class_interface *class_intf) ...@@ -546,14 +539,13 @@ void class_interface_unregister(struct class_interface *class_intf)
if (!parent) if (!parent)
return; return;
down_write(&parent->subsys.rwsem); down(&parent->sem);
list_del_init(&class_intf->node); list_del_init(&class_intf->node);
if (class_intf->remove) { if (class_intf->remove) {
list_for_each_entry(class_dev, &parent->children, node) list_for_each_entry(class_dev, &parent->children, node)
class_intf->remove(class_dev); class_intf->remove(class_dev);
} }
up_write(&parent->subsys.rwsem); up(&parent->sem);
class_put(parent); class_put(parent);
} }
......
...@@ -10,18 +10,15 @@ ...@@ -10,18 +10,15 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/err.h> #include <linux/err.h>
struct class_simple { struct class_simple {
struct class_device_attribute attr;
struct class class; struct class class;
}; };
#define to_class_simple(d) container_of(d, struct class_simple, class) #define to_class_simple(d) container_of(d, struct class_simple, class)
struct simple_dev { struct simple_dev {
struct list_head node; struct list_head node;
dev_t dev;
struct class_device class_dev; struct class_device class_dev;
}; };
#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev) #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
...@@ -35,12 +32,6 @@ static void release_simple_dev(struct class_device *class_dev) ...@@ -35,12 +32,6 @@ static void release_simple_dev(struct class_device *class_dev)
kfree(s_dev); kfree(s_dev);
} }
static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
struct simple_dev *s_dev = to_simple_dev(class_dev);
return print_dev_t(buf, s_dev->dev);
}
static void class_simple_release(struct class *class) static void class_simple_release(struct class *class)
{ {
struct class_simple *cs = to_class_simple(class); struct class_simple *cs = to_class_simple(class);
...@@ -75,12 +66,6 @@ struct class_simple *class_simple_create(struct module *owner, char *name) ...@@ -75,12 +66,6 @@ struct class_simple *class_simple_create(struct module *owner, char *name)
cs->class.class_release = class_simple_release; cs->class.class_release = class_simple_release;
cs->class.release = release_simple_dev; cs->class.release = release_simple_dev;
cs->attr.attr.name = "dev";
cs->attr.attr.mode = S_IRUGO;
cs->attr.attr.owner = owner;
cs->attr.show = show_dev;
cs->attr.store = NULL;
retval = class_register(&cs->class); retval = class_register(&cs->class);
if (retval) if (retval)
goto error; goto error;
...@@ -143,7 +128,7 @@ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, ...@@ -143,7 +128,7 @@ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev,
} }
memset(s_dev, 0x00, sizeof(*s_dev)); memset(s_dev, 0x00, sizeof(*s_dev));
s_dev->dev = dev; s_dev->class_dev.devt = dev;
s_dev->class_dev.dev = device; s_dev->class_dev.dev = device;
s_dev->class_dev.class = &cs->class; s_dev->class_dev.class = &cs->class;
...@@ -154,8 +139,6 @@ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, ...@@ -154,8 +139,6 @@ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev,
if (retval) if (retval)
goto error; goto error;
class_device_create_file(&s_dev->class_dev, &cs->attr);
spin_lock(&simple_dev_list_lock); spin_lock(&simple_dev_list_lock);
list_add(&s_dev->node, &simple_dev_list); list_add(&s_dev->node, &simple_dev_list);
spin_unlock(&simple_dev_list_lock); spin_unlock(&simple_dev_list_lock);
...@@ -200,7 +183,7 @@ void class_simple_device_remove(dev_t dev) ...@@ -200,7 +183,7 @@ void class_simple_device_remove(dev_t dev)
spin_lock(&simple_dev_list_lock); spin_lock(&simple_dev_list_lock);
list_for_each_entry(s_dev, &simple_dev_list, node) { list_for_each_entry(s_dev, &simple_dev_list, node) {
if (s_dev->dev == dev) { if (s_dev->class_dev.devt == dev) {
found = 1; found = 1;
break; break;
} }
......
...@@ -79,14 +79,14 @@ void put_driver(struct device_driver * drv) ...@@ -79,14 +79,14 @@ void put_driver(struct device_driver * drv)
* since most of the things we have to do deal with the bus * since most of the things we have to do deal with the bus
* structures. * structures.
* *
* The one interesting aspect is that we initialize @drv->unload_sem * The one interesting aspect is that we setup @drv->unloaded
* to a locked state here. It will be unlocked when the driver * as a completion that gets complete when the driver reference
* reference count reaches 0. * count reaches 0.
*/ */
int driver_register(struct device_driver * drv) int driver_register(struct device_driver * drv)
{ {
INIT_LIST_HEAD(&drv->devices); INIT_LIST_HEAD(&drv->devices);
init_MUTEX_LOCKED(&drv->unload_sem); init_completion(&drv->unloaded);
return bus_add_driver(drv); return bus_add_driver(drv);
} }
...@@ -97,7 +97,7 @@ int driver_register(struct device_driver * drv) ...@@ -97,7 +97,7 @@ int driver_register(struct device_driver * drv)
* *
* Again, we pass off most of the work to the bus-level call. * Again, we pass off most of the work to the bus-level call.
* *
* Though, once that is done, we attempt to take @drv->unload_sem. * Though, once that is done, we wait until @drv->unloaded is completed.
* This will block until the driver refcount reaches 0, and it is * This will block until the driver refcount reaches 0, and it is
* released. Only modular drivers will call this function, and we * released. Only modular drivers will call this function, and we
* have to guarantee that it won't complete, letting the driver * have to guarantee that it won't complete, letting the driver
...@@ -107,8 +107,7 @@ int driver_register(struct device_driver * drv) ...@@ -107,8 +107,7 @@ int driver_register(struct device_driver * drv)
void driver_unregister(struct device_driver * drv) void driver_unregister(struct device_driver * drv)
{ {
bus_remove_driver(drv); bus_remove_driver(drv);
down(&drv->unload_sem); wait_for_completion(&drv->unloaded);
up(&drv->unload_sem);
} }
/** /**
......
...@@ -25,7 +25,7 @@ struct kobj_map { ...@@ -25,7 +25,7 @@ struct kobj_map {
int (*lock)(dev_t, void *); int (*lock)(dev_t, void *);
void *data; void *data;
} *probes[255]; } *probes[255];
struct rw_semaphore *sem; struct semaphore *sem;
}; };
int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
...@@ -53,7 +53,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, ...@@ -53,7 +53,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->range = range; p->range = range;
p->data = data; p->data = data;
} }
down_write(domain->sem); down(domain->sem);
for (i = 0, p -= n; i < n; i++, p++, index++) { for (i = 0, p -= n; i < n; i++, p++, index++) {
struct probe **s = &domain->probes[index % 255]; struct probe **s = &domain->probes[index % 255];
while (*s && (*s)->range < range) while (*s && (*s)->range < range)
...@@ -61,7 +61,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, ...@@ -61,7 +61,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->next = *s; p->next = *s;
*s = p; *s = p;
} }
up_write(domain->sem); up(domain->sem);
return 0; return 0;
} }
...@@ -75,7 +75,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) ...@@ -75,7 +75,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
if (n > 255) if (n > 255)
n = 255; n = 255;
down_write(domain->sem); down(domain->sem);
for (i = 0; i < n; i++, index++) { for (i = 0; i < n; i++, index++) {
struct probe **s; struct probe **s;
for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) { for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
...@@ -88,7 +88,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) ...@@ -88,7 +88,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
} }
} }
} }
up_write(domain->sem); up(domain->sem);
kfree(found); kfree(found);
} }
...@@ -99,7 +99,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) ...@@ -99,7 +99,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
unsigned long best = ~0UL; unsigned long best = ~0UL;
retry: retry:
down_read(domain->sem); down(domain->sem);
for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) { for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
struct kobject *(*probe)(dev_t, int *, void *); struct kobject *(*probe)(dev_t, int *, void *);
struct module *owner; struct module *owner;
...@@ -120,7 +120,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) ...@@ -120,7 +120,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
module_put(owner); module_put(owner);
continue; continue;
} }
up_read(domain->sem); up(domain->sem);
kobj = probe(dev, index, data); kobj = probe(dev, index, data);
/* Currently ->owner protects _only_ ->probe() itself. */ /* Currently ->owner protects _only_ ->probe() itself. */
module_put(owner); module_put(owner);
...@@ -128,12 +128,11 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) ...@@ -128,12 +128,11 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
return kobj; return kobj;
goto retry; goto retry;
} }
up_read(domain->sem); up(domain->sem);
return NULL; return NULL;
} }
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
struct subsystem *s)
{ {
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL); struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
...@@ -151,6 +150,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, ...@@ -151,6 +150,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,
base->get = base_probe; base->get = base_probe;
for (i = 0; i < 255; i++) for (i = 0; i < 255; i++)
p->probes[i] = base; p->probes[i] = base;
p->sem = &s->rwsem; p->sem = sem;
return p; return p;
} }
...@@ -131,7 +131,7 @@ int platform_device_register(struct platform_device * pdev) ...@@ -131,7 +131,7 @@ int platform_device_register(struct platform_device * pdev)
pdev->dev.bus = &platform_bus_type; pdev->dev.bus = &platform_bus_type;
if (pdev->id != -1) if (pdev->id != -1)
snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s%u", pdev->name, pdev->id); snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
else else
strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
......
...@@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file); ...@@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file);
/* /*
* declare system_subsys * declare system_subsys
*/ */
decl_subsys(system, &ktype_sysdev, NULL); static decl_subsys(system, &ktype_sysdev, NULL);
int sysdev_class_register(struct sysdev_class * cls) int sysdev_class_register(struct sysdev_class * cls)
{ {
...@@ -102,7 +102,8 @@ EXPORT_SYMBOL_GPL(sysdev_class_register); ...@@ -102,7 +102,8 @@ EXPORT_SYMBOL_GPL(sysdev_class_register);
EXPORT_SYMBOL_GPL(sysdev_class_unregister); EXPORT_SYMBOL_GPL(sysdev_class_unregister);
static LIST_HEAD(global_drivers); static LIST_HEAD(sysdev_drivers);
static DECLARE_MUTEX(sysdev_drivers_lock);
/** /**
* sysdev_driver_register - Register auxillary driver * sysdev_driver_register - Register auxillary driver
...@@ -112,14 +113,14 @@ static LIST_HEAD(global_drivers); ...@@ -112,14 +113,14 @@ static LIST_HEAD(global_drivers);
* If @cls is valid, then @drv is inserted into @cls->drivers to be * If @cls is valid, then @drv is inserted into @cls->drivers to be
* called on each operation on devices of that class. The refcount * called on each operation on devices of that class. The refcount
* of @cls is incremented. * of @cls is incremented.
* Otherwise, @drv is inserted into global_drivers, and called for * Otherwise, @drv is inserted into sysdev_drivers, and called for
* each device. * each device.
*/ */
int sysdev_driver_register(struct sysdev_class * cls, int sysdev_driver_register(struct sysdev_class * cls,
struct sysdev_driver * drv) struct sysdev_driver * drv)
{ {
down_write(&system_subsys.rwsem); down(&sysdev_drivers_lock);
if (cls && kset_get(&cls->kset)) { if (cls && kset_get(&cls->kset)) {
list_add_tail(&drv->entry, &cls->drivers); list_add_tail(&drv->entry, &cls->drivers);
...@@ -130,8 +131,8 @@ int sysdev_driver_register(struct sysdev_class * cls, ...@@ -130,8 +131,8 @@ int sysdev_driver_register(struct sysdev_class * cls,
drv->add(dev); drv->add(dev);
} }
} else } else
list_add_tail(&drv->entry, &global_drivers); list_add_tail(&drv->entry, &sysdev_drivers);
up_write(&system_subsys.rwsem); up(&sysdev_drivers_lock);
return 0; return 0;
} }
...@@ -144,7 +145,7 @@ int sysdev_driver_register(struct sysdev_class * cls, ...@@ -144,7 +145,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
void sysdev_driver_unregister(struct sysdev_class * cls, void sysdev_driver_unregister(struct sysdev_class * cls,
struct sysdev_driver * drv) struct sysdev_driver * drv)
{ {
down_write(&system_subsys.rwsem); down(&sysdev_drivers_lock);
list_del_init(&drv->entry); list_del_init(&drv->entry);
if (cls) { if (cls) {
if (drv->remove) { if (drv->remove) {
...@@ -154,7 +155,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls, ...@@ -154,7 +155,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
} }
kset_put(&cls->kset); kset_put(&cls->kset);
} }
up_write(&system_subsys.rwsem); up(&sysdev_drivers_lock);
} }
EXPORT_SYMBOL_GPL(sysdev_driver_register); EXPORT_SYMBOL_GPL(sysdev_driver_register);
...@@ -193,13 +194,13 @@ int sysdev_register(struct sys_device * sysdev) ...@@ -193,13 +194,13 @@ int sysdev_register(struct sys_device * sysdev)
if (!error) { if (!error) {
struct sysdev_driver * drv; struct sysdev_driver * drv;
down_write(&system_subsys.rwsem); down(&sysdev_drivers_lock);
/* Generic notification is implicit, because it's that /* Generic notification is implicit, because it's that
* code that should have called us. * code that should have called us.
*/ */
/* Notify global drivers */ /* Notify global drivers */
list_for_each_entry(drv, &global_drivers, entry) { list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->add) if (drv->add)
drv->add(sysdev); drv->add(sysdev);
} }
...@@ -209,7 +210,7 @@ int sysdev_register(struct sys_device * sysdev) ...@@ -209,7 +210,7 @@ int sysdev_register(struct sys_device * sysdev)
if (drv->add) if (drv->add)
drv->add(sysdev); drv->add(sysdev);
} }
up_write(&system_subsys.rwsem); up(&sysdev_drivers_lock);
} }
return error; return error;
} }
...@@ -218,8 +219,8 @@ void sysdev_unregister(struct sys_device * sysdev) ...@@ -218,8 +219,8 @@ void sysdev_unregister(struct sys_device * sysdev)
{ {
struct sysdev_driver * drv; struct sysdev_driver * drv;
down_write(&system_subsys.rwsem); down(&sysdev_drivers_lock);
list_for_each_entry(drv, &global_drivers, entry) { list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->remove) if (drv->remove)
drv->remove(sysdev); drv->remove(sysdev);
} }
...@@ -228,7 +229,7 @@ void sysdev_unregister(struct sys_device * sysdev) ...@@ -228,7 +229,7 @@ void sysdev_unregister(struct sys_device * sysdev)
if (drv->remove) if (drv->remove)
drv->remove(sysdev); drv->remove(sysdev);
} }
up_write(&system_subsys.rwsem); up(&sysdev_drivers_lock);
kobject_unregister(&sysdev->kobj); kobject_unregister(&sysdev->kobj);
} }
...@@ -255,7 +256,7 @@ void sysdev_shutdown(void) ...@@ -255,7 +256,7 @@ void sysdev_shutdown(void)
pr_debug("Shutting Down System Devices\n"); pr_debug("Shutting Down System Devices\n");
down_write(&system_subsys.rwsem); down(&sysdev_drivers_lock);
list_for_each_entry_reverse(cls, &system_subsys.kset.list, list_for_each_entry_reverse(cls, &system_subsys.kset.list,
kset.kobj.entry) { kset.kobj.entry) {
struct sys_device * sysdev; struct sys_device * sysdev;
...@@ -268,7 +269,7 @@ void sysdev_shutdown(void) ...@@ -268,7 +269,7 @@ void sysdev_shutdown(void)
pr_debug(" %s\n", kobject_name(&sysdev->kobj)); pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */ /* Call global drivers first. */
list_for_each_entry(drv, &global_drivers, entry) { list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->shutdown) if (drv->shutdown)
drv->shutdown(sysdev); drv->shutdown(sysdev);
} }
...@@ -284,7 +285,7 @@ void sysdev_shutdown(void) ...@@ -284,7 +285,7 @@ void sysdev_shutdown(void)
cls->shutdown(sysdev); cls->shutdown(sysdev);
} }
} }
up_write(&system_subsys.rwsem); up(&sysdev_drivers_lock);
} }
...@@ -319,7 +320,7 @@ int sysdev_suspend(u32 state) ...@@ -319,7 +320,7 @@ int sysdev_suspend(u32 state)
pr_debug(" %s\n", kobject_name(&sysdev->kobj)); pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */ /* Call global drivers first. */
list_for_each_entry(drv, &global_drivers, entry) { list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->suspend) if (drv->suspend)
drv->suspend(sysdev, state); drv->suspend(sysdev, state);
} }
...@@ -375,7 +376,7 @@ int sysdev_resume(void) ...@@ -375,7 +376,7 @@ int sysdev_resume(void)
} }
/* Call global drivers. */ /* Call global drivers. */
list_for_each_entry(drv, &global_drivers, entry) { list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->resume) if (drv->resume)
drv->resume(sysdev); drv->resume(sysdev);
} }
......
...@@ -4370,6 +4370,10 @@ int __init floppy_init(void) ...@@ -4370,6 +4370,10 @@ int __init floppy_init(void)
goto out_flush_work; goto out_flush_work;
} }
err = platform_device_register(&floppy_device);
if (err)
goto out_flush_work;
for (drive = 0; drive < N_DRIVE; drive++) { for (drive = 0; drive < N_DRIVE; drive++) {
if (!(allowed_drive_mask & (1 << drive))) if (!(allowed_drive_mask & (1 << drive)))
continue; continue;
...@@ -4379,23 +4383,12 @@ int __init floppy_init(void) ...@@ -4379,23 +4383,12 @@ int __init floppy_init(void)
disks[drive]->private_data = (void *)(long)drive; disks[drive]->private_data = (void *)(long)drive;
disks[drive]->queue = floppy_queue; disks[drive]->queue = floppy_queue;
disks[drive]->flags |= GENHD_FL_REMOVABLE; disks[drive]->flags |= GENHD_FL_REMOVABLE;
disks[drive]->driverfs_dev = &floppy_device.dev;
add_disk(disks[drive]); add_disk(disks[drive]);
} }
err = platform_device_register(&floppy_device);
if (err)
goto out_del_disk;
return 0; return 0;
out_del_disk:
for (drive = 0; drive < N_DRIVE; drive++) {
if (!(allowed_drive_mask & (1 << drive)))
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
del_gendisk(disks[drive]);
}
out_flush_work: out_flush_work:
flush_scheduled_work(); flush_scheduled_work();
if (usage_count) if (usage_count)
...@@ -4600,7 +4593,6 @@ void cleanup_module(void) ...@@ -4600,7 +4593,6 @@ void cleanup_module(void)
int drive; int drive;
init_completion(&device_release); init_completion(&device_release);
platform_device_unregister(&floppy_device);
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
unregister_blkdev(FLOPPY_MAJOR, "fd"); unregister_blkdev(FLOPPY_MAJOR, "fd");
...@@ -4614,6 +4606,7 @@ void cleanup_module(void) ...@@ -4614,6 +4606,7 @@ void cleanup_module(void)
} }
put_disk(disks[drive]); put_disk(disks[drive]);
} }
platform_device_unregister(&floppy_device);
devfs_remove("floppy"); devfs_remove("floppy");
del_timer_sync(&fd_timeout); del_timer_sync(&fd_timeout);
......
...@@ -302,7 +302,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data) ...@@ -302,7 +302,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
static int __init genhd_device_init(void) static int __init genhd_device_init(void)
{ {
bdev_map = kobj_map_init(base_probe, &block_subsys); bdev_map = kobj_map_init(base_probe, &block_subsys_sem);
blk_dev_init(); blk_dev_init();
subsystem_register(&block_subsys); subsystem_register(&block_subsys);
return 0; return 0;
...@@ -430,43 +430,58 @@ static int block_hotplug_filter(struct kset *kset, struct kobject *kobj) ...@@ -430,43 +430,58 @@ static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp, static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size) int num_envp, char *buffer, int buffer_size)
{ {
struct device *dev = NULL;
struct kobj_type *ktype = get_ktype(kobj); struct kobj_type *ktype = get_ktype(kobj);
struct device *physdev;
struct gendisk *disk;
struct hd_struct *part;
int length = 0; int length = 0;
int i = 0; int i = 0;
/* get physical device backing disk or partition */
if (ktype == &ktype_block) { if (ktype == &ktype_block) {
struct gendisk *disk = container_of(kobj, struct gendisk, kobj); disk = container_of(kobj, struct gendisk, kobj);
dev = disk->driverfs_dev; add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
&length, "MINOR=%u", disk->first_minor);
} else if (ktype == &ktype_part) { } else if (ktype == &ktype_part) {
struct gendisk *disk = container_of(kobj->parent, struct gendisk, kobj); disk = container_of(kobj->parent, struct gendisk, kobj);
dev = disk->driverfs_dev; part = container_of(kobj, struct hd_struct, kobj);
} add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
&length, "MINOR=%u",
disk->first_minor + part->partno);
} else
return 0;
if (dev) { add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length,
/* add physical device, backing this device */ "MAJOR=%u", disk->major);
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
/* add physical device, backing this device */
physdev = disk->driverfs_dev;
if (physdev) {
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
&length, "PHYSDEVPATH=%s", path); &length, "PHYSDEVPATH=%s", path);
kfree(path); kfree(path);
/* add bus name of physical device */ if (physdev->bus)
if (dev->bus)
add_hotplug_env_var(envp, num_envp, &i, add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length, buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name); "PHYSDEVBUS=%s",
physdev->bus->name);
/* add driver name of physical device */ if (physdev->driver)
if (dev->driver)
add_hotplug_env_var(envp, num_envp, &i, add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length, buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name); "PHYSDEVDRIVER=%s",
physdev->driver->name);
envp[i] = NULL;
} }
/* terminate, set to next free slot, shrink available space */
envp[i] = NULL;
envp = &envp[i];
num_envp -= i;
buffer = &buffer[length];
buffer_size -= length;
return 0; return 0;
} }
......
...@@ -108,13 +108,6 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) ...@@ -108,13 +108,6 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
spin_unlock(&i2c_dev_array_lock); spin_unlock(&i2c_dev_array_lock);
} }
static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
return print_dev_t(buf, MKDEV(I2C_MAJOR, i2c_dev->minor));
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf) static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
{ {
struct i2c_dev *i2c_dev = to_i2c_dev(class_dev); struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
...@@ -451,11 +444,11 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) ...@@ -451,11 +444,11 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
else else
i2c_dev->class_dev.dev = adap->dev.parent; i2c_dev->class_dev.dev = adap->dev.parent;
i2c_dev->class_dev.class = &i2c_dev_class; i2c_dev->class_dev.class = &i2c_dev_class;
i2c_dev->class_dev.devt = MKDEV(I2C_MAJOR, i2c_dev->minor);
snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor); snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor);
retval = class_device_register(&i2c_dev->class_dev); retval = class_device_register(&i2c_dev->class_dev);
if (retval) if (retval)
goto error; goto error;
class_device_create_file(&i2c_dev->class_dev, &class_device_attr_dev);
class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name); class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name);
return 0; return 0;
error: error:
......
...@@ -46,15 +46,7 @@ static ssize_t show_name(struct class_device *cd, char *buf) ...@@ -46,15 +46,7 @@ static ssize_t show_name(struct class_device *cd, char *buf)
return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name); return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name);
} }
static ssize_t show_dev(struct class_device *cd, char *buf)
{
struct video_device *vfd = container_of(cd, struct video_device, class_dev);
dev_t dev = MKDEV(VIDEO_MAJOR, vfd->minor);
return print_dev_t(buf,dev);
}
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
struct video_device *video_device_alloc(void) struct video_device *video_device_alloc(void)
{ {
...@@ -347,12 +339,11 @@ int video_register_device(struct video_device *vfd, int type, int nr) ...@@ -347,12 +339,11 @@ int video_register_device(struct video_device *vfd, int type, int nr)
if (vfd->dev) if (vfd->dev)
vfd->class_dev.dev = vfd->dev; vfd->class_dev.dev = vfd->dev;
vfd->class_dev.class = &video_class; vfd->class_dev.class = &video_class;
vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
strlcpy(vfd->class_dev.class_id, vfd->devfs_name + 4, BUS_ID_SIZE); strlcpy(vfd->class_dev.class_id, vfd->devfs_name + 4, BUS_ID_SIZE);
class_device_register(&vfd->class_dev); class_device_register(&vfd->class_dev);
class_device_create_file(&vfd->class_dev, class_device_create_file(&vfd->class_dev,
&class_device_attr_name); &class_device_attr_name);
class_device_create_file(&vfd->class_dev,
&class_device_attr_dev);
#if 1 /* needed until all drivers are fixed */ #if 1 /* needed until all drivers are fixed */
if (!vfd->release) if (!vfd->release)
......
...@@ -66,16 +66,7 @@ static struct file_operations usb_fops = { ...@@ -66,16 +66,7 @@ static struct file_operations usb_fops = {
.open = usb_open, .open = usb_open,
}; };
static void release_usb_class_dev(struct class_device *class_dev) static struct class_simple *usb_class;
{
dbg("%s - %s", __FUNCTION__, class_dev->class_id);
kfree(class_dev);
}
static struct class usb_class = {
.name = "usb",
.release = &release_usb_class_dev,
};
int usb_major_init(void) int usb_major_init(void)
{ {
...@@ -87,9 +78,9 @@ int usb_major_init(void) ...@@ -87,9 +78,9 @@ int usb_major_init(void)
goto out; goto out;
} }
error = class_register(&usb_class); usb_class = class_simple_create(THIS_MODULE, "usb");
if (error) { if (IS_ERR(usb_class)) {
err("class_register failed for usb devices"); err("class_simple_create failed for usb devices");
unregister_chrdev(USB_MAJOR, "usb"); unregister_chrdev(USB_MAJOR, "usb");
goto out; goto out;
} }
...@@ -102,18 +93,11 @@ int usb_major_init(void) ...@@ -102,18 +93,11 @@ int usb_major_init(void)
void usb_major_cleanup(void) void usb_major_cleanup(void)
{ {
class_unregister(&usb_class); class_simple_destroy(usb_class);
devfs_remove("usb"); devfs_remove("usb");
unregister_chrdev(USB_MAJOR, "usb"); unregister_chrdev(USB_MAJOR, "usb");
} }
static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
int minor = (int)(long)class_get_devdata(class_dev);
return print_dev_t(buf, MKDEV(USB_MAJOR, minor));
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
/** /**
* usb_register_dev - register a USB device, and ask for a minor number * usb_register_dev - register a USB device, and ask for a minor number
* @intf: pointer to the usb_interface that is being registered * @intf: pointer to the usb_interface that is being registered
...@@ -141,7 +125,6 @@ int usb_register_dev(struct usb_interface *intf, ...@@ -141,7 +125,6 @@ int usb_register_dev(struct usb_interface *intf,
int minor_base = class_driver->minor_base; int minor_base = class_driver->minor_base;
int minor = 0; int minor = 0;
char name[BUS_ID_SIZE]; char name[BUS_ID_SIZE];
struct class_device *class_dev;
char *temp; char *temp;
#ifdef CONFIG_USB_DYNAMIC_MINORS #ifdef CONFIG_USB_DYNAMIC_MINORS
...@@ -181,22 +164,18 @@ int usb_register_dev(struct usb_interface *intf, ...@@ -181,22 +164,18 @@ int usb_register_dev(struct usb_interface *intf,
devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name); devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
/* create a usb class device for this usb interface */ /* create a usb class device for this usb interface */
class_dev = kmalloc(sizeof(*class_dev), GFP_KERNEL); temp = strrchr(name, '/');
if (class_dev) { if (temp && (temp[1] != 0x00))
memset(class_dev, 0x00, sizeof(struct class_device)); ++temp;
class_dev->class = &usb_class; else
class_dev->dev = &intf->dev; temp = name;
intf->class_dev = class_simple_device_add(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
temp = strrchr(name, '/'); if (IS_ERR(intf->class_dev)) {
if (temp && (temp[1] != 0x00)) spin_lock (&minor_lock);
++temp; usb_minors[intf->minor] = NULL;
else spin_unlock (&minor_lock);
temp = name; devfs_remove (name);
snprintf(class_dev->class_id, BUS_ID_SIZE, "%s", temp); retval = PTR_ERR(intf->class_dev);
class_set_devdata(class_dev, (void *)(long)intf->minor);
class_device_register(class_dev);
class_device_create_file(class_dev, &class_device_attr_dev);
intf->class_dev = class_dev;
} }
exit: exit:
return retval; return retval;
...@@ -239,11 +218,8 @@ void usb_deregister_dev(struct usb_interface *intf, ...@@ -239,11 +218,8 @@ void usb_deregister_dev(struct usb_interface *intf,
snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
devfs_remove (name); devfs_remove (name);
class_simple_device_remove(MKDEV(USB_MAJOR, intf->minor));
if (intf->class_dev) { intf->class_dev = NULL;
class_device_unregister(intf->class_dev);
intf->class_dev = NULL;
}
intf->minor = -1; intf->minor = -1;
} }
EXPORT_SYMBOL(usb_deregister_dev); EXPORT_SYMBOL(usb_deregister_dev);
......
...@@ -29,7 +29,7 @@ static struct kobj_map *cdev_map; ...@@ -29,7 +29,7 @@ static struct kobj_map *cdev_map;
/* degrade to linked list for small systems */ /* degrade to linked list for small systems */
#define MAX_PROBE_HASH (CONFIG_BASE_SMALL ? 1 : 255) #define MAX_PROBE_HASH (CONFIG_BASE_SMALL ? 1 : 255)
static DEFINE_RWLOCK(chrdevs_lock); static DECLARE_MUTEX(chrdevs_lock);
static struct char_device_struct { static struct char_device_struct {
struct char_device_struct *next; struct char_device_struct *next;
...@@ -55,13 +55,13 @@ int get_chrdev_list(char *page) ...@@ -55,13 +55,13 @@ int get_chrdev_list(char *page)
len = sprintf(page, "Character devices:\n"); len = sprintf(page, "Character devices:\n");
read_lock(&chrdevs_lock); down(&chrdevs_lock);
for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
for (cd = chrdevs[i]; cd; cd = cd->next) for (cd = chrdevs[i]; cd; cd = cd->next)
len += sprintf(page+len, "%3d %s\n", len += sprintf(page+len, "%3d %s\n",
cd->major, cd->name); cd->major, cd->name);
} }
read_unlock(&chrdevs_lock); up(&chrdevs_lock);
return len; return len;
} }
...@@ -91,7 +91,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, ...@@ -91,7 +91,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
memset(cd, 0, sizeof(struct char_device_struct)); memset(cd, 0, sizeof(struct char_device_struct));
write_lock_irq(&chrdevs_lock); down(&chrdevs_lock);
/* temporary */ /* temporary */
if (major == 0) { if (major == 0) {
...@@ -126,10 +126,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, ...@@ -126,10 +126,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
} }
cd->next = *cp; cd->next = *cp;
*cp = cd; *cp = cd;
write_unlock_irq(&chrdevs_lock); up(&chrdevs_lock);
return cd; return cd;
out: out:
write_unlock_irq(&chrdevs_lock); up(&chrdevs_lock);
kfree(cd); kfree(cd);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -140,7 +140,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) ...@@ -140,7 +140,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
struct char_device_struct *cd = NULL, **cp; struct char_device_struct *cd = NULL, **cp;
int i = major_to_index(major); int i = major_to_index(major);
write_lock_irq(&chrdevs_lock); up(&chrdevs_lock);
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major == major && if ((*cp)->major == major &&
(*cp)->baseminor == baseminor && (*cp)->baseminor == baseminor &&
...@@ -150,7 +150,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) ...@@ -150,7 +150,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
cd = *cp; cd = *cp;
*cp = cd->next; *cp = cd->next;
} }
write_unlock_irq(&chrdevs_lock); up(&chrdevs_lock);
return cd; return cd;
} }
...@@ -381,8 +381,6 @@ void cdev_del(struct cdev *p) ...@@ -381,8 +381,6 @@ void cdev_del(struct cdev *p)
} }
static decl_subsys(cdev, NULL, NULL);
static void cdev_default_release(struct kobject *kobj) static void cdev_default_release(struct kobject *kobj)
{ {
struct cdev *p = container_of(kobj, struct cdev, kobj); struct cdev *p = container_of(kobj, struct cdev, kobj);
...@@ -435,13 +433,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data) ...@@ -435,13 +433,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
void __init chrdev_init(void) void __init chrdev_init(void)
{ {
/* cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
* Keep cdev_subsys around because (and only because) the kobj_map code
* depends on the rwsem it contains. We don't make it public in sysfs,
* however.
*/
subsystem_init(&cdev_subsys);
cdev_map = kobj_map_init(base_probe, &cdev_subsys);
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm.h> #include <linux/pm.h>
...@@ -102,7 +101,7 @@ struct device_driver { ...@@ -102,7 +101,7 @@ struct device_driver {
char * name; char * name;
struct bus_type * bus; struct bus_type * bus;
struct semaphore unload_sem; struct completion unloaded;
struct kobject kobj; struct kobject kobj;
struct list_head devices; struct list_head devices;
...@@ -148,6 +147,7 @@ struct class { ...@@ -148,6 +147,7 @@ struct class {
struct subsystem subsys; struct subsystem subsys;
struct list_head children; struct list_head children;
struct list_head interfaces; struct list_head interfaces;
struct semaphore sem; /* locks both the children and interfaces lists */
struct class_attribute * class_attrs; struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs; struct class_device_attribute * class_dev_attrs;
...@@ -184,6 +184,7 @@ struct class_device { ...@@ -184,6 +184,7 @@ struct class_device {
struct kobject kobj; struct kobject kobj;
struct class * class; /* required */ struct class * class; /* required */
dev_t devt; /* dev_t, creates the sysfs "dev" */
struct device * dev; /* not necessary, but nice to have */ struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */ void * class_data; /* class-specific data */
......
...@@ -7,6 +7,6 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *, ...@@ -7,6 +7,6 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
kobj_probe_t *, int (*)(dev_t, void *), void *); kobj_probe_t *, int (*)(dev_t, void *), void *);
void kobj_unmap(struct kobj_map *, dev_t, unsigned long); void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *); struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
struct kobj_map *kobj_map_init(kobj_probe_t *, struct subsystem *); struct kobj_map *kobj_map_init(kobj_probe_t *, struct semaphore *);
#endif #endif
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/spinlock.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/kobject_uevent.h> #include <linux/kobject_uevent.h>
...@@ -102,6 +103,7 @@ struct kset { ...@@ -102,6 +103,7 @@ struct kset {
struct subsystem * subsys; struct subsystem * subsys;
struct kobj_type * ktype; struct kobj_type * ktype;
struct list_head list; struct list_head list;
spinlock_t list_lock;
struct kobject kobj; struct kobject kobj;
struct kset_hotplug_ops * hotplug_ops; struct kset_hotplug_ops * hotplug_ops;
}; };
......
...@@ -26,7 +26,7 @@ struct kref { ...@@ -26,7 +26,7 @@ struct kref {
void kref_init(struct kref *kref); void kref_init(struct kref *kref);
void kref_get(struct kref *kref); void kref_get(struct kref *kref);
void kref_put(struct kref *kref, void (*release) (struct kref *kref)); int kref_put(struct kref *kref, void (*release) (struct kref *kref));
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _KREF_H_ */ #endif /* _KREF_H_ */
...@@ -140,9 +140,9 @@ void kobject_init(struct kobject * kobj) ...@@ -140,9 +140,9 @@ void kobject_init(struct kobject * kobj)
static void unlink(struct kobject * kobj) static void unlink(struct kobject * kobj)
{ {
if (kobj->kset) { if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem); spin_lock(&kobj->kset->list_lock);
list_del_init(&kobj->entry); list_del_init(&kobj->entry);
up_write(&kobj->kset->subsys->rwsem); spin_unlock(&kobj->kset->list_lock);
} }
kobject_put(kobj); kobject_put(kobj);
} }
...@@ -168,13 +168,13 @@ int kobject_add(struct kobject * kobj) ...@@ -168,13 +168,13 @@ int kobject_add(struct kobject * kobj)
kobj->kset ? kobj->kset->kobj.name : "<NULL>" ); kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
if (kobj->kset) { if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem); spin_lock(&kobj->kset->list_lock);
if (!parent) if (!parent)
parent = kobject_get(&kobj->kset->kobj); parent = kobject_get(&kobj->kset->kobj);
list_add_tail(&kobj->entry,&kobj->kset->list); list_add_tail(&kobj->entry,&kobj->kset->list);
up_write(&kobj->kset->subsys->rwsem); spin_unlock(&kobj->kset->list_lock);
} }
kobj->parent = parent; kobj->parent = parent;
...@@ -380,6 +380,7 @@ void kset_init(struct kset * k) ...@@ -380,6 +380,7 @@ void kset_init(struct kset * k)
{ {
kobject_init(&k->kobj); kobject_init(&k->kobj);
INIT_LIST_HEAD(&k->list); INIT_LIST_HEAD(&k->list);
spin_lock_init(&k->list_lock);
} }
...@@ -444,7 +445,7 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name) ...@@ -444,7 +445,7 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
struct list_head * entry; struct list_head * entry;
struct kobject * ret = NULL; struct kobject * ret = NULL;
down_read(&kset->subsys->rwsem); spin_lock(&kset->list_lock);
list_for_each(entry,&kset->list) { list_for_each(entry,&kset->list) {
struct kobject * k = to_kobj(entry); struct kobject * k = to_kobj(entry);
if (kobject_name(k) && !strcmp(kobject_name(k),name)) { if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
...@@ -452,7 +453,7 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name) ...@@ -452,7 +453,7 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
break; break;
} }
} }
up_read(&kset->subsys->rwsem); spin_unlock(&kset->list_lock);
return ret; return ret;
} }
...@@ -524,7 +525,6 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a) ...@@ -524,7 +525,6 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
} }
} }
EXPORT_SYMBOL(kobject_get_path);
EXPORT_SYMBOL(kobject_init); EXPORT_SYMBOL(kobject_init);
EXPORT_SYMBOL(kobject_register); EXPORT_SYMBOL(kobject_register);
EXPORT_SYMBOL(kobject_unregister); EXPORT_SYMBOL(kobject_unregister);
...@@ -532,7 +532,6 @@ EXPORT_SYMBOL(kobject_get); ...@@ -532,7 +532,6 @@ EXPORT_SYMBOL(kobject_get);
EXPORT_SYMBOL(kobject_put); EXPORT_SYMBOL(kobject_put);
EXPORT_SYMBOL(kobject_add); EXPORT_SYMBOL(kobject_add);
EXPORT_SYMBOL(kobject_del); EXPORT_SYMBOL(kobject_del);
EXPORT_SYMBOL(kobject_rename);
EXPORT_SYMBOL(kset_register); EXPORT_SYMBOL(kset_register);
EXPORT_SYMBOL(kset_unregister); EXPORT_SYMBOL(kset_unregister);
......
...@@ -42,14 +42,21 @@ void kref_get(struct kref *kref) ...@@ -42,14 +42,21 @@ void kref_get(struct kref *kref)
* in as this function. * in as this function.
* *
* Decrement the refcount, and if 0, call release(). * Decrement the refcount, and if 0, call release().
* Return 1 if the object was removed, otherwise return 0. Beware, if this
* function returns 0, you still can not count on the kref from remaining in
* memory. Only use the return value if you want to see if the kref is now
* gone, not present.
*/ */
void kref_put(struct kref *kref, void (*release) (struct kref *kref)) int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{ {
WARN_ON(release == NULL); WARN_ON(release == NULL);
WARN_ON(release == (void (*)(struct kref *))kfree); WARN_ON(release == (void (*)(struct kref *))kfree);
if (atomic_dec_and_test(&kref->refcount)) if (atomic_dec_and_test(&kref->refcount)) {
release(kref); release(kref);
return 1;
}
return 0;
} }
EXPORT_SYMBOL(kref_init); EXPORT_SYMBOL(kref_init);
......
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