Commit cfe15b8a authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/driver-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 2ed3d4f0 b168474c
...@@ -1247,6 +1247,12 @@ W: http://nfs.sourceforge.net/ ...@@ -1247,6 +1247,12 @@ W: http://nfs.sourceforge.net/
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/ W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
S: Maintained S: Maintained
KERNEL EVENT LAYER (KOBJECT_UEVENT)
P: Robert Love
M: rml@novell.com
L: linux-kernel@vger.kernel.org
S: Maintained
LANMEDIA WAN CARD DRIVER LANMEDIA WAN CARD DRIVER
P: Andrew Stanley-Jones P: Andrew Stanley-Jones
M: asj@lanmedia.com M: asj@lanmedia.com
......
...@@ -135,6 +135,52 @@ static struct kobj_type ktype_bus = { ...@@ -135,6 +135,52 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL); decl_subsys(bus, &ktype_bus, NULL);
static int __bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct list_head *head;
struct device *dev;
int error = 0;
if (!(bus = get_bus(bus)))
return -EINVAL;
head = &bus->devices.list;
dev = list_prepare_entry(start, head, bus_list);
list_for_each_entry_continue(dev, head, bus_list) {
get_device(dev);
error = fn(dev, data);
put_device(dev);
if (error)
break;
}
put_bus(bus);
return error;
}
static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
void * data, int (*fn)(struct device_driver *, void *))
{
struct list_head *head;
struct device_driver *drv;
int error = 0;
if (!(bus = get_bus(bus)))
return -EINVAL;
head = &bus->drivers.list;
drv = list_prepare_entry(start, head, kobj.entry);
list_for_each_entry_continue(drv, head, kobj.entry) {
get_driver(drv);
error = fn(drv, data);
put_driver(drv);
if (error)
break;
}
put_bus(bus);
return error;
}
/** /**
* bus_for_each_dev - device iterator. * bus_for_each_dev - device iterator.
* @bus: bus type. * @bus: bus type.
...@@ -154,30 +200,16 @@ decl_subsys(bus, &ktype_bus, NULL); ...@@ -154,30 +200,16 @@ decl_subsys(bus, &ktype_bus, NULL);
* to retain this data, it should do, and increment the reference * to retain this data, it should do, and increment the reference
* count in the supplied callback. * count in the supplied callback.
*/ */
int bus_for_each_dev(struct bus_type * bus, struct device * start, int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *)) void * data, int (*fn)(struct device *, void *))
{ {
struct device *dev; int ret;
struct list_head * head;
int error = 0;
if (!(bus = get_bus(bus)))
return -EINVAL;
head = &bus->devices.list;
dev = list_prepare_entry(start, head, bus_list);
down_read(&bus->subsys.rwsem); down_read(&bus->subsys.rwsem);
list_for_each_entry_continue(dev, head, bus_list) { ret = __bus_for_each_dev(bus, start, data, fn);
get_device(dev);
error = fn(dev, data);
put_device(dev);
if (error)
break;
}
up_read(&bus->subsys.rwsem); up_read(&bus->subsys.rwsem);
put_bus(bus); return ret;
return error;
} }
/** /**
...@@ -203,27 +235,12 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, ...@@ -203,27 +235,12 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *)) void * data, int (*fn)(struct device_driver *, void *))
{ {
struct list_head * head; int ret;
struct device_driver *drv;
int error = 0;
if(!(bus = get_bus(bus)))
return -EINVAL;
head = &bus->drivers.list;
drv = list_prepare_entry(start, head, kobj.entry);
down_read(&bus->subsys.rwsem); down_read(&bus->subsys.rwsem);
list_for_each_entry_continue(drv, head, kobj.entry) { ret = __bus_for_each_drv(bus, start, data, fn);
get_driver(drv);
error = fn(drv, data);
put_driver(drv);
if(error)
break;
}
up_read(&bus->subsys.rwsem); up_read(&bus->subsys.rwsem);
put_bus(bus); return ret;
return error;
} }
/** /**
...@@ -325,10 +342,10 @@ int device_attach(struct device * dev) ...@@ -325,10 +342,10 @@ int device_attach(struct device * dev)
* driver_attach - try to bind driver to devices. * driver_attach - try to bind driver to devices.
* @drv: driver. * @drv: driver.
* *
* Walk the list of devices that the bus has on it and try to match * Walk the list of devices that the bus has on it and try to
* the driver with each one. * match the driver with each one. If driver_probe_device()
* If bus_match() returns 0 and the @dev->driver is set, we've found * returns 0 and the @dev->driver is set, we've found a
* a compatible pair. * compatible pair.
* *
* Note that we ignore the -ENODEV error from driver_probe_device(), * Note that we ignore the -ENODEV error from driver_probe_device(),
* since it's perfectly valid for a driver not to bind to any devices. * since it's perfectly valid for a driver not to bind to any devices.
...@@ -590,7 +607,9 @@ int bus_rescan_devices(struct bus_type * bus) ...@@ -590,7 +607,9 @@ int bus_rescan_devices(struct bus_type * bus)
{ {
int count = 0; int count = 0;
bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); down_write(&bus->subsys.rwsem);
__bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
up_write(&bus->subsys.rwsem);
return count; return count;
} }
......
...@@ -283,8 +283,34 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp, ...@@ -283,8 +283,34 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
{ {
struct class_device *class_dev = to_class_dev(kobj); struct class_device *class_dev = to_class_dev(kobj);
int retval = 0; int retval = 0;
int i = 0;
int length = 0;
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
if (class_dev->dev) {
/* add physical device, backing this device */
struct device *dev = class_dev->dev;
char *path = kobject_get_path(&dev->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)
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->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;
}
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,
......
...@@ -209,12 +209,12 @@ void device_initialize(struct device *dev) ...@@ -209,12 +209,12 @@ void device_initialize(struct device *dev)
*/ */
int device_add(struct device *dev) int device_add(struct device *dev)
{ {
struct device * parent; struct device *parent = NULL;
int error; int error = -EINVAL;
dev = get_device(dev); dev = get_device(dev);
if (!dev || !strlen(dev->bus_id)) if (!dev || !strlen(dev->bus_id))
return -EINVAL; goto Error;
parent = get_device(dev->parent); parent = get_device(dev->parent);
......
...@@ -438,8 +438,46 @@ static int block_hotplug_filter(struct kset *kset, struct kobject *kobj) ...@@ -438,8 +438,46 @@ static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
return ((ktype == &ktype_block) || (ktype == &ktype_part)); return ((ktype == &ktype_block) || (ktype == &ktype_part));
} }
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);
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;
} else if (ktype == &ktype_part) {
struct gendisk *disk = container_of(kobj->parent, struct gendisk, kobj);
dev = disk->driverfs_dev;
}
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, "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);
envp[i] = NULL;
}
return 0;
}
static struct kset_hotplug_ops block_hotplug_ops = { static struct kset_hotplug_ops block_hotplug_ops = {
.filter = block_hotplug_filter, .filter = block_hotplug_filter,
.hotplug = block_hotplug,
}; };
/* declare block_subsys. */ /* declare block_subsys. */
......
...@@ -56,7 +56,7 @@ int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, ...@@ -56,7 +56,7 @@ int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
sd = sysfs_new_dirent(parent_sd, element); sd = sysfs_new_dirent(parent_sd, element);
if (!sd) if (!sd)
return -ENOMEM; return 0;
sd->s_mode = mode; sd->s_mode = mode;
sd->s_type = type; sd->s_type = type;
...@@ -201,7 +201,7 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) ...@@ -201,7 +201,7 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
return err; return err;
} }
struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd) struct nameidata *nd)
{ {
struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
...@@ -277,7 +277,7 @@ void sysfs_remove_dir(struct kobject * kobj) ...@@ -277,7 +277,7 @@ void sysfs_remove_dir(struct kobject * kobj)
pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
down(&dentry->d_inode->i_sem); down(&dentry->d_inode->i_sem);
list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
if (!sd->s_element) if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED))
continue; continue;
list_del_init(&sd->s_sibling); list_del_init(&sd->s_sibling);
sysfs_drop_dentry(sd, dentry); sysfs_drop_dentry(sd, dentry);
......
...@@ -330,11 +330,13 @@ static int sysfs_release(struct inode * inode, struct file * filp) ...@@ -330,11 +330,13 @@ static int sysfs_release(struct inode * inode, struct file * filp)
{ {
struct kobject * kobj = to_kobj(filp->f_dentry->d_parent); struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
struct attribute * attr = to_attr(filp->f_dentry); struct attribute * attr = to_attr(filp->f_dentry);
struct module * owner = attr->owner;
struct sysfs_buffer * buffer = filp->private_data; struct sysfs_buffer * buffer = filp->private_data;
if (kobj) if (kobj)
kobject_put(kobj); kobject_put(kobj);
module_put(attr->owner); /* After this point, attr should not be accessed. */
module_put(owner);
if (buffer) { if (buffer) {
if (buffer->page) if (buffer->page)
......
...@@ -76,11 +76,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) ...@@ -76,11 +76,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
return error; return error;
} }
int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
return sysfs_create(dentry, mode, NULL);
}
struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name) struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name)
{ {
struct qstr qstr; struct qstr qstr;
......
...@@ -22,7 +22,7 @@ static struct super_operations sysfs_ops = { ...@@ -22,7 +22,7 @@ static struct super_operations sysfs_ops = {
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
}; };
struct sysfs_dirent sysfs_root = { static struct sysfs_dirent sysfs_root = {
.s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling), .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling),
.s_children = LIST_HEAD_INIT(sysfs_root.s_children), .s_children = LIST_HEAD_INIT(sysfs_root.s_children),
.s_element = NULL, .s_element = NULL,
......
...@@ -9,12 +9,6 @@ ...@@ -9,12 +9,6 @@
#include "sysfs.h" #include "sysfs.h"
struct inode_operations sysfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = sysfs_follow_link,
.put_link = sysfs_put_link,
};
static int object_depth(struct kobject * kobj) static int object_depth(struct kobject * kobj)
{ {
struct kobject * p = kobj; struct kobject * p = kobj;
...@@ -157,7 +151,7 @@ static int sysfs_getlink(struct dentry *dentry, char * path) ...@@ -157,7 +151,7 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
} }
int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
int error = -ENOMEM; int error = -ENOMEM;
unsigned long page = get_zeroed_page(GFP_KERNEL); unsigned long page = get_zeroed_page(GFP_KERNEL);
...@@ -167,13 +161,20 @@ int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) ...@@ -167,13 +161,20 @@ int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
return 0; return 0;
} }
void sysfs_put_link(struct dentry *dentry, struct nameidata *nd) static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd)
{ {
char *page = nd_get_link(nd); char *page = nd_get_link(nd);
if (!IS_ERR(page)) if (!IS_ERR(page))
free_page((unsigned long)page); free_page((unsigned long)page);
} }
struct inode_operations sysfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = sysfs_follow_link,
.put_link = sysfs_put_link,
};
EXPORT_SYMBOL_GPL(sysfs_create_link); EXPORT_SYMBOL_GPL(sysfs_create_link);
EXPORT_SYMBOL_GPL(sysfs_remove_link); EXPORT_SYMBOL_GPL(sysfs_remove_link);
...@@ -17,8 +17,6 @@ extern void sysfs_remove_subdir(struct dentry *); ...@@ -17,8 +17,6 @@ extern void sysfs_remove_subdir(struct dentry *);
extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
extern int sysfs_follow_link(struct dentry *, struct nameidata *);
extern void sysfs_put_link(struct dentry *, struct nameidata *);
extern struct rw_semaphore sysfs_rename_sem; extern struct rw_semaphore sysfs_rename_sem;
extern struct super_block * sysfs_sb; extern struct super_block * sysfs_sb;
extern struct file_operations sysfs_dir_operations; extern struct file_operations sysfs_dir_operations;
......
...@@ -183,6 +183,7 @@ int kobject_add(struct kobject * kobj) ...@@ -183,6 +183,7 @@ int kobject_add(struct kobject * kobj)
unlink(kobj); unlink(kobj);
if (parent) if (parent)
kobject_put(parent); kobject_put(parent);
kobject_put(kobj);
} else { } else {
kobject_hotplug(kobj, KOBJ_ADD); kobject_hotplug(kobj, KOBJ_ADD);
} }
......
...@@ -120,9 +120,8 @@ static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action, ...@@ -120,9 +120,8 @@ static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action,
sprintf(attrpath, "%s/%s", path, attr->name); sprintf(attrpath, "%s/%s", path, attr->name);
rc = send_uevent(signal, attrpath, NULL, gfp_mask); rc = send_uevent(signal, attrpath, NULL, gfp_mask);
kfree(attrpath); kfree(attrpath);
} else { } else
rc = send_uevent(signal, path, NULL, gfp_mask); rc = send_uevent(signal, path, NULL, gfp_mask);
}
exit: exit:
kfree(path); kfree(path);
...@@ -148,7 +147,6 @@ int kobject_uevent_atomic(struct kobject *kobj, enum kobject_action action, ...@@ -148,7 +147,6 @@ int kobject_uevent_atomic(struct kobject *kobj, enum kobject_action action,
{ {
return do_kobject_uevent(kobj, action, attr, GFP_ATOMIC); return do_kobject_uevent(kobj, action, attr, GFP_ATOMIC);
} }
EXPORT_SYMBOL_GPL(kobject_uevent_atomic); EXPORT_SYMBOL_GPL(kobject_uevent_atomic);
static int __init kobject_uevent_init(void) static int __init kobject_uevent_init(void)
...@@ -164,11 +162,11 @@ static int __init kobject_uevent_init(void) ...@@ -164,11 +162,11 @@ static int __init kobject_uevent_init(void)
return 0; return 0;
} }
core_initcall(kobject_uevent_init); postcore_initcall(kobject_uevent_init);
#else #else
static inline int send_uevent(const char *signal, const char *obj, static inline int send_uevent(const char *signal, const char *obj,
const void *buf, int buflen, int gfp_mask) char **envp, int gfp_mask)
{ {
return 0; return 0;
} }
......
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