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
against the LSB, and can be replaced by using udev.
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 = {
static void driver_release(struct kobject * kobj)
{
struct device_driver * drv = to_driver(kobj);
up(&drv->unload_sem);
complete(&drv->unloaded);
}
static struct kobj_type ktype_driver = {
......@@ -465,6 +465,7 @@ int bus_add_device(struct device * dev)
up_write(&dev->bus->subsys.rwsem);
device_add_attrs(bus, dev);
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
}
return error;
}
......@@ -481,6 +482,7 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
sysfs_remove_link(&dev->kobj, "bus");
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev);
down_write(&dev->bus->subsys.rwsem);
......
......@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
......@@ -139,6 +140,7 @@ int class_register(struct class * cls)
INIT_LIST_HEAD(&cls->children);
INIT_LIST_HEAD(&cls->interfaces);
init_MUTEX(&cls->sem);
error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
if (error)
return error;
......@@ -195,33 +197,6 @@ void class_device_remove_bin_file(struct class_device *class_dev,
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
class_device_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf)
......@@ -298,9 +273,9 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct class_device *class_dev = to_class_dev(kobj);
int retval = 0;
int i = 0;
int length = 0;
int retval = 0;
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,
&length, "PHYSDEVPATH=%s", path);
kfree(path);
/* add bus name of physical device */
if (dev->bus)
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name);
/* add driver name of physical device */
if (dev->driver)
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"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 */
envp[i] = NULL;
envp = &envp[i];
num_envp -= i;
buffer = &buffer[length];
buffer_size -= length;
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MINOR=%u", MINOR(class_dev->devt));
}
/* 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) {
/* have the bus specific function add its stuff */
retval = class_dev->class->hotplug (class_dev, envp, num_envp,
......@@ -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)
{
kobj_set_kset_s(class_dev, class_obj_subsys);
......@@ -425,16 +414,21 @@ int class_device_add(struct class_device *class_dev)
/* now take care of our own registration */
if (parent) {
down_write(&parent->subsys.rwsem);
down(&parent->sem);
list_add_tail(&class_dev->node, &parent->children);
list_for_each_entry(class_intf, &parent->interfaces, node)
if (class_intf->add)
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_dev_link(class_dev);
class_device_driver_link(class_dev);
if (class_dev->dev)
sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
register_done:
if (error && parent)
......@@ -455,16 +449,16 @@ void class_device_del(struct class_device *class_dev)
struct class_interface * class_intf;
if (parent) {
down_write(&parent->subsys.rwsem);
down(&parent->sem);
list_del_init(&class_dev->node);
list_for_each_entry(class_intf, &parent->interfaces, node)
if (class_intf->remove)
class_intf->remove(class_dev);
up_write(&parent->subsys.rwsem);
up(&parent->sem);
}
class_device_dev_unlink(class_dev);
class_device_driver_unlink(class_dev);
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device");
class_device_remove_attrs(class_dev);
kobject_del(&class_dev->kobj);
......@@ -516,8 +510,8 @@ void class_device_put(struct class_device *class_dev)
int class_interface_register(struct class_interface *class_intf)
{
struct class * parent;
struct class_device * class_dev;
struct class *parent;
struct class_device *class_dev;
if (!class_intf || !class_intf->class)
return -ENODEV;
......@@ -526,14 +520,13 @@ int class_interface_register(struct class_interface *class_intf)
if (!parent)
return -EINVAL;
down_write(&parent->subsys.rwsem);
down(&parent->sem);
list_add_tail(&class_intf->node, &parent->interfaces);
if (class_intf->add) {
list_for_each_entry(class_dev, &parent->children, node)
class_intf->add(class_dev);
}
up_write(&parent->subsys.rwsem);
up(&parent->sem);
return 0;
}
......@@ -546,14 +539,13 @@ void class_interface_unregister(struct class_interface *class_intf)
if (!parent)
return;
down_write(&parent->subsys.rwsem);
down(&parent->sem);
list_del_init(&class_intf->node);
if (class_intf->remove) {
list_for_each_entry(class_dev, &parent->children, node)
class_intf->remove(class_dev);
}
up_write(&parent->subsys.rwsem);
up(&parent->sem);
class_put(parent);
}
......
......@@ -10,18 +10,15 @@
#include <linux/config.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/err.h>
struct class_simple {
struct class_device_attribute attr;
struct class class;
};
#define to_class_simple(d) container_of(d, struct class_simple, class)
struct simple_dev {
struct list_head node;
dev_t dev;
struct class_device 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)
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)
{
struct class_simple *cs = to_class_simple(class);
......@@ -75,12 +66,6 @@ struct class_simple *class_simple_create(struct module *owner, char *name)
cs->class.class_release = class_simple_release;
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);
if (retval)
goto error;
......@@ -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));
s_dev->dev = dev;
s_dev->class_dev.devt = dev;
s_dev->class_dev.dev = device;
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,
if (retval)
goto error;
class_device_create_file(&s_dev->class_dev, &cs->attr);
spin_lock(&simple_dev_list_lock);
list_add(&s_dev->node, &simple_dev_list);
spin_unlock(&simple_dev_list_lock);
......@@ -200,7 +183,7 @@ void class_simple_device_remove(dev_t dev)
spin_lock(&simple_dev_list_lock);
list_for_each_entry(s_dev, &simple_dev_list, node) {
if (s_dev->dev == dev) {
if (s_dev->class_dev.devt == dev) {
found = 1;
break;
}
......
......@@ -79,14 +79,14 @@ void put_driver(struct device_driver * drv)
* since most of the things we have to do deal with the bus
* structures.
*
* The one interesting aspect is that we initialize @drv->unload_sem
* to a locked state here. It will be unlocked when the driver
* reference count reaches 0.
* The one interesting aspect is that we setup @drv->unloaded
* as a completion that gets complete when the driver reference
* count reaches 0.
*/
int driver_register(struct device_driver * drv)
{
INIT_LIST_HEAD(&drv->devices);
init_MUTEX_LOCKED(&drv->unload_sem);
init_completion(&drv->unloaded);
return bus_add_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.
*
* 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
* released. Only modular drivers will call this function, and we
* have to guarantee that it won't complete, letting the driver
......@@ -107,8 +107,7 @@ int driver_register(struct device_driver * drv)
void driver_unregister(struct device_driver * drv)
{
bus_remove_driver(drv);
down(&drv->unload_sem);
up(&drv->unload_sem);
wait_for_completion(&drv->unloaded);
}
/**
......
......@@ -25,7 +25,7 @@ struct kobj_map {
int (*lock)(dev_t, void *);
void *data;
} *probes[255];
struct rw_semaphore *sem;
struct semaphore *sem;
};
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->data = data;
}
down_write(domain->sem);
down(domain->sem);
for (i = 0, p -= n; i < n; i++, p++, index++) {
struct probe **s = &domain->probes[index % 255];
while (*s && (*s)->range < range)
......@@ -61,7 +61,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->next = *s;
*s = p;
}
up_write(domain->sem);
up(domain->sem);
return 0;
}
......@@ -75,7 +75,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
if (n > 255)
n = 255;
down_write(domain->sem);
down(domain->sem);
for (i = 0; i < n; i++, index++) {
struct probe **s;
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)
}
}
}
up_write(domain->sem);
up(domain->sem);
kfree(found);
}
......@@ -99,7 +99,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
unsigned long best = ~0UL;
retry:
down_read(domain->sem);
down(domain->sem);
for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
struct kobject *(*probe)(dev_t, int *, void *);
struct module *owner;
......@@ -120,7 +120,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
module_put(owner);
continue;
}
up_read(domain->sem);
up(domain->sem);
kobj = probe(dev, index, data);
/* Currently ->owner protects _only_ ->probe() itself. */
module_put(owner);
......@@ -128,12 +128,11 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
return kobj;
goto retry;
}
up_read(domain->sem);
up(domain->sem);
return NULL;
}
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,
struct subsystem *s)
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
{
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), 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,
base->get = base_probe;
for (i = 0; i < 255; i++)
p->probes[i] = base;
p->sem = &s->rwsem;
p->sem = sem;
return p;
}
......@@ -131,7 +131,7 @@ int platform_device_register(struct platform_device * pdev)
pdev->dev.bus = &platform_bus_type;
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
strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
......
......@@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file);
/*
* declare system_subsys
*/
decl_subsys(system, &ktype_sysdev, NULL);
static decl_subsys(system, &ktype_sysdev, NULL);
int sysdev_class_register(struct sysdev_class * cls)
{
......@@ -102,7 +102,8 @@ EXPORT_SYMBOL_GPL(sysdev_class_register);
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
......@@ -112,14 +113,14 @@ static LIST_HEAD(global_drivers);
* If @cls is valid, then @drv is inserted into @cls->drivers to be
* called on each operation on devices of that class. The refcount
* 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.
*/
int sysdev_driver_register(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
down_write(&system_subsys.rwsem);
down(&sysdev_drivers_lock);
if (cls && kset_get(&cls->kset)) {
list_add_tail(&drv->entry, &cls->drivers);
......@@ -130,8 +131,8 @@ int sysdev_driver_register(struct sysdev_class * cls,
drv->add(dev);
}
} else
list_add_tail(&drv->entry, &global_drivers);
up_write(&system_subsys.rwsem);
list_add_tail(&drv->entry, &sysdev_drivers);
up(&sysdev_drivers_lock);
return 0;
}
......@@ -144,7 +145,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
void sysdev_driver_unregister(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
down_write(&system_subsys.rwsem);
down(&sysdev_drivers_lock);
list_del_init(&drv->entry);
if (cls) {
if (drv->remove) {
......@@ -154,7 +155,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
}
kset_put(&cls->kset);
}
up_write(&system_subsys.rwsem);
up(&sysdev_drivers_lock);
}
EXPORT_SYMBOL_GPL(sysdev_driver_register);
......@@ -193,13 +194,13 @@ int sysdev_register(struct sys_device * sysdev)
if (!error) {
struct sysdev_driver * drv;
down_write(&system_subsys.rwsem);
down(&sysdev_drivers_lock);
/* Generic notification is implicit, because it's that
* code that should have called us.
*/
/* Notify global drivers */
list_for_each_entry(drv, &global_drivers, entry) {
list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->add)
drv->add(sysdev);
}
......@@ -209,7 +210,7 @@ int sysdev_register(struct sys_device * sysdev)
if (drv->add)
drv->add(sysdev);
}
up_write(&system_subsys.rwsem);
up(&sysdev_drivers_lock);
}
return error;
}
......@@ -218,8 +219,8 @@ void sysdev_unregister(struct sys_device * sysdev)
{
struct sysdev_driver * drv;
down_write(&system_subsys.rwsem);
list_for_each_entry(drv, &global_drivers, entry) {
down(&sysdev_drivers_lock);
list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->remove)
drv->remove(sysdev);
}
......@@ -228,7 +229,7 @@ void sysdev_unregister(struct sys_device * sysdev)
if (drv->remove)
drv->remove(sysdev);
}
up_write(&system_subsys.rwsem);
up(&sysdev_drivers_lock);
kobject_unregister(&sysdev->kobj);
}
......@@ -255,7 +256,7 @@ void sysdev_shutdown(void)
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,
kset.kobj.entry) {
struct sys_device * sysdev;
......@@ -268,7 +269,7 @@ void sysdev_shutdown(void)
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */
list_for_each_entry(drv, &global_drivers, entry) {
list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->shutdown)
drv->shutdown(sysdev);
}
......@@ -284,7 +285,7 @@ void sysdev_shutdown(void)
cls->shutdown(sysdev);
}
}
up_write(&system_subsys.rwsem);
up(&sysdev_drivers_lock);
}
......@@ -319,7 +320,7 @@ int sysdev_suspend(u32 state)
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */
list_for_each_entry(drv, &global_drivers, entry) {
list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->suspend)
drv->suspend(sysdev, state);
}
......@@ -375,7 +376,7 @@ int sysdev_resume(void)
}
/* Call global drivers. */
list_for_each_entry(drv, &global_drivers, entry) {
list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->resume)
drv->resume(sysdev);
}
......
......@@ -4370,6 +4370,10 @@ int __init floppy_init(void)
goto out_flush_work;
}
err = platform_device_register(&floppy_device);
if (err)
goto out_flush_work;
for (drive = 0; drive < N_DRIVE; drive++) {
if (!(allowed_drive_mask & (1 << drive)))
continue;
......@@ -4379,23 +4383,12 @@ int __init floppy_init(void)
disks[drive]->private_data = (void *)(long)drive;
disks[drive]->queue = floppy_queue;
disks[drive]->flags |= GENHD_FL_REMOVABLE;
disks[drive]->driverfs_dev = &floppy_device.dev;
add_disk(disks[drive]);
}
err = platform_device_register(&floppy_device);
if (err)
goto out_del_disk;
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:
flush_scheduled_work();
if (usage_count)
......@@ -4600,7 +4593,6 @@ void cleanup_module(void)
int drive;
init_completion(&device_release);
platform_device_unregister(&floppy_device);
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
unregister_blkdev(FLOPPY_MAJOR, "fd");
......@@ -4614,6 +4606,7 @@ void cleanup_module(void)
}
put_disk(disks[drive]);
}
platform_device_unregister(&floppy_device);
devfs_remove("floppy");
del_timer_sync(&fd_timeout);
......
......@@ -302,7 +302,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
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();
subsystem_register(&block_subsys);
return 0;
......@@ -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,
int num_envp, char *buffer, int buffer_size)
{
struct device *dev = NULL;
struct kobj_type *ktype = get_ktype(kobj);
struct device *physdev;
struct gendisk *disk;
struct hd_struct *part;
int length = 0;
int i = 0;
/* get physical device backing disk or partition */
if (ktype == &ktype_block) {
struct gendisk *disk = container_of(kobj, struct gendisk, kobj);
dev = disk->driverfs_dev;
disk = container_of(kobj, struct gendisk, kobj);
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
&length, "MINOR=%u", disk->first_minor);
} else if (ktype == &ktype_part) {
struct gendisk *disk = container_of(kobj->parent, struct gendisk, kobj);
dev = disk->driverfs_dev;
}
disk = container_of(kobj->parent, struct gendisk, kobj);
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 physical device, backing this device */
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length,
"MAJOR=%u", disk->major);
/* 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,
&length, "PHYSDEVPATH=%s", path);
kfree(path);
/* add bus name of physical device */
if (dev->bus)
if (physdev->bus)
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name);
"PHYSDEVBUS=%s",
physdev->bus->name);
/* add driver name of physical device */
if (dev->driver)
if (physdev->driver)
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name);
envp[i] = NULL;
"PHYSDEVDRIVER=%s",
physdev->driver->name);
}
/* 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;
}
......
......@@ -108,13 +108,6 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
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)
{
struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
......@@ -451,11 +444,11 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
else
i2c_dev->class_dev.dev = adap->dev.parent;
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);
retval = class_device_register(&i2c_dev->class_dev);
if (retval)
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);
return 0;
error:
......
......@@ -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);
}
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(dev, S_IRUGO, show_dev, NULL);
struct video_device *video_device_alloc(void)
{
......@@ -347,12 +339,11 @@ int video_register_device(struct video_device *vfd, int type, int nr)
if (vfd->dev)
vfd->class_dev.dev = vfd->dev;
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);
class_device_register(&vfd->class_dev);
class_device_create_file(&vfd->class_dev,
&class_device_attr_name);
class_device_create_file(&vfd->class_dev,
&class_device_attr_dev);
#if 1 /* needed until all drivers are fixed */
if (!vfd->release)
......
......@@ -66,16 +66,7 @@ static struct file_operations usb_fops = {
.open = usb_open,
};
static void release_usb_class_dev(struct class_device *class_dev)
{
dbg("%s - %s", __FUNCTION__, class_dev->class_id);
kfree(class_dev);
}
static struct class usb_class = {
.name = "usb",
.release = &release_usb_class_dev,
};
static struct class_simple *usb_class;
int usb_major_init(void)
{
......@@ -87,9 +78,9 @@ int usb_major_init(void)
goto out;
}
error = class_register(&usb_class);
if (error) {
err("class_register failed for usb devices");
usb_class = class_simple_create(THIS_MODULE, "usb");
if (IS_ERR(usb_class)) {
err("class_simple_create failed for usb devices");
unregister_chrdev(USB_MAJOR, "usb");
goto out;
}
......@@ -102,18 +93,11 @@ int usb_major_init(void)
void usb_major_cleanup(void)
{
class_unregister(&usb_class);
class_simple_destroy(usb_class);
devfs_remove("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
* @intf: pointer to the usb_interface that is being registered
......@@ -141,7 +125,6 @@ int usb_register_dev(struct usb_interface *intf,
int minor_base = class_driver->minor_base;
int minor = 0;
char name[BUS_ID_SIZE];
struct class_device *class_dev;
char *temp;
#ifdef CONFIG_USB_DYNAMIC_MINORS
......@@ -181,22 +164,18 @@ int usb_register_dev(struct usb_interface *intf,
devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
/* create a usb class device for this usb interface */
class_dev = kmalloc(sizeof(*class_dev), GFP_KERNEL);
if (class_dev) {
memset(class_dev, 0x00, sizeof(struct class_device));
class_dev->class = &usb_class;
class_dev->dev = &intf->dev;
temp = strrchr(name, '/');
if (temp && (temp[1] != 0x00))
++temp;
else
temp = name;
snprintf(class_dev->class_id, BUS_ID_SIZE, "%s", temp);
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;
temp = strrchr(name, '/');
if (temp && (temp[1] != 0x00))
++temp;
else
temp = name;
intf->class_dev = class_simple_device_add(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
if (IS_ERR(intf->class_dev)) {
spin_lock (&minor_lock);
usb_minors[intf->minor] = NULL;
spin_unlock (&minor_lock);
devfs_remove (name);
retval = PTR_ERR(intf->class_dev);
}
exit:
return retval;
......@@ -239,11 +218,8 @@ void usb_deregister_dev(struct usb_interface *intf,
snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
devfs_remove (name);
if (intf->class_dev) {
class_device_unregister(intf->class_dev);
intf->class_dev = NULL;
}
class_simple_device_remove(MKDEV(USB_MAJOR, intf->minor));
intf->class_dev = NULL;
intf->minor = -1;
}
EXPORT_SYMBOL(usb_deregister_dev);
......
......@@ -29,7 +29,7 @@ static struct kobj_map *cdev_map;
/* degrade to linked list for small systems */
#define MAX_PROBE_HASH (CONFIG_BASE_SMALL ? 1 : 255)
static DEFINE_RWLOCK(chrdevs_lock);
static DECLARE_MUTEX(chrdevs_lock);
static struct char_device_struct {
struct char_device_struct *next;
......@@ -55,13 +55,13 @@ int get_chrdev_list(char *page)
len = sprintf(page, "Character devices:\n");
read_lock(&chrdevs_lock);
down(&chrdevs_lock);
for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
for (cd = chrdevs[i]; cd; cd = cd->next)
len += sprintf(page+len, "%3d %s\n",
cd->major, cd->name);
}
read_unlock(&chrdevs_lock);
up(&chrdevs_lock);
return len;
}
......@@ -91,7 +91,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
memset(cd, 0, sizeof(struct char_device_struct));
write_lock_irq(&chrdevs_lock);
down(&chrdevs_lock);
/* temporary */
if (major == 0) {
......@@ -126,10 +126,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
}
cd->next = *cp;
*cp = cd;
write_unlock_irq(&chrdevs_lock);
up(&chrdevs_lock);
return cd;
out:
write_unlock_irq(&chrdevs_lock);
up(&chrdevs_lock);
kfree(cd);
return ERR_PTR(ret);
}
......@@ -140,7 +140,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
struct char_device_struct *cd = NULL, **cp;
int i = major_to_index(major);
write_lock_irq(&chrdevs_lock);
up(&chrdevs_lock);
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major == major &&
(*cp)->baseminor == baseminor &&
......@@ -150,7 +150,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
cd = *cp;
*cp = cd->next;
}
write_unlock_irq(&chrdevs_lock);
up(&chrdevs_lock);
return cd;
}
......@@ -381,8 +381,6 @@ void cdev_del(struct cdev *p)
}
static decl_subsys(cdev, NULL, NULL);
static void cdev_default_release(struct kobject *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)
void __init chrdev_init(void)
{
/*
* 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);
cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
}
......
......@@ -15,7 +15,6 @@
#include <linux/ioport.h>
#include <linux/kobject.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pm.h>
......@@ -102,7 +101,7 @@ struct device_driver {
char * name;
struct bus_type * bus;
struct semaphore unload_sem;
struct completion unloaded;
struct kobject kobj;
struct list_head devices;
......@@ -148,6 +147,7 @@ struct class {
struct subsystem subsys;
struct list_head children;
struct list_head interfaces;
struct semaphore sem; /* locks both the children and interfaces lists */
struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs;
......@@ -184,6 +184,7 @@ struct class_device {
struct kobject kobj;
struct class * class; /* required */
dev_t devt; /* dev_t, creates the sysfs "dev" */
struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */
......
......@@ -7,6 +7,6 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
kobj_probe_t *, int (*)(dev_t, void *), void *);
void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
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
......@@ -20,6 +20,7 @@
#include <linux/types.h>
#include <linux/list.h>
#include <linux/sysfs.h>
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/kref.h>
#include <linux/kobject_uevent.h>
......@@ -102,6 +103,7 @@ struct kset {
struct subsystem * subsys;
struct kobj_type * ktype;
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
struct kset_hotplug_ops * hotplug_ops;
};
......
......@@ -26,7 +26,7 @@ struct kref {
void kref_init(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 /* _KREF_H_ */
......@@ -140,9 +140,9 @@ void kobject_init(struct kobject * kobj)
static void unlink(struct kobject * kobj)
{
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
spin_lock(&kobj->kset->list_lock);
list_del_init(&kobj->entry);
up_write(&kobj->kset->subsys->rwsem);
spin_unlock(&kobj->kset->list_lock);
}
kobject_put(kobj);
}
......@@ -168,13 +168,13 @@ int kobject_add(struct kobject * kobj)
kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
spin_lock(&kobj->kset->list_lock);
if (!parent)
parent = kobject_get(&kobj->kset->kobj);
list_add_tail(&kobj->entry,&kobj->kset->list);
up_write(&kobj->kset->subsys->rwsem);
spin_unlock(&kobj->kset->list_lock);
}
kobj->parent = parent;
......@@ -380,6 +380,7 @@ void kset_init(struct kset * k)
{
kobject_init(&k->kobj);
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)
struct list_head * entry;
struct kobject * ret = NULL;
down_read(&kset->subsys->rwsem);
spin_lock(&kset->list_lock);
list_for_each(entry,&kset->list) {
struct kobject * k = to_kobj(entry);
if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
......@@ -452,7 +453,7 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
break;
}
}
up_read(&kset->subsys->rwsem);
spin_unlock(&kset->list_lock);
return ret;
}
......@@ -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_register);
EXPORT_SYMBOL(kobject_unregister);
......@@ -532,7 +532,6 @@ EXPORT_SYMBOL(kobject_get);
EXPORT_SYMBOL(kobject_put);
EXPORT_SYMBOL(kobject_add);
EXPORT_SYMBOL(kobject_del);
EXPORT_SYMBOL(kobject_rename);
EXPORT_SYMBOL(kset_register);
EXPORT_SYMBOL(kset_unregister);
......
......@@ -42,14 +42,21 @@ void kref_get(struct kref *kref)
* in as this function.
*
* 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 == (void (*)(struct kref *))kfree);
if (atomic_dec_and_test(&kref->refcount))
if (atomic_dec_and_test(&kref->refcount)) {
release(kref);
return 1;
}
return 0;
}
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